gd32f330g 的i2c从机收发
时间: 2025-05-23 08:05:21 浏览: 19
### 关于GD32F330G I2C从机收发实现及代码示例
#### 背景介绍
GD32系列微控制器提供了丰富的外设功能,其中包括I2C通信模块。对于GD32F330G芯片而言,其I2C外设支持主/从模式下的数据传输。在从机模式下,设备能够响应主机发起的数据请求或写入操作。
为了实现I2C从机的功能,通常需要完成以下几个方面的配置:
1. 初始化GPIO引脚为I2C模式。
2. 配置I2C时钟频率以及地址匹配机制。
3. 设置中断处理程序以捕获事件(如接收到起始信号、停止信号或数据到达)。
4. 编写具体的读取和写入逻辑来管理缓冲区中的数据流。
以下是基于GD32F330G的I2C从机收发的一个典型实现方案[^5]:
---
#### GPIO初始化设置
首先定义用于I2C通信的两个主要引脚——SDA(数据线)和SCL(时钟线)。这些引脚应被配置成复用推挽输出模式,并启用内部上拉电阻。
```c
void i2c_gpio_init(void)
{
rcu_periph_clock_enable(RCU_GPIOB); // 启用GPIOB时钟
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6 | GPIO_PIN_7);
gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);
gpio_af_set(GPIOB, GPIO_AF_1, GPIO_PIN_6 | GPIO_PIN_7); // 将PB6/PB7映射到I2C1
}
```
---
#### I2C硬件参数配置
接下来对I2C本身进行必要的初始化工作,包括指定目标地址、设定波特率等属性。
```c
void i2c_config(void)
{
/* 开启对应外设时钟 */
rcu_periph_clock_enable(RCU_I2C1);
/* 结构体填充默认值 */
struct i2c_init_struct i2c_initpara;
memset(&i2c_initpara, 0, sizeof(i2c_initpara));
/* 参数赋值 */
i2c_initpara.i2c_analog_filter = ENABLE; // 模拟滤波开启
i2c_initpara.i2c_digital_filter_cnt = 0x00; // 数字噪声过滤计数清零
i2c_initpara.i2c_ack_state = I2C_ACK_ENABLE; // 应答使能
i2c_initpara.i2c_own_address1 = SLAVE_ADDRESS;// 自身从属节点ID号
i2c_initpara.i2c_timing = 0x00900AF8; // 定义时间常量适应当前系统晶振条件
i2c_init(I2C1, &i2c_initpara);
/* 打开全局控制开关 */
i2c_enable(I2C1);
i2c_slave_disable_acknowledge_stop_detection(I2C1); // 停止检测ACKNOLWGE状态变化触发STOP condition
}
```
---
#### 中断服务函数设计
当有新的事务发生时,比如接收到启动位或者数据包到来,则会产生相应的中断标志位通知CPU采取行动。下面展示了一个简单的ISR框架用来处理各种可能的情况。
```c
uint8_t rx_buffer[RX_BUFFER_SIZE];
volatile uint16_t rx_index = 0;
void I2C1_EV_IRQHandler(void)
{
if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_SBSEND)) {
// 主器件发送START后进入此分支
i2c_acknowledge_config(I2C1, ENABLE);
} else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_ADDSEND)) {
// 地址匹配成功后的动作
if (!i2c_transmitter_receiver_mode_select(I2C1)) {
// 如果是接收方向...
i2c_memory_addressing_mode_config(I2C1, I2C_MEMORY_ADDR_8BIT);
i2c_data_transfer_direction_config(I2C1, I2C_RECEIVER_MODE);
}
} else if (i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_RDT)) {
// 接受到单字节数据
rx_buffer[rx_index++] = i2c_data_receive(I2C1);
if(rx_index >= RX_BUFFER_SIZE){
// 数据溢出保护措施
rx_index=RX_BUFFER_SIZE-1;
}
}
// 清除所有相关联的中断源标记
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_ALL);
}
// 类似地还需要编写错误处理部分的回调方法
void I2C1_ER_IRQHandler(void){...}
```
---
#### 测试验证过程
最后一步就是通过实际测试确认整个链路能否正常运作起来。可以通过连接一台PC端模拟器充当Master角色向Slave发出命令序列;与此同时观察Slave侧是否按照预期返回期望的结果集即可判断项目成败与否。
---
阅读全文
相关推荐














