![](https://saas.bk-cdn.com/t/e9fbc666-55b7-49dd-94e9-e60545a05df0/u/fa650263-636b-4a46-85be-cbcd773ecde8/1709448548953/image.png)
main.c
函数书写规范
在这一部分主要是主函数的逻辑代码,包含**数码管**
,**按键**
,**LED**
,以及**定时器中断**
头文件引用
和宏定义
#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
#define u8 unsigned char
#define u16 unsigned int
变量声明区
u8 code SegDuan[10] = {0xc0 , 0xf9 , 0xa4 , 0xb0 , 0x99 , 0x92 , 0x82 , 0xf8 , 0x80 , 0x90};
//数码管段码
u8 code 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 code RTC_write[3] = {0x80 , 0x82 , 0x84};//读写指令码
u8 code RTC_read[3] = {0x81 , 0x83 , 0x85};
u8 RTC_Tim[3] = {0x58 , 0x59 , 0x23}; //24H 实时时钟的时分秒采用BCD码开始写入和后续更新共用同一个数组
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 Set_HC573(unsigned char channel, unsigned char dat)
{
P0 = dat; //待设置数据
switch(channel) //选通锁存器
{
case 4:
P2 = (P2 & 0x1f) | 0x80; //Y4输出0,LED控制
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0; //Y5输出0,蜂鸣器和继电器控制
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0; //Y6输出0,数码管位选
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0; //Y7输出0,数码管段码
break;
case 0:
P2 = (P2 & 0x1f) | 0x00; //所有锁存器不选择
break;
}
P2 = (P2 & 0x1f) | 0x00; //设置完成,关闭全部锁存器
}
void Disp_Bit(unsigned char pos, unsigned char value)
{
Set_HC573(6, 0x01 << pos); //数码管的段位
Set_HC573(7, value); //数码管显示内容
}
void SysInit()
{
Set_HC573(0, 0x00); //关闭所有锁存器
Set_HC573(5, 0x00); //关闭蜂鸣器和继电器
Set_HC573(4, 0xff); //关闭全部指示灯
DisplaySMG_All(0xff); //关闭全部数码管
}
DS1302
实时时钟读取
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]);
}
}
由此可以看出写0x8E是解除写保护的地址,最高位写1即0x80是开启写保护,0x00是解除写保护
u8 code RTC_write[3] = {0x80 , 0x82 , 0x84};//读写指令码,即上图的时分秒读取指令
u8 code RTC_read[3] = {0x81 , 0x83 , 0x85};
定时器
0,1,2
void Timer1Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初始值
TH1 = 0xD1; //设置定时初始值
TF1 = 0; //清除TF1标志
ET1 = 1;
EA = 1;
TR1 = 1; //定时器1开始计时
}
void Fre_Timer0() //测量频率专用
{
AUXR &= 0x7f;//12T
TMOD |= 0x05;//16位不可重装载
TH0 = 0;
TL0 = 0;
TF0 = 0;
TR0 = 1;
}
/*
void Timer2Init(void) //50毫秒@12.000MHz
{
AUXR &= 0xFB; //定时器时钟12T模式
T2L = 0xB0; //设置定时初值
T2H = 0x3C; //设置定时初值
AUXR |= 0x10;//定时器2开始计时
IE2|=0x04; //看手册找例程
EA=1;
}
*/备选定时器
按键
处理
//=================按键的功能实现函数==================
void S12_Funtion()
{
}
void S13_Funtion()
{
}
void S16_Funtion()
{
}
void S17_Funtion()
{
}
//==================矩阵键盘扫描处理===================
void Scan_Keys_2x2()
{
if(KeyDly)return;//定时器扫描
KeyDly = 1;
R1 = 0;
R2 = 1;
//扫描S12键
if(C1 == 0)
{
DelaySMG(1000);
if(C1 == 0)
{
S12_Funtion();
while(C1 == 0)
{
Display_Num();
}
}
}
//扫描S16键
if(C2 == 0)
{
DelaySMG(1000);
if(C2 == 0)
{
S16_Funtion();
while(C2 == 0)
{
Display_Num();
}
}
}
R1 = 1;
R2 = 0;
//扫描S13键
if(C1 == 0)
{
DelaySMG(1000);
if(C1 == 0)
{
S13_Funtion();
while(C1 == 0)
{
Display_Num();
}
}
}
//扫描S17键
if(C2 == 0)
{
DelaySMG(1000);
if(C2 == 0)
{
S17_Funtion();
while(C2 == 0)
{
Display_Num();
}
}
}
}
数码管
处理
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;//“&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();
}
LED
处理
void LedProc()
{
if(LedDly)return;
LedDly = 1;
}
中断服务
函数
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;
}
部分原文参照链接:https://blog.csdn.net/qq_57511928/article/details/124726361
主函数main.c
void main()
{
SysInit();
Timer1Init();
RTC_Config();
Fre_Timer0();
AT24C02_Write(AT24C02_addrInput,N,AT24C02_darInput);
while(1)
{
KeyProc();//三个处理函数
SegProc();
LedProc();
}
iic.c
函数书写规范
PCF
数模转换
sbit sda=P2^1;
sbit scl=P2^0;
unsigned char PCF8591_ADC()
{
unsigned char Vp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(0x03); //Rb2 若需要DA转换尽量写成0x43,0x41
//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); //打开out就行与通道无关
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}
AT24C02
->EEPROM
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();
}
onewire.c
函数书写规范
DS18B20
温度读取
unsigned int rd_temperature()
{
unsigned int LSB,MSB,temp;
init_ds18b20();
Write_DS18B20(0xcc);//跳过rom
Write_DS18B20(0x44);//转换
//以上部分可以单独取出在函数开始前转化一次
init_ds18b20();
Write_DS18B20(0xcc);
Write_DS18B20(0xbe);
LSB = Read_DS18B20();
MSB = Read_DS18B20();
temp = (MSB << 8) | LSB;//只取整数部分
return temp;
}