前言
為了減少篇幅,各模塊的初始化均在模塊配置中,可以隨時去翻看博客,還有function里面的函數,將不再羅列出來,只是截圖展示。
一、題目
基本要求
1.1 使用 CT117E 嵌入式競賽板,完成試題功能的程序設計與調試;
1.2 設計與調試過程中,可參考組委會提供的“資源數據包”;
1.3 Keil 工程文件以準考證號命名,完成設計后,提交完整、可編譯的 Keil工程文件到服務器。
硬件框圖
通過按鍵設置定時時間,啟動定時器后,開始倒計時;計時過程中,可以暫停、取消定時器。在定時時間內,按要求輸出 PWM 信號和控制 LED 指示燈。系統框圖如圖 1 所示:
功能描述
1、LCD 顯示
LCD 顯示存儲位置、定時時間和當前狀態。系統預留 5 個存儲位置用于存儲常用的定時時間。當定時器停止時,當前狀態為 Standby;當系統正在設置時間時,當前狀態為 Setting;當定時器運行時,當前狀態為 Running,定時器暫停時,當前狀態為 Pause。
2、按鍵功能
系統使用 4 個按鍵,B1、B2、B3 和 B4。
按鍵 B1 為存儲位置切換鍵。每按一次,存儲位置依次以 1、2、3、4、5循環切換,切換后定時時間設定為當前位置存儲的時間。
按鍵 B2 為時間位置(時、分、秒)切換鍵和存儲鍵。短按 B2 鍵進入時間設置狀態。每次短按 B2 鍵,設置位置以時、分、秒循環切換,并突出顯示(高亮)當前位置;設置完后,長按 B2 鍵(超過 0.8 秒)把設置的時間存儲到當前的存儲位置,并推出設置狀態。如果是臨時設置定時時間,則不需存儲,直接按定時器啟動按鍵。
按鍵 B3 為時、分、秒(按鍵 B2 確定當前位置)數字增加鍵。每短按B3 一次,數字遞增一次;按住 B3 超過 0.8 秒,則數字快速遞增,直到松開B3 按鍵。數字遞增時,超出范圍則從頭循環。
按鍵 B4 為定時器啟動鍵。短按 B4,定時器啟動,開始運行;運行期間短按 B4,暫停定時器,再短按 B4,恢復定時器運行;長按 B4(超過 0.8 秒),則取消定時器運行,回到 Standby 狀態。
3、PWM 輸出和 LED 顯示
定時器運行時,PA6 口輸出 PWM 信號,同時 LED 燈(LD1)以 0.5 秒的頻率閃爍。PWM 信號頻率為 1KHz,占空比為 80%。
定時器停止或暫停時,停止輸入 PWM 信號,LED 燈滅。
4、定時時間存儲
設定好的定時時間存儲在 EEPROM 中。
掉電重啟后,顯示存儲位置 1 的定時時間。
二、模塊初始化以及功能分析
1.模塊的初始化
需要用的模塊:LCD、IIC、四個按鍵、LED、TIM3(PA
6)
2.模塊功能分析
LCD:顯示-----》Display();
IIC:讀取和存儲信息到EEPROM-----》Write_Time();Read_Time();
按鍵:對參數進行調整-----》KEY_Handle();KEY_Scan();
LED:提示作用-----》LED();
TIM3:初始化
(本次賽題主要是考代碼邏輯,特別是按鍵處理的方法。在模塊方面用的比較少)
三、函數實現
1.void Display(void);
顯示功能如下:
Location表示設置時間的地址,Location為4時,表示不設置時間。(單獨點亮一個字符,方法如下,若有其他方法,歡迎評論)
mode表示定時器的四種狀態:
0:Standby
1:Setting
2:Running
3:Pause
void Dispaly(void)
{
sprintf((char *)str," N0 %d",signal + 1);
LCD_DisplayStringLine(Line1, str);
if(Location == 4)//設置部分
{
LCD_ClearLine(Line4);
LCD_SetTextColor(Black);
sprintf((char *)str," %02d: %02d: %02d",Now_Time[0],Now_Time[1],Now_Time[2]);
LCD_DisplayStringLine(Line4, str);
}
else if(Location == 0)
{
LCD_SetTextColor(Black);
sprintf((char *)str," : %.2d: %.2d",Now_Time[1],Now_Time[2]);
LCD_DisplayStringLine(Line4, str);
LCD_SetTextColor(Red);
LCD_DisplayChar(Line4,210, Now_Time[0]/10 + 0x30);
LCD_DisplayChar(Line4,195, Now_Time[0]%10 + 0x30);
LCD_SetTextColor(Black);
}
else if(Location == 1)
{
LCD_SetTextColor(Black);
sprintf((char *)str," %.2d: : %.2d",Now_Time[0],Now_Time[2]);
LCD_DisplayStringLine(Line4, str);
LCD_SetTextColor(Red);
LCD_DisplayChar(Line4,150, Now_Time[1]/10 + 0x30);
LCD_DisplayChar(Line4,135, Now_Time[1]%10 + 0x30);
LCD_SetTextColor(Black);
}
else if(Location == 2)
{
LCD_SetTextColor(Black);
sprintf((char *)str," %.2d: %.2d: ",Now_Time[0],Now_Time[1]);
LCD_DisplayStringLine(Line4, str);
LCD_SetTextColor(Red);
LCD_DisplayChar(Line4,60, Now_Time[2]/10 + 0x30);
LCD_DisplayChar(Line4,45, Now_Time[2]%10 + 0x30);
LCD_SetTextColor(Black);
}
if(mode == 0)
LCD_DisplayStringLine(Line7, " Standby ");
else if(mode == 1)
LCD_DisplayStringLine(Line7, " Setting ");
else if(mode == 2)
LCD_DisplayStringLine(Line7, " Running ");
else if(mode == 3)
LCD_DisplayStringLine(Line7, " Pause ");
}
2.void Read_Time(void);void Write_Time(void);
void Write_Time(void)
{
IIC_Write(0x00,Hour[0]); HAL_Delay(10);
IIC_Write(0x01,Minute[0]);HAL_Delay(10);
IIC_Write(0x02,Second[0]);HAL_Delay(10);
IIC_Write(0x10,Hour[1]); HAL_Delay(10);
IIC_Write(0x11,Minute[1]);HAL_Delay(10);
IIC_Write(0x12,Second[1]);HAL_Delay(10);
IIC_Write(0x20,Hour[2]); HAL_Delay(10);
IIC_Write(0x21,Minute[2]);HAL_Delay(10);
IIC_Write(0x22,Second[2]);HAL_Delay(10);
IIC_Write(0x30,Hour[3]); HAL_Delay(10);
IIC_Write(0x31,Minute[3]);HAL_Delay(10);
IIC_Write(0x32,Second[3]);HAL_Delay(10);
IIC_Write(0x40,Hour[4]); HAL_Delay(10);
IIC_Write(0x41,Minute[4]);HAL_Delay(10);
IIC_Write(0x42,Second[4]);HAL_Delay(10);
}
void Read_Time(void)
{
Hour[0] = IIC_Read(0x00);HAL_Delay(10);
Minute[0] = IIC_Read(0x01);HAL_Delay(10);
Second[0] = IIC_Read(0x02);HAL_Delay(10);
Hour[1] = IIC_Read(0x10);HAL_Delay(10);
Minute[1] = IIC_Read(0x11);HAL_Delay(10);
Second[1] = IIC_Read(0x12);HAL_Delay(10);
Hour[2] = IIC_Read(0x20);HAL_Delay(10);
Minute[2] = IIC_Read(0x21);HAL_Delay(10);
Second[2] = IIC_Read(0x22);HAL_Delay(10);
Hour[3] = IIC_Read(0x30);HAL_Delay(10);
Minute[3] = IIC_Read(0x31);HAL_Delay(10);
Second[3] = IIC_Read(0x32);HAL_Delay(10);
Hour[4] = IIC_Read(0x40);HAL_Delay(10);
Minute[4] = IIC_Read(0x41);HAL_Delay(10);
Second[4] = IIC_Read(0x42);HAL_Delay(10);
}
3.uint8_t KEY_Scan(uint8_t mode);
由于本實驗牽扯到長按(大于0.8s)和短按,并且長按是需要實時操作對應變量,所以長按的操作需要檢測到馬上執行。不能等按完了才執行。所以這里用0.2s的延時,次數加到4以后就進行長按操作。
變量聲明:
Now_Time是當前顯示的時間。
Time是存儲的時間。
考慮到有暫時設定時間且不進行存儲的情況,后面也引入了Aim_Time,定時結束的目標時間。
uint8_t KEY_Scan(uint8_t mode)
{
static uint8_t flag=1;
uint8_t count = 0;
if(mode) flag = 1;
if(flag &&(KEY_B1 == 0 || KEY_B2 == 0 || KEY_B3 == 0 || KEY_B4== 0 ))
{
HAL_Delay(10);
flag = 0;
if (KEY_B1 == 0) return B1_Press;
else if (KEY_B2 == 0)
{
while(KEY_B2 == 0){
HAL_Delay(200);
count++;//每0.2s加一
}
if(count <= 4) return B2_Press;
else return B2_Press_Long;
}
else if (KEY_B3 == 0)
{
while(KEY_B3 == 0){
Dispaly();
HAL_Delay(200);
count++;//每0.2s加一
if(count > 4)
{
Now_Time[Location] = Now_Time[Location]+1;
Now_Time[0] = Now_Time[0]%24;
Now_Time[1] = Now_Time[1]%60;
Now_Time[2] = Now_Time[2]%60;
Hour[signal]= Now_Time[0];
Minute[signal] = Now_Time[1];
Second[signal] = Now_Time[2];
}
}
if(count <= 4) return B3_Press;
}
else if (KEY_B4 == 0)
{
while(KEY_B4 == 0){
HAL_Delay(200);
count++;//每0.2s加一
}
if(count <= 4) return B4_Press;
else return B4_Press_Long;
}
}else if(KEY_B1 == KEY_B2 == KEY_B3 == KEY_B4 == 1) flag = 1;
return 0;
}
4.void KEY_Handle(uint8_t key);
按鍵 B1 為存儲位置切換鍵。每按一次,存儲位置依次以 1、2、3、4、5循環切換,切換后定時時間設定為當前位置存儲的時間。(signal 變化)
按鍵 B2 為時間位置(時、分、秒)切換鍵和存儲鍵。短按 B2 鍵進入時間設置狀態。每次短按 B2 鍵,設置位置以時、分、秒循環切換,并突出顯示(高亮)當前位置;設置完后,長按 B2 鍵(超過 0.8 秒)把設置的時間存儲到當前的存儲位置,并推出設置狀態。如果是臨時設置定時時間,則不需存儲,直接按定時器啟動按鍵。(Location變化)
按鍵 B3 為時、分、秒(按鍵 B2 確定當前位置)數字增加鍵。每短按B3 一次,數字遞增一次;按住 B3 超過 0.8 秒,則數字快速遞增,直到松開B3 按鍵。數字遞增時,超出范圍則從頭循環。(Now_Time變化)
按鍵 B4 為定時器啟動鍵。短按 B4,定時器啟動,開始運行;運行期間短按 B4,暫停定時器,再短按 B4,恢復定時器運行;長按 B4(超過 0.8 秒),則取消定時器運行,回到 Standby 狀態。(mode 變化)
void KEY_Handle(uint8_t Key)
{
if(Key == B1_Press)
{
Location = 4;
signal++;
signal = signal % 5;
Now_Time[0] = Hour[signal];
Now_Time[1] = Minute[signal];
Now_Time[2] = Second[signal];
}
else if(Key == B2_Press)
{
mode = 1;
if(Location == 4)
Location = 0;
else
{
Location++;
Location = Location % 3;
}
}
else if(Key == B2_Press_Long)
{
Location = 4;
mode = 0;
Hour[signal]= Now_Time[0];Minute[signal] = Now_Time[1];Second[signal] = Now_Time[2];
Write_Time();
}
else if(Key == B3_Press)
{
Now_Time[Location] = Now_Time[Location]+1;
Now_Time[0] = Now_Time[0]%24;
Now_Time[1] = Now_Time[1]%60;
Now_Time[2] = Now_Time[2]%60;
}
else if(Key == B4_Press)
{
if(mode == 1)
{
mode = 2;
HAL_TIM_Base_Start(&htim3);
Location = 4;
Aim_Time[signal] = Now_Time[0];
Aim_Time[signal] = Now_Time[1];
Aim_Time[signal] = Now_Time[2];
Now_Time[0] = Now_Time[1] = Now_Time[2] = 0;
}
else if(mode == 2) mode = 3;//暫停
else
{
Aim_Time[signal] = Hour[signal];
Aim_Time[signal] = Minute[signal];
Aim_Time[signal] = Second[signal];
mode = 2;
HAL_TIM_Base_Start(&htim3);
}
}
else if(Key == B4_Press_Long)
{
mode = 0;
}
}
5.void LED(void);void LED_OFF(void);
void LED(void);每進入一次LD1變換一次(TOGGLE函數似乎用不了,本人也不清楚)
void LED_OFF(void);關閉所有LED
void LED(void)
{
static uint16_t i;
i++;
if(i % 2)HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET);
else
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_RESET);
}
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15
|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
void LED_OFF(void)
{
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8
|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
6.void ADD(void);
時間加1函數
定時到目標時間的結束標志mode = 0;
void ADD(void)
{
Now_Time[2]++;
if(Now_Time[2] >= 60)
{
Now_Time[2] = 0;
Now_Time[1]++;
}
if(Now_Time[1] >= 60)
{
Now_Time[1] = 0;
Now_Time[0]++;
}
Now_Time[0] = Now_Time[0] % 24;
if(Now_Time[0] == Aim_Time[0] && Now_Time[1] ==Aim_Time[1] && Now_Time[2] == Aim_Time[2]) mode = 0;
}
7.int main(void);
初始化;
LCD_Init();
LCD_Clear(White);
LCD_SetTextColor(Black);
I2CInit();
IIC_Write(0x00,0);HAL_Delay(10);
IIC_Write(0x01,0);HAL_Delay(10);
IIC_Write(0x02,0);HAL_Delay(10);
IIC_Write(0x10,0);HAL_Delay(10);
IIC_Write(0x11,1);HAL_Delay(10);
IIC_Write(0x12,0);HAL_Delay(10);
IIC_Write(0x20,5);HAL_Delay(10);
IIC_Write(0x21,20);HAL_Delay(10);
IIC_Write(0x22,00);HAL_Delay(10);
IIC_Write(0x30,13);HAL_Delay(10);
IIC_Write(0x31,14);HAL_Delay(10);
IIC_Write(0x32,52);HAL_Delay(10);
IIC_Write(0x40,23);HAL_Delay(10);
IIC_Write(0x41,59);HAL_Delay(10);
IIC_Write(0x42,59);HAL_Delay(10);
LED_OFF();
HAL_Delay(100);
Read_Time();
HAL_Delay(1000);
while(1);
Dispaly();
key = KEY_Scan(0);
KEY_Handle(key);
if(mode == 2 && num == 1)
{
LED();
}
else if(mode != 2)
{
HAL_TIM_Base_Stop(&htim3);
LED_OFF();
}
if(nCount == 1 && mode == 2)
{
nCount = 0;
ADD();
}
8.void SysTick_Handler(void);
上面的num和nCount在哪變了,在哪計時呢?
就在滴答定時器里面咯。
大家打開stm32g4xx_it.c
if(mode == 2)
{
i++;j++;
}
if(i >= 1000)
{
nCount = 1;
i = 0;
}
if(j >= 500)
{
num = 1;
j = 0;
}
9.定時器輸出PWM(Cubemx);
PWM未測試,有問題歡迎評論。
上一篇:STM32H7外設配置速查【QSPI部分】
下一篇:STM32F4——GPIO基本應用及復用
推薦閱讀
史海拾趣
在21世紀初,由一群資深的留學歸國科學家組成的團隊在深圳創立了微芯生物。他們專注于創新藥物研發,特別是在小分子藥物領域。初創期,公司面臨技術難題和資金壓力,但他們憑借對技術的執著和深厚的專業背景,成功研發出多款具有突破性的新藥候選物,為公司的發展奠定了堅實的基礎。
為了進一步提升公司的競爭力和市場份額,Carlisle Interconnect Components公司積極尋求與產業鏈上下游企業的戰略合作。通過與原材料供應商、設備制造商以及終端客戶的緊密合作,公司實現了產業鏈的整合和優化。這種合作模式不僅降低了公司的生產成本和風險,更提高了產品的質量和交付速度,為公司贏得了更多的競爭優勢。
在Harry Hoffman的領導下,Hoffman Engineering不斷擴展其產品線。從最初的壓力機安全保護裝置,公司逐漸研發出蒲公英掘具、碟靶投擲器、廚房用電動攪拌器等一系列創新產品。這些產品不僅豐富了Hoffman Engineering的市場布局,也展現了公司在不同領域的技術實力。特別是Hoffman的機柜系列產品,如接線箱和電源插座,逐漸成為市場上的熱門產品,為公司帶來了穩定的收入來源。
作為一家領先的電子公司,因美納深知自己的社會責任。公司積極參與各種公益活動,推動基因測序技術在醫療、環保等領域的應用。同時,因美納還注重可持續發展,通過采用環保材料、優化生產流程等方式降低對環境的影響。這種積極履行社會責任和推動可持續發展的做法贏得了社會各界的廣泛贊譽。
近年來,AAC公司一直致力于技術創新和產品研發。在聲學、光學、觸感、傳感器及半導體等領域,AAC積累了近三十年的技術經驗。這些技術積累使得AAC能夠不斷推出具有創新性和競爭力的新產品。例如,AAC在某次創新峰會上發布了超寬頻音質的Opera高低音分頻方案、旗艦級體驗大眾化的聲學觸覺一體化Combo方案以及安卓觸感“天花板級”的仿生振感馬達等三大技術新品。這些新品的發布不僅彰顯了AAC在電聲元器件領域的技術實力,也為智能手機等消費電子行業注入了新的活力。
這五個故事只是AAC公司發展歷程中的一部分,但它們足以展現AAC在電子行業中的不斷進取和創新精神。從一個合資企業起步,到如今成為全球著名的電聲元器件制造商之一,AAC憑借敏銳的市場洞察、堅定的發展決心以及持續的技術創新,在電子行業書寫了自己的傳奇篇章。
請注意,以上內容僅是基于參考文章的事實性描述,并未涉及對AAC公司的任何評價或判斷。同時,由于我無法獲取AAC公司的實時信息,因此以上內容可能與AAC公司的最新發展情況有所出入。如需了解更多關于AAC公司的最新信息,建議查閱相關新聞或訪問AAC公司官方網站。
隨著電子行業的快速發展,Calex Mfg. Co., Inc.深知技術創新的重要性。公司投入大量研發資源,成功開發出一系列具有領先技術的電子產品。這些產品不僅性能卓越,而且具有高性價比,迅速贏得了市場的認可。公司憑借這些技術突破,逐漸在電子行業中占據了一席之地。
TPMS(Tire Pressure Monitoring System,汽車輪胎壓力監測系統)主要用于汽車行駛過程中實時監測輪胎氣壓,并對輪胎低氣壓或者漏氣導致氣壓不足進行報警,以保障行車安全。 TPMS分為兩種類型,一種是間接式TPMS(Wheel-Speed Based TPMS, ...… 查看全部問答∨ |
|
硬件:bank6接2片64M SDRAM,BA0接A25,BA1接26 Bootloader:ok2440提供的 今天焊接了器件之后在ADS下用AXD調試 b ResetHandler ResetHandler ldr r0,=W ...… 查看全部問答∨ |
RS422的幾個引腳分別做什么用的,R+ R-什么區別,如果連接兩個RS422,引腳怎么對接?R+連T+,R-連R+嗎?RS232是全雙工還是半雙工? 呵呵,問題挺多的,內行人士多多指教,回答多多益善啊!!… 查看全部問答∨ |
本人想在wince系統下開發視頻軟件。目前porting 完成ffmpeg. 發現ffmpeg中有armv4,armv5,armv6的有關idct部分的代碼, armv4,armv5部分通過config已經編譯通過,但是發現好像沒有地方使用,不知道這部分的代碼是否可以使用在ffmpeg ...… 查看全部問答∨ |
|
如題,我想在Window平臺創建sqlce數據庫,然后把sql2000的數據導出到這個sqlce數據庫中,如何實現?最好有VC++6的代碼。… 查看全部問答∨ |
|
請教版主一個開關總中斷的問題; 我現在在發送串口數據的時候要關,開總中斷,時間要求比較嚴,我看你以前的貼子 ///////////////////////////////////////////////////////////////////////////////////// 香水城發表于 2010-1-13 11:51 ...… 查看全部問答∨ |
【DSP應用系統設計 】 (趙勇,甘泉 著) 【TMS320C54XX DSP實用技術】第2版 (汪安民 陳明欣 朱明 著) 【TMS320C54X DSP 結構、原理及應用】第2版 (戴明楨 周建江 著) 各位大哥誰有這三本書的電子檔,萬分感謝了 ...… 查看全部問答∨ |