目录
题目分析
就在前不久第十三届蓝桥杯比赛结束,我就把单片机的题目拿过来看了看,下面是我对题目的分析和本次题目的代码。项目工程在文章的末尾,欢迎大家参考和指正。
在看到这道题的时候,看到了题目说按键动作不影响数码管显示和数据采集过程。说明数码管和采集过程需要在中断完成。本道题由于有单总线的存在,造成了数码管扫描时间加长,会造成最后一位数码管格外亮或者视觉暂留效果消失。为解决这一问题,我的方法是修改了DS18B20底层驱动代码,在读取温度的同时也进行了数码管的扫描操作。还得注意的是,由于定时器中断的打开,如果DS1302和DS18B20不放到中断函数里面的话,会造成读取的数据错误,这个原因是,在读取数据的过程中产生了中断,破坏了读取数据的时序。废话不多说了,看源代码吧。
代码分析
主函数
void main(void)
{
//ds1302初始化
DS1302_Init(Init_Time);
Timer0Init();
while(1)
{
//key
if(Key_Flag==1)
{
KeyValue = KeyScan();
switch(KeyValue)
{
case 12:
SegShow_Flag++;
if(SegShow_Flag>2)
{
SegShow_Flag=0;
}
break;
case 13:
Mode_Flag = !Mode_Flag; //显示界面
break;
case 16:
temp = ParameterChang(SegShow_Flag,temp,0);
break;
case 17:
temp = ParameterChang(SegShow_Flag,temp,1);
break;
}
//时间显示模式标记
SegTime_Flag = TimeShow(SegShow_Flag,KeyValue);
Key_Flag=0;
}
}
}
中断函数
//定时器中断服务函数
void Time0Handler(void) interrupt 1 //默认中断优先级 1
{
static u16 tt=0;
//数码管扫描
SegScan(tab,SegNum);
tt++;
if((tt%1000) == 0)//100ms
{
Key_Flag=1;
Timer_Flag=1;
SegDispaly(SegShow_Flag,SegTime_Flag,temperature,shijian,temp,SegNum);
//led
LedFuction(Mode_Flag,RelaySwitch_Flag,shijian);
//继电器
RelaySwitch_Flag = RelayFuction(Mode_Flag,temperature,temp,shijian);
}
if(tt >= 7000) //700ms
{
tt=0;
//时间
DS1302_Get(shijian);
//温度
//12位精度,延时不足。第一次数值错误,不读
if(Temperature_Flag == 0)
{
Temperature_Flag=1;
TemperGet();
}
else
{
temperature = TemperGet();
}
}
}
数码管显示
//显示函数
void SegScan(unsigned char tab[],unsigned char ptr[])
{
static unsigned char dspcom;
P0 = 0xff;
P2 = ((P2&0x1f)|0xE0);
P2 &= 0x1f;
P0 = 1<<dspcom;
P2 = ((P2&0x1f)|0xC0);
P2 &= 0x1f;
P0 = tab[ptr[dspcom]];
P2 = ((P2&0x1f)|0xE0);
P2 &= 0x1f;
if(++dspcom >= 8)
{
dspcom = 0;
}
}
界面切换
//数码管显示信息
void SegDispaly(u8 SegShow_Flag,u8 SegTime_Flag,long temperature,u8* time,u8 temp,u8* ptr)
{
//温度界面
if(SegShow_Flag == 0)
{
ptr[0]=21;
ptr[1]=1;
ptr[2]=22;
ptr[3]=22;
ptr[4]=22;
ptr[5]=temperature/100000;
ptr[6]=temperature%100000/10000+10;
ptr[7]=temperature%10000/1000;
}
//时间界面
else if(SegShow_Flag == 1)
{
ptr[0]=21;
ptr[1]=2;
ptr[2]=22;
if(SegTime_Flag == 0)
{
ptr[3]=time[2]/10;
ptr[4]=time[2]%10;
ptr[5]=20;
ptr[6]=time[1]/10;
ptr[7]=time[1]%10;
}
else
{
ptr[3]=time[1]/10;
ptr[4]=time[1]%10;
ptr[5]=20;
ptr[6]=time[0]/10;
ptr[7]=time[0]%10;
}
}
//参数界面
else if(SegShow_Flag == 2)
{
ptr[0]=21;
ptr[1]=3;
ptr[2]=22;
ptr[3]=22;
ptr[4]=22;
ptr[5]=22;
ptr[6]=temp/10;
ptr[7]=temp%10;
}
}
剩下的就是继电器和led的显示,这里就不都一一展出啦,需要的伙伴可以在下面链接自行下载。
代码链接
链接:https://pan.baidu.com/s/1DAbZ5t6LMn_uOdZORoh8HA
提取码:mwl6
--来自百度网盘超级会员V5的分享