题目分析
1.各模块分析
本次蓝桥杯程序设计题难度相比去年有了明显的下降,大部分功能比较常规(如按键模块没有出现要求长按,多击等形式),主要考的模块包括:数码管,按键,led, DAC输出电压 ,频率测量,ds1302时钟芯片模块。
2.重难点分析
其中重点在于频率的测量与显示,所以按键模块不能对P34引脚做手脚(因为是用P34来进行频率测量的会导致误差)。
本次比赛存在设置校准值(有负有正)对实际频率进行矫正(第十四届国赛考点),我是选择设置一个标志位变量来判断频率校准值为正还是负,就可以把测量的频率变量定义为unsigned int 类型来实现频率上限的增加(如果定义成int类型在加上校准值的话可能会存在溢出的问题),还有比较基本的,所有参数真正意义上的修改只有在退出参数界面才能实现(西风哥的视频有讲)。
然后再扣一点细节的话,就是数码管的减速变量的值应当选择100以下(题目要求,响应时间<0.1s),但具体会不会影响很大也是不到嘞。
- if(++Key_Slow_Down==10){Key_Slow_Down=0;} //每10ms检测按键
- if(++Seg_Slow_Down==100){Seg_Slow_Down=0;} //每100ms检测数码管
小白代码参考
(由于是比赛时写的,加上作者还是小白,也许仍然存在一些缺陷,欢迎指正批评!)
1. main.c
- #include
- #include "Seg.h"
- #include "Key.h"
- #include "Led.h"
- #include "iic.h"
- #include "ds1302.h"
- #include "intrins.h"
- unsigned char Key_Val,Key_Down,Key_Up,Key_Old; //按键相关变量
- unsigned char Key_Slow_Down; //按键减速变量
-
- unsigned char Seg_Buf[8]={16,16,16,16,16,16,16,16}; //数码管各位置数据
- unsigned char Seg_Point[8]={0,0,0,0,0,0,0,0}; //数码管各位置小数点亮灭情况
- unsigned int Seg_Slow_Down; //数码管减速变量
- unsigned char Seg_Pos; //数码管位置
-
- unsigned char Led_Buf[8]={0,0,0,0,0,0,0,0}; //led显示情况
-
- bit Dat_Mode=0; //参数界面切换 0是参数 1是校准值
- bit Dat_Flag=0; //判断参数是正还是负 0是正 1是负
- bit Final_Flag=0; //回显模式的变换 0是最大频率 1记录时间
- bit Error_Flag=0; //判断是否错误中间变量
- bit Error_Real=0; //判断是否错误变量
- unsigned char Mode_Show=0; //总模式切换
-
- unsigned int Freq_Set=2000; //设置的频率参数
- unsigned int Freq_Set_Temp=2000; //设置的频率参数中间变量
- unsigned int Freq_Fix=0; //设置的频率校准值
- unsigned int Freq_Fix_Temp=0; //设置的频率校准值中间变量
- unsigned int Freq; //测量得到的频率
- unsigned int Freq_Max=0; //频率最大值
-
- unsigned char Time[3]={0x05,0x02,0x13}; //存放时间变量
- unsigned char Max_Time[3]={0,0,0}; //存放频率最大值的时间数组
-
- unsigned int Time_1s=0; //用于每1秒读取频率
- unsigned char Time_200ms=0; //用于灯闪烁
- unsigned char Time_200ms_L1=0; //用于灯闪烁
- void Key_Proc()
- {
- if(Key_Slow_Down)
- {
- return;
- }
- Key_Slow_Down=1;
-
- Key_Val=Key_Choose();
- Key_Down=Key_Val & (Key_Old ^ Key_Val);
- Key_Up=~Key_Val & (Key_Old ^ Key_Val);
- Key_Old=Key_Val;
-
-
- switch(Key_Down)
- {
- case 4:
- if(++Mode_Show==4)
- {
- Mode_Show=0;
- }
- break;
-
- case 5:
- if(Mode_Show==1)
- {
- Dat_Mode^=1;
- }
- else if(Mode_Show==3)
- {
- Final_Flag^=1;
- }
- break;
-
- case 8:
- if(Mode_Show==1)
- {
- if(Dat_Mode==0)
- {
- Freq_Set_Temp+=1000;
- if(Freq_Set_Temp>9000)
- {
- Freq_Set_Temp=9000;
- }
- }
- else if(Dat_Mode==1)
- {
- if(Dat_Flag==0)
- {
- Freq_Fix_Temp+=100;
- }
- if(Dat_Flag==1&&Freq_Fix_Temp<=100)
- {
- Freq_Fix_Temp-=100;
- Dat_Flag=0;
- }
- if(Dat_Flag==1&&Freq_Fix_Temp>100)
- {
- Freq_Fix_Temp-=100;
- }
- if(Freq_Fix_Temp>900)
- {
- Freq_Fix_Temp=900;
- }
- }
- }
- break;
-
- case 9:
- if(Mode_Show==1)
- {
- if(Dat_Mode==0)
- {
- Freq_Set_Temp-=1000;
- if(Freq_Set_Temp<1000)
- {
- Freq_Set_Temp=1000;
- }
- }
- else if(Dat_Mode==1)
- {
- if(Dat_Flag==1&&Freq_Fix_Temp>=100)
- {
- Freq_Fix_Temp+=100;
- }
- if(Dat_Flag==0&&Freq_Fix_Temp<100)
- {
- Dat_Flag=1;
- Freq_Fix_Temp+=100;
- }
- if(Dat_Flag==0&&Freq_Fix_Temp>=100)
- {
- Freq_Fix_Temp-=100;
- }
- if(Freq_Fix_Temp>900)
- {
- Freq_Fix_Temp=900;
- }
- }
- }
- break;
-
- }
- }
-
- void Seg_Proc()
- {
- if(Seg_Slow_Down)
- {
- return;
- }
- Seg_Slow_Down=1;
-
- Ds1302_Read(Time);
-
- switch(Mode_Show)
- {
- case 0:
- if(Error_Flag==0)
- {
- Seg_Buf[0]=15;
- Seg_Buf[1]=16;
- Seg_Buf[2]=16;
- if(Freq/10000==0)
- {
- Seg_Buf[3]=16;
- }
- else
- {
- Seg_Buf[3]=Freq/10000;
- }
- if(Freq/10000==0&&Freq/1000%10==0)
- {
- Seg_Buf[4]=16;
- }
- else
- {
- Seg_Buf[4]=Freq/1000%10;
- }
- if(Freq/100%10==0&&Freq/10000==0&&Freq/1000%10==0)
- {
- Seg_Buf[5]=16;
- }
- else
- {
- Seg_Buf[5]=Freq/100%10;
- }
- if(Freq/10%10==0&&Freq/100%10==0&&Freq/10000==0&&Freq/1000%10==0)
- {
- Seg_Buf[6]=16;
- }
- else
- {
- Seg_Buf[6]=Freq/10%10;
- }
- Seg_Buf[7]=Freq%10;
- }
- else if(Error_Flag==1)
- {
- Seg_Buf[0]=15;
- Seg_Buf[1]=16;
- Seg_Buf[2]=16;
- Seg_Buf[3]=16;
- Seg_Buf[4]=16;
- Seg_Buf[5]=16;
- Seg_Buf[6]=20;
- Seg_Buf[7]=20;
- }
- break;
-
- case 1:
- if(Dat_Mode==0)
- {
- Seg_Buf[0]=19;
- Seg_Buf[1]=1;
- Seg_Buf[2]=16;
- Seg_Buf[3]=16;
- Seg_Buf[4]=Freq_Set_Temp/1000;
- Seg_Buf[5]=Freq_Set_Temp/100%10;
- Seg_Buf[6]=Freq_Set_Temp/10%10;
- Seg_Buf[7]=Freq_Set_Temp%10;
- }
- else if(Dat_Mode==1)
- {
- Seg_Buf[0]=19;
- Seg_Buf[1]=2;
- Seg_Buf[2]=16;
- Seg_Buf[3]=16;
- if(Dat_Flag==0)
- {
- Seg_Buf[4]=16;
- }
- if(Dat_Flag==1)
- {
- Seg_Buf[4]=17;
- }
- if(Freq_Fix_Temp/100%10==0)
- {
- Seg_Buf[5]=16;
- }
- else
- {
- Seg_Buf[5]=Freq_Fix_Temp/100%10;
- }
- if(Freq_Set_Temp/10%10==0&&Freq_Fix_Temp/100%10==0)
- {
- Seg_Buf[6]=16;
- }
- else
- {
- Seg_Buf[6]=Freq_Set_Temp/10%10;
- }
- Seg_Buf[7]=Freq_Set_Temp%10;
- }
- break;
-
- case 2:
- Seg_Buf[0]=Time[2]/16;
- Seg_Buf[1]=Time[2]%16;
- Seg_Buf[2]=17;
- Seg_Buf[3]=Time[1]/16;
- Seg_Buf[4]=Time[1]%16;
- Seg_Buf[5]=17;
- Seg_Buf[6]=Time[0]/16;
- Seg_Buf[7]=Time[0]%16;
- break;
-
- case 3:
- if(Final_Flag==0)
- {
- Seg_Buf[0]=18;
- Seg_Buf[1]=15;
- Seg_Buf[2]=16;
- if(Freq_Max/10000==0)
- {
- Seg_Buf[3]=16;
- }
- else
- {
- Seg_Buf[3]=Freq_Max/10000;
- }
- if(Freq_Max/10000==0&&Freq_Max/1000%10==0)
- {
- Seg_Buf[4]=16;
- }
- else
- {
- Seg_Buf[4]=Freq_Max/1000%10;
- }
- if(Freq_Max/100%10==0&&Freq_Max/10000==0&&Freq_Max/1000%10==0)
- {
- Seg_Buf[5]=16;
- }
- else
- {
- Seg_Buf[5]=Freq_Max/100%10;
- }
- if(Freq_Max/10%10==0&&Freq_Max/100%10==0&&Freq_Max/10000==0&&Freq_Max/1000%10==0)
- {
- Seg_Buf[6]=16;
- }
- else
- {
- Seg_Buf[6]=Freq_Max/10%10;
- }
- Seg_Buf[7]=Freq_Max%10;
- }
- else if(Final_Flag==1)
- {
- Seg_Buf[0]=18;
- Seg_Buf[1]=10;
- Seg_Buf[2]=Max_Time[2]/16;
- Seg_Buf[3]=Max_Time[2]%16;
- Seg_Buf[4]=Max_Time[1]/16;
- Seg_Buf[5]=Max_Time[1]%16;
- Seg_Buf[6]=Max_Time[0]/16;
- Seg_Buf[7]=Max_Time[0]%16;
- }
- break;
-
-
- }
-
-
-
- }
-
- void Led_Proc()
- {
-
- if(Freq<=500&&Error_Flag==0)
- {
- DA_Write(51);
- }
- else if(Freq>500&&Freq<=Freq_Set&&Error_Flag==0)
- {
- DA_Write(((4*(Freq-500.0))/(Freq_Set-500)+1.0)*51);
- }
- else if(Freq>500&&Error_Flag==0)
- {
- DA_Write(255);
- }
- else if(Error_Flag==1)
- {
- DA_Write(0);
- }
-
- if(Freq<=Freq_Set)
- {
- Led_Buf[1]=0;
- }
-
- if(Error_Flag)
- {
- Led_Buf[1]=1;
- }
-
- if(Freq<=Freq_Set&&Error_Real==0)
- {
- Led_Buf[1]=0;
- }
- }
- //
- void Timer1Init(void) //1毫秒@12.000MHz
- {
- AUXR &= 0x7F; //定时器1时钟12T模式
- AUXR &= 0xBF; //定时器0时钟12T模式
-
- TMOD |= 0x05; //设置定时器模式
-
- TL1 = 0x18; //设置定时初值
- TH1 = 0xFC; //设置定时初值
- TF1 = 0; //清除TF1标志
- TR1 = 1; //定时器1开始计时
- ET1=1;
- EA=1;
-
- TL0 = 0; //设置定时初值
- TH0 = 0; //设置定时初值
- TF0 = 0; //清除TF0标志
- TR0 = 1; //定时器0开始计时
- }
-
- void Timer1_Rountine(void) interrupt 3
- {
- TL1 = 0x18; //设置定时初值
- TH1 = 0xFC; //设置定时初值
-
- if(++Key_Slow_Down==10){Key_Slow_Down=0;}
- if(++Seg_Slow_Down==100){Seg_Slow_Down=0;}
- if(++Seg_Pos==8){Seg_Pos=0;}
-
- if(Mode_Show==0)
- {
- Freq_Set_Temp=Freq_Set;
- Freq_Fix_Temp=Freq_Fix;
- Dat_Mode=0;
- Error_Flag=Error_Real;
- }
- if(Mode_Show==2)
- {
- Freq_Set=Freq_Set_Temp;
- Freq_Fix=Freq_Fix_Temp;
- Final_Flag=0;
- Error_Real=Error_Flag;
- }
-
-
- if(++Time_1s>1000)
- {
- Time_1s=0;
- Freq=(TH0<<8)|TL0;
- if(Dat_Flag==0)
- {
- Error_Flag=0;
- Freq=(TH0<<8)|TL0+Freq_Fix;
- }
- else if(Dat_Flag==1&&Freq>=Freq_Fix)
- {
- Error_Flag=0;
- Freq=(TH0<<8)|TL0-Freq_Fix;
- }
- else if(Dat_Flag==1&&Freq
- {
- Error_Flag=1;
- }
- if(Freq>Freq_Max)
- {
- Freq_Max=Freq;
- Max_Time[0]=Time[0];
- Max_Time[1]=Time[1];
- Max_Time[2]=Time[2];
- }
- TL0=0;
- TH0=0;
- }
-
-
- if(Mode_Show==0)
- {
- Time_200ms++;
- if(Time_200ms<=200)
- {
- Led_Buf[0]=1;
- }
- if(Time_200ms>200&&Time_200ms<400)
- {
- Led_Buf[0]=0;
- }
- if(Time_200ms>=400)
- {
- Time_200ms=0;
- }
- }
- else
- {
- Led_Buf[0]=0;
- }
-
- if(Freq>Freq_Set&&Error_Flag==0)
- {
- Time_200ms_L1++;
- if(Time_200ms_L1<=200)
- {
- Led_Buf[1]=1;
- }
- if(Time_200ms_L1>200&&Time_200ms_L1<400)
- {
- Led_Buf[1]=0;
- }
- if(Time_200ms_L1>=400)
- {
- Time_200ms_L1=0;
- }
- }
- else if(Freq<=Freq_Set&&Error_Real==0)
- {
- Led_Buf[1]=0;
- }
- else if(Error_Real==1)
- {
- Led_Buf[1]=1;
- }
-
-
- Seg_Choose(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
- Led_Choose(Seg_Pos,Led_Buf[Seg_Pos]);
-
- }
-
- void main()
- {
- P0=0xff;
- P2=P2&0x1f|0x9f;
- P2&=0x1f;
-
- P0=0x00;
- P2=P2&0x1f|0xa0;
- P2&=0x1f;
-
- Freq=0;
- Timer1Init();
- Ds1302_Set(Time);
- while(1)
- {
- Key_Proc();
- Seg_Proc();
- Led_Proc();
- }
- }
2.数码管
- #include
-
- unsigned char Seg_Table[]={
- // 0 1 2 3 4 5 6 7 8 9 A B C D E F
- 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
- //black - H P L
- 0x00,0x40,0x76,0x73,0x38};
-
- unsigned char Seg_Location[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
-
- void Seg_Choose(unsigned char Location,Dat,Point)
- {
- //实现数码管清零
- P0=0x00;
- P2=P2&0x1f|0xe0;
- P2&=0x1f;
-
- //实现数码管选择位置
- P0=Seg_Location[Location];
- P2=P2&0x1f|0xc0;
- P2&=0x1f;
-
- //实现数码管选择数据
- P0=~Seg_Table[Dat];
- if(Point)
- {
- P0&=0x7f;
- }
- P2=P2&0x1f|0xe0;
- P2&=0x1f;
- }
3.按键
- #include
-
- unsigned char Key_Choose()
- {
- unsigned char Temp;
- EA=0;
- P44=0;P42=1;P35=1;
- if(P30==0){Temp=7;}
- if(P31==0){Temp=6;}
- if(P32==0){Temp=5;}
- if(P33==0){Temp=4;}
-
- P44=1;P42=0;P35=1;
- if(P30==0){Temp=11;}
- if(P31==0){Temp=10;}
- if(P32==0){Temp=9;}
- if(P33==0){Temp=8;}
-
- P44=1;P42=1;P35=0;
- if(P30==0){Temp=15;}
- if(P31==0){Temp=14;}
- if(P32==0){Temp=13;}
- if(P33==0){Temp=12;}
-
- // P44=1;P42=1;P35=1;P34=0;
- // if(P30==0){Temp=19;}
- // if(P31==0){Temp=18;}
- // if(P32==0){Temp=17;}
- // if(P33==0){Temp=16;}
-
- EA=1;
- P3=0xff;
- return Temp;
- }
4.Led灯显示
- #include
-
- void Led_Choose(unsigned char Location,Enable)
- {
- static unsigned char Temp=0x00;
- static unsigned char Temp_Old=0xff;
- if(Enable)
- {
- Temp|=0x01<
- }
- else
- {
- Temp&=~(0x01<
- }
- if(Temp!=Temp_Old)
- {
- P0=~Temp;
- P2=P2&0x1f|0x80;
- P2&=0x1f;
- Temp_Old=Temp;
- }
- }
5.iic
- /* # I2C代码片段说明
- 1. 本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
- 2. 参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
- 中对单片机时钟频率的要求,进行代码调试和修改。
- */
- #include
- #include "intrins.h"
-
- sbit scl=P2^0;
- sbit sda=P2^1;
-
- #define DELAY_TIME 10
-
- //
- static void I2C_Delay(unsigned char n)
- {
- do
- {
- _nop_();_nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();_nop_();
- _nop_();_nop_();_nop_();_nop_();_nop_();
- }
- while(n--);
- }
-
- //
- void I2CStart(void)
- {
- sda = 1;
- scl = 1;
- I2C_Delay(DELAY_TIME);
- sda = 0;
- I2C_Delay(DELAY_TIME);
- scl = 0;
- }
-
- //
- void I2CStop(void)
- {
- sda = 0;
- scl = 1;
- I2C_Delay(DELAY_TIME);
- sda = 1;
- I2C_Delay(DELAY_TIME);
- }
-
- //
- void I2CSendByte(unsigned char byt)
- {
- unsigned char i;
-
- for(i=0; i<8; i++){
- scl = 0;
- I2C_Delay(DELAY_TIME);
- if(byt & 0x80){
- sda = 1;
- }
- else{
- sda = 0;
- }
- I2C_Delay(DELAY_TIME);
- scl = 1;
- byt <<= 1;
- I2C_Delay(DELAY_TIME);
- }
-
- scl = 0;
- }
-
- //
- unsigned char I2CReceiveByte(void)
- {
- unsigned char da;
- unsigned char i;
- for(i=0;i<8;i++){
- scl = 1;
- I2C_Delay(DELAY_TIME);
- da <<= 1;
- if(sda)
- da |= 0x01;
- scl = 0;
- I2C_Delay(DELAY_TIME);
- }
- return da;
- }
-
- //
- unsigned char I2CWaitAck(void)
- {
- unsigned char ackbit;
-
- scl = 1;
- I2C_Delay(DELAY_TIME);
- ackbit = sda;
- scl = 0;
- I2C_Delay(DELAY_TIME);
-
- return ackbit;
- }
-
- //
- void I2CSendAck(unsigned char ackbit)
- {
- scl = 0;
- sda = ackbit;
- I2C_Delay(DELAY_TIME);
- scl = 1;
- I2C_Delay(DELAY_TIME);
- scl = 0;
- sda = 1;
- I2C_Delay(DELAY_TIME);
- }
- //
- void DA_Write(unsigned char Dat)
- {
- I2CStart();
- I2CSendByte(0x90);
- I2CWaitAck();
- I2CSendByte(0x41);
- I2CWaitAck();
- I2CSendByte(Dat);
- I2CWaitAck();
- I2CStop();
- }
6.ds1302
- #include
- #include "intrins.h"
-
- sbit SCK=P1^7;
- sbit SDA=P2^3;
- sbit RST=P1^3;
-
- //
- void Write_Ds1302(unsigned char temp)
- {
- unsigned char i;
- for (i=0;i<8;i++)
- {
- SCK = 0;
- SDA = temp&0x01;
- temp>>=1;
- SCK=1;
- }
- }
-
- //
- 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;
- }
-
- //
- 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)
- temp|=0x80;
- SCK=1;
- }
- RST=0; _nop_();
- SCK=0; _nop_();
- SCK=1; _nop_();
- SDA=0; _nop_();
- SDA=1; _nop_();
- return (temp);
- }
- //
- void Ds1302_Set(unsigned char *Time)
- {
- Write_Ds1302_Byte( 0x8e,0x00 );
- Write_Ds1302_Byte( 0x80,Time[0] );
- Write_Ds1302_Byte( 0x82,Time[1] );
- Write_Ds1302_Byte( 0x84,Time[2] );
- Write_Ds1302_Byte( 0x8e,0x80 );
- }
- //
- void Ds1302_Read(unsigned char *Time)
- {
- Time[0]=Read_Ds1302_Byte ( 0x81 );
- Time[1]=Read_Ds1302_Byte ( 0x83 );
- Time[2]=Read_Ds1302_Byte ( 0x85 );
- }
注:本文转载自blog.csdn.net的多睡午觉的文章"https://blog.csdn.net/2401_83340925/article/details/137744937"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
评论记录:
回复评论: