刚入职不久,下面是使用stm8s005k6写的eeprom驱动程序。 #include " bsp_i2c.h " /* 在stm8平台下移植,只需要改下面的宏定义即可 */ #define PORT_I2C_SCL GPIOC #define PIN_I2C_SCL GPIO_PIN_1 #define PORT_I2C_SDA
刚入职不久,下面是使用stm8s005k6写的eeprom驱动程序。
#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; }bsp_i2c.c
#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__ */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; }bsp_eeprom.c
#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__ */bsp_eeprom.h