剛入職不久,下面是使用stm8s005k6寫的eeprom驅動程序。EEPROM型號為ST公司的M24C256.

#include "bsp_i2c.h" /* 在stm8平台下移植,只需要改下面的宏定義即可 */ #define PORT_I2C_SCL GPIOC #define PIN_I2C_SCL GPIO_PIN_1 #define PORT_I2C_SDA GPIOC #define PIN_I2C_SDA GPIO_PIN_2 static void i2c_Delay(void); static void i2c_PinModeOutput(void); static void i2c_PinModeInput(void); static void i2c_SCL(uint8_t stat); static void i2c_SDA(uint8_t stat); static uint8_t i2c_ReadSDA(void); /* * 函 數 名: i2c_InitGpio * 功能說明: 初始化IIC接口 * 形 參: 無 * 返 回 值: 無 */ void i2c_InitGpio(void) { GPIO_Init(PORT_I2C_SCL, PIN_I2C_SCL, GPIO_MODE_OUT_PP_LOW_FAST); GPIO_Init(PORT_I2C_SDA, PIN_I2C_SDA, GPIO_MODE_OUT_PP_LOW_FAST); i2c_Stop(); } /* * 函 數 名: i2c_Delay * 功能說明: 延時函數 * 形 參: 無 * 返 回 值: 無 */ static void i2c_Delay(void) { uint8_t time = 10; while (time--); } /* * 函 數 名: i2c_PinModeOutput * 功能說明: 將SDA線的端口設置為輸出 * 形 參: 無 * 返 回 值: 無 */ static void i2c_PinModeOutput(void) { GPIO_Init(PORT_I2C_SDA, PIN_I2C_SDA, GPIO_MODE_OUT_PP_LOW_FAST); } /* * 函 數 名: i2c_PinModeOutput * 功能說明: 將SDA線的端口設置為輸入 * 形 參: 無 * 返 回 值: 無 */ static void i2c_PinModeInput(void) { GPIO_Init(PORT_I2C_SDA, PIN_I2C_SDA, GPIO_MODE_IN_FL_NO_IT); } /* * 函 數 名: i2c_SCL * 功能說明: 控制SCL線電平狀態 * 形 參: stat:0 輸出低電平,1 輸出高電平 * 返 回 值: 無 */ static void i2c_SCL(uint8_t stat) { if (stat) { GPIO_WriteHigh(PORT_I2C_SCL, PIN_I2C_SCL); } else { GPIO_WriteLow(PORT_I2C_SCL, PIN_I2C_SCL); } } /* * 函 數 名: i2c_SDA * 功能說明: 控制SDA線電平狀態 * 形 參: stat:0 輸出低電平,1 輸出高電平 * 返 回 值: 無 */ static void i2c_SDA(uint8_t stat) { if (stat) { GPIO_WriteHigh(PORT_I2C_SDA, PIN_I2C_SDA); } else { GPIO_WriteLow(PORT_I2C_SDA, PIN_I2C_SDA); } } /* * 函 數 名: i2c_ReadSDA * 功能說明: 讀取SDA線電平狀態 * 形 參: 無 * 返 回 值: 0 或 1 */ static uint8_t i2c_ReadSDA(void) { if (GPIO_ReadInputPin(PORT_I2C_SDA, PIN_I2C_SDA)) { return 1; } else { return 0; } } /* * 函 數 名: i2c_Start * 功能說明: IIC總線起始信號 * 形 參: 無 * 返 回 值: 無 */ void i2c_Start(void) { i2c_PinModeOutput(); i2c_SDA(1); i2c_Delay(); i2c_SCL(1); i2c_Delay(); i2c_SDA(0); i2c_Delay(); i2c_SCL(0); i2c_Delay(); } /* * 函 數 名: i2c_Stop * 功能說明: IIC總線停止信號 * 形 參: 無 * 返 回 值: 無 */ void i2c_Stop(void) { i2c_PinModeOutput(); i2c_SCL(0); i2c_SDA(0); i2c_Delay(); i2c_SCL(1); i2c_Delay(); i2c_SDA(1); i2c_Delay(); } /* * 函 數 名: i2c_WriteByte * 功能說明: IIC總線寫數據 * 形 參: _ucByte:寫入的一個字節數據 * 返 回 值: 無 */ void i2c_WriteByte(uint8_t _ucByte) { uint8_t i; i2c_PinModeOutput(); i2c_SCL(0); i2c_Delay(); for (i = 0; i < 8; i++) { if (_ucByte & 0x80) { i2c_SDA(1); } else { i2c_SDA(0); } _ucByte = _ucByte << 1; i2c_SCL(1); i2c_Delay(); i2c_SCL(0); i2c_Delay(); } i2c_SDA(1); } /* * 函 數 名: i2c_ReadByte * 功能說明: IIC總線讀數據 * 形 參: 無 * 返 回 值: recv:讀取的一個字節數據 */ uint8_t i2c_ReadByte(void) { uint8_t i; uint8_t recv = 0; i2c_PinModeOutput(); i2c_SDA(1); i2c_Delay(); i2c_PinModeInput(); for (i = 0; i < 8; i++) { recv = recv << 1; i2c_SCL(1); i2c_Delay(); if (i2c_ReadSDA()) { recv |= 0x01; } else { recv |= 0x00; } i2c_SCL(0); i2c_Delay(); } return recv; } /* * 函 數 名: i2c_Ack * 功能說明: IIC總線主機主動應答 * 形 參: 無 * 返 回 值: 無 */ void i2c_Ack(void) { i2c_PinModeOutput(); i2c_SCL(0); i2c_SDA(0); i2c_Delay(); i2c_SCL(1); i2c_Delay(); i2c_SCL(0); } /* * 函 數 名: i2c_NAck * 功能說明: IIC總線主機主動非應答 * 形 參: 無 * 返 回 值: 無 */ void i2c_NAck(void) { i2c_PinModeOutput(); i2c_SCL(0); i2c_SDA(1); i2c_Delay(); i2c_SCL(1); i2c_Delay(); i2c_SCL(0); } /* * 函 數 名: i2c_CheckAck * 功能說明: IIC總線檢測應答信號 * 形 參: 無 * 返 回 值: 0 應答信號,1 非應答信號 */ uint8_t i2c_CheckAck(void) { uint8_t time = 0; i2c_PinModeOutput(); i2c_SDA(1); i2c_Delay(); i2c_SCL(1); i2c_Delay(); i2c_PinModeInput(); while (i2c_ReadSDA()) { time++; if (time >= 100) { return 1; } } i2c_SCL(0); return 0; }

#ifndef __BSP_I2C_H__ #define __BSP_I2C_H__ #include "stm8s.h" #define I2C_WR ((uint8_t) 0) /* 寫控制bit */ #define I2C_RD ((uint8_t) 1) /* 讀控制bit */ #define ACK ((uint8_t) 0) #define NOACK ((uint8_t) 1) void i2c_InitGpio(void); void i2c_Start(void); void i2c_Stop(void); void i2c_WriteByte(uint8_t _ucByte); uint8_t i2c_ReadByte(void); void i2c_Ack(void); void i2c_NAck(void); uint8_t i2c_CheckAck(void); #endif /* __BSP_I2C_H__ */

#include "m24256_driver.h" #include "bsp_i2c.h" #include "modbus_driver.h" //uint8_t g_ucIsEEPROMBusy; /* * 函 數 名: M24256_Init * 功能說明: 初始化 * 形 參: 無 * 返 回 值: 無 */ void M24256_Init(void) { i2c_InitGpio(); } /* * 函 數 名: M24256_WriteByte * 功能說明: 寫一個字節 * 形 參: _usAddress:地址 * _ucByte:數據 * 返 回 值: 無 */ uint8_t M24256_WriteByte(uint16_t _usAddress, uint8_t _ucByte) { uint16_t i; for (i = 0; i < 3000; i++) { i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_WR); /* 選中器件 + 寫 */ if (i2c_CheckAck() == ACK) { break; } } if (i >= 3000) { i2c_Stop(); return 0; } /* 發送地址 */ i2c_WriteByte((_usAddress & 0xFF00) >> 8); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 2; } i2c_WriteByte(_usAddress & 0x00FF); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 3; } /* 讀數據 */ i2c_WriteByte(_ucByte); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 4; } i2c_Stop(); return 5; } /* * 函 數 名: M24256_ReadByte * 功能說明: 讀一個字節 * 形 參: _usAddress:地址 * 返 回 值: recv:讀取到的一個字節數據 */ uint8_t M24256_ReadByte(uint16_t _usAddress) { uint8_t recv = 0; uint16_t i; for (i = 0; i < 3000; i++) { i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_WR); /* 選中器件 + 寫 */ if (i2c_CheckAck() == ACK) { break; } } if (i >= 3000) { i2c_Stop(); return 0; } /* 發送地址 */ i2c_WriteByte((_usAddress & 0xFF00) >> 8); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } i2c_WriteByte(_usAddress & 0x00FF); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_RD); /* 選中器件 + 讀 */ if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } recv = i2c_ReadByte(); i2c_NAck(); i2c_Stop(); return recv; } /* * 函 數 名: M24256_ReadBlock * 功能說明: 從串行EEPROM指定地址處開始讀取若干數據 * 形 參: _usAddress : 起始地址 * _usSize : 數據長度,單位為字節 * _pReadBuf : 存放讀到的數據的緩沖區指針 * 返 回 值: 0 表示失敗,1表示成功 */ unsigned char M24256_ReadBlock(unsigned char *_pReadBuf, unsigned short _usSize, unsigned short _usAddress) { uint16_t i; for (i = 0; i < 3000; i++) { i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_WR); /* 選中器件 + 寫 */ if (i2c_CheckAck() == ACK) { break; } } if (i >= 3000) { i2c_Stop(); return 0; } /* 發送地址 */ i2c_WriteByte((_usAddress & 0xFF00) >> 8); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } i2c_WriteByte(_usAddress &0x00FF); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_RD); /* 選中器件 + 讀 */ if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } /* 循環讀取數據 */ for (i = 0; i < _usSize; i++) { _pReadBuf[i] = i2c_ReadByte(); if (i != _usSize - 1) { i2c_Ack(); } else { i2c_NAck(); /* 讀完最后一個字節,主機發送非應答 */ } } i2c_Stop(); return 1; } /* * 函 數 名: M24256_WriteBlock * 功能說明: 向串行EEPROM指定地址寫入若干數據,采用頁寫操作提高寫入效率 * 形 參: _usAddress : 起始地址 * _usSize : 數據長度,單位為字節 * _pWriteBuf : 存放讀到的數據的緩沖區指針 * 返 回 值: 0 表示失敗,1表示成功 */ unsigned char M24256_WriteBlock(unsigned char *_pWriteBuf, unsigned short _usSize, unsigned short _usAddress) { uint16_t i, m; uint16_t usAddr; usAddr = _usAddress; for (i = 0; i < _usSize; i++) { if ((i == 0) || (usAddr & (EE_PAGE_SIZE - 1)) == 0) { i2c_Stop(); /* 重復發送起始信號,eeprom要重新開始寫要等待10ms左右 */ for (m = 0; m < 3000; m++) { i2c_Start(); i2c_WriteByte(EE_DEV_ADDR | I2C_WR); if (i2c_CheckAck() == ACK) { break; } } if (m >= 3000) { i2c_Stop(); /* 寫eeprom超時 */ return 0; } /* 發送地址 */ i2c_WriteByte((usAddr & 0xFF00) >> 8); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } i2c_WriteByte(usAddr & 0x00FF); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } } /* 寫入數據 */ i2c_WriteByte(_pWriteBuf[i]); if (i2c_CheckAck() == NOACK) { i2c_Stop(); return 0; } usAddr++; } i2c_Stop(); return 1; }

#ifndef __M24256_DRIVER_H__ #define __M24256_DRIVER_H__ #include "stm8s.h" #define EE_MODEL_NAME "M24256" #define EE_DEV_ADDR 0xA0 /* 設備地址 */ #define EE_PAGE_SIZE 64 /* 頁面大小(字節) */ #define EE_SIZE (32*1024) /* 總容量(字節) */ #define EE_ADDR_BYTES 1 /* 地址字節個數 */ extern unsigned char g_ucIsEEPROMBusy; void M24256_Init(void); uint8_t M24256_WriteByte(uint16_t _usAddress, uint8_t _ucByte); uint8_t M24256_ReadByte(uint16_t _usAddress); unsigned char M24256_ReadBlock(unsigned char *_pReadBuf, unsigned short _usSize, unsigned short _usAddress); unsigned char M24256_WriteBlock(unsigned char *_pWriteBuf, unsigned short _usSize, unsigned short _usAddress); void ee_Test(void); #endif /* __M24256_DRIVER_H__ */