??【藍(lán)橋杯嵌入式】專題正在持續(xù)更新中,原理圖解析?,各模塊分析?以及歷年真題講解?都在這兒哦,歡迎大家前往訂閱本專題,獲取更多詳細(xì)信息哦??
??【藍(lán)橋杯嵌入式】藍(lán)橋杯第十屆省賽真題
??【藍(lán)橋杯嵌入式】藍(lán)橋杯第十三屆省賽程序真題
??本系列專欄 - ??藍(lán)橋杯嵌入式_勾欄聽曲_0的博客
??歡迎大家 ??? ?點(diǎn)贊?? ?評(píng)論?? ?收藏??
??個(gè)人主頁 - ?勾欄聽曲_0的博客??
??希望本文能對(duì)你有所幫助,如有不足請(qǐng)指正,共同進(jìn)步吧??
??君子欲訥于言而敏于行。??
題目
硬件框圖
??
功能要求
功能概述
????????1)設(shè)計(jì)一個(gè)停車計(jì)費(fèi)系統(tǒng),能夠完成費(fèi)率設(shè)置、費(fèi)用計(jì)算等功能。
????????2)使用串口獲取車輛進(jìn)、出停車場信息和時(shí)間,并能夠輸出計(jì)費(fèi)信息。
????????3)使用按鍵完成費(fèi)率設(shè)置、調(diào)整功能。
????????4)按照顯示要求,通過LCD顯示停車狀態(tài)、費(fèi)率參數(shù)。
????????5)通過PA7輸出固定頻率和占空比的脈沖信號(hào)或持續(xù)低電平。
????????6)使用LED指示燈完成相關(guān)指示功能。
性能要求
????????1)計(jì)費(fèi)信息輸出響應(yīng)時(shí)間:≤0.1秒;
????????2)按鍵響應(yīng)時(shí)間:≤0.2秒;
????????3)車位數(shù)量:8個(gè)。
LED顯示界面
????????1)車位顯示界面
????????在車位顯示界面下,通過LCD顯示界面名稱(Data)、停車場內(nèi)目前的停車數(shù)量和空閑車位,CNBR和VNBR代表兩類不同的停車類型。
?
? ? ? ? 上圖所示停車數(shù)量共6輛,CNBR類2輛,VNBR類4輛,空閑車位2個(gè)。
????????2)費(fèi)率設(shè)置界面
????????在費(fèi)率設(shè)置界面下,通過LCD顯示界面名稱(Para)、CNBR類型和VNBR類型停車的費(fèi)率,單位為元/小時(shí),保留小數(shù)點(diǎn)后2位有效數(shù)字。
?
????????上圖所示CNBR類停車費(fèi)率位3.50元/小時(shí),VNBR類型停車費(fèi)率位2.00元/小時(shí)。
????????3)LCD通用顯示要求
????????顯示背景色(BackColor):黑色顯示前景色(TextColor):白色
????????請(qǐng)嚴(yán)格按照?qǐng)D示2、3要求設(shè)計(jì)各個(gè)信息項(xiàng)的名稱(區(qū)分字母大小寫)和行列位置。
按鍵功能
????????1)B1:定義為“界面切換”按鍵,切換LCD顯示“車位顯示界面”和“費(fèi)率設(shè)置界面”。
????????2)B2:定義為“加”按鍵,每次按下B2按鍵,CNBR、VNBR費(fèi)率增加0.5元。
? ? ? ? 3)B3:定義為“減”按鍵,每次按下B3按鍵,CNBR、VNBR費(fèi)率減少0.5元。
????????4)B4:定義為“控制”按鍵,按下后,切換PA7端口輸出狀態(tài)(2KHz,20%占空比的脈沖信號(hào)或持續(xù)低電平),切換要求如下圖所示。
?
????????5)通用按鍵設(shè)計(jì)要求
????????按鍵應(yīng)進(jìn)行有效的防抖處理,避免出現(xiàn)一次按下、多次觸發(fā)等情形。
????????按鍵B2、B3僅在費(fèi)率設(shè)置界面有效。
串口功能
????????1)使用競賽平臺(tái)上的USB轉(zhuǎn)串口完成相關(guān)功能設(shè)計(jì)。
????????2)串口通信波特率設(shè)置為9600bps。
????????3)使用4個(gè)任意ASCII字符組成的字符串標(biāo)識(shí)車輛,作為車輛編號(hào)。
????????4)串口接收車輛出入信息
????????入停車場
????????????????停車類型:車輛編號(hào):進(jìn)入時(shí)間(YYMMDDHHmmSs)舉例:
????????????????????????CNBR:A392:200202120000
????????????????????????表示停車類型CNBR,編號(hào)為A392的車輛,進(jìn)入停車場時(shí)間為2020年2月2日12時(shí)整。
????????出停車場
????????????????停車類型:車輛編號(hào):退出時(shí)間舉例:
????????????????????????VNBR: D583:200202132500
????????????????????????表示停車類型 VNBR,編號(hào)為D583的車輛,退出停車場時(shí)間為2020年2月2日13時(shí)25分。
????????5)串口輸出計(jì)費(fèi)信息
????????停車類型:車輛編號(hào):停車時(shí)長:費(fèi)用舉例:
????????串口接收車輛入停車場信息????????VNBR: D583:200202120000
????????串口接收車輛出停車場信息????????VNBR: D583:200202213205
????????串口輸出計(jì)費(fèi)信息??????????????????????VNBR:D583:10:20.00
????????表示停車類型VNBR,編號(hào)為D583的車輛,停車時(shí)長為10小時(shí),停車費(fèi)用為20.00元。
????????6)說明
????????車輛出入信息通過“資源數(shù)據(jù)包”中提供的串口助手向競賽平臺(tái)發(fā)送字符串,格式需要嚴(yán)格按照示例要求。
? ? ? ? 停車時(shí)長:整數(shù),單位為小時(shí),不足1小時(shí),按1小時(shí)統(tǒng)計(jì)。
? ? ? ? 停車費(fèi)用:以元為單位,按小時(shí)計(jì)費(fèi),保留小數(shù)點(diǎn)后2位有效數(shù)字。
????????系統(tǒng)收到入停車場信息后,不需要回復(fù);接收到出停車場信息后,解析、計(jì)算并通過串口回復(fù)計(jì)費(fèi)信息。
????????當(dāng)接收到的字符串格式不正確或存在邏輯錯(cuò)誤,系統(tǒng)通過串口輸出固定提示信息字符串 Error 。
LED指示燈功能
????????1)若停車場內(nèi)存在空閑車位,指示燈LD1點(diǎn)亮,否則熄滅。
????????2)PA7輸出2KHz,20%占空比脈沖信號(hào)期間,指示燈LD2點(diǎn)亮,否則熄滅。
初始狀態(tài)說明
????????1)上電默認(rèn)PA7處于低電平狀態(tài)。
????????2)上電默認(rèn)處于車位顯示界面。
????????3)上電默認(rèn)參數(shù),CNBR費(fèi)率3.50元/小時(shí),VNBR費(fèi)率2.00元/小時(shí)。
????????4)每次重新上電后,默認(rèn)空閑車位為8個(gè)。
真題講解系列文章重點(diǎn)關(guān)注頂層邏輯代碼編寫,各模塊的代碼編寫大家可點(diǎn)擊藍(lán)橋杯嵌入式專題,里面有各個(gè)模塊的詳細(xì)解析與代碼編寫
?賽題分析
? ? ? ? 拿到賽題,第一件事就是看硬件框圖,因?yàn)榭梢钥闯霰緦觅愵}的重點(diǎn)考點(diǎn)。除了老三樣(LED,按鍵,LCD)以外,就是我們的重點(diǎn)考點(diǎn)了。很顯然,本次賽題的考點(diǎn)是串口通信與脈沖頻率的設(shè)置。
? ? ? ? 然后我們?cè)賮砝斫饩唧w要實(shí)現(xiàn)的功能??吹焦δ芨攀?,可以知道串口通信對(duì)應(yīng)著停車計(jì)費(fèi)系統(tǒng),而脈沖頻率對(duì)應(yīng)著改變PA7的占空比。其他細(xì)節(jié)方面我們通過代碼來進(jìn)一步了解。
代碼實(shí)現(xiàn)
串口模塊
? ? ? ? 最重要的功能就是完整接收串口傳來的出入車庫的車輛信息。然后判斷是接收的信息車牌是否已經(jīng)存在,已經(jīng)存在就代表是出庫 ,不存在就代表入庫,出庫就要進(jìn)行計(jì)費(fèi)計(jì)算,并通過串口將結(jié)果按賽題要求打印出來。期間出入庫是,改變相應(yīng)的變量值,如空閑車位等。
void uart_rx_proc()
{
if(rx_pointer>0)
{
if(rx_pointer==22 && i < 8) //如果接收到的是22個(gè)字符
{
sscanf(rxdata,"%4s:%4s:%12s",car_type,car_data,car_time); //將字符串拆分
int j = 0;
for( j=0;j < 8;j++)
{
if ((strcmp(car_data, Car[j].car_data) == 0) && (strcmp(car_type, Car[j].car_type) == 0)) //如果與之前數(shù)據(jù)的DATA相同,則代表這次是出庫,計(jì)算費(fèi)用,并通過串口發(fā)送
{
char tyear[4],tm[2],td[2],th[2],tf[2],ts[2], tyear1[4],tm1[2],td1[2],th1[2],tf1[2],ts1[2];
int year,m,d,h,f,s,year1,m1,d1,h1,f1,s1;
int time = 0;
double fee;
sscanf(car_time,"%2s%2s%2s%2s%2s%2s",tyear,tm,td,th,tf,ts); //將表示時(shí)間的字符串分割
sscanf(Car[j].car_time,"%2s%2s%2s%2s%2s%2s",tyear1,tm1,td1,th1,tf1,ts1);
year=atoi(tyear); //將字符串轉(zhuǎn)為整形變量
m = atoi(tm);
d = atoi(td);
h = atoi(th);
f = atoi(tf);
s = atoi(ts);
year1=atoi(tyear1);
m1 = atoi(tm1);
d1 = atoi(td1);
h1 = atoi(th1);
f1 = atoi(tf1);
s1 = atoi(ts1);
if(year1 == year) //計(jì)算時(shí)間
{
if(m == m1)
{
time = ceil( ( ((d*24+h)*60+f)*60+s - ((d1*24+h1)*60+f1)*60+s1 ) / 3600); //ceil向下取整,計(jì)算出停車多少小時(shí)
}
}
if(strcmp(car_type,"CNBR") == 0) //判斷車型
{
fee = time * CNBR_fee;
CNBR_sum--;
}
else
{
fee = time * VNBR_fee;
VNBR_sum--;
}
char temp[20];
sprintf(temp,"%s:%s:%d:%.2f",car_type,car_data,time,fee);
HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50); //串口發(fā)送計(jì)費(fèi)信息
if(i != j) //如果匹配的不是已入庫的最后一個(gè),就將最后一個(gè)入庫的信息復(fù)制到這個(gè)位置上
{
sprintf(Car[j].car_type,"%s",Car[i].car_type); //將最后入庫的信息復(fù)制到當(dāng)前出庫的位置
sprintf(Car[j].car_data,"%s",Car[i].car_data);
sprintf(Car[j].car_time,"%s",Car[i].car_time);
}
i--; //i--后,下次有新入庫的車輛就直接覆蓋這次最后入庫的信息
break;
}
else
{
if(j >= 7) //說明未匹配成功
{
sscanf(rxdata,"%4s:%4s:%12s",Car[i].car_type,Car[i].car_data,Car[i].car_time); //將字符串拆分
char temp[20];
sprintf(temp,"%s:%s:%s",Car[i].car_type,Car[i].car_data,Car[i].car_time);
HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50); //串口發(fā)送入庫信息
i++;
if(strcmp(Car[i].car_type,"VNBR") == 0)
{
VNBR_sum++;
}
else
{
CNBR_sum++;
}
}
}
}
}
else
{
char temp[20];
sprintf(temp,"Error");
HAL_UART_Transmit(&huart1,(uint8_t *)temp,strlen(temp),50); //串口發(fā)送一個(gè)錯(cuò)誤提示
}
rx_pointer=0;
memset(rxdata,0,30);
LDLE_sum = 8-i;
if(i == 8)
{
TurnOff_LED(1);
}
else
{
TurnOn_LED(1);
}
}
}
????????在串口調(diào)試工具中的實(shí)現(xiàn)效果 (第一次黑色信息為串口發(fā)送給開發(fā)板的讓車庫信息,第二次為出車庫信息)
按鍵模塊
? ? ? ? 按鍵模塊就是簡單的界面切換,費(fèi)率的加減。要注意的是第四個(gè)按鍵被設(shè)置為改變PA7頻率的按鍵。
void key_proc()
{
if(key[0].key_flag == 1)
{
view++;
if(view==2) view=0;
LCD_Clear(Black); //清屏
key[0].key_flag = 0;
}
if(view==1 && key[1].key_flag == 1)
{
CNBR_fee += 0.5;
VNBR_fee += 0.5;
key[1].key_flag = 0;
LCD_Clear(Black);
}
else if(view==1 && key[2].key_flag == 1)
{
CNBR_fee -= 0.5;
VNBR_fee -= 0.5;
key[2].key_flag = 0;
LCD_Clear(Black);
}
if(key[3].key_flag == 1)
{
if(pa7_duty == 0)
{
pa7_duty = 20;
TurnOn_LED(2);
}
else
{
pa7_duty = 0;
TurnOff_LED(2);
}
__HAL_TIM_SetCompare(&htim17,TIM_CHANNEL_1,pa7_duty); //設(shè)置占空比pa7_duty
key[2].key_flag = 0;
}
}
LCD模塊文章來源:http://www.zghlxwxcb.cn/news/detail-414096.html
? ? ? ? LCD就是按賽題要求顯示相應(yīng)內(nèi)容即可。注意:從第11屆開始,已經(jīng)要求LCD顯示必須完全按照賽題上的格式來顯示,每一行每一列顯示什么一定要注意。文章來源地址http://www.zghlxwxcb.cn/news/detail-414096.html
void disp_proc()
{
if(view==0)
{
char text[30];
sprintf(text," Data ");
LCD_DisplayStringLine(Line1, (uint8_t *)text);
sprintf(text," CNBR:%d",CNBR_sum);
LCD_DisplayStringLine(Line3, (uint8_t *)text);
sprintf(text," VNBR:%d",VNBR_sum);
LCD_DisplayStringLine(Line5, (uint8_t *)text);
sprintf(text," IDLE:%d",LDLE_sum);
LCD_DisplayStringLine(Line7, (uint8_t *)text);
}
else if(view==1)
{
char text[30];
sprintf(text," Para ");
LCD_DisplayStringLine(Line2, (uint8_t *)text);
sprintf(text," CNBR:%.2f",CNBR_fee);
LCD_DisplayStringLine(Line4, (uint8_t *)text);
sprintf(text," VNBR:%.2f",VNBR_fee);
LCD_DisplayStringLine(Line6, (uint8_t *)text);
}
}
到了這里,關(guān)于【藍(lán)橋杯嵌入式】藍(lán)橋杯第十二屆省賽程序真題,真題分析與代碼講解的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!