蓝桥杯单片机【第15届省赛】
main.c
#include <STC15F2K60S2.H>
#include <String.H>
#include "Hardware.h"
#include "iic.h"
#include "ds1302.h"
/*变量声明区*/
unsigned char Key_Val,Key_Old,Key_Down,Key_Up;
unsigned int Slow_Down;
bit Key_Flag,Seg_Flag; //按键、数码管减速标志
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10}; //数码管显示区
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0}; //数码管小数点显示
unsigned char ucLed[8] = {0,0,0,0,0,0,0,0}; //led显示区
unsigned char Seg_Pos; //数码管循环变量
unsigned char Sys_Tick; //1s计时 频率专用
unsigned int Freq; //实时频率
float Voltage; //实时电压
unsigned char Rtc[3] = {13,3,5}; //实时时钟
unsigned char Seg_Disp_Mode; //数码管显示模式 0-频率 1-参数 2-时间 3-回显
bit Seg_Disp_Mode_1_Son; //参数设置界面子界面 0-超限界面 1-校准值界面
bit Seg_Disp_Mode_3_Son; //回显界面子界面 0-频率 1-时间
unsigned char Freq_Super_Disp = 2; //超限参数 显示 //unsigned char Freq_Super_Steer = 2; //超限参数 控制
unsigned char Freq_Compare_Disp; //校准值 显示
bit Signed_Flag; //符号标志 0-正 1-负
unsigned int Freq_Effective; //校准后 频率
unsigned int Freq_Effective_Max; //校准后 最大频率
unsigned char Rtc_Effective_Max[3]; //最大频率发送时间
bit Error_Flag; //频率校验错误 0-未错误 1-错误
unsigned char Time_200ms; //0.2s计时
bit Led_Shift; //led闪烁标志位
/*按键处理函数*/
void Key_Proc()
{
if(Key_Flag) return ;
Key_Flag = 1;
Key_Val = Key_Read();
Key_Down = Key_Val & (Key_Val ^ Key_Old);
Key_Up = ~Key_Val & (Key_Val ^ Key_Old);
Key_Old = Key_Val;
switch(Key_Down)
{
case 4: //显示界面切换
Seg_Disp_Mode = ++Seg_Disp_Mode % 4;
if(Seg_Disp_Mode == 1) //entry参数界面
Seg_Disp_Mode_1_Son = 0; //默认超限界面
if(Seg_Disp_Mode == 3) //entry回显界面
Seg_Disp_Mode_3_Son = 0; //默认 频率
break;
case 5:
//超限参数 校准值 显示切换
if(Seg_Disp_Mode == 1) //参数界面下
Seg_Disp_Mode_1_Son ^= 1;
//最大频率 最大时间 显示切换
if(Seg_Disp_Mode == 3) //回显界面下
Seg_Disp_Mode_3_Son ^= 1;
break;
case 8: //参数界面 +
if(Seg_Disp_Mode == 1) //参数界面下
if(Seg_Disp_Mode_1_Son == 0) //超限参数
{
Freq_Super_Disp = Freq_Super_Disp == 9 ? 9 : Freq_Super_Disp+1;
}
else //校准值
{
if(Signed_Flag == 1) //负数
{
Freq_Compare_Disp = Freq_Compare_Disp - 1;
}
else if(Signed_Flag == 0) //正数
Freq_Compare_Disp = Freq_Compare_Disp == 9 ? 9 : Freq_Compare_Disp+1;
if(Freq_Compare_Disp == 0) //值=0 为正数
Signed_Flag = 0;
}
break;
case 9: //参数界面 -
if(Seg_Disp_Mode == 1) //参数界面下
if(Seg_Disp_Mode_1_Son == 0) //超限参数
{
Freq_Super_Disp = Freq_Super_Disp == 1 ? 1 : Freq_Super_Disp-1;
}
else //校准值
{
if(Signed_Flag == 1 || Freq_Compare_Disp == 0) //负数
{
if(Signed_Flag == 0)
Signed_Flag = 1;
Freq_Compare_Disp = Freq_Compare_Disp == 9 ? 9 : Freq_Compare_Disp+1;
}
else if(Signed_Flag == 0) //正数
{
Freq_Compare_Disp = Freq_Compare_Disp - 1;
}
if(Freq_Compare_Disp == 0) //值=0 为正数
Signed_Flag = 0;
}
break;
}
}
/*信息处理函数*/
void Seg_Proc()
{
if(Seg_Flag) return ;
Seg_Flag = 1;
/*数据获取*/
Rtc_Read(Rtc);
/*数据显示*/
switch(Seg_Disp_Mode)
{
unsigned char i;
case 0: //频率显示
Seg_Buf[0] = 11; //F
Seg_Buf[1] = 10; //熄灭
if(Error_Flag == 0) //数据正确
{
Seg_Buf[3] = Freq_Effective / 10000 % 10;
Seg_Buf[4] = Freq_Effective / 1000 % 10;
Seg_Buf[5] = Freq_Effective / 100 % 10;
Seg_Buf[6] = Freq_Effective / 10 % 10;
Seg_Buf[7] = Freq_Effective % 10;
for(i=0;i<4;i++) //高位熄灭
if(Seg_Buf[3+i] == 0)
Seg_Buf[3+i] = 10;
else//如果高位没有熄灭
return; //就跳出
}
else //数据错误
{
Seg_Buf[1] = Seg_Buf[2] = Seg_Buf[3] = Seg_Buf[4] = Seg_Buf[5] = 10; //熄灭
Seg_Buf[6] = Seg_Buf[7] = 16; //LL
}
break;
case 1: //参数界面
Seg_Buf[0] = 12; //P
Seg_Buf[1] = (unsigned char)Seg_Disp_Mode_1_Son + 1; //1 2
if(Seg_Disp_Mode_1_Son == 0) //超限参数
{
Seg_Buf[3] = 10;
Seg_Buf[4] = Freq_Super_Disp; //超限值*1000
Seg_Buf[5] = Seg_Buf[6] = Seg_Buf[7] = 0;
}
else //校准值
{
/*符号显示*/
if(Signed_Flag == 1) //负数
Seg_Buf[4] = 15;
else //正数
Seg_Buf[4] = 10;
/*数据显示*/
if(Freq_Compare_Disp == 0) //校准值为0
{
Seg_Buf[5] = Seg_Buf[6] = 10;
Seg_Buf[7] = 0;
}
else
{
Seg_Buf[5] = Freq_Compare_Disp; //校准值*100
Seg_Buf[6] = Seg_Buf[7] = 0;
}
}
break;
case 2: //时间显示界面
Seg_Buf[2] = Seg_Buf[5] =15 ;//-
for(i=0;i<3;i++)
{
Seg_Buf[3*i] = Rtc[i] / 10 % 10;
Seg_Buf[3*i+1] = Rtc[i] % 10;
}
break;
case 3: //回显界面
Seg_Buf[0] = 13;// H
if(Seg_Disp_Mode_3_Son == 0) //频率
{
Seg_Buf[1] = 11;// F
Seg_Buf[2] = 10; //熄灭
Seg_Buf[3] = Freq_Effective_Max / 10000 % 10;
Seg_Buf[4] = Freq_Effective_Max / 1000 % 10;
Seg_Buf[5] = Freq_Effective_Max / 100 % 10;
Seg_Buf[6] = Freq_Effective_Max / 10 % 10;
Seg_Buf[7] = Freq_Effective_Max % 10;
for(i=0;i<4;i++)
if(Seg_Buf[3+i] == 0)
Seg_Buf[3+i] = 10;
else
return ;
}
else //时间
{
Seg_Buf[1] = 14;// A
for(i=0;i<3;i++)
{
Seg_Buf[2+2*i] = Rtc_Effective_Max[i] / 10 % 10;
Seg_Buf[2+2*i+1] = Rtc_Effective_Max[i] % 10;
}
}
break;
}
}
/*其他显示函数*/
void Led_Proc()
{
/*频率是1s由定时器控制变化的,不能跟随数码管减速,影响转化速率*/
if(Signed_Flag == 0) //校验值 = 正
Freq_Effective = Freq + Freq_Compare_Disp*100;
else //校验值 = 负
Freq_Effective = Freq - Freq_Compare_Disp*100;
/*校验数据有效判断*/
if(Freq_Effective < 0) //校验后为负数
{
Error_Flag = 1;
Voltage = 0; //输出电压0V
}
else
Error_Flag = 0;
if((Freq_Effective > Freq_Effective_Max) && !Error_Flag) //当前频率为最大频率
{ // 同时是有效数据
Freq_Effective_Max = Freq_Effective; //更新最大值
memcpy(Rtc_Effective_Max,Rtc,3); //更新最大值获取时间
}
/*输出电压*/
if(Error_Flag == 0)
if((Freq_Effective/500) && (Freq_Effective<=(Freq_Super_Disp*1000)))
Voltage = 4.0/(Freq_Super_Disp*1000-500) * (Freq_Effective - 500) + 1;
else if(Freq_Effective<500)
Voltage = 1;
else
Voltage = 5;
/*DA输出电压*/
DA_Write(Voltage * 51);
/*led*/
ucLed[0] = Led_Shift * (Seg_Disp_Mode == 0); //频率显示界面 0.2s闪烁
ucLed[1] =Error_Flag==1 | (Led_Shift * (Freq_Effective > Freq_Super_Disp * 1000)); // 频率>超限参数
}
/*定时器0初始化 频率读取*/
void Timer0_Init(void)
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x05; //设置定时器模式
TL0 = 0; //设置定时初始值
TH0 = 0; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
/*定时器1初始化*/
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x18; //设置定时初始值
TH1 = 0xFC; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
EA = 1;
ET1 = 1;
}
/*定时器1中断服务子函数*/
void Timer1_Server() interrupt 3
{
if(++Slow_Down == 100) Slow_Down = Seg_Flag = 0; //数码管减速
if(Slow_Down % 10 == 0) Key_Flag = 0; //按键减速
if(++Seg_Pos == 8) Seg_Pos = 0; //数码管循环
if(++Sys_Tick == 200) //频率测量
{
Freq = (TH0 << 8) | TL0;
Freq *= 5;
TH0 = TL0 = Sys_Tick = 0;
}
Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]); //数码管点亮
Led_Disp(Seg_Pos,ucLed[Seg_Pos]); //led点亮
if(++Time_200ms == 200)
{
Time_200ms = 0;
Led_Shift ^= 1;
}
}
void Delay1000ms(void) //@12.000MHz
{
unsigned char data i, j, k;
// _nop_();
// _nop_();
i = 46;
j = 153;
k = 245;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
/*主函数*/
void main()
{
System_Init();
Rtc_Write(Rtc);
Timer0_Init(); //用于频率获取
Timer1_Init();
Delay1000ms(); //延时1s等待频率读取完成
while(1)
{
Key_Proc();
Seg_Proc();
Led_Proc();
}
}
总结
用到的串口和频率获取比较难,16届考的超声波,同理
底层不要太记住,到时候考试电脑上有,多翻一翻就可以

5039

被折叠的 条评论
为什么被折叠?



