gd32f103 iic接收发送
时间: 2025-05-16 09:41:08 浏览: 15
### GD32F103 IIC 协议配置与示例代码
#### 背景介绍
GD32F103 是基于 ARM Cortex-M3 内核的高性能微控制器,其架构设计类似于 STM32F103 系列。因此,在实现 IIC (Inter-Integrated Circuit) 协议时,可以参考类似的硬件外设操作方法[^1]。
为了完成 IIC 数据的接收与发送,需要对 GD32F103 的 IIC 外设进行初始化设置,并编写相应的数据传输函数。以下是详细的配置教程和示例代码。
---
#### 配置步骤说明
##### 1. GPIO 初始化
IIC 使用两根线 SDA 和 SCL 进行通信,分别对应于 GPIO 引脚的功能复用模式。需将对应的 GPIO 设置为开漏输出模式并启用上拉电阻。
```c
void gpio_iic_init(void)
{
rcu_periph_clock_enable(RCU_GPIOA); // 启用GPIOA时钟
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9 | GPIO_PIN_10);
gpio_output_options_set(GPIOA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_9 | GPIO_PIN_10);
gpio_af_set(GPIOA, GPIO_AF_4, GPIO_PIN_9 | GPIO_PIN_10); // 将PA9/PA10配置为AF4(IIC功能)
}
```
上述代码中 `RCU` 表示复位和时钟控制模块,用于使能相关外设的时钟源[^3]。
##### 2. IIC 外设初始化
通过配置寄存器设定 IIC 工作参数,包括波特率、地址模式以及主从设备角色等。
```c
void iic_config(void)
{
/* 开启IIC时钟 */
rcu_periph_clock_enable(RCU_I2C1);
/* 配置IIC工作参数 */
i2c_struct_para_init(&i2c_initpara);
i2c_initpara.i2c_timen = 0x1E; // 波特率分频因子(根据实际晶振调整)
i2c_initpara.i2c_ownaddr = 0xA0 << 1; // 设备自己的7位地址左移一位
i2c_initpara.i2c_ackfunc = I2C_ACK_ENABLE;
i2c_initpara.i2c_duty = I2C_DUTY_CYCLE_2;
i2c_init(I2C1, &i2c_initpara);
i2c_enable(I2C1);
nvic_irq_enable(I2C1_EVENT_IRQn, 1, 0); // 中断优先级配置
}
```
此部分实现了基本的 IIC 参数初始化,其中中断可选配以满足实时性需求。
##### 3. 数据发送函数
定义一个通用的数据写入接口供调用者使用:
```c
uint8_t iic_send_byte(uint8_t slave_addr, uint8_t reg_addr, uint8_t data)
{
if(i2c_start_on_bus(I2C1)) {
return ERROR;
}
if(!i2c_master_addressing(I2C1, slave_addr, I2C_TRANSMITTER)){
return ERROR;
}
while(i2c_flag_get(I2C1, I2C_FLAG_TBE) == RESET){} // 等待缓冲区为空
i2c_data_transmit(I2C1, reg_addr); // 发送寄存器地址
while(i2c_flag_get(I2C1, I2C_FLAG_BTF) == RESET){}
i2c_data_transmit(I2C1, data); // 发送具体数据
while(i2c_flag_get(I2C1, I2C_FLAG_BTF) == RESET){}
i2c_stop_on_bus(I2C1);
return SUCCESS;
}
```
##### 4. 数据接收函数
同样构建读取远程器件寄存器值的方法如下所示:
```c
uint8_t iic_read_byte(uint8_t slave_addr, uint8_t reg_addr, uint8_t *pdata)
{
if(i2c_start_on_bus(I2C1)) {return ERROR;}
if(!i2c_master_addressing(I2C1, slave_addr, I2C_TRANSMITTER)){
return ERROR;
}
while(i2c_flag_get(I2C1, I2C_FLAG_TBE) == RESET){}
i2c_data_transmit(I2C1, reg_addr);
while(i2c_flag_get(I2C1, I2C_FLAG_BTF) == RESET){}
if(i2c_restart_on_bus(I2C1)) {return ERROR;}
if(!i2c_master_addressing(I2C1, slave_addr, I2C_RECEIVER)){
return ERROR;
}
while(i2c_flag_get(I2C1, I2C_FLAG_RBNE) == RESET){}
(*pdata) = i2c_data_receive(I2C1);
i2c_stop_on_bus(I2C1);
return SUCCESS;
}
```
以上两个函数封装了完整的启动条件判断、目标地址指定及停止信号生成逻辑[^2]。
---
### 示例应用案例
假设我们要向某款 OLED 屏幕(采用 SSD1306 控制芯片)发送命令字节来清屏,则可以这样调用前述 API:
```c
int main()
{
gpio_iic_init();
iic_config();
uint8_t cmd_clear_screen = 0xE2; // 假定这是OLED屏幕的一个清除显示缓存指令码
iic_send_byte(0x3C<<1, 0x00, cmd_clear_screen);
while(1){
;
}
}
```
这里需要注意的是不同型号显示屏可能具有不同的物理连接方式及其默认从属节点地址,请查阅相应资料确认后再编程实践。
---
阅读全文
相关推荐


















