藍(lán)橋杯嵌入式第十屆省賽真題
1.題目分析
總的來說這題考點(diǎn)特別的少,邏輯也比我之前發(fā)的12屆的停車計(jì)費(fèi)簡單得多,還是一樣 代碼結(jié)尾自取。完全免費(fèi)
相對(duì)來說能從這題學(xué)到的。對(duì)我來說我覺得是 封裝一些“狀態(tài)”數(shù)組。可以讓代碼的可讀性和復(fù)用性高很多。
思路其實(shí)很簡單,就是切換界面和獲取adc的值,并和上下限比較進(jìn)行對(duì)應(yīng)操作。
](https://imgtu.com/i/IvVBp4)
2.項(xiàng)目結(jié)構(gòu)
變量設(shè)計(jì):
u32 TimingDelay = 0;
//切換設(shè)置函數(shù)
void setting();
void Delay_Ms(u32 nTime);
//更新
void Upate_Data();
//渲染主界面
void Fflush_Main();
//渲染設(shè)置界面
void Fflush_Setting();
//Key_4,3的對(duì)應(yīng)控制這里的flag我覺得用的挺好的
//后面大家會(huì)看到
void Key4_Control(int flag);
void Key3_Control(int flag);
//高光展示
void DymaicShow(int flag);
//控制狀態(tài)
void Status_Control()
//展示數(shù)組(個(gè)人習(xí)慣)
char MaxVolDisplay[24];
char MinVolDisplay[24];
char UpperDisplay[24];
char LowerDisplay[24];
char StatusDisplay[24];
char VolDisplay[24];
//狀態(tài)數(shù)組
char *Status[8]={"Normal","Upper ","Lower "};
//LED燈數(shù)組 這里也非常有用,可以和后面的led燈編號(hào)對(duì)照
uint16_t LED_Arr[9]={0,LED1,LED2,LED3,LED4,LED5,LED6,LED7,LED8};
//電壓
double Vol = 3.22;
double MaxVol = 2.4;
double MinVOl = 1.2;
//LED編號(hào)
int UpperLED = 1;
int LowerLED = 2;
//狀態(tài)值 和狀態(tài)數(shù)組比較
int Status_Flag = 0;
2.1數(shù)組思路
首先先來聊聊為什么這里的LED要利用編號(hào) 而不是規(guī)定死字符串 “LD1”,“LD2”這樣的。因?yàn)槿绻?guī)定死字符串的話,到時(shí)候報(bào)警燈點(diǎn)亮的時(shí)候,還需要解析字符串取出最后一位的數(shù)字,麻煩
我們不如換一種思路 規(guī)定字符串為“LD”而我們?cè)诤竺鎰?dòng)態(tài)的拼接LED的編號(hào)。也就是這樣
sprintf(UpperDisplay," Upper:LD%d",UpperLED);
就做到了利用UpperDisplay動(dòng)態(tài)展示對(duì)應(yīng)的數(shù)據(jù)。并且UpperLED可以用來后面點(diǎn)亮燈。
這也是為什么我要把LED封裝成數(shù)組。
我們可以輕易的做到 利用UpperLED作為LED數(shù)組的下標(biāo),點(diǎn)亮對(duì)應(yīng)的LED 這樣點(diǎn)亮就非常方便了,而不需要if判斷。如下
(這里的flag是用來交替閃爍的,200ms的時(shí)候 flag會(huì)自己取反,做到亮滅交替)
LED_Control(LED_Arr[UpperLED],Led_Flag);
那么前面的Status_Flag和char *Status[8]也是同理了;
這里我們就可以引出我的第一個(gè)函數(shù)
Status_Control.c
void Status_Control()
{
if(Vol>MaxVol)
{
//這里的標(biāo)志位是到時(shí)中斷里200ms取反一次的 做到間斷閃爍
LED_Control(LED_Arr[UpperLED],Led_Flag);
Status_Flag=1;
return;
}
if(Vol<MinVOl)
{
LED_Control(LED_Arr[LowerLED],Led_Flag);
Status_Flag=2;
return;
}
Status_Flag=0;
}
可以很清晰的通過代碼看出。不同的Status_Flag 到時(shí)就會(huì)動(dòng)態(tài)的控制char *Status[8]展示他對(duì)應(yīng)的該有的變量
sprintf(StatusDisplay," Status:%s",Status[Status_Flag]);
LCD_DisplayStringLine(Line5,StatusDisplay);
2.2Key_Flag控制對(duì)應(yīng)邏輯
重點(diǎn)就在這四個(gè)函數(shù)
void Key4_Control(int flag);
void Key3_Control(int flag);
void DymaicShow(int flag);
分析題目我們可以讀出,在Setting界面修改的時(shí)候,需要在最大電壓值,最小電壓值,最大電壓LED編號(hào)和最小電壓LED編號(hào)。這
四個(gè)地方切換,并通過KEY3,KEY4控制他們的加減。
他們的共性就是 4 個(gè)位置 對(duì)應(yīng)四個(gè)不同的操作模式和操作邏輯。
(高光+KEY4+KEY3)*4個(gè)位置 那么有12種情況,為此寫12個(gè)函數(shù)未免太過麻煩了。
我們抽象的來想,可以是 3個(gè)操作,各自對(duì)應(yīng)4個(gè)模式 。 把三個(gè)操作抽象成函數(shù)。
而三個(gè)操作里面對(duì)應(yīng)的四種情況其實(shí)是平行關(guān)系的。
這個(gè)平行關(guān)系我們就用Flag替代。例如flag為1,執(zhí)行三個(gè)函數(shù)里各自的情況1,flag2執(zhí)行三個(gè)函數(shù)里各自的情況2。
而按鍵2 就是我們用來觸發(fā)Flag改變的,邏輯如下(14-30行)
如此我們的代碼耦合性就會(huì)降低 ,函數(shù)各司其職。
//切屏函數(shù)
void setting()
{
char key;
int flag=0;
LCD_Clear(White);
Fflush_Setting();
while(1)
{
key = KEY_Scan();
Vol=Get_Adc();
Status_Control();
DymaicShow(flag);
switch(key)
{
//返回主界面
case '1':
LCD_Clear(White);
LCD_SetBackColor(White);
return;
case '2':
flag++;
if(flag>=4){ flag=0; }
break;
case '3':
Key3_Control(flag);
break;
case '4':
Key4_Control(flag);
break;
}
}
}
2.3KEY控制操作
利用前面的操作,這里我們就可以做按鍵在不同高亮位置時(shí)不同對(duì)應(yīng)的情況了,其實(shí)我覺得應(yīng)該用switch case會(huì)更加好一點(diǎn),結(jié)構(gòu)更加清晰,但是當(dāng)時(shí)寫完懶得改了。
void Key3_Control(int flag)
{
//最大電壓值
if(flag==0)
{
//浮點(diǎn)數(shù)計(jì)算精度問題
if(MaxVol+0.3<3.300000000000001)
{
MaxVol+=0.3;
return;
}
MaxVol=3.3;
}
//最小電壓值
else if(flag==1)
{
if(MinVOl+0.3<3.300000000000001)
{
MinVOl+=0.3;
return;
}
MinVOl=3.3;
}
//最大電壓值LED編號(hào)
else if(flag==2)
{
//這里要先關(guān)燈,不然警告閃燈的時(shí)候,假設(shè)LED1亮還沒熄滅的時(shí)候,
//我們按下Key3切換,那么LED2閃爍,LED1還在亮
LED_Control(LEDALL,0);
//最大編號(hào)
if(UpperLED==8)
{
UpperLED=8;
return;
}
//如果往上+1的時(shí)候,和最小電壓編號(hào)的LED編號(hào)相等的時(shí)候
//那么我們需要過這個(gè)編號(hào),讓兩個(gè)編號(hào)不相等
if(UpperLED+1==LowerLED)
{
//但是如果跨過LowerLED的編號(hào)后會(huì)超過8,那么也不行的哦
if(UpperLED+1==8)
{
return;
}
//邏輯完成,直接跨越
UpperLED+=2;
return;
}
//其他情況正常+1,后續(xù)最小電壓那些也是同理,我就不寫那么多注釋了
UpperLED++;
}
//最小電壓值LED編號(hào)
else if(flag==3)
{
LED_Control(LEDALL,0);
if(LowerLED==8)
{
LowerLED=8;
return;
}
if(LowerLED+1==UpperLED)
{
if(LowerLED+1==8)
{
return;
}
LowerLED+=2;
return;
}
LowerLED++;
}
}
KEY4_Control也是這個(gè)道理。這里就不復(fù)制展示了,代碼文章結(jié)尾自取
高亮部分我來求解一下,大家有沒有更好的解法,我只會(huì)這種最笨的方式
void DymaicShow(int flag)
{
LCD_SetBackColor(White);
if(flag==0)
{
LCD_DisplayStringLine(Line1, " Setting");
LCD_DisplayStringLine(Line4,MinVolDisplay);
LCD_DisplayStringLine(Line5,UpperDisplay);
LCD_DisplayStringLine(Line6,LowerDisplay);
//單獨(dú)某一行刷新改色
LCD_SetBackColor(Yellow);
sprintf(MaxVolDisplay," Max Volt:%.2f ",MaxVol);
LCD_DisplayStringLine(Line3,MaxVolDisplay);
return;
}
if(flag==1)
{
LCD_DisplayStringLine(Line1, " Setting");
LCD_DisplayStringLine(Line3,MaxVolDisplay);
LCD_DisplayStringLine(Line5,UpperDisplay);
LCD_DisplayStringLine(Line6,LowerDisplay);
LCD_SetBackColor(Yellow);
sprintf(MinVolDisplay," Min Volt:%.2f ",MinVOl);
LCD_DisplayStringLine(Line4,MinVolDisplay);
return;
}
if(flag==2)
{
LCD_DisplayStringLine(Line1, " Setting");
LCD_DisplayStringLine(Line3,MaxVolDisplay);
LCD_DisplayStringLine(Line4,MinVolDisplay);
LCD_DisplayStringLine(Line6,LowerDisplay);
LCD_SetBackColor(Yellow);
sprintf(UpperDisplay," Upper:LD%d ",UpperLED);
LCD_DisplayStringLine(Line5,UpperDisplay);
return;
}
if(flag==3)
{
LCD_DisplayStringLine(Line1, " Setting");
LCD_DisplayStringLine(Line3,MaxVolDisplay);
LCD_DisplayStringLine(Line4,MinVolDisplay);
LCD_DisplayStringLine(Line5,UpperDisplay);
LCD_SetBackColor(Yellow);
sprintf(LowerDisplay," Lower:LD%d ",LowerLED);
LCD_DisplayStringLine(Line6,LowerDisplay);
return;
}
}
最后就是這個(gè)中斷里取反的操作 很簡單的
void SysTick_Handler(void)
{
TimingDelay--;
//低于下限電壓
if(Status_Flag==2)
{
if(++Led_Dealy==200)
{
Led_Flag= !Led_Flag;
Led_Dealy=0;
}
}
//高于上限電壓
else if(Status_Flag==1)
{
if(++Led_Dealy==200)
{
Led_Flag= !Led_Flag;
Led_Dealy=0;
}
}
}
整體和邏輯有關(guān)的代碼大概就是這樣了文章來源:http://www.zghlxwxcb.cn/news/detail-421290.html
我個(gè)人認(rèn)為最好的地方就是我用了數(shù)組和對(duì)應(yīng)的Flag標(biāo)識(shí),來和數(shù)組組成映射關(guān)系,在代碼里的很多地方都因此受益。還是個(gè)小萌新哈,如果大家有更好的方式也歡迎大家提出
下載資源鏈接 鏈接:源碼文章來源地址http://www.zghlxwxcb.cn/news/detail-421290.html
到了這里,關(guān)于藍(lán)橋杯嵌入式第十屆省賽真題的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!