代码刚刚测试过,全部有效,有部分注释,使用的定时器1来显示LED和数码管,刚刚学习时参考xmf老师的B站视频,后来改成了参考指导书的内容。
内容纯干货好吧(第7,8,9,10,11,12,13届的程序题全部用的这个模板实现)
main.c#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
#define u8 unsigned char
#define u16 unsigned int
#define N 2 //测试AT24C02
u8 SegDuan[10] = {0xc0 , 0xf9 , 0xa4 , 0xb0 , 0x99 , 0x92 , 0x82 , 0xf8 , 0x80 , 0x90};
u8 SegDat[8] = {0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff , 0xff} , SegPos = 0;
u8 uLed = 0;
u8 KeyValue = 0 , KeyOldValue = 0 ,KeyDown = 0;
u16 KeyDly = 0 , SegDly = 0 , LedDly = 0;
u8 RTC_write[3] = {0x80 , 0x82 , 0x84};
u8 RTC_read[3] = {0x81 , 0x83 , 0x85};
u8 RTC_Tim[3] = {0x58 , 0x59 , 0x23}; //24H
u16 T_dat = 0;
u16 Vp_dat = 0;
//频率计数
u16 Fre_dat = 0,u_1s = 0;
u8 AT24C02_addrInput = 0,AT24C02_darInput[N] = {20,10};
void SysInit()
{
P0 = 0xff;
P2 = (P2 & 0x1f) | (4 << 5);
P2 &= 0x1f;
P0 = 0x00;
P2 = (P2 & 0x1f) | (5 << 5);
P2 &= 0x1f;
}
void Disp_Bit(u8 *dat , u8 pos)
{
P0 = 0x01 << pos;
P2 = (P2 & 0x1f) | (6 << 5);
P2 &= 0x1f;
P0 = dat[pos];
P2 = (P2 & 0x1f) | (7 << 5);
P2 &= 0x1f;
}
void RTC_Config()
{
u8 i;
Write_Ds1302_Byte(0x8e , 0x00);
for(i = 0;i < 3;i++)
{
Write_Ds1302_Byte(RTC_write[i] , RTC_Tim[i]);
}
Write_Ds1302_Byte(0x8e , 0x80);
}
void RTC_ReadProc()
{
u8 i;
for(i = 0;i < 3;i++)
{
RTC_Tim[i] = Read_Ds1302_Byte(RTC_read[i]);
}
}
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初始值
TH1 = 0xD1; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;
EA = 1;
}
void Fre_Timer0()
{
AUXR &= 0x7f;
TMOD |= 0x04;
TH0 = 0;
TL0 = 0;
TF0 = 0;
TR0 = 1;
ET1 = 1;
}
u8 KBT_Read()
{
u8 keyvalue;
u16 keynew;
P44 = 0;P42 = 1;P35 = 1;P34 = 1;
keynew = (P3 & 0x0f);
P44 = 1;P42 = 0;P35 = 1;P34 = 1;
keynew = (keynew << 4) | (P3 & 0x0f);
P44 = 1;P42 = 1;P35 = 0;P34 = 1;
keynew = (keynew << 4) | (P3 & 0x0f);
P44 = 1;P42 = 1;P35 = 1;P34 = 0;
keynew = (keynew << 4) | (P3 & 0x0f);
switch(~keynew)
{
case 0x8000:keyvalue = 4;break;
case 0x4000:keyvalue = 5;break;
case 0x2000:keyvalue = 6;break;
case 0x1000:keyvalue = 7;break;
//
// case 0x0800:keyvalue = 8;break;
// case 0x0400:keyvalue = 9;break;
// case 0x0200:keyvalue = 10;break;
// case 0x0100:keyvalue = 11;break;
//
// case 0x0080:keyvalue = 12;break;
// case 0x0040:keyvalue = 13;break;
// case 0x0020:keyvalue = 14;break;
// case 0x0010:keyvalue = 15;break;
//
// case 0x0008:keyvalue = 16;break;
// case 0x0004:keyvalue = 17;break;
// case 0x0002:keyvalue = 18;break;
// case 0x0001:keyvalue = 19;break;
default:keyvalue = 0; //千万别忘记这一句
}
return keyvalue;
}
void KeyProc()
{
if(KeyDly)return;
KeyDly = 1;
KeyValue = KBT_Read();
KeyDown = KeyValue & (KeyOldValue ^ KeyValue);
KeyOldValue = KeyValue;
switch(KeyDown)
{
case 4:
break;
case 5:
break;
case 6:
break;
case 7:
break;
}
}
void Disp_Tim()
{
//根据要求填写
SegDat[0] = SegDuan[RTC_Tim[2] / 16];
SegDat[1] = SegDuan[RTC_Tim[2] % 16];
SegDat[3] = SegDuan[RTC_Tim[1] / 16];
SegDat[4] = SegDuan[RTC_Tim[1] % 16];
SegDat[6] = SegDuan[RTC_Tim[0] / 16];
SegDat[7] = SegDuan[RTC_Tim[0] % 16];
}
void Disp_Tem()
{
//根据要求填写
SegDat[0] = 0xc6;
SegDat[1] = 0xff;
SegDat[2] = 0xff;
SegDat[3] = 0xff;
SegDat[4] = 0xff;
SegDat[5] = SegDuan[T_dat / 100];
SegDat[6] = SegDuan[T_dat / 10 % 10] & 0x7f;
SegDat[7] = SegDuan[T_dat % 10];
}
void Disp_Vp()
{
//根据要求填写
SegDat[0] = 0xc1;
SegDat[1] = 0xff;
SegDat[2] = 0xff;
SegDat[3] = 0xff;
SegDat[4] = 0xff;
SegDat[5] = SegDuan[Vp_dat / 100] & 0x7f;
SegDat[6] = SegDuan[Vp_dat / 10 % 10];
SegDat[7] = SegDuan[Vp_dat % 10];
}
void Disp_Fre()
{
//根据要求填写
SegDat[0] = 0x8e;
SegDat[1] = 0xff;
SegDat[2] = 0xff;
SegDat[3] = SegDuan[Fre_dat / 10000];
SegDat[4] = SegDuan[Fre_dat / 1000 % 10];
SegDat[5] = SegDuan[Fre_dat / 100 % 10];
SegDat[6] = SegDuan[Fre_dat / 10 % 10];
SegDat[7] = SegDuan[Fre_dat % 10];
}
void Disp_AT24C02()
{
SegDat[0] = SegDuan[AT24C02_darInput[0] / 100];
SegDat[1] = SegDuan[AT24C02_darInput[0] / 10 % 10];
SegDat[2] = SegDuan[AT24C02_darInput[0] % 10];
SegDat[3] = 0xff;
SegDat[4] = 0xff;
SegDat[5] = SegDuan[AT24C02_darInput[1] / 100];
SegDat[6] = SegDuan[AT24C02_darInput[1] / 10 % 10];
SegDat[7] = SegDuan[AT24C02_darInput[1] % 10];
}
void SegProc()
{
if(SegDly)return;
SegDly = 1;
RTC_ReadProc();
T_dat = rd_temperature() * 0.0625 * 10 + 0.5; //0.5用来四舍五入
Vp_dat = PCF8591_ADC() * 500.0 / 255;
AT24C02_Read(AT24C02_addrInput,N,AT24C02_darInput);
// Disp_Tim();
// Disp_Fre();
// Disp_Tem();
// Disp_Vp();
Disp_AT24C02();
}
void LedProc()
{
if(LedDly)return;
LedDly = 1;
}
void main()
{
SysInit();
Timer1Init();
RTC_Config();
Fre_Timer0();
AT24C02_Write(AT24C02_addrInput,N,AT24C02_darInput);
while(1)
{
KeyProc();
SegProc();
LedProc();
}
}
void Service1() interrupt 3
{
//刷新时间
if(++LedDly == 100)LedDly = 0;
if(++SegDly == 500)SegDly = 0;
if(++KeyDly == 10)KeyDly = 0;
//频率计数
if(++u_1s == 1000)
{
u_1s = 0;
TR0 = 0;
Fre_dat = (TH0 << 8) | TL0;
TH0 = 0;
TL0 = 0;
TF0 = 0;
TR0 = 1;
}
//数码管显示
Disp_Bit(SegDat,SegPos);
if(++SegPos == 8)SegPos = 0;
//LED显示
P0 = ~uLed;
P2 = (P2 & 0x1f) | (4 << 5);
P2 &= 0x1f;
}
iic.c
#include "iic.h"
#define DELAY_TIME 5
//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//I2C总线启动信号
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//I2C总线停止信号
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;
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;
}
unsigned char PCF8591_ADC()
{
unsigned char Vp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03); //Rb2
//IIC_SendByte(0x01); //光敏电阻
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
Vp = IIC_RecByte();
IIC_SendAck(1);
IIC_Stop();
return Vp;
}
void PCF8591_DAC(unsigned char dat)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x40); //Rb2
//IIC_SendByte(0x01); //光敏电阻
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
void AT24C02_Read(unsigned char addr,unsigned char num,unsigned char *dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
while(num--)
{
*dat++ = IIC_RecByte();
if(num)
IIC_SendAck(0);
else
IIC_SendAck(1);
IIC_Delay(200);
}
IIC_Stop();
}
void AT24C02_Write(unsigned char addr,unsigned char num,unsigned char *dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
while(num--)
{
IIC_SendByte(*dat++);
IIC_WaitAck();
}
IIC_Stop();
}
iic.h
#ifndef _IIC_H #define _IIC_H #includeonewire.c#include "intrins.h" 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); unsigned char PCF8591_ADC(); void PCF8591_DAC(unsigned char dat); void AT24C02_Write(unsigned char addr,unsigned char num,unsigned char *dat); void AT24C02_Read(unsigned char addr,unsigned char num,unsigned char *dat); #endif
#include "onewire.h"
//单总线内部延时函数
void Delay_OneWire(unsigned int t)
{
t*=12;
while(t--);
}
//单总线写操作
void Write_DS18B20(unsigned char dat)
{
unsigned char i;
for(i=0;i<8;i++)
{
DQ = 0;
DQ = dat&0x01;
Delay_OneWire(5);
DQ = 1;
dat >>= 1;
}
Delay_OneWire(5);
}
//单总线读操作
unsigned char Read_DS18B20(void)
{
unsigned char i;
unsigned char dat;
for(i=0;i<8;i++)
{
DQ = 0;
dat >>= 1;
DQ = 1;
if(DQ)
{
dat |= 0x80;
}
Delay_OneWire(5);
}
return dat;
}
//DS18B20初始化
bit init_ds18b20(void)
{
bit initflag = 0;
DQ = 1;
Delay_OneWire(12);
DQ = 0;
Delay_OneWire(80);
DQ = 1;
Delay_OneWire(10);
initflag = DQ;
Delay_OneWire(5);
return initflag;
}
unsigned int rd_temperature()
{
unsigned int LSB,MSB,temp;
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0x44);
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
temp = (MSB << 8) | LSB;
return temp;
}
onewire.h
#ifndef __ONEWIRE_H #define __ONEWIRE_H #includeds1302.csbit DQ = P1^4; unsigned int rd_temperature(); #endif
#include "ds1302.h"
//写字节
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK = 0;
SDA_RTC = temp&0x01;
temp>>=1;
SCK=1;
}
}
//向DS1302寄存器写入数据
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
Write_Ds1302(dat);
RST=0;
}
//从DS1302寄存器读出数据
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address);
for (i=0;i<8;i++)
{
SCK=0;
temp>>=1;
if(SDA_RTC)
temp|=0x80;
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA_RTC=0; _nop_();
SDA_RTC=1; _nop_();
return (temp);
}
ds1302.h
(这里要特别注意,iic.h和ds1302.h中的SDA有重定义,所以我把ds1302的SDA改成了SDA_RTC。当然,只有在需要两个头文件同时使用时才需要进行修改,一个项目里面只需要ds1302或者只需要iic时没必要进行修改)
#ifndef __DS1302_H #define __DS1302_H #include#include sbit SCK = P1^7; sbit SDA_RTC = P2^3; sbit RST = P1^3; void Write_Ds1302(unsigned char temp); void Write_Ds1302_Byte( unsigned char address,unsigned char dat ); unsigned char Read_Ds1302_Byte( unsigned char address ); #endif



