参考代码
.C文件
模拟I2C驱动代码,只需要配置好模拟IO的读写即可。
/*******************************************************************************
**函数名称:void I2C_Init()
**功能描述:初始化I2C1接口
**入口参数:
**输出:无
*******************************************************************************/
void IIC_Init()
{
GPIO_Init(GPIOC , GPIO_Pin_0 , GPIO_Mode_Out_OD_HiZ_Slow); //SDA
GPIO_Init(GPIOC , GPIO_Pin_1 , GPIO_Mode_Out_OD_HiZ_Slow); //SCL
IIC_SCL_HIGH();
IIC_SDA_HIGH();
}
//产生IIC起始信号
void IIC_Start(void)
{
SDA_OUT(); //sda线输出
/* IIC_SCL_LOW();
delay_us(1); */
IIC_SDA_HIGH();
delay_us(1);
IIC_SCL_HIGH();
delay_us(4);//建立时间是I2C_SDA保持时间>4.7us
IIC_SDA_LOW();//START:when CLK is high,DATA change form high to low
delay_us(4);//保持时间是>4us
IIC_SCL_LOW();//钳住I2C总线,准备发送或接收数据
// delay_us(5);
}
//产生IIC停止信号
void IIC_Stop(void)
{
SDA_OUT();//sda线输出
IIC_SCL_LOW();
delay_us(1);
IIC_SDA_LOW();//STOP:when CLK is high DATA change form low to high
// IIC_SCL_HIGH();
delay_us(4);//建立时间大于4.7us
IIC_SCL_HIGH();
delay_us(1);
IIC_SDA_HIGH();//发送I2C总线结束信号
delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
SDA_IN(); //SDA设置为输入
IIC_SDA_HIGH();delay_us(1);
IIC_SCL_HIGH();delay_us(1);
while(READ_SDA)
{
ucErrTime++;
if(ucErrTime>250)
{
IIC_Stop();
printf("device no ack\r\n");
return 1;
}
}
IIC_SCL_LOW();//时钟输出0
// delay_us(5);
return 0;
}
//产生ACK应答
void IIC_Ack(void)
{
IIC_SCL_LOW();
SDA_OUT();
IIC_SDA_LOW();
delay_us(5);
IIC_SCL_HIGH();
delay_us(5);
IIC_SCL_LOW();
// delay_us(5);
}
//不产生ACK应答
void IIC_NAck(void)
{
IIC_SCL_LOW();
SDA_OUT();
IIC_SDA_HIGH();
delay_us(5);
IIC_SCL_HIGH();
delay_us(5);
IIC_SCL_LOW();
// delay_us(5);
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void IIC_Send_Byte(u8 txd)
{
u8 t;
SDA_OUT();
IIC_SCL_LOW(); //拉低时钟开始数据传输
for (t = 0; t < 8; t++)
{
// IIC_SDA = ((txd & 0x80) >> 7);
if (txd & 0x80)
{
IIC_SDA_HIGH();
}
else
{
IIC_SDA_LOW();
}
txd <<= 1;
delay_us(2); //对TEA5767这三个延时都是必须的
IIC_SCL_HIGH();
delay_us(2);
IIC_SCL_LOW();
delay_us(2);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i, receive = 0;
// IIC_SCL_LOW();
// IIC_SDA_LOW();
SDA_IN(); //SDA设置为输入
for (i = 0; i < 8; i++)
{
// IIC_SDA_LOW();
IIC_SCL_LOW();
delay_us(3);
IIC_SCL_HIGH();
// delay_us(2);
receive <<= 1;
if (READ_SDA)
receive|= 0x01;
delay_us(3);
}
if (!ack)
IIC_NAck(); //发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
.H文件
仅包含部分代码,函数接口可视情况暴露出来即可。
#ifndef ___AT24C02_H___
#define ___AT24C02_H___
#include "stm8l15x.h"
#define SLAVE_ADDRESS 0x90
#define IRBUFSIZE 500
//字节转换--1字节x2转2字节
#define BUILD_UINT16(loByte, hiByte) \
((u16)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))
//IO方向设置-------------因STM8单片机的I2C引脚为OD设计,同时故不需要设置CR1寄存器(详见数据手册及参考手册)
#define SDA_IN() GPIO_Init(GPIOC , GPIO_Pin_0 , GPIO_Mode_In_FL_No_IT/* GPIO_Mode_Out_OD_HiZ_Slow */);
#define SDA_OUT() GPIO_Init(GPIOC , GPIO_Pin_0 , GPIO_Mode_Out_OD_HiZ_Slow);
// #define SDA_OUT() {GPIOC->DDR |= GPIO_Pin_0;GPIOC->CR1 &= (uint8_t)(~(GPIO_Pin_0)); \
// GPIOC->CR2 &= (uint8_t)(~(GPIO_Pin_0));} /* Set OD Output */
//IO操作函数{GPIOC->DDR &= (uint8_t)(~(GPIO_Pin_0));} /* Set Floating input No Interrupt */
#define IIC_SCL_HIGH() GPIO_SetBits(GPIOC, GPIO_Pin_1);
#define IIC_SCL_LOW() GPIO_ResetBits(GPIOC, GPIO_Pin_1);
#define IIC_SDA_HIGH() GPIO_SetBits(GPIOC, GPIO_Pin_0);
#define IIC_SDA_LOW() GPIO_ResetBits(GPIOC, GPIO_Pin_0);
// STM8系列单片机可在输入或输出模式下读取IO状态------不需要改变IO的模式可读取
#define READ_SDA GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0)