本帖最后由 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, 下载次数: 623)
|