0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【GD32 MCU 入门教程】GD32 MCU 常见外设介绍(7)I2C 模块介绍

聚沃科技 2024-08-16 09:54 次阅读

7.1.I2C 基础知识

I2C(Inter-Integrated Circuit)总线是一种由Philips公司开发的两线式串行总线,用于内部IC控制的具有多端控制能力的双线双向串行数据总线系统,能够用于替代标准的并行总线,连接各种集成 电路和功能模块。I2C器件能够减少电路间的连接,减少电路板的尺寸,降低硬件成本并提高系统的可靠性。I2C总线传输模式具有向下兼容性,传输速率标准模式下可达100kbps,快速模式下可 达400kbps,高速模式下可达3.4Mbps。

为了清楚起见,在此对I2C通信中关于设备的基本概念进行简要讲解。

① 发送设备:发送数据到总线上的设备。

② 接收设备:从总线上接收数据的设备。

③ 主设备:启动数据传输并产生时钟信号的设备。

④ 从设备:被主设备寻址的设备。

多主:多个主设备可以尝试在不破坏信息的前提下同时控制线。

同步:同步两个或更多设备之间的时钟信号的过程。

仲裁:如果超过一个主设备同时试图控制总线,只有一个主设备被允许,且获胜主设备的信息不被破坏。

(1)I2C设备连接原理 I2C设备连接示意图如设备连接示意图所示。I2C总线是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据。在GD32 MCU与被控IC(集成电路)之间、IC与IC之间进行双向传送,最高传送速率1Mbps。各种设备均并联在总线上,两条总线都被上拉电阻上拉到VCC,所有设备地位对等,都可作为主机或从机,就像电话机一样只要拨通各自的号码就能正常工作,所以,每个设备都有唯一的地址。在信息的传输过程中,I2C总线上并接的每个设备既是主设备(或从设备),又是发送设备(或接收设备),这取决于它所要完成的功能。每个设备都可以把总线接地拉低,却不允许把总线电平直接连到VCC上置高。把总线电平拉低称为占用总线,总线电平为高等待被拉低则称为总线被释放。

I2C 设备连接示意图

输入图片说明

由于SDA和SCL均为双向I/O线,都是开漏极端(输出1时,为高阻状态),因此I2C总线上的所有设备的SDA和SCL引脚都要外接上拉电阻。

(2)I2C数据通信协议

I2C数据通信时序图如I2C数据通信时序图所示。下面首先介绍起始位和停止位,起始位和停止位都是由主设备产生的,如图中虚线所示。当SCL时钟线为高电平时,SDA数据线上由高到低的跳变,产生一个开始信号,即起始位。当SCL时钟线为高电平时,SDA数据线上由低到高的跳变,将产生一个停止信号,即停止位。起始位之后,总线被认为忙,即有数据在传输,传输的第一个字节,即7位从地址和R/ ̄W 位。当R/ ̄W位为0时,主机向从机发送数据;当R/ ̄W位为1时,主机接收来自从机的数据。在每个字节后的第九个SCL时钟上,接收机发送ACK位。停止位之后,总线被认为闲,空闲状态时,SDA和SCL都是高电平。

注意:当SCL位为高电平时,SDA的数据必须保持稳定,否则,由于起始位和停止位的电气边沿特性,SDA上数据发生改变将被识别为起始位或停止位。所以,只有当SCL为低电平时才允许SDA上的数据改变。

I2C 数据通信时序图

输入图片说明

I2C总线上每位数据传输的示意图

输入图片说明

(3)I2C的寻址方式 GD32 MCU的I2C模块支持7位和10位两种寻址模式,7位寻址模式最多寻址128个设备,10位寻址模式最多寻址1024个设备。I2C总线理论上可以允许的最大设备数是以总线上所有器件的电容总和不超过400pF为限(其中,包括连线本身的电容和其连接端的引出等效电容),总线上所有器件要依靠SDA发送的地址信号寻址,不需要片选信号。

① 7位寻址模式

如图下图所示为7位地址方式下的I2C数据传输格式,第一个字节由7位从地址和R/ ̄W读/写位组成。不论总线上传送的是地址还是数据信息,每个字节传输完毕,接收设备都会发送响应位(ACK)。地址类信息传输之后是数据信息,直到接收到停止信息。

7 位寻址模式数据格式

输入图片说明

② 10位寻址模式

如下图所示为10位地址方式下的I2C数据传输格式。第一个字节由二进制位11110、从地址的最高两位及R/ ̄W读/写控制位组成。第一个字节传输完毕后是ACK响应位。第二个字节就是10位从地址的低8位,后面是响应位和数据。

10 位寻址模式数据格式

输入图片说明

③ 二次发送从地址模式(重复产生起始条件)

主机可以在不停止数据传输的情况下,通过产生重复的起始条件,改变SDA上数据流的方向,这称为RESTART。再次发送起始信号后,需重新发送从地址和R/ ̄W读/写控制位。重新产生起始条件数据传输格式如图所示。

输入图片说明

7.2.GD32 I2C 外设原理简介

因篇幅有限,本文无法详细介绍GD32所有系列I2C外设接口,下面以GD32F30x为列,着重介绍下GD32F30x的I2C外设简介和结构框图,后介绍下各个系列的差异。

GD32 I2C 主要特性

GD32F30X系列I2C 接口模块实现了 I2C 协议的标速模式,快速模式以及快速+ 模式,具备CRC 计算和校验功能、支持 SMBus(系统管理总线) 和 PMBus(电源管理总线),此外还支持多主机 I2C 总线架构。 I2C 接口模块也支持 DMA 模式,可有效减轻 CPU 的负担。

GD32 MCU I2C模块主要特性描述如下:

◼ 并行总线至 I2C 总线协议的转换及接口;

◼ 同一接口既可实现主机功能又可实现从机功能;

◼ 主从机之间的双向数据传输;

◼ 支持 7 位和 10 位的地址模式和广播寻址;

◼ 支持 I2C 多主机模式;

◼ 支持标速(最高 100 KHz),快速(最高 400 KHz) 和快速+ 模式(最高 1MHz);

◼ 从机模式下可配置的 SCL 主动拉低;

◼ 支持 DMA 模式;

◼ 兼容 SMBus 2.0 和 PMBus;

◼ 两个中断:字节成功发送中断和错误事件中断;

◼ 可选择的 PEC(报文错误校验) 生成和校验;

I2C 结构框图介绍

I2C内部结构框图如下图所示,该结构框图可分为五个部分:

1、用于产生I2C通信时序;

2、用于收发I2C数据,当有数据需要发送时,会首先将数据填充到数据寄存器,然后数据被自动移位到移位寄存器,通过SDA引脚发送出去,当有数据需要接受时,首先会根据SCL选择的时钟边沿在移位寄存器中锁存SDA数据,当数据接受到后,数据被移到数据缓冲寄存器,并置位接受缓冲区非空标志;

3、用于收发数据CRC计算;

4、用于I2C模块控制及相关标志位查询;

5、系统通过APB总线对I2C数据寄存器及控制寄存器进行操作。

输入图片说明

各系列 I2C 功能差异

GD32各系列MCU有关IIC功能差异如各系列I2C功能差异表所示。

输入图片说明

7.3.硬件连接说明

如AT24C02C EEPROM IIC接口参考电路图所示,AT24C02C为IIC接口的EEPROM,该电路图为其典型参考电路,其中5脚为I2C SDA引脚,6脚为I2C SCL引脚,I2C总线需要通过4.7K欧姆电阻上拉。

输入图片说明

7.4.软件配置说明

本小节讲解I2C_Example下的I2C0主机历程,本例程讲解IIC作为主机情况下对从机的读写,并引入超时恢复机制。

IIC 初始化配置

IIC初始化配置代码如代码清单I2C初始化配置所示,首先进行GPIO初始化,然后对IIC外设进行初始化。注意本例程仅讲解IIC0的外设引脚及模块初始化,若其他IIC模块可参考修改。

void I2C_init(uint32_t I2Cx) { GPIO_Configuration_I2C(I2Cx); i2c_clock_config(I2Cx, 400000, I2C_DTCY_2); /* I2C address configure */ i2c_mode_addr_config(I2Cx, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0); /* enable acknowledge */ i2c_ack_config(I2Cx, I2C_ACK_DISABLE); /* enable I2Cx */ i2c_enable(I2Cx); }

时钟及 GPIO 引脚配置

时钟及GPIO引脚配置如代码清单I2C时钟及GPIO引脚配置所示,在例程中PB6、PB7引脚需要配置为复用开漏模式。

void GPIO_Configuration_I2C(uint32_t I2Cx) { uint32_t GPIO_SDA; uint32_t GPIO_SCL; uint32_t GPIO_Pin_SDA,GPIO_Pin_SCL; rcu_periph_reset_enable(RCU_I2C0RST); rcu_periph_reset_disable(RCU_I2C0RST); #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X || GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X /* enable GPIOB clock */ rcu_periph_clock_enable(RCU_GPIOB); /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X rcu_periph_clock_enable(RCU_AF); #elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X #endif GPIO_SCL=GPIOB; GPIO_Pin_SCL=GPIO_PIN_6; GPIO_SDA=GPIOB; GPIO_Pin_SDA=GPIO_PIN_7; #endif /* Reset I2C1 IP */ // I2C_DeInit(I2Cx); #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X /* I2C0 GPIO ports */ /* connect PB6 to I2C0_SCL */ gpio_init(GPIO_SCL, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SCL); /* connect PB7 to I2C0_SDA */ gpio_init(GPIO_SDA, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SDA); #elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X #if defined GD32F1X0 || GD32F3X0 || GD32E23X /* I2C GPIO ports */ /* connect I2C_SCL_GPIO_PIN to I2C_SCL */ gpio_af_set(GPIO_SCL, GPIO_AF_1, GPIO_Pin_SCL); /* connect I2C_SDA_GPIO_PIN to I2C_SDA */ gpio_af_set(GPIO_SDA, GPIO_AF_1, GPIO_Pin_SDA); #elif defined GD32F4XX gpio_af_set(GPIO_SCL, GPIO_AF_4, GPIO_Pin_SCL); gpio_af_set(GPIO_SDA, GPIO_AF_4, GPIO_Pin_SDA); #endif gpio_mode_set(GPIO_SCL, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_Pin_SCL); gpio_output_options_set(GPIO_SCL, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SCL); gpio_mode_set(GPIO_SDA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_Pin_SDA); gpio_output_options_set(GPIO_SDA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SDA); #endif }

I2C 多字节写操作

I2C多字节写操作如代码清单IIC写多字节操作所示,该函数接口实现IIC外设对IIC从机的多字节写操作。

/*! \brief I2Cx Write NBytes \param[in] i2c_periph : I2Cx(x=0,1) \param[in] addr : slave address \param[in] start_Addr : reg \param[in] number_Bytes: number to Write \param[in] ADDR_Length : number of the addr */ I2C_Status I2Cx_Write_NBytes(uint32_t I2Cx,uint8_t driver_Addr, uint16_t start_Addr, uint8_t number_Bytes, uint8_t *write_Buffer,uint8_t ADDR_Length) { uint32_t I2C_Timeout = I2C_SHORT_TIMEOUT; i2c_ack_config(I2Cx,I2C_ACK_ENABLE); while(i2c_flag_get(I2Cx, I2C_FLAG_I2CBSY)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_start_on_bus(I2Cx); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_master_addressing(I2Cx, driver_Addr, I2C_TRANSMITTER); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_flag_clear(I2Cx,I2C_FLAG_ADDSEND); I2C_Timeout = I2C_SHORT_TIMEOUT; while(SET != i2c_flag_get( I2Cx , I2C_FLAG_TBE )) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_enable(I2Cx); if(ADDR_Length)//Á½×Ö½ÚµØÖ· { i2c_data_transmit(I2Cx, (uint8_t)((start_Addr & 0xFF00) >> 8)); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_data_transmit(I2Cx, (uint8_t)(start_Addr & 0x00FF)); } else { i2c_data_transmit(I2Cx, start_Addr); } I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } while(number_Bytes) { i2c_data_transmit(I2Cx, *write_Buffer); I2C_Timeout = I2C_SHORT_TIMEOUT; //while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED))//5 // while(!i2c_flag_get(I2Cx, I2C_BTC))// while(!i2c_flag_get(I2Cx, I2C_FLAG_TBE)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* point to the next location where the byte read will be saved */ write_Buffer++; /* decrement the read bytes counter */ number_Bytes--; } // while(!i2c_flag_get(I2C1, I2C_BTC)) // { // if((I2C_Timeout--) == 0) // { // Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); // return I2C_FAIL; // } // } /* send a stop condition to I2C bus */ i2c_stop_on_bus(I2Cx); I2C_Timeout = I2C_SHORT_TIMEOUT; while (I2C_CTL0(I2Cx) & 0x0200) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_ack_config(I2Cx,I2C_ACK_ENABLE); return I2C_OK; }

IIC 多字节读操作

IIC多字节读操作如代码清单IIC多字节读操作所示,该函数接口可实现对IIC从机的多字节读功能。

I2C_Status I2Cx_Read_NBytes(uint32_t I2Cx,uint8_t driver_Addr, uint16_t start_Addr, uint8_t number_Bytes, uint8_t *read_Buffer,uint8_t ADDR_Length) { uint32_t I2C_Timeout = I2C_SHORT_TIMEOUT; i2c_ack_config(I2Cx,I2C_ACK_ENABLE); while(i2c_flag_get(I2Cx, I2C_FLAG_I2CBSY)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } if(number_Bytes==2) { i2c_ackpos_config(I2Cx,I2C_ACKPOS_NEXT); } i2c_start_on_bus(I2Cx); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_master_addressing(I2Cx, driver_Addr, I2C_TRANSMITTER); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* clear the ADDSEND bit */ i2c_flag_clear(I2Cx,I2C_FLAG_ADDSEND); I2C_Timeout = I2C_SHORT_TIMEOUT; while(SET != i2c_flag_get( I2Cx , I2C_FLAG_TBE )) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_enable(I2Cx); if(ADDR_Length)//Á½×Ö½ÚµØÖ· { i2c_data_transmit(I2Cx, (uint8_t)((start_Addr & 0xFF00) >> 8)); I2C_Timeout = I2C_SHORT_TIMEOUT; //while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING)) while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_data_transmit(I2Cx, (uint8_t)(start_Addr & 0x00FF)); } else { i2c_data_transmit(I2Cx, start_Addr); } I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_start_on_bus(I2Cx); I2C_Timeout = I2C_SHORT_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_SBSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } i2c_master_addressing(I2Cx, driver_Addr, I2C_RECEIVER); I2C_Timeout = I2C_SHORT_TIMEOUT; if(number_Bytes<3) { i2c_ack_config(I2Cx,I2C_ACK_DISABLE); } while(!i2c_flag_get(I2Cx, I2C_FLAG_ADDSEND)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* clear the ADDSEND bit */ i2c_flag_clear(I2Cx,I2C_FLAG_ADDSEND); if(number_Bytes==1) { i2c_stop_on_bus(I2Cx); } while(number_Bytes) { if(3 == number_Bytes){ /* wait until BTC bit is set */ I2C_Timeout = I2C_LONG_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* disable acknowledge */ /* disable acknowledge */ i2c_ack_config(I2Cx,I2C_ACK_DISABLE); } if(2 == number_Bytes){ /* wait until BTC bit is set */ I2C_Timeout = I2C_LONG_TIMEOUT; while(!i2c_flag_get(I2Cx, I2C_FLAG_BTC)) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* send a stop condition to I2C bus */ i2c_stop_on_bus(I2Cx); I2C_Timeout = I2C_SHORT_TIMEOUT; while (I2C_CTL0(I2Cx) & 0x0200) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } } /* wait until the RBNE bit is set and clear it */ if(i2c_flag_get(I2Cx, I2C_FLAG_RBNE)){ /* read a byte from the EEPROM */ *read_Buffer = i2c_data_receive(I2Cx); /* point to the next location where the byte read will be saved */ read_Buffer++; /* decrement the read bytes counter */ number_Bytes--; } } while(I2C_CTL0(I2Cx)&0x0200) { if((I2C_Timeout--) == 0) { Resume_IIC(I2C_LONG_TIMEOUT,I2Cx); return I2C_FAIL; } } /* enable acknowledge */ i2c_ack_config(I2Cx,I2C_ACK_ENABLE); i2c_ackpos_config(I2Cx,I2C_ACKPOS_CURRENT); return I2C_OK; }

IIC 超时恢复机制

IIC超时恢复机制实现如代码清单IIC超时恢复机制所示。

uint32_t I2C_Timeout; void Delay_I2C(uint32_t i) { while(i--); } void Resume_IIC(uint32_t Timeout,uint32_t I2Cx ) { uint32_t GPIO_SDA; uint32_t GPIO_SCL; uint32_t GPIO_Pin_SDA,GPIO_Pin_SCL; #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X || GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X /* enable GPIOB clock */ rcu_periph_clock_enable(RCU_GPIOB); /* enable I2C0 clock */ rcu_periph_clock_enable(RCU_I2C0); #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X rcu_periph_clock_enable(RCU_AF); #elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X #endif #endif GPIO_SCL=GPIOB; GPIO_Pin_SCL=GPIO_PIN_6; GPIO_SDA=GPIOB; GPIO_Pin_SDA=GPIO_PIN_7; do{ #if defined GD32F10X_HD || GD32F30X_HD || GD32F20X_CL || GD32E10X /* I2C0 GPIO ports */ /* connect PB6 to I2C0_SCL */ gpio_init(GPIO_SCL, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SCL); /* connect PB7 to I2C0_SDA */ gpio_init(GPIO_SDA, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SDA); #elif defined GD32F1X0 || GD32F4XX || GD32F3X0 || GD32E23X #if defined GD32F1X0 || GD32F3X0 || GD32E23X /* I2C GPIO ports */ /* connect I2C_SCL_GPIO_PIN to I2C_SCL */ gpio_af_set(GPIO_SCL, GPIO_AF_1, GPIO_Pin_SCL); /* connect I2C_SDA_GPIO_PIN to I2C_SDA */ gpio_af_set(GPIO_SDA, GPIO_AF_1, GPIO_Pin_SDA); #elif defined GD32F4XX gpio_af_set(GPIO_SCL, GPIO_AF_4, GPIO_Pin_SCL); gpio_af_set(GPIO_SDA, GPIO_AF_4, GPIO_Pin_SDA); #endif gpio_mode_set(GPIO_SCL, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_Pin_SCL); gpio_output_options_set(GPIO_SCL, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SCL); gpio_mode_set(GPIO_SDA, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_Pin_SDA); gpio_output_options_set(GPIO_SDA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_Pin_SDA); #endif gpio_bit_reset(GPIO_SCL, GPIO_Pin_SCL); Delay_I2C(20); gpio_bit_reset(GPIO_SDA, GPIO_Pin_SDA); Delay_I2C(20); gpio_bit_set(GPIO_SCL, GPIO_Pin_SCL); Delay_I2C(20); gpio_bit_set(GPIO_SDA, GPIO_Pin_SDA); Delay_I2C(20); if(Timeout-- == 0) return; }while((!gpio_input_bit_get(GPIO_SDA, GPIO_Pin_SDA))&(!gpio_input_bit_get(GPIO_SCL, GPIO_Pin_SCL))); I2C_init(I2Cx); }

主函数说明

本例程主函数如代码清单I2C例程主函数所示。

int main(void) { I2C_init(I2C0); I2Cx_Write_NBytes(I2C0,0xA0, 0,8, Write_Buf,0); I2Cx_Read_NBytes(I2C0,0xA0, 0,8, Read_Buf,0); while (1) { }

7.5.I2C 使用注意事项

1、I2C总线需要上拉;

2、I2C引脚需要配置为复用开漏模式;

3、若采用查询方式进行I2C数据传输,有可能会由于总线干扰,导致I2C卡死,可以在查询方式上增加超时机制,如果超时重配IIC恢复总线通信(注意重配IIC时,建议先将I2C模块Deinit,然后 在调用Init函数进行初始化)。

4、若采用软件模拟IIC的方式,在移植过程中出现问题,可能是由于代码执行效率的问题,可以排查软件延迟时间和其他芯片上的软件延迟时间是否相同,可以通过调整软件延迟时间进行测试;或者有可能是由于初始化配置IO端口的时候可能会引入干扰,可以先配置IO口输出高,然后再配置为推挽或开漏模式。

教程GD32 MCU方案商聚沃科技原创发布,了解更多GD32 MCU教程,关注聚沃科技官网

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6031

    文章

    44507

    浏览量

    632454
  • mcu
    mcu
    +关注

    关注

    146

    文章

    16956

    浏览量

    350131
  • 嵌入式
    +关注

    关注

    5065

    文章

    18998

    浏览量

    302632
  • I2C
    I2C
    +关注

    关注

    28

    文章

    1479

    浏览量

    123187
  • GD32
    +关注

    关注

    7

    文章

    403

    浏览量

    24178
收藏 人收藏

    评论

    相关推荐

    GD32 MCU 入门教程GD32 MCU 常见外设介绍(12)FMC 模块介绍

    闪存控制器(FMC),提供了片上闪存需要的所有功能。FMC 也提供了页擦除,整片擦除,以及32 位整字或 16 位半字编程闪存等操作。 GD32 MCU 支持不同类型编程的具体说明如下表 GD32
    的头像 发表于 08-21 09:56 957次阅读
    <b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入门教程</b>】<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>常见外设</b><b class='flag-5'>介绍</b>(12)FMC <b class='flag-5'>模块</b><b class='flag-5'>介绍</b>

    GD32 MCU移植

    gd32是一款国产单片机。该芯片在很多方面和STM32有异曲同工之处。资料不是很多! GD32外设方面、和STM32没有多大区别。 只是需要注意资源的引脚分配。虽然和STM32使用方式一样、但是也存在
    发表于 03-23 13:40

    GD32MCU介绍

    其实兆芯的MCU为了兼容ST,外设的寄存器设计与ST保持一致了。比如GD32VF103或者GD32E103系列的USBFS这个外设,基本等同
    发表于 11-01 06:03

    GD32 MCU原理及固件库开发指南》+读后感

    ,包括ADC和DAC。 第7介绍GD32 MCU的基础通信外设,包括USART、I2C和SPI
    发表于 06-06 21:52

    兆易创新GD32 MCU选型手册,适用于GD32全系列MCU

    兆易创新GD32MCU选型手册,适用于GD32全系列MCUGD32MCU选型手册,适用于GD32全系列MCU
    发表于 10-19 17:26 49次下载

    你了解GD32 MCU的命名规则吗

    下面为大家介绍GD32 MCU的通用命名规则,以GD32F303ZGT6为例,其中,GD32代表GD32
    的头像 发表于 01-13 09:38 3413次阅读
    你了解<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b>的命名规则吗

    GD32 MCU的选项字节是什么?

    GD32 MCU的选项字节是什么,有什么功能呢?选项字节被误篡改如何回复?
    的头像 发表于 01-17 09:42 1231次阅读
    <b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b>的选项字节是什么?

    不同型号的GD32 MCU如何区分?

    大家是否碰到过以下应用场景:同一套软件代码希望跑在不同型号的GD32 MCU中,但有些地方需要根据MCU型号进行调整?或者上位机或其他MCUGD3
    的头像 发表于 01-27 09:32 934次阅读
    不同型号的<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b>如何区分?

    GD32 MCU 入门教程】一、GD32 MCU 开发环境搭建(1)使用Keil开发GD32

    GD32系列为通用型MCU,所以开发环境也可以使用通用型的IDE,目前使用较多的是KEIL、IAR、 GCC和Embedded Builder,客户可以根据个人喜好来选择相应的开发环境。
    的头像 发表于 08-08 15:01 986次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入门教程</b>】一、<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> 开发环境搭建(1)使用Keil开发<b class='flag-5'>GD32</b>

    GD32 MCU 入门教程】一、GD32 MCU 开发环境搭建(2)使用 IAR 开发 GD32

    GD32系列为通用型MCU,所以开发环境也可以使用通用型的IDE,目前使用较多的是KEIL、IAR、 GCC和Embedded Builder,客户可以根据个人喜好来选择相应的开发环境。
    的头像 发表于 08-08 15:40 562次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入门教程</b>】一、<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> 开发环境搭建(<b class='flag-5'>2</b>)使用 IAR 开发 <b class='flag-5'>GD32</b>

    GD32 MCU 入门教程】一、GD32 MCU 开发环境搭建(3)使用 Embedded Builder 开发 GD32

    GD32系列为通用型MCU,所以开发环境也可以使用通用型的IDE,目前使用较多的是KEIL、IAR、 GCC和Embedded Builder,客户可以根据个人喜好来选择相应的开发环境。
    的头像 发表于 08-08 16:03 802次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入门教程</b>】一、<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> 开发环境搭建(3)使用 Embedded Builder 开发 <b class='flag-5'>GD32</b>

    GD32 MCU 入门教程】二、GD32 MCU 烧录说明(1)ISP 烧录

    ISP:In System Programing,在系统编程,通过MCU片内的引导程序进行Flash编程。 GD32片内有一个只读信息块,用于存放引导装载程序,引导程序在MCU出厂前就会提前烧录好
    的头像 发表于 08-08 16:20 735次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入门教程</b>】二、<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> 烧录说明(1)ISP 烧录

    GD32 MCU 入门教程GD32 MCU 常见外设介绍(14)RTC 模块介绍

    GD32 MCU内部提供了一个RTC(实时时钟)模块,通过RTC可以实现日历时钟、闹钟等功能。RTC也可以用于深度睡眠或待机模式的低功耗唤醒。不同系列的GD32
    的头像 发表于 08-23 09:18 364次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入门教程</b>】<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>常见外设</b><b class='flag-5'>介绍</b>(14)RTC <b class='flag-5'>模块</b><b class='flag-5'>介绍</b>

    GD32 MCU 入门教程GD32 MCU FPU 使用方法

    GD32 MCU FPU 使用方法
    的头像 发表于 08-25 09:24 454次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> <b class='flag-5'>入门教程</b>】<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> FPU 使用方法

    GD32 MCU入门教程GD32 MCU GPIO 结构与使用注意事项

    本文是专门为基于GD32 MCU开发的工程设计人员提供,主要介绍了GPIO的功能配置、内部结构以及在不同场景使用时的注意事项,旨在帮助GD32 MC
    的头像 发表于 09-07 10:34 557次阅读
    【<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b><b class='flag-5'>入门教程</b>】<b class='flag-5'>GD32</b> <b class='flag-5'>MCU</b> GPIO 结构与使用注意事项