基于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错误标志位
设计资源 培训 开发板 精华推荐
- #第五届立创电子设计大赛#基于ESP8266OLED开发板WIFIkeil
- 具有折返电流限制的 LTC1771EMS8 2.5V/1A 稳压器的典型应用电路
- OM6716: 应答器评估和开发套件2, 带射频电路板的RKE/PKE
- NCP1075NONGEVB:8W、双通道、非隔离评估板
- NSI45090JDT4G 大电流 LED 灯串的典型应用
- MAXREFDES1176:采用MAX17690,MAX17606和MAX5969B的PoE供电设备和同步5V / 1.4A无光耦反激式DC-DC转换器
- 使用 Microchip Technology 的 SY88883V 的参考设计
- LT8390IFE 98% 效率、48W、12V/4A 微型降压-升压稳压器的典型应用电路
- ADA4858-3ACPZ-R7 反相运算放大器增益配置的典型应用电路
- 具有睡眠模式支持的 PWM 锁定转子检测应用电路