stm8s使⽤IO⼝模拟I2C
刚⼊职不久,下⾯是使⽤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))    {
return1;
}
else
{
return0;
}
}
/*
*    函数名: 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总线主机主动⾮应答
recv函数*    形参: ⽆
*    返回值: ⽆
*/
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)
{
return1;
}
}
i2c_SCL(0);
return0;
}
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();
return0;
}
/* 发送地址 */
i2c_WriteByte((_usAddress & 0xFF00) >> 8);
if (i2c_CheckAck() == NOACK)
{
i2c_Stop();
return2;
}
i2c_WriteByte(_usAddress & 0x00FF);
if (i2c_CheckAck() == NOACK)
{
i2c_Stop();
return3;
}
/* 读数据 */
i2c_WriteByte(_ucByte);
if (i2c_CheckAck() == NOACK)
{
i2c_Stop();
return4;
}
i2c_Stop();