【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

代码实现
#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;
}
运行效果下图

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;
}
运行效果如下图
