[G32R] 【G32R501 Micro-EVB测评】8.I2C通信

[复制链接]
157|4
yuyy1989 发表于 2025-12-26 10:33 | 显示全部楼层 |阅读模式

【G32R501 Micro-EVB测评】8.I2C通信

1.I2C简介

I2C(Inter-Integrated Circuit)总线由荷兰的飞利浦半导体在1982年开发,是一种用于连接微控制器和外围设备的串行通信协议,设计I2C的初衷是减少电视机等复杂电子系统内部的布线数量,同时也降低制造成本。通过使用只有两根线的通信总线,它有效地减少了器件间连接的复杂性,由一条双向的数据线(SDA)和一条时钟线(SCL)组成。I2C总线支持多主多从的通信方式,每个设备都有一个唯一的地址,通过地址来区分不同的设备。
G32R501有1个I2C模块,支持主机从机模式,接收FIFO和发送FIFO,数据传输速率:10 kbps~400 kbps

2.配置I2C的相关函数

1.I2C_disableModule()禁用I2C模块
2.I2C_initMaster()初始化I2C为主机模式并设置波特率
3.I2C_setBitCount()设置数据宽度
4.I2C_setAddressMode()设置地址模式
5.I2C_enableFIFO()开启FIFO
6.I2C_enableModule()开启I2C模块
7.I2C_setSlaveAddress()设置从机地址
8.I2C_setConfig()设置主机从机发送接收模式
9.I2C_sendStartCondition()发送开始条件
10.I2C_putData()发送1字节数据
11.I2C_sendStopCondition()发送停止条件

3.I2C点亮OLED

手上有个OLED的屏幕,主控SSD1315使用I2C通信,接下来编程点亮这块屏幕
在数据手册找到I2C的IO

ScreenShot_2025-12-25_170118_360.png
代码实现

#include "device.h"
#include "stdio.h"
#include "yuyy_ssd1315.h"
#include "yuyy_fonts.h"
void I2C_Init(void)
{
    GPIO_setPinConfig(GPIO_0_I2CA_SDA);
    GPIO_setDrivingCapability(0,GPIO_DRIVE_LEVEL_VERY_HIGH);
    GPIO_setPadConfig(0, GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode(0, GPIO_QUAL_ASYNC);
    GPIO_setPinConfig(GPIO_1_I2CA_SCL);
    GPIO_setDrivingCapability(1,GPIO_DRIVE_LEVEL_VERY_HIGH);
    GPIO_setPadConfig(1, GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode(1, GPIO_QUAL_ASYNC);
  
    I2C_disableModule(I2CA_BASE);
    I2C_initMaster(I2CA_BASE, DEVICE_APBCLK_FREQ, 100000, I2C_DUTYCYCLE_50);
    I2C_setBitCount(I2CA_BASE, I2C_BITCOUNT_8);
    I2C_setAddressMode(I2CA_BASE, I2C_ADDR_MODE_7BITS);
    I2C_enableFIFO(I2CA_BASE);
    I2C_enableModule(I2CA_BASE);
}

void I2C_SendRegDatas(uint32_t base,uint8_t addr,uint8_t reg,uint8_t *data,uint16_t len)
{
    while(I2C_getStopConditionStatus(base));
    I2C_setSlaveAddress(base, addr);
    while(I2C_isBusBusy(base));

    I2C_setDataCount(base, len+1);
    I2C_setConfig(base, I2C_MASTER_SEND_MODE);
    I2C_sendStartCondition(base);
    I2C_putData(base, reg);
    while (len > 0)
    {
        while(len > 0 && I2C_getTxFIFOStatus(base) <I2C_FIFO_TXFULL)
        {
            I2C_putData(base, *data);
            data++;
            len--;
        }
    }
    I2C_sendStopCondition(base);
}

YUYY_SSD1315_DEV_Type oled;
void OLED_Init(void)
{
    YUYY_SSD1315_InitConfig_Type config;
    YUYY_SSD1315_ConfigInit(&config);
    oled.com_type = YUYY_SSD1315_COM_I2C_SA0_0;
    oled.driver.com = (uint32_t *)I2CA_BASE;
    oled.driver.i2c_senddatas_func = (YUYY_SSD1315_I2CSendDatasFunc_Type)I2C_SendRegDatas;
    YUYY_SSD1315_Init(&oled,&config);
    YUYY_SSD1315_ClearScreen(&oled);
    YUYY_SSD1315_DisplayASCIIString8x16(&oled,0,0,"G32R501Micro-EVB",YUYY_SSD1315_DISPLAY_MODE_NOMARL,0);
    YUYY_SSD1315_DisplayASCIIString8x16(&oled,2,0,"I2C OLED Test",YUYY_SSD1315_DISPLAY_MODE_NOMARL,0);
    YUYY_SSD1315_DisplayASCIIString8x16(&oled,4,0,"Code by yuyy1989",YUYY_SSD1315_DISPLAY_MODE_NOMARL,0);
}

int main()
{
    Device_init();
    Interrupt_initModule();
    Interrupt_initVectorTable();
    Interrupt_setPriorityGroup(INTERRUPT_PRIGROUP_PREEMPT_7_6_SUB_5_0);
    Interrupt_enableMaster();
    I2C_Init();
    OLED_Init();
    while(1)
    {
    }
    return 1;
}

运行效果下图

ScreenShot_2025-12-25_170520_249.png

4.I2C读取温湿度传感器数据

AHT20是一款温湿度传感器,使用I2C通信,接下来编程读取温湿度传感器的数据并显示在OLED上

#include "device.h"
#include "stdio.h"
#include "yuyy_ssd1315.h"
#include "yuyy_fonts.h"
#include "yuyy_aht20.h"
void I2C_Init(void)
{
    GPIO_setPinConfig(GPIO_0_I2CA_SDA);
    GPIO_setDrivingCapability(0,GPIO_DRIVE_LEVEL_VERY_HIGH);
    GPIO_setPadConfig(0, GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode(0, GPIO_QUAL_ASYNC);
    GPIO_setPinConfig(GPIO_1_I2CA_SCL);
    GPIO_setDrivingCapability(1,GPIO_DRIVE_LEVEL_VERY_HIGH);
    GPIO_setPadConfig(1, GPIO_PIN_TYPE_PULLUP);
    GPIO_setQualificationMode(1, GPIO_QUAL_ASYNC);
  
    I2C_disableModule(I2CA_BASE);
    I2C_initMaster(I2CA_BASE, DEVICE_APBCLK_FREQ, 100000, I2C_DUTYCYCLE_50);
    I2C_setBitCount(I2CA_BASE, I2C_BITCOUNT_8);
    I2C_setAddressMode(I2CA_BASE, I2C_ADDR_MODE_7BITS);
    I2C_enableFIFO(I2CA_BASE);
    I2C_enableModule(I2CA_BASE);
}

uint8_t I2C_SendDatas(uint32_t base,uint8_t addr,uint8_t *data,uint16_t len)
{
    while(I2C_getStopConditionStatus(base));
    I2C_setSlaveAddress(base, addr);
    while(I2C_isBusBusy(base));
    I2C_setDataCount(base, len);
    I2C_setConfig(base, I2C_MASTER_SEND_MODE);
    I2C_sendStartCondition(base);
    while (len > 0)
    {
        while(len > 0 && I2C_getTxFIFOStatus(base) <I2C_FIFO_TXFULL)
        {
            I2C_putData(base, *data);
            data++;
            len--;
        }
    }
    I2C_sendStopCondition(base);
    return 0;
}

uint8_t  I2C_ReadDatas(uint32_t base,uint8_t addr,uint8_t *data,uint16_t len)
{
    while(I2C_getStopConditionStatus(base));
    I2C_setSlaveAddress(base, addr);
    while(I2C_isBusBusy(base));
    I2C_setDataCount(base, len);
    I2C_setConfig(base, I2C_MASTER_RECEIVE_MODE);
    I2C_sendStartCondition(base);
    while (len > 0)
    {
        while(len > 0 && I2C_getRxFIFOStatus(base) > I2C_FIFO_TXEMPTY)
        {
            *data = I2C_getData(base);
            data++;
            len--;
        }
    }
    I2C_sendStopCondition(base);
    return 0;
}
void I2C_SendRegDatas(uint32_t base,uint8_t addr,uint8_t reg,uint8_t *data,uint16_t len)
{
    while(I2C_getStopConditionStatus(base));
    I2C_setSlaveAddress(base, addr);
    while(I2C_isBusBusy(base));
    I2C_setDataCount(base, len+1);
    I2C_setConfig(base, I2C_MASTER_SEND_MODE);
    I2C_sendStartCondition(base);
    I2C_putData(base, reg);
    while (len > 0)
    {
        while(len > 0 && I2C_getTxFIFOStatus(base) <I2C_FIFO_TXFULL)
        {
            I2C_putData(base, *data);
            data++;
            len--;
        }
    }
    I2C_sendStopCondition(base);
}

YUYY_SSD1315_DEV_Type oled;
void OLED_Init(void)
{
    YUYY_SSD1315_InitConfig_Type config;
    YUYY_SSD1315_ConfigInit(&config);
    oled.com_type = YUYY_SSD1315_COM_I2C_SA0_0;
    oled.driver.com = (uint32_t *)I2CA_BASE;
    oled.driver.i2c_senddatas_func = (YUYY_SSD1315_I2CSendDatasFunc_Type)I2C_SendRegDatas;
    YUYY_SSD1315_Init(&oled,&config);
    YUYY_SSD1315_ClearScreen(&oled);
    YUYY_SSD1315_DisplayASCIIString8x16(&oled,0,0,"G32R501Micro-EVB",YUYY_SSD1315_DISPLAY_MODE_NOMARL,0);
    YUYY_SSD1315_DisplayASCIIString8x16(&oled,2,0,"I2C OLED AHT20",YUYY_SSD1315_DISPLAY_MODE_NOMARL,0);
    YUYY_SSD1315_DisplayASCIIString8x16(&oled,6,0,"Code by yuyy1989",YUYY_SSD1315_DISPLAY_MODE_NOMARL,0);
}

YUYY_AHT20_DEV_Type aht20;
void AHT20_Init(void)
{
    aht20.i2cx = (uint32_t *)I2CA_BASE;
    aht20.delayms_func = (YUYY_AHT20_DelayMsFunc_Type)APP_DelayMs;
    aht20.i2c_senddatas_func = (YUYY_AHT20_I2CSendDatasFunc_Type)I2C_SendDatas;
    aht20.i2c_readdatas_func = (YUYY_AHT20_I2CReadDatasFunc_Type)I2C_ReadDatas;
    YUYY_AHT20_Init(&aht20);
}

int main()
{
    int16_t tem,hum;
    char str[20];
    Device_init();
    Interrupt_initModule();
    Interrupt_initVectorTable();
    Interrupt_setPriorityGroup(INTERRUPT_PRIGROUP_PREEMPT_7_6_SUB_5_0);
    Interrupt_enableMaster();
    I2C_Init();
    OLED_Init();
    AHT20_Init();
    while(1)
    {
        if(YUYY_AHT20_ReadHT(&aht20,&tem,&hum) == 0)
        {
            sprintf(str,"T:%.2f H:%.2f",tem/100.0,hum/100.0);
            YUYY_SSD1315_DisplayASCIIString8x16(&oled,4,0,str,YUYY_SSD1315_DISPLAY_MODE_NOMARL,0);
        }
        APP_DelayMs(1000);
    }
    return 1;
}

运行效果如下图

ScreenShot_2025-12-25_182421_119.png

梦塑者 发表于 2025-12-27 09:35 | 显示全部楼层
I2C居然带有FIFO,这款R501的硬件配置还是丰富的
观星者宁静 发表于 2025-12-27 21:01 | 显示全部楼层
I2C模式 至少还是要使用中断模式来处理。
查询模式还是有点麻烦
星空魔法师 发表于 2026-1-8 22:38 | 显示全部楼层
代码实现部分很清晰, 步骤完整,逻辑清晰。
阳光爆裂 发表于 2026-1-8 19:39 | 显示全部楼层
我也有一块和楼主一样的温湿度传感器模块
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

181

主题

987

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部
0