本帖最后由 owenli520 于 2015-1-25 14:30 编辑
基于IAR STM8 2.10开发环境,STM8S005K6单片机,模拟IIC方式读写AT24C16或AT24C32,已验证可以正常对AT24C32进行读写数据,只是有个疑问,对于单片机接SDA脚的IO口进行方向控制反而引起时序不正常而读写不了数据,例程中是将此IO口始终设置为输出,不知道会不会有隐患,有待测试...
以下是代码,完整代码请下载附件,包含完整工程!
#include "24Cxx.h"
#include "stm8s.h"
#include "stm8s_gpio.h"
#define AT24C32_SETSDAIN GPIO_Init(AT24C32_SDA_PORT, GPIO_PIN_6, GPIO_MODE_IN_FL_NO_IT)
#define AT24C32_SETSDAOUT GPIO_Init(AT24C32_SDA_PORT, GPIO_PIN_6, GPIO_MODE_OUT_OD_LOW_SLOW)
#define I2C_SLAW 0xA0 /*器件地址选择及写标志*/
#define I2C_SLAR 0xA1 /*器件地址选择及读标志*/
void nops(void)
{
// asm("nop");
// asm("nop");
uint16_t i = 0;
for (; i < 5; i++);
}
// 总线复位
void I2C_Reset(void)
{
AT24C32_SCL_HIGH;
AT24C32_SDA_HIGH;
}
// I2C操作严重错误
void I2C_Error(void)
{
//复位I2C总线
I2C_Reset();
//进入死循环
while (1)
{
}
}
// 发送起始条件
void I2C_Start_A(void) /*起始条件*/
{
AT24C32_SCL_HIGH;
nops();
AT24C32_SDA_LOW;
nops();
AT24C32_SCL_LOW;
nops();
}
// 停止条件
void I2C_Stop_A(void)
{
AT24C32_SDA_LOW;
nops();
AT24C32_SCL_HIGH;
nops();
AT24C32_SDA_HIGH;
nops();
AT24C32_SCL_LOW;
nops();
}
// 产生一个时钟信号
uint8_t I2C_GenerateClock(void)
{
uint8_t bData = 0;
uint16_t t = 0;
AT24C32_SCL_HIGH;
nops();
for (t = 0; t < 6; t++);
if (AT24C32_READSDA)
{
bData = 1;
}
AT24C32_SCL_LOW;
nops();
return bData;
}
// 应答位
void I2C_Ack(uint8_t bAckYes)
{
if (bAckYes)
{
AT24C32_SDA_LOW;
}
else
{
AT24C32_SDA_HIGH;
}
I2C_GenerateClock();
AT24C32_SDA_HIGH;
}
// 发送数据子程序, ucData为要求发送的数据
uint8_t I2C_Send(uint8_t ucData)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
if (ucData & 0x80)
{
AT24C32_SDA_HIGH;
}
else
{
AT24C32_SDA_LOW;
}
ucData <<= 1;
I2C_GenerateClock();
}
AT24C32_SDA_HIGH;
return (!I2C_GenerateClock());
}
// 读一个字节的数据,并返回该字节值
uint8_t I2C_Read(void)
{
uint8_t ucData = 0;
uint8_t i;
for (i = 0; i < 8; i++)
{
ucData <<= 1;
if (I2C_GenerateClock())
{
ucData |= 1;
}
}
return ucData;
}
// 设置下一步操作的地址(一字节地址)
uint8_t I2C_SetAddress(uint16_t u16Addr)
{
// 发送启动信号
I2C_Start_A();
// 发送访问地址
return (I2C_Send(I2C_SLAW) && I2C_Send(u16Addr));
}
// 设置下一步操作的地址(两字节地址)
uint8_t I2C_SetAddress16(uint16_t u16Addr)
{
// 发送启动信号
I2C_Start_A();
// 发送从器件地址
// 发送访问地址
return (I2C_Send(I2C_SLAW) && I2C_Send(u16Addr >> 8) && I2C_Send(u16Addr & 0xff));
}
// 向8位地址的器件( 如:24C02 )写数据 bAddressIs16bit = 0
// 向16位地址的器件( 如:24C32 )写数据 bAddressIs16bit = 1
void Write_Byte_24c32(uint8_t *pDat, uint16_t u16Addr, uint8_t ucNbyte, uint8_t bAddressIs16bit)
{
uint8_t bWriteError = FALSE; //写数据出错标志位
uint8_t i;
uint8_t ucDataBuf = 0;
uint32_t Cnt = 0;
for (i = 0; i < ucNbyte; i++)
{
if (bAddressIs16bit)
{
if (I2C_SetAddress16(u16Addr + i) == 0)
{
bWriteError = TRUE;
break;
}
}
else
{
if (I2C_SetAddress(u16Addr + i) == 0)
{
bWriteError = TRUE;
break;
}
}
ucDataBuf = *(pDat + i);
if (I2C_Send(ucDataBuf) == 0)
{
bWriteError = TRUE;
break;
}
I2C_Stop_A();
ucDataBuf = 12;
do
{
I2C_Start_A();
} while ((++Cnt < 500000) && I2C_Send(I2C_SLAW) == 0);
//如果50mS内还没有响应,则进入保护性报警状态
if (Cnt == 500000)
{
bWriteError = TRUE;
break;
}
I2C_Stop_A();
}
if (bWriteError)
{
I2C_Error();
}
}
// 从8位地址的器件( 如:24C02 )读数据 bAddressIs16bit = 0
// 从16位地址的器件( 如:24C32 )读数据 bAddressIs16bit = 1
void Read_nByte_24c32(uint8_t *pDat, uint16_t u16Addr, uint8_t ucNbyte, uint8_t bAddressIs16bit)
{
uint8_t bReadError标志寄存器 = FALSE; //读EEPROM错误标志位
uint8_t i;
uint8_t ucDataBuf = 0;
if (bAddressIs16bit)
{
if (I2C_SetAddress16(u16Addr) == 0)
{
bReadError = TRUE;
}
}
else
{
if (I2C_SetAddress(u16Addr) == 0)
{
bReadError = TRUE;
}
}
if (bReadError)
{
I2C_Error();
}
I2C_Start_A();
if (I2C_Send(I2C_SLAR) == 0)
{
bReadError = TRUE;
}
if (bReadError)
{
I2C_Error();
}
for (i = 0; i < ucNbyte; i++)
{
ucDataBuf = I2C_Read();
*(pDat + i) = ucDataBuf;
I2C_Ack(i != (ucNbyte - 1));
}
I2C_Stop_A();
}
uint8_t Read_Byte_24c32(uint16_t u16Addr)
{
uint8_t EepromDataBuf = 0xFF;
//从16位地址的器件( 如:24C32 )读数据 bAddressIs16bit = 1
Read_nByte_24c32(&EepromDataBuf, u16Addr, 1, DEVICE_ADDR);
return EepromDataBuf;
}
//修改EEPROM数据
void ModifData_24c32(uint16_t u16Addr, uint8_t *pDat, uint16_t uclen)
{
//向16位地址的器件( 如:24C32 )写数据 bAddressIs16bit = 1
Write_Byte_24c32(pDat, u16Addr, uclen, DEVICE_ADDR);
}
STM8S005K6_24Cxx_IIC_Test_Simulator.zip
(301.58 KB)
|