构建驱动模块2-- STM32模拟IIC访问 (AT24C02)EEPROM 操作
模拟IIC接口可以使用任意两个IO口实现,不受芯片引脚限制,而且硬件IIC在通信出错后,无法自行恢复,模拟IIC则可以迅速恢复;通过调整延时参数,可以调节访问速度。本程序把模拟II2C封装成一个模块,AT24C02只需要调用该模块即可。
1、初始化EEPROM设备。调用 EEPRomhardwareInit("24c02",0);接口即可。在设备管理层生成一个EEPROM节点。
/**********************************************************************************************************
*
* 函数名:EEPRomhardwareInit
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
void EEPRomhardwareInit(ht_int8_t *name,ht_int16_t devno)//初始化EEPROM设备 其中devno是挂载端口,devno=0 表示挂载到0硬件接口。
{
char str[64];
EEPRom_dev =(ht_device_t) cmMalloc(sizeof(struct ht_device) );
if(EEPRom_dev==NULL)
{
cmFault(SYS_ERROR_MEMMALLOC_ABNORMAL,RECORD_FLAG);
}
cmMemset(EEPRom_dev,0,sizeof(struct ht_device));
EEPRom_dev -> open = bspEEPROMOpen;
EEPRom_dev -> close = bspEEPROMClose;
EEPRom_dev -> read = bspEEPROMRead;
EEPRom_dev->control = NULL;
EEPRom_dev->del=bspEEPROMdel;
EEPRom_dev->help=bspEEPROMhelp;
EEPRom_dev->write = bspEEPROMWrite;
EEPRom_dev->user_privatedata = NULL;
sprintf(str,"%s-%d",name,devno);
if( gI2chardwareInit("Gi2c",devno)>0)
{
htDevFsRegister( EEPRom_dev,str);
htDevFsAssociated(EEPRom_dev,"Gi2c",devno);
}
else
{
cmFree(EEPRom_dev);
}
}
2、实现open、Close、write、read、del等接口。
/**********************************************************************************************************
*
* 函数名:bspEEPROMWrite
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_inline ht_int32_t bspEEPROMWrite (ht_device_t dev, ht_uint32_t WriteAddr, const void *buffer, ht_int32_t NumByteToWrite)
{
ht_int32_t iResult = NumByteToWrite;
ht_uint8_t *Dat = (ht_uint8_t *)( buffer),i;
ht_uint8_t buf[2];
i2c_msg_t msg;
htDevFsHandle i2cfd=NULL;
if(dev->isChildFlag)//是否存在硬件操作接口
i2cfd=htDevFsOpen(dev->childname,0);//接口名称固定为"Gi2c"
if(i2cfd==NULL)
{
return -1 ;
}
for(i=0;i<NumByteToWrite;i++)//写数据到EEPROM
{
buf[0]=(ht_uint8_t)WriteAddr++;//设定地址
buf[1]=Dat[i];//设定数据
msg.pMsg=&buf[0];
msg.Len=2;//传输长度
msg.Stop=1; //完成本次传输是否停止
htDevFsControl(i2cfd,CMD_I2C_WRITE,(void*)&msg);//读取操作命令
OSTimeDlyHMSM(0,0,0,8);
}
htDevFsClose(i2cfd);
return iResult;
}
/**********************************************************************************************************
*
* 函数名:bspEEPROMRead
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_inline ht_int32_t bspEEPROMRead (ht_device_t dev, ht_uint32_t pos, void *buffer, ht_int32_t size)
{
ht_int32_t iResult = size;
ht_uint8_t *Dat = (ht_uint8_t *)( buffer),i;
ht_uint8_t buf[2];
i2c_msg_t msg;
htDevFsHandle i2cfd=NULL;
if(dev->isChildFlag)
i2cfd=htDevFsOpen(dev->childname,0);
if(i2cfd==NULL)
{
return -1 ;
}
for(i=0;i<size;i++)
{
buf[0]=(ht_uint8_t)pos++;//设置读取地址
msg.pMsg=&buf[0];//读取字节
msg.Len=1;
msg.Total=2;
htDevFsControl(i2cfd,CMD_I2C_WRITEREAD,(void*)&msg);//读取操作命令
Dat[i]=buf[1];
}
htDevFsClose(i2cfd);
return iResult;
}
/**********************************************************************************************************
*
* 函数名:bspEEPROMOpen
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_inline ht_int32_t bspEEPROMOpen (ht_device_t dev, ht_uint32_t oflag)
{
i2c_cfg_t i2c_cfg;
i2c_msg_t msg;
htDevFsHandle i2cfd=NULL;
if(dev->isChildFlag)
{
i2cfd=htDevFsOpen(dev->childname,0);
if(i2cfd==NULL)
{
return -1;
}
}
//*设置IIC访问速度和设备器件地址参数*//
i2c_cfg.hcfI2cDelayTime=16;
i2c_cfg.hcfSlaveAddress=0xa0;
if(htDevFsControl(i2cfd,CMD_I2C_CFG,(void*)&i2c_cfg)<0)
{
return -1;
}
htDevFsClose(i2cfd);
return HT_EOK;
}
/**********************************************************************************************************
*
* 函数名:bspEEPROMClose
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_inline ht_int32_t bspEEPROMClose (ht_device_t dev)
{
return HT_EOK;
}
/**********************************************************************************************************
*
* 函数名:bspEEPROMdel
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_inline ht_int32_t bspEEPROMdel(ht_device_t dev)
{
ht_int8_t str[32];
htDevFsUnregister(dev);//卸载驱动
cmFree(dev);//释放Device
return 1;
}
/**********************************************************************************************************
*
* 函数名:bspEEPROMhelp
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0
* EEPROM测试操作
**********************************************************************************************************/
ht_inline ht_int32_t bspEEPROMhelp (ht_device_t dev, ht_int8_t argc, ht_int8_t * argv[])
{
int arg=0,i,j;
htDevFsHandle fd;
ht_uint8_t Rbuffer[10];
ht_uint8_t Tbuffer[10];
ht_uint16_t temp;
static ht_uint8_t cnt=0;
if(arg<=argc)
{
if (strcmp((char const *) argv[2], "test")==0)
{
ht_printk("devname %s\r\n",argv[1]);
fd=htDevFsOpen( argv[1],0);
if(fd!=NULL)
{
for(j=0;j<5;j++)
{
cnt++;
ht_printk("Write:");
for(i=0;i<10;i++)
{
Tbuffer[i]=i+cnt;
ht_printk("%02x ",Tbuffer[i]);
}
ht_printk("\r\n");
if( htDevFsWrite(fd,0,Tbuffer,10)==10)
{
ht_printk("bspEEPROMWrite is Ok \r\n");
}
OSTimeDlyHMSM(0,0,0,300);
if( htDevFsRead(fd,0,Rbuffer,10)==10)
{
ht_printk("bspEEPROMRead is Ok \r\n");
}
ht_printk("Read:");
for(i=0;i<10;i++)
{
ht_printk("%02x ",Rbuffer[i]);
}
ht_printk("\r\n");
}
}
htDevFsClose(fd);
}
else
{
ht_printk("can not find dev\r\n");
}
}
}
3、实际操作II2C端口
//EEPROM读操作
for(i=0;i<size;i++)
{
buf[0]=(ht_uint8_t)pos++;
msg.pMsg=&buf[0];
msg.Len=1;
msg.Total=2;
htDevFsControl(i2cfd,CMD_I2C_WRITEREAD,(void*)&msg);
Dat[i]=buf[1];
}
//EEPROM写操作
for(i=0;i<NumByteToWrite;i++)
{
buf[0]=(ht_uint8_t)WriteAddr++;
buf[1]=Dat[i];
msg.pMsg=&buf[0];
msg.Len=2;
msg.Stop=1;
htDevFsControl(i2cfd,CMD_I2C_WRITE,(void*)&msg);
OSTimeDlyHMSM(0,0,0,8);
}
4、配置GI2C 硬件接口
/**********************************************************************************************************
*
* 函数名:GI2C1_GPIO_Config_bf
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_inline void GI2C1_GPIO_Config_bf(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能GPIOB时钟
//GPIOB8,B9初始化设置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //普通输出模式
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; //开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //100MHz
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化IO
//ht_printk(" GI2C1_GPIO_Config_bf OK\r\n");
GPIO_WriteBit(GPIOB,GPIO_Pin_8,1);
GPIO_WriteBit(GPIOB,GPIO_Pin_9,1);
}
/**********************************************************************************************************
*
* 函数名:GI2C1_SDA_Set
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_inline void GI2C1_SDA_Set(ht_uint8_t Data)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_9,Data);
}
/**********************************************************************************************************
*
* 函数名:GI2C1_SCL_Set
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_inline void GI2C1_SCL_Set (ht_uint8_t Data)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_8,Data);
}
/**********************************************************************************************************
*
* 函数名:GI2C1_ReadBit
* 功 能:
* 参 数:
* 返回值:
* 版 本:REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_inline ht_uint8_t GI2C1_ReadBit (void)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_9);
}
//配置GI2C1
const struct hcfResource gI2C1DrvResources[] ={
{ "I2C_Init", HT_RES_ADDR, { (void **)&GI2C1_GPIO_Config_bf } },
{ "I2C_SDA_SET", HT_RES_ADDR, { (void **)&GI2C1_SDA_Set } },
{ "I2C_SCL_SET", HT_RES_ADDR, { (void **)&GI2C1_SCL_Set } },
{ "I2C_BIT_READ", HT_RES_ADDR, { (void **)&GI2C1_ReadBit } },
{ "I2C_SPEED", HT_RES_INT, (void **)16 },
};
5、测试结果
EPPROM读取结果: