蓝桥杯CT107D之AT24C02(EEPROM)
程序员文章站
2022-04-01 09:57:31
...
IIC驱动程序
#include "reg52.h"
#include "intrins.h"
#include "iic.h"
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
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);
SCL = 0;
SDA = 1;
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;
byt <<= 1;
IIC_Delay(DELAY_TIME);
}
SCL = 0;
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
AT24C02驱动程序
//向AT24C02指定地址写入单字节数据
void Write_EEPROM(unsigned char address,unsigned char Data)
{
IIC_Start();
IIC_SendByte(AT24C02_AddrW);
if(!IIC_WaitAck())
IIC_SendByte(address);
if(!IIC_WaitAck())
IIC_SendByte(Data);
if(!IIC_WaitAck());
IIC_Stop();
}
//读取AT24C02指定地址的单字节数据
unsigned char Read_EEPROM(unsigned char address)
{
unsigned char temp;
IIC_Start();
IIC_SendByte(AT24C02_AddrW);
if(!IIC_WaitAck())
IIC_SendByte(address);
if(!IIC_WaitAck())
IIC_Start();
IIC_SendByte(AT24C02_AddrR);
if(!IIC_WaitAck())
temp = IIC_RecByte();
if(!IIC_WaitAck())
IIC_Stop();
return temp;
}
数码管用拆数函数
#include "reg52.h"
#include "smg.h"
unsigned char c[N];
unsigned char SMG_chai(unsigned int t)
{
unsigned char i=0;
if(t<10)
c[i]=t;
else
{
while(1)
{
c[i]=t%10;
t=t/10;
i++;
if(t<10)
break;
}
c[i]=t;
}
return i;
}
主函数
#include "reg52.h"
#include "iic.h"
#include "smg.h"
#define FOSC 11059200L
#define T1MS (65536-FOSC/1000) //1T模式
sfr AUXR = 0x8e;
sfr P4 = 0xC0; //定义P4口
sbit LED_1 = P0^0;
sbit N_RELAY = P0^4;
sbit N_BUZZ = P0^6;
unsigned char code Duan[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴极段选0~9
unsigned char code Wei[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //共阴极位选 1--8
unsigned char temp=0,s=0,i1=0;
void T0Init();
void main()
{
P2 = 0xa0; N_BUZZ=0; N_RELAY=0; P2 = 0x00;
P2 = 0x80; P0=0xff; P2 = 0x00; //关灯
temp = Read_EEPROM(0x00);
Write_EEPROM(0x00,++temp);
T0Init();
while(1)
{
i1 = SMG_chai(temp);
}
}
void T0Init()
{
AUXR |= 0x80; //定时器0为1T模式
// AUXR &= 0x7f; //定时器0为12T模式
TMOD = 0x00; //设置定时器为模式0(16位自动重装载)
TL0 = T1MS; //初始化计时值
TH0 = T1MS >> 8;
TR0 = 1; //定时器0开始计时
ET0 = 1; //使能定时器0中断
EA = 1;
}
/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
static int count = 5;
P0=0xff; //关闭下段选,达到消隐的目的。
P2 = 0xe0; P0=~Duan[c[s]]; P2 = 0x00;
P0=0x00; //进入位选前先把P0清零,禁止选通数码管。
P2 = 0xc0; P0=~Wei[7-s]; P2 = 0x00;
P0=0xff;
if(s<i1)
{
s++;
}
else
s=0;
if(count-- == 0)
{
count = 5;
}
}