700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > ​HC32L130/HC32L136华大单片机硬件I2C驱动代码(从机为存储芯片EEPROM(AT24C02 FM24CL64B))​

​HC32L130/HC32L136华大单片机硬件I2C驱动代码(从机为存储芯片EEPROM(AT24C02 FM24CL64B))​

时间:2020-12-05 11:44:43

相关推荐

​HC32L130/HC32L136华大单片机硬件I2C驱动代码(从机为存储芯片EEPROM(AT24C02 FM24CL64B))​

由于同事嫌弃模拟I2C速度太慢了 所以想改成硬件I2C

我试过例程的驱动代码 不太行 存储地址也是8位的 所以参考了一些博文 修改了下例程的代码 亲测有效

希望能帮到大家 代码如下这里用的是I2C0,用到的SCL为引脚PB08 SDA为引脚PB09

#include "i2c.h"#include "gpio.h"#define I2C_SLAVEADDR 0xA0 //从机地址static uint8_t u8Senddata[10] = {0x11,0x33,0x22,0x55,0x44,0x77,0x66,0x99,0x88,0xAA}; //发送数组uint8_t u8Recdata[10]={0x00}; //接收数组en_result_t I2C_MasterWriteData(M0P_I2C_TypeDef* I2CX,uint16_t u8Addr,uint8_t *pu8Data,uint32_t u32Len);en_result_t I2C_MasterReadData(M0P_I2C_TypeDef* I2CX,uint16_t u8Addr,uint8_t *pu8Data,uint32_t u32Len);void App_I2cCfg(void);void App_PortCfg(void);int32_t main(void){///< I2C 模块配置App_I2cCfg();///< IO端口配置App_PortCfg();I2C_SetFunc(M0P_I2C0,I2cModule_En); ///< 向I2C总线发起开始信号I2C_SetFunc(M0P_I2C0,I2cStart_En); while(1){///< eeprom写数据I2C_MasterWriteData(M0P_I2C0,0x5555,u8Senddata,10); delay1ms(500);///< eeprom读数据I2C_MasterReadData(M0P_I2C0,0x5555,u8Recdata,10); delay1ms(500);} }///< IO端口配置void App_PortCfg(void){stc_gpio_cfg_t stcGpioCfg;DDL_ZERO_STRUCT(stcGpioCfg); ///< 初始化结构体变量的值为0Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); ///< 开启GPIO时钟门控 stcGpioCfg.enDir = GpioDirOut;///< 端口方向配置->输出stcGpioCfg.enOD = GpioOdEnable; ///< 端口开漏输出配置->开漏输出使能stcGpioCfg.enPu = GpioPuEnable; ///< 端口上拉配置->使能stcGpioCfg.enPd = GpioPdDisable; ///< 端口下拉配置->禁止stcGpioCfg.bOutputVal = TRUE;///< 默认高电平Gpio_Init(GpioPortB, GpioPin8,&stcGpioCfg); ///< 初始化PB08Gpio_Init(GpioPortB, GpioPin9,&stcGpioCfg); ///< 初始化PB09Gpio_SetAfMode(GpioPortB, GpioPin8,GpioAf1);///< 配置PB08为SCLGpio_SetAfMode(GpioPortB, GpioPin9,GpioAf1);///< 配置PB09为SDA }///< I2C 模块配置void App_I2cCfg(void){stc_i2c_cfg_t stcI2cCfg;DDL_ZERO_STRUCT(stcI2cCfg); ///< 初始化结构体变量的值为0Sysctrl_SetPeripheralGate(SysctrlPeripheralI2c0,TRUE); ///< 开启I2C0时钟门控 stcI2cCfg.u32Pclk = Sysctrl_GetPClkFreq(); ///< 获取PCLK时钟stcI2cCfg.u32Baud = 100000; ///< 波特率100kHzstcI2cCfg.enMode = I2cMasterMode; ///< I2C主机模式stcI2cCfg.u8SlaveAddr = 0x55; ///< 从地址,主模式无效stcI2cCfg.bGc = FALSE; ///< 广播地址应答使能关闭,主模式无效I2C_Init(M0P_I2C0, &stcI2cCfg);///< 模块初始化 }/********************************************************************************** \brief 主机接收函数**** \param u8Addr从机内存地址,pu8Data读数据存放缓存,u32Len读数据长度**** \retval 读数据是否成功********************************************************************************/en_result_t I2C_MasterReadData(M0P_I2C_TypeDef* I2CX,uint16_t u8Addr,uint8_t *pu8Data,uint32_t u32Len){en_result_t enRet = Error;uint8_t u8State=0;uint8_t u8i=0;uint8_t u16i=0;uint8_t u16ii=0;I2C_SetFunc(I2CX,I2cStart_En);while(1){uint32_t jnum = 0;while(0 == I2C_GetIrq(I2CX)){jnum++;if(jnum>10000){enRet = Error;return enRet;}}u8State = I2C_GetState(I2CX);switch(u8State){case 0x08: ///< 已发送起始条件,将发送SLA+Wu16ii++;if(u16ii<=1){I2C_ClearFunc(I2CX,I2cStart_En);I2C_WriteByte(I2CX,I2C_SLAVEADDR); }if(u16ii>1){I2C_ClearFunc(I2CX,I2cStart_En);I2C_WriteByte(I2CX,I2C_SLAVEADDR|0x01);///< 发送SLA+R,开始从从机读取数据}break;case 0x18: ///< 已发送SLA+W,并接收到ACKI2C_WriteByte(I2CX,(uint8_t)(u8Addr>>8)); ///<高8位地址 发送从机内存地址break;case 0x28: ///< 已发送数据,接收到ACK, 此处是已发送从机内存地址u8Addr并接收到ACKu16i++;I2C_WriteByte(I2CX,(uint8_t)u8Addr); ///<低8位地址 发送从机内存地址if(u16i>1)I2C_SetFunc(I2CX,I2cStart_En); ///< 发送重复起始条件break;case 0x10: ///< 已发送重复起始条件I2C_ClearFunc(I2CX,I2cStart_En);I2C_WriteByte(I2CX,I2C_SLAVEADDR|0x01);///< 发送SLA+R,开始从从机读取数据break;case 0x40: ///< 已发送SLA+R,并接收到ACKif(u32Len>1){I2C_SetFunc(I2CX,I2cAck_En); ///< 使能主机应答功能}break;case 0x50: ///< 已接收数据字节,并已返回ACK信号pu8Data[u8i++] = I2C_ReadByte(I2CX);if(u8i==u32Len-1){I2C_ClearFunc(I2CX,I2cAck_En);///< 已接收到倒数第二个字节,关闭ACK应答功能}break;case 0x58: ///< 已接收到最后一个数据,NACK已返回pu8Data[u8i++] = I2C_ReadByte(I2CX);I2C_SetFunc(I2CX,I2cStop_En);///< 发送停止条件break;case 0x38: ///< 在发送地址或数据时,仲裁丢失I2C_SetFunc(I2CX,I2cStart_En); ///< 当总线空闲时发起起始条件break;case 0x48: ///< 发送SLA+R后,收到一个NACKI2C_SetFunc(I2CX,I2cStop_En);///< 发送停止条件I2C_SetFunc(I2CX,I2cStart_En); ///< 发送起始条件break;default:I2C_SetFunc(I2CX,I2cStart_En); ///< 其他错误状态,重新发送起始条件break;}I2C_ClearIrq(I2CX); ///< 清除中断状态标志位if(u8i==u32Len) ///< 数据全部读取完成,跳出while循环{break;}}enRet = Ok;return enRet;}/********************************************************************************** \brief 主机发送函数**** \param u8Addr从机内存地址,pu8Data写数据,u32Len写数据长度**** \retval 写数据是否成功********************************************************************************/en_result_t I2C_MasterWriteData(M0P_I2C_TypeDef* I2CX,uint16_t u8Addr,uint8_t *pu8Data,uint32_t u32Len){en_result_t enRet = Error;uint8_t u8i=0;uint8_t u16i=0;uint8_t u8State=0;I2C_SetFunc(I2CX,I2cStart_En);while(1){uint32_t jnum = 0;while(0 == I2C_GetIrq(I2CX)){jnum++;if(jnum>10000){enRet = Error;return enRet;}} u8State = I2C_GetState(I2CX);switch(u8State){case 0x08: ///< 已发送起始条件I2C_ClearFunc(I2CX,I2cStart_En);I2C_WriteByte(I2CX,I2C_SLAVEADDR); ///< 从设备地址发送break;case 0x18: ///< 已发送SLA+W,并接收到ACKI2C_WriteByte(I2CX,(uint8_t)(u8Addr>>8)); ///<高8位地址 从设备内存地址发送break;case 0x28: ///< 上一次发送数据后接收到ACKu16i++;I2C_WriteByte(I2CX,(uint8_t)u8Addr); ///<低8位地址 从设备内存地址发送if(u16i>1)I2C_WriteByte(I2CX,pu8Data[u8i++]); ///< 继续发送数据break;case 0x20: ///< 上一次发送SLA+W后,收到NACKcase 0x38: ///< 上一次在SLA+读或写时丢失仲裁I2C_SetFunc(I2CX,I2cStart_En); ///< 当I2C总线空闲时发送起始条件break;case 0x30: ///< 已发送I2Cx_DATA中的数据,收到NACK,将传输一个STOP条件I2C_SetFunc(I2CX,I2cStop_En); ///< 发送停止条件break;default:break;}if(u8i>u32Len){I2C_SetFunc(I2CX,I2cStop_En); ///< 此顺序不能调换,出停止条件I2C_ClearIrq(I2CX);break;}I2C_ClearIrq(I2CX);///< 清除中断状态标志位}enRet = Ok;return enRet;}/******************************************************************************* EOF (not truncated)******************************************************************************/

欢迎评论 一起学习!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。