gd32i2c中断接收与发送
时间: 2023-09-10 17:01:44 浏览: 472
GD32 I2C(Inter-Integrated Circuit)是一种多主机串行总线通信协议,其中断接收和发送主要是通过I2C的中断实现的。
在GD32 MCU中使用I2C进行数据传输时,可以通过配置I2C的中断使能来实现接收和发送的中断处理。
对于接收方面,可以使用I2C的接收中断来处理数据的接收。首先,需要配置I2C的接收中断使能,并且设置接收数据的缓冲区和接收数据长度。当I2C接收到数据时,会触发接收中断,通过中断处理程序可以将接收到的数据从I2C接收缓冲区中读取出来并进行相应的处理。
对于发送方面,可以使用I2C的发送中断来处理数据的发送。同样需要配置I2C的发送中断使能,并设置发送数据的缓冲区和发送数据长度。在发送数据时,通过中断处理程序将数据逐个发送出去,直到发送完所有数据。
在使用中断的时候,需要在中断处理程序中注意处理错误中断,如传输错误或者设备地址无响应等情况。
总结来说,GD32 I2C中断接收与发送的实现主要包括配置中断使能、设置接收/发送数据的缓冲区和长度以及在中断处理程序中处理接收和发送的数据。中断的使用可以提高数据传输的效率和可靠性,并且能够及时处理异常情况,保证通信的稳定性。
相关问题
gd32 i2c 中断
### GD32 I2C 中断配置及问题解决
#### 配置概述
为了使 GD32 微控制器通过 I2C 协议作为从设备运行并与树莓派通信,需要正确配置硬件和软件环境。具体来说,当启用 `ENABLE_I2C_TEST` 宏并将其设为 `yes` 时,会编译与 I2C1 相关的功能代码[^1]。此外,在头文件 `i2c.h` 中定义 `I2C1_MODE` 的值为 `I2C1_MODE_SLAVE` 可以确保 I2C1 工作在从机模式下。
#### 软件实现细节
以下是基于上述描述的具体实现方法:
1. **宏定义配置**
在项目的 Makefile 文件中添加如下内容来激活 I2C 测试功能:
```makefile
ENABLE_I2C_TEST = yes
```
2. **头文件修改**
修改 `i2c.h` 头文件中的宏定义部分,指定 I2C1 运行于从机模式:
```c
#define I2C1_MODE I2C1_MODE_SLAVE
```
3. **初始化函数编写**
初始化 I2C 接口的代码通常包括以下步骤:
- 设置 GPIO 引脚为复用功能。
- 配置 I2C 寄存器参数(如地址匹配、时钟频率等)。
下面是一个简单的初始化示例代码片段:
```c
void i2c_init(void) {
rcu_periph_clock_enable(RCU_GPIOB); // 开启GPIOB时钟
rcu_periph_clock_enable(RCU_I2C1); // 开启I2C1时钟
gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);
/* 配置I2C*/
i2c_mode_config(I2C1, I2C_MODE_I2CM);
i2c_own_address_set(I2C1, I2C_ADDRESSINGMODE_7BIT, SLAVE_ADDR << 1);
i2c_ack_config(I2C1, I2C_ACK_ENABLE);
i2c_interrupt_enable(I2C1, I2C_INT_ERR | I2C_INT_STPDET | I2C_INT_ADDSEND | I2C_INT_RBNE | I2C_INT_TBE);
i2c_enable(I2C1);
}
```
4. **中断处理程序设计**
当接收到数据或完成传输操作时,GD32 将触发相应的中断事件。下面展示了一个典型的中断服务例程 (ISR),用于捕获这些事件:
```c
void I2C1_EV_IRQHandler(void){
if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_ADDSEND)){
i2c_clear_addsent_flag(I2C1);
g_recv_index = 0;
}else if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_RBNE)){
g_buffer[g_recv_index++] = i2c_data_receive(I2C1);
}
}
void I2C1_ER_IRQHandler(void){
if(i2c_interrupt_flag_get(I2C1, I2C_INT_FLAG_BERR)){
i2c_interrupt_flag_clear(I2C1, I2C_INT_FLAG_BERR);
}
}
```
以上代码展示了如何设置 I2C 从机模式以及响应来自主控端的数据请求过程。
#### 常见问题及其解决方案
- 如果发现无法正常进入 ISR,则需确认 NVIC 是否已开启对应外设中断源;
- 数据丢失可能源于缓冲区溢出,请适当调整数组大小或者优化轮询逻辑;
- 地址冲突可能导致通讯失败,建议仔细核对双方设定的一致性。
GD32硬件I2C中断
### GD32 I2C 中断配置及问题解决
#### 配置 I2C 中断
为了使能并配置 GD32 的 I2C 中断,需按照如下方式进行初始化:
1. **开启外设时钟**
在使用 I2C 功能之前,必须先打开对应的 APB1 外设时钟。对于 I2C1 来说,在 RCC_APB1PeriphClockCmd 函数中加入相应的参数即可。
2. **初始化结构体变量**
创建 `I2C_InitTypeDef` 类型的实例用于存储 I2C 初始化参数,并通过调用 `I2C_StructInit()` 设置默认值[^3]。
3. **设置工作模式**
将设备设定为主模式还是从模式取决于具体应用场景需求。当作为从机时,可以通过定义宏如 `#define I2C1_MODE I2C1_MODE_SLAVE` 并确保 Makefile 文件中有 `ENABLE_I2C_TEST = yes` 以便编译相关代码片段。
4. **配置中断优先级**
使用 NVIC (Nested Vectored Interrupt Controller) 对应函数为 I2C 设定合适的抢占和响应优先级别,保证其能够在期望的时间内得到处理。
5. **注册回调函数**
定义好各个事件发生后的动作逻辑,比如接收到数据后如何处理等操作,通常是在用户自定义的应用层实现这部分功能。
```c
// 开启 I2C1 和 GPIOA 时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
// 初始化 I2C 结构体
I2C_InitTypeDef I2C_InitStructure;
I2C_StructInit(&I2C_InitStructure);
// 配置 SDA/SCL 引脚
GPIO_InitTypeDef GPIO_InitStructure;
...
// 进入从机模式
#define I2C1_MODE I2C1_MODE_SLAVE
// 设置 I2C 参数...
I2C_InitStructure.I2C_Mode = I2C_Mode_Slave;
...
// 使能 I2C 接口
I2C_Cmd(I2C1, ENABLE);
// 配置中断源
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn; // 或者 I2C1_ER_IRQn 错误中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// 注册中断服务程序
void I2C1_EV_IRQHandler(void){
if (I2C_GetITStatus(I2C1, I2C_IT_EVT)){
// 处理事件
...
}
}
```
#### 解决常见问题
针对可能出现的问题,特别是硬件层面导致的通信异常情况,可以采取以下措施:
- 当遇到 I2C 总线卡死现象时,尝试利用 STOP 命令清除忙状态标志位而不是依赖于软件复位整个模块,因为后者可能会丢失当前配置信息[^1]。
- 如果发现即使重启也无法恢复正常,则可能是由于外部因素引起的数据冲突或物理连接不良造成的;此时应该仔细检查线路连接状况以及上拉电阻是否正常工作。
- 另一种有效的方式是增加超时机制来检测长时间未完成的操作,并据此做出适当反应,防止系统陷入无限等待的状态。
阅读全文
相关推荐














