RVMCU课堂「14」: 手把手教你玩转RVSTAR—I2C总线通信篇
扫描二维码
随时随地手机看文章
系统环境
软件平台
硬件需求
I²C是由NXP(原PHILIPS)公司开发的两线式串行总线,用于连接微控制器及其外围芯片,目前已成为一种行业标准,在微控制器设计中被大量采用,在RV-STAR所使用的GD32VF103微控制器上也集成了I²C接口。
I²C在应用时,在发送了起始信号(Start)后,要先发送一个7位的从机地址,紧跟着的第8位是数据方向位(R/W),“0”表示接下来要发送数据,“1”表示接下来要读数据。当发送完这个8个位后,如果发送的地址有设备存在,这个设备应该回复一个ACK(拉低SDA,输出“0”),这样才会继续进行通信流程。
OLED液晶屏介绍
OLED(Organic Light-Emitting Diode,有机发光二极管)因为具备轻薄、省电、显示效果好等特性,被广泛应用手机、音乐播放器等电子设备中。
尺寸 | 0.96英寸 |
分辨率 | 128*64 |
可视角度 | 大于160° |
功耗 | 0.06w |
供电范围 | 3.3v~5v |
工作温度 | -30℃~70℃ |
体积 | 27mm*27mm*2mm |
亮度 | 可通过指令控制 |
驱动芯片 | SSD1306 |
接口 | I2C |
GD32VF103的I²C接口
GD32VF103的I²C(内部集成电路总线)模块提供了符合工业标准的两线串行制接口,可用于MCU和外部I²C设备的通讯。I²C总线使用两条串行线:串行数据线SDA和串行时钟线SCL。I²C接口模块实现了I²C协议的标速模式(最高100KHz)和快速模式(最高400KHz),具备CRC计算和校验功能,支持SMBus(系统管理总线)和 PMBus(电源管理总线)。此外还支持多主机I²C总线架构。I²C接口模块也支持DMA模式,可有效减轻CPU的负担。
实验部分
首先需要将RV-STAR开发板及OLED显示屏参照下图使用杜邦线进行连线:
void I2C_Configuration(void)
{
uint32_t GPIO_SDA, GPIO_SCL;
uint32_t GPIO_PIN_SDA, GPIO_PIN_SCL;
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_I2C1);
GPIO_SDA = GPIOB;
GPIO_PIN_SDA = GPIO_PIN_11;
GPIO_SCL = GPIOB;
GPIO_PIN_SCL = GPIO_PIN_10;
gpio_init(GPIO_SCL, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_SCL);
gpio_init(GPIO_SDA, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_SDA);
i2c_clock_config(I2C1, 400000, I2C_DTCY_2);
i2c_mode_addr_config(I2C1, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x30);
i2c_enable(I2C1);
i2c_ack_config(I2C1, I2C_ACK_ENABLE);
}
void I2C_WriteByte(uint8_t addr, uint8_t data)
{
/* wait until I2C bus is idle */
while(i2c_flag_get(I2C1, I2C_FLAG_I2CBSY));
/* send a start condition to I2C bus */
i2c_start_on_bus(I2C1);
/* wait until SBSEND bit is set */
while(!i2c_flag_get(I2C1, I2C_FLAG_SBSEND));
/* send slave address to I2C bus*/
i2c_master_addressing(I2C1, 0x78, I2C_TRANSMITTER);
/* wait until ADDSEND bit is set*/
while(!i2c_flag_get(I2C1, I2C_FLAG_ADDSEND));
/* clear ADDSEND bit */
i2c_flag_clear(I2C1, I2C_FLAG_ADDSEND);
/* send a addr byte */
i2c_data_transmit(I2C1, addr);
/* wait until the transmission data register is empty*/
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));
/* send a data byte */
i2c_data_transmit(I2C1, data);
/* wait until the transmission data register is empty*/
while(!i2c_flag_get(I2C1, I2C_FLAG_TBE));
/* send a stop condition to I2C bus*/
i2c_stop_on_bus(I2C1);
/* wait until stop condition generate */
while(I2C_CTL0(I2C1)