基于蓝桥杯的单片机模块练习——IIC驱动的注释及修改
iic.c
/*
程序说明: IIC总线驱动程序
软件环境: Keil uVision 4.10
硬件环境: CT107单片机综合实训平台 8051,12MHz
日 期: 2011-8-9
*/
#include "iic.h"
//=====================================================
//总结:IIC_SendByte(unsigned char byt)函数不要忘记释放SDA = 1;
// IIC_SendAck(bit ackbit)函数不要忘记释放SDA = 1;
//====================================================
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;//在SCL高电平期间,SDA由高变低
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;//在SCL高电平期间,SDA由低变高
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0:应答,1:非应答
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);//第9个时钟周期
SCL = 0;
SDA = 1;//释放sda
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;//数据位是高电平
else SDA = 0;//数据位是低电平
IIC_Delay(DELAY_TIME);
SCL = 1;//SCL高电平期间,SDA的数据要保持稳定
byt <<= 1;//发送的数据左移,准备发送下一位
IIC_Delay(DELAY_TIME);//等待SDA的数据被读取
}
SCL = 0;
//***********需要自己添加的两行**************
SDA = 1;//释放SDA
IIC_Delay(DELAY_TIME);
//***********需要自己添加的两行**************
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);//在SCL高电平期间,读取SDA的数据
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
iic.h
#ifndef _IIC_H
#define _IIC_H
#include "SystemInit.h"
#include "intrins.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
#endif
注意:在第九届决赛的代码编写中我发现一个问题:读取PCF8591的电压显示在数码管上的数值不稳定,一直在跳变。(AT24C02的读取也是有问题的)经过不断地尝试,我发现把#define DELAY_TIME 5中的5改成小一点的数3,就可以解决问题。
但是,同样不能把它改的太小,如果改成2又会出现读取错误。
但是我想不明白其中的缘由。
转载:
原文链接:https://blog.csdn.net/KelvinFlying/article/details/46674339