本文是在STM8L15x系列的芯片上,使用软件模拟的I2C来实现对24LC16B进行操作的函数库。
头文件定义:
#ifndef _24LC16B_H
#define _24LC16B_H
#include "Hal_I2CSoft.h"
#define MAXROM_24LC16B (2048)
extern void Hal24LC16BInit(I2CSoftConfig_t* i2cCfg);
extern u8 Hal24LC16B_ReadByte(u16 addr);
extern void Hal24LC16B_WriteByte(u16 addr, u8 data);
extern void Hal24LC16B_ReadBuf(u16 addr, u8 *buf, u16 len);
extern void Hal24LC16B_WriteBuf(u16 addr, u8 *buf, u16 len);
extern void Hal24L68B_WritePage(u16 addr, u8 *buf);
#endif
具体操作函数:
/**
******************************************************************************
* @f文件 24LC16B.c
* @作者 huangqi
* @版本 V1.0.0
* @日期 2014-12-20
* @描述 Microchip 的24LC16B的操作函数库
******************************************************************************
*/
#include "Hal_I2CSoft.h"
#include "24LC16B.h"
I2CSoftConfig_t *i2cCfg;
/*****************************************************************************
* @函数名 Hal24LC16BInit
*
* @功能 初始化24LC16B
*
* @参数 i2cCfg: I2CSoft端口信息
*
* @返回值 无
*****************************************************************************/
void Hal24LC16BInit(I2CSoftConfig_t* i2cPortConfig)
{
i2cCfg = i2cPortConfig;
I2CSoft_Init(i2cCfg);
}
/*****************************************************************************
* @函数名 Hal24LC16B_ReadByte
*
* @功能 向24LC16B读一个字节
*
* @参数 addr: 地址
*
* @返回值 读出的字节
*****************************************************************************/
u8 Hal24LC16B_ReadByte(u16 addr)
{
u8 tmp = 0;
do
{
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1));//写命令
}
while(I2CSoft_WaitAck(i2cCfg));
I2CSoft_SendByte(i2cCfg, addr%256);
I2CSoft_WaitAck(i2cCfg);
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1)+1);//写命令
I2CSoft_WaitAck(i2cCfg);
tmp = I2CSoft_RecvByte(i2cCfg,0);
I2CSoft_Stop(i2cCfg);
return tmp;
}
/*****************************************************************************
* @函数名 Hal24LC16B_WriteByte
*
* @功能 向24LC16B写入一个字节
*
* @参数 addr: 地址
* data: 需要写的数据
*
* @返回值 无
*****************************************************************************/
void Hal24LC16B_WriteByte(u16 addr, u8 data)
{
do
{
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1));//写命令
}
while(I2CSoft_WaitAck(i2cCfg));
I2CSoft_SendByte(i2cCfg, addr%256);
I2CSoft_WaitAck(i2cCfg);
I2CSoft_SendByte(i2cCfg, data);//写命令
I2CSoft_WaitAck(i2cCfg);
I2CSoft_Stop(i2cCfg);
//delay_us(3000);//必须等待EEPROM写入完成
}
/*****************************************************************************
* @函数名 Hal24LC16B_WriteByte
*
* @功能 向24LC16B写入一页(共16Byte)
*
* @参数 addr: 地址
* data: 需要写的数据
*
* @返回值 无
*****************************************************************************/
void Hal24L68B_WritePage(u16 addr, u8 *buf)
{
u8 cnt=16;
if((addr+16)%256<16)
return;
do
{
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1));//写命令
}
while(I2CSoft_WaitAck(i2cCfg));
I2CSoft_SendByte(i2cCfg, addr%256);
I2CSoft_WaitAck(i2cCfg);
while(cnt--)
{
I2CSoft_SendByte(i2cCfg, *buf++);//写命令
I2CSoft_WaitAck(i2cCfg);
}
I2CSoft_Stop(i2cCfg);
//delay_us(3000);//必须等待EEPROM写入完成
}
/*****************************************************************************
* @函数名 Hal24LC16B_ReadBuf
*
* @功能 向24LC16B读取数据
*
* @参数 addr: 地址
* buf: 读出的数据
* len: 需要读数据的长度
*
* @返回值 无
*****************************************************************************/
void Hal24LC16B_ReadBuf(u16 addr, u8 *buf, u16 len)
{
u16 i = 0;
if((len>0)&&(addr+len)>=(MAXROM_24LC16B-1))
return;
do
{
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1));//写命令
}
while(I2CSoft_WaitAck(i2cCfg));
I2CSoft_SendByte(i2cCfg, addr%256);
I2CSoft_WaitAck(i2cCfg);
I2CSoft_Start(i2cCfg);
I2CSoft_SendByte(i2cCfg, 0xA0+((addr/256)<<1)+1);//写命令
I2CSoft_WaitAck(i2cCfg);
for(i = 0; i *buf++ = I2CSoft_RecvByte(i2cCfg,1); } *buf = I2CSoft_RecvByte(i2cCfg,0); I2CSoft_Stop(i2cCfg); } /***************************************************************************** * @函数名 Hal24LC16B_WriteBuf * * @功能 向24LC16B写入数据 * * @参数 addr: 地址 * buf: 需要写的数据 * len: 写入数据的长度 * * @返回值 无 *****************************************************************************/ void Hal24LC16B_WriteBuf(u16 addr, u8* buf, u16 len) { u16 i; if((len>0)&&(addr+len)>=(MAXROM_24LC16B-1)) return; for(i=0; i Hal24LC16B_WriteByte(addr++,*buf++); } } I2C软件模拟驱动: 头文件: #ifndef _HAL_I2CSOFT_H #define _HAL_I2CSOFT_H #include "stm8l15x.h" typedef struct I2CSoftConfig_t { GPIO_TypeDef* SCL_Port; GPIO_Pin_TypeDef SCL_Pin; GPIO_TypeDef* SDA_Port; GPIO_Pin_TypeDef SDA_Pin; }I2CSoftConfig_t; //extern void delay_us(u16 time); extern void I2CSoft_Init(I2CSoftConfig_t* i2cConfg); extern void I2CSoft_Start(I2CSoftConfig_t *i2cPortConfig); extern void I2CSoft_Stop(I2CSoftConfig_t *i2cPortConfig); extern u8 I2CSoft_WaitAck(I2CSoftConfig_t *i2cPortConfig); extern void I2CSoft_SendByte(I2CSoftConfig_t *i2cPortConfig, u8 sendByte); extern u8 I2CSoft_RecvByte(I2CSoftConfig_t *i2cPortConfig, u8 ack); #endif I2C协议实现: /** ****************************************************************************** * @f文件 hal_Flash.c * @作者 huangqi * @版本 V1.0.0 * @日期 2014-12-23 * @描述 模拟I2C的相关操作 ****************************************************************************** */ #include "Hal_I2CSoft.h" void delay_us(u32 us) { for( u32 x=us;x>0;x-- ) { nop();nop();nop();nop(); } } void I2CSoft_Init(I2CSoftConfig_t* i2cPortConfig) { GPIO_Init(i2cPortConfig->SCL_Port,i2cPortConfig->SCL_Pin,GPIO_Mode_Out_PP_Low_Slow);//GPIO_Mode_Out_OD_Low_Slow); GPIO_Init(i2cPortConfig->SDA_Port,i2cPortConfig->SDA_Pin,GPIO_Mode_Out_OD_Low_Slow);//GPIO_Mode_Out_OD_Low_Slow); } void I2CSoft_Start(I2CSoftConfig_t* i2cPortConfig) { // i2cPortConfig->SDA_Port->DDR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SDA_Port->ODR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; delay_us(2); i2cPortConfig->SDA_Port->ODR &= ~i2cPortConfig->SDA_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; } void I2CSoft_Stop(I2CSoftConfig_t* i2cPortConfig) { i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; // i2cPortConfig->SDA_Port->DDR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SDA_Port->ODR &= ~i2cPortConfig->SDA_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; i2cPortConfig->SDA_Port->ODR |= i2cPortConfig->SDA_Pin; delay_us(2); } u8 I2CSoft_WaitAck(I2CSoftConfig_t* i2cPortConfig) { u8 ucErrTime; // i2cPortConfig->SDA_Port->DDR &= ~i2cPortConfig->SDA_Pin; i2cPortConfig->SDA_Port->ODR |= i2cPortConfig->SDA_Pin; //开漏输出将NMOS关闭,作为输入使用 //delay_us(2); i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; delay_us(2); while(i2cPortConfig->SDA_Port->IDR & i2cPortConfig->SDA_Pin) { ucErrTime++; if(ucErrTime>250) { I2CSoft_Stop(i2cPortConfig); return 1; } } i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; // delay_us(2); return 0; } static void I2CSoft_Ack(I2CSoftConfig_t* i2cPortConfig) { i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; //i2cPortConfig->SDA_Port->DDR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SDA_Port->ODR &= ~i2cPortConfig->SDA_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; } static void I2CSoft_NoAck(I2CSoftConfig_t* i2cPortConfig) { i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin; // i2cPortConfig->SDA_Port->DDR |= i2cPortConfig->SDA_Pin; i2cPortConfig->SDA_Port->ODR |= i2cPortConfig->SDA_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR |= i2cPortConfig->SCL_Pin; delay_us(2); i2cPortConfig->SCL_Port->ODR &= ~i2cPortConfig->SCL_Pin;
上一篇:STM8L的LCD接口详解及驱动程序
下一篇:STM8工具之IAR--调试
推荐阅读最新更新时间:2024-11-06 14:49