欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > GD32 IIC(I2C)通信(使用示例为SD2068)

GD32 IIC(I2C)通信(使用示例为SD2068)

2025/5/25 6:55:53 来源:https://blog.csdn.net/Blasit/article/details/148156379  浏览:    关键词:GD32 IIC(I2C)通信(使用示例为SD2068)

一、前言

        最近需要用到GD32的I2C通信,虽然是第一次做I2C通信,但是GD32完整的标准库有现存的I2C通信示例,虽然示例是EEPROM的通信,但是调用的函数应该是大差不差,所以上手比较简单,这里简单记录一下笔记,方便下次使用。

二、GD32与SD2068 的连接

  • SDA:GD32的I2C数据线(我选用的PB10)。

  • SCL:GD32的I2C时钟线(我选用的PB11)。

三、I2C初始化

宏定义和头文件:

#include "gd32e23x.h" //已经包含了gd32e23x_i2c.h#define I2C_PERIPH             I2C1
#define I2C_SPEED              100000
#define I2C_BUS_ADDRESS        0x32
#define I2C_RCUX               RCU_I2C1
#define I2C_RCU_GPIOX          RCU_GPIOB
#define I2C_SCL_PIN            GPIO_PIN_10
#define I2C_SDA_PIN            GPIO_PIN_11

1、GPIO初始化

void i2c_gpio_config(void)
{/* 时钟初始化 */rcu_periph_clock_enable(I2C_RCU_GPIOX);/* I2C_SCL 引脚复用 */gpio_af_set(GPIOB, GPIO_AF_1, I2C_SCL_PIN);/* I2C_SDA 引脚复用 */gpio_af_set(GPIOB, GPIO_AF_1, I2C_SDA_PIN);/* 初始化GPIO复用功能模式 */gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SCL_PIN);gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN);gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SDA_PIN);gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN);
}

 2、I2C功能初始化

void i2c_config(void)
{// 启用 I2C 外设的时钟rcu_periph_clock_enable(I2C_RCUX);// 配置 I2C 的时钟参数:// I2C_PERIPH:这里使用的I2C1// I2C_SPEED:通信速率(单位为 Hz,常用为 100000 或 400000),这里使用100000i2c_clock_config(I2C_PERIPH, I2C_SPEED, I2C_DTCY_2);// 配置 I2C 工作模式和地址:// I2C_ADDFORMAT_7BITS:使用 7 位地址模式// I2C_BUS_ADDRESS:SD2068器件代码0110010 = 0x32i2c_mode_addr_config(I2C_PERIPH, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C_BUS_ADDRESS);// 启用 I2C 外设i2c_enable(I2C_PERIPH);// 使能 ACK 应答功能,确保在接收数据后自动发送 ACKi2c_ack_config(I2C_PERIPH, I2C_ACK_ENABLE);
}

四、I2C写实现

        主要过程就是:空闲->发送START 信号->发送设备、寄存器地址和方向->发送数据。封装函数如下:

void i2c_write_multi(uint8_t reg_addr, uint8_t *data, uint8_t dataSize)
{// 等待 I2C 总线空闲,防止冲突while(i2c_flag_get(I2C_PERIPH, I2C_FLAG_I2CBSY));// 发送 START 信号,起始 I2C 通信i2c_start_on_bus(I2C_PERIPH);while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND));// 发送设备地址和写入方向(最低位0)i2c_master_addressing(I2C_PERIPH, I2C_BUS_ADDRESS << 1, I2C_TRANSMITTER);//i2c_data_transmit(I2C_PERIPH, I2C_BUS_ADDRESS << 1);while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND));// 清除地址发送标志位i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND);// 发送寄存器地址(子地址)i2c_data_transmit(I2C_PERIPH, reg_addr);while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE));// 开始循环写入多个数据字节while(dataSize--) {delay_1ms(5);i2c_data_transmit(I2C_PERIPH, *data++);while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE));}// 发送 STOP 信号,结束通信i2c_stop_on_bus(I2C_PERIPH);while(I2C_CTL0(I2C_PERIPH) & I2C_CTL0_STOP);
}

五、I2C读实现

        通信过程与写类似,直接上实现代码:

void i2c_read_multi(uint8_t reg_addr, uint8_t *data, uint8_t dataSize)
{// 等待 I2C 总线空闲while(i2c_flag_get(I2C_PERIPH, I2C_FLAG_I2CBSY));// 发送起始信号i2c_start_on_bus(I2C_PERIPH);while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND));// 发送设备地址i2c_master_addressing(I2C_PERIPH, I2C_BUS_ADDRESS << 1, I2C_TRANSMITTER);while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND));//清地址标志i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND);// 写入要读取的寄存器地址(子地址)i2c_data_transmit(I2C_PERIPH, reg_addr);while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_TBE));while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_BTC));// 第二次起始信号,重新启动为“读模式”i2c_start_on_bus(I2C_PERIPH);while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_SBSEND));// 发送设备地址,读方向(1)i2c_master_addressing(I2C_PERIPH, I2C_BUS_ADDRESS << 1, I2C_RECEIVER);while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_ADDSEND));i2c_flag_clear(I2C_PERIPH, I2C_FLAG_ADDSEND);// 如果只读取1个字节,提前关闭ACK,准备发送STOPif (dataSize == 1) {i2c_ack_config(I2C_PERIPH, I2C_ACK_DISABLE);i2c_stop_on_bus(I2C_PERIPH);}// 读取多个字节循环for (uint8_t i = 0; i < dataSize; i++) {delay_1ms(5);if (i == dataSize - 2) {// 读取即将完成,关闭ACK,准备发送STOPi2c_ack_config(I2C_PERIPH, I2C_ACK_DISABLE);i2c_stop_on_bus(I2C_PERIPH);}while(!i2c_flag_get(I2C_PERIPH, I2C_FLAG_RBNE));data[i] = i2c_data_receive(I2C_PERIPH);}// 等待 STOP 传输完毕while(I2C_CTL0(I2C_PERIPH) & I2C_CTL0_STOP);// 恢复 ACK 设置(便于下次通信)i2c_ack_config(I2C_PERIPH, I2C_ACK_ENABLE);i2c_ackpos_config(I2C_PERIPH, I2C_ACKPOS_CURRENT);
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词