Lab3 : 自行車碼表 - 點(diǎn)燈比實(shí)驗(yàn)難

多圖殺貓。實(shí)驗(yàn)環(huán)境為Windows颜阐。

咳咳跪解,本次實(shí)驗(yàn)感覺環(huán)境好難配啊,實(shí)驗(yàn)倒是感覺起來容易一些(果然有攻略就是舒服)楷兽。

實(shí)驗(yàn)準(zhǔn)備 - 點(diǎn)燈

1. STM32CubeMX

接下來把文末下載區(qū)的幾個(gè)全部先下載下來備用地熄。

首先安裝主程序STM32CubeMX,就一路下一步下一步下一步就好了芯杀,看得懂的比如說安裝目錄之類的改一下就好了端考,不需要防備360安全套餐、百度全家桶等揭厚。

打開程序之后界面長這樣却特。

STM32CubeMX

萌新上來什么都不懂,跟著教程直接新建工程筛圆,選擇了核心板的型號STM32F103C8之后直接點(diǎn)OK裂明。

new project

點(diǎn)擊Project選項(xiàng)卡中的setting,進(jìn)入到項(xiàng)目設(shè)置太援。填寫完項(xiàng)目名稱闽晦、位置以及工具鏈。在圖中提岔,我選的是MDK-ARM V5仙蛉,下載列表中有相關(guān)工具下載(Keil)。

Project Settings

全部設(shè)置好之后唧垦,點(diǎn)擊下方OK按鈕捅儒。說時(shí)遲那時(shí)快,只聽砰的一聲振亮,一個(gè)討厭的警示框跳出來了巧还。告訴我們,有個(gè)依賴沒有滿足坊秸。

找不到依賴啊找不到

此時(shí)可以直接點(diǎn)擊Yes開啟自動(dòng)下載模式麸祷,全自動(dòng)安裝,你值得擁有褒搔!

下載中 ...

但是由于各種原因斷在70M這個(gè)位置兩次之后我心灰意冷選擇放棄阶牍,各種查找資料之后發(fā)現(xiàn)還可以進(jìn)行本地安裝喷面。

首先是從Help選型卡中的Install New Libraries進(jìn)入庫管理界面。

進(jìn)入Libraries Manager

此時(shí)走孽,左下角有一個(gè)** From Local ... **按鈕惧辈,將下載的V1.3.0包以及V1.3.1補(bǔ)丁順序打入即可。安裝完畢后可以看到安裝的是當(dāng)前最新版本磕瓷。

Libraries Manager

接下來為了點(diǎn)亮小燈盒齿,需要找一個(gè)引腳輸出高電平形成電流。在此困食,我選擇將PA9接口置為GPIO_Output模式边翁。多說一句,實(shí)際上這個(gè)地方的配置不是必須的硕盹,因?yàn)檫@里的配置最終也是由MX轉(zhuǎn)譯成為C的代碼符匾,而在Keil中才是真正的編譯,即可以在代碼中直接編寫相應(yīng)的流程瘩例。不過啊胶,話說回來,能自動(dòng)干的東西為啥要碼代碼仰剿。

引腳設(shè)置

而后创淡,點(diǎn)擊代碼生成按鈕痴晦。

生成按鈕

生成結(jié)束后后會(huì)在項(xiàng)目的文件夾下生成一個(gè)由設(shè)置所決定的工程文件夾南吮。而Open Project目前點(diǎn)了還沒有作用,因?yàn)檫€沒有裝相應(yīng)的軟件誊酌。

Code Generation

至此部凑,STM32CubeMX的流程就結(jié)束了。

2. Keil

STM32CubeMX生成出了整個(gè)工程的目錄碧浊,但是需要一個(gè)軟件將其打開涂邀。我選擇使用Keil v5(其實(shí)是先選的v5,上面的Project Setting中有設(shè)置)箱锐。

Keil的安裝就沒有上面那個(gè)這么麻煩比勉,直接下一步下一步下一步,注冊碼也有注冊機(jī)直接可以搞定驹止。過程一如參考資料里的安裝教程浩聋。

話接上集,直接點(diǎn)擊Open Project按鈕臊恋,打開項(xiàng)目工程文件衣洁。中間還會(huì)需要安裝一個(gè)依賴包,繼續(xù)同意即可抖仅。

可以從圖中看到坊夫,STM32CubeMX已經(jīng)幫我們生成好了一系列的基礎(chǔ)文件砖第,從中進(jìn)行修改以滿足我們的要求即可。

項(xiàng)目結(jié)構(gòu)

由于我們在MX中已經(jīng)有進(jìn)行過設(shè)置环凿,修改了PA9為輸出引腳梧兼,在代碼中就得到了體現(xiàn)。下方即為生成的GPIO初始化代碼智听。

自動(dòng)生成的GPIO初始化代碼

main函數(shù)中調(diào)用了GPIO初始化函數(shù)之后袱院,PA9就開始持續(xù)輸出高電平。而為了讓小燈閃爍瞭稼,自然不能一直高電平下去忽洛,而是需要輸出一個(gè)矩形波。

閃爍代碼

至此环肘,代碼已經(jīng)全部寫完欲虚。而在下載之前,需要在Flash -> Configure Flash Tools -> Utilities中悔雹,將Use Debug Driver的勾去掉复哆,轉(zhuǎn)而使用ST-LINK V/2。

配置圖

按F7進(jìn)行模塊編譯腌零,按F8下載到板子吧梯找!

值得一提的是,下載之后益涧,并不會(huì)立刻有反應(yīng)锈锤。而是需要斷電重啟或者使用板子上帶的RST按鈕進(jìn)行重置之后程序才會(huì)正式開始運(yùn)行。

注意注意闲询,我圖中是將小燈直接連入GND以及VCC久免,但是有的小燈比較脆弱,這么做會(huì)直接燒掉扭弧。所以穩(wěn)妥的做法應(yīng)該在連接電路中再加一個(gè)電阻阎姥。s

小燈直接接入GND及3.3V
小燈閃爍

實(shí)驗(yàn)步驟

0. 連接圖

按照Lab3攻略上說的連好圖,先假裝自己連對了確實(shí)連對了鸽捻。

其中呼巴,ST-LINK接四根線3.3V、GND御蒲、SWDIO衣赶、SWCLK分別對應(yīng)STM32板子上的3.3V、GND删咱、DIO屑埋、DCLK。此為燒錄用的線路痰滋。而PA9摘能、PA10為串口通信所用的線路续崖。所以圖中使用了兩個(gè)USB口。

面包板上線的連接方式為從引腳出來之后經(jīng)過按鈕到GND团搞。

連接圖

1. UART串口輸出

首先進(jìn)入STM32CubeMX严望。按照實(shí)驗(yàn)中的要求,在右側(cè)芯片設(shè)置中逻恐,將PA12像吻、PA11定為輸入(接按鈕),PA10复隆、PA9分別定為TX拨匆、RX(接電腦串口)。

引腳配置

同時(shí)挽拂,在左側(cè)的配置中惭每,將USART1的模式定為Half-Duplex。這步所對應(yīng)生成的代碼與實(shí)驗(yàn)攻略中的代碼略有差別亏栈。但是在不指定模式的情況下台腥,PA9以及PA10會(huì)被認(rèn)為是GPIO_Output而與PA11一起進(jìn)行初始化,而不是TX绒北、RX口黎侈。所以在此選擇一個(gè)模式。

USART1半雙工模式

配置完畢闷游,接下來是代碼生成峻汉,點(diǎn)擊按鈕靜靜等待即可。

少女祈禱中储藐。俱济。嘶是。

代碼生成完之后钙勃,基本的函數(shù)已經(jīng)都有了。但是還需要自己手動(dòng)填寫一些代碼聂喇,如UART0_Init()等辖源。而stm32f1xx_hal_msp.c中所需填寫的函數(shù)與Half-Duplex模式一致,所以不需要進(jìn)行大幅度改動(dòng)希太。只需要將攻略的幾行代碼填入即可克饶。

void UART0_Init(UART_HandleTypeDef* UartHandle){
    UartHandle->Instance = USART1;
    UartHandle->Init.BaudRate = 9600;
    UartHandle->Init.WordLength = UART_WORDLENGTH_8B;
    UartHandle->Init.StopBits = UART_STOPBITS_1;
    UartHandle->Init.Parity = UART_PARITY_NONE;
    UartHandle->Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UartHandle->Init.Mode = UART_MODE_TX_RX;
    
    HAL_UART_Init(UartHandle);
}

int main(void) {
...
    UART_HandleTypeDef UartHandle;
    UART0_Init(&UartHandle);

    while (1) {
        HAL_UART_Transmit(&UartHandle, (uint8_t*)"press\r\n", 7, 500);
        HAL_Delay(100); 
    }
}

HAL_UART_Transmit有4個(gè)參數(shù),第一個(gè)參數(shù)是串口的句柄誊辉,第二個(gè)參數(shù)是一個(gè)二進(jìn)制數(shù)組(char*)矾湃,第三個(gè)參數(shù)是要發(fā)送的數(shù)據(jù)長度,第四個(gè)是發(fā)送超時(shí)的判定時(shí)間堕澄。

運(yùn)行結(jié)果

2. 接入開關(guān)

在0中已經(jīng)將線連好邀跃。

3. 檢測按鈕被按下

由于按鈕接地霉咨,所以,當(dāng)按鈕被按下時(shí)拍屑,PA11應(yīng)該可以檢測到一個(gè)低電平的輸入途戒。編寫程序的時(shí)候,可以根據(jù)這一點(diǎn)僵驰,讀取PA11的引腳值喷斋,并據(jù)此判斷。

但是蒜茴,在實(shí)驗(yàn)過程中結(jié)果并不理想星爪。測試結(jié)果如下。

PA11引腳讀取

注意到按鈕的狀態(tài)是不斷變化的粉私,而我并沒有去接觸按鍵移必。這種情況可能是由于電路本身不精密所導(dǎo)致的。~~~~(Update:做了第4項(xiàng)實(shí)驗(yàn)之后毡鉴,發(fā)現(xiàn)同樣的接法PA12沒問題崔泵,看來主要是因?yàn)榘粹o的問題才導(dǎo)致了抖動(dòng))(Update: 突然覺得可能是面包板的問題)

硬件難改,但實(shí)驗(yàn)也不能這么停止猪瞬。仿照計(jì)算機(jī)組成實(shí)驗(yàn)的思想憎瘸,嘗試著使用按鍵防抖動(dòng)的方法檢測按鍵是否被按下。具體方法是檢測按鍵被穩(wěn)定按下某幾個(gè)周期之后陈瘦,才表示真正檢測到了按鍵事件幌甘。

但是實(shí)際測試結(jié)果并不理想,由圖可以看出痊项。我依然沒有按任何的按鍵锅风,而串口卻一直有輸出。

按鍵防抖動(dòng)

思考了一下鞍泉,發(fā)現(xiàn)可能是由于兩次檢測時(shí)間間隔太短皱埠,導(dǎo)致跳變的引腳值被記錄多次。此時(shí)咖驮,使用延時(shí)檢測即可边器,即兩次檢測之間間隔拉大。

下方代碼為最終版本托修,即加了anti_jitter即HAL_Delay的結(jié)果忘巧。

#define MAX_BITCOUNT 0xff
#define CHECK_DELAY 10

void anti_jitter(int *bitcount, int state){
    *bitcount <<= 1;
    *bitcount &= MAX_BITCOUNT;
    *bitcount += state & 1;
}

int main(void)
{
    int total, bitcount;
    char str[64];
    int send = 0;
// something for initialization.
    total = 0; bitcount = MAX_BITCOUNT ;
    while (1) {
        int cnt;
        GPIO_PinState state;
        state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
        HAL_Delay(CHECK_DELAY);
        anti_jitter(&bitcount, state);
        if (bitcount == 0){
            if (!send){
                send = 1;
                total++;
                cnt = sprintf(str, "Press 11 %d times\r\n", total);
                HAL_UART_Transmit(&UartHandle, (uint8_t*)str, cnt, 500);
            }
        }else{
            send = 0;
        }
    }
}

最終代碼能夠做到無誤檢測,同時(shí)在按鍵被按下之后睦刃,響應(yīng)時(shí)間較短砚嘴。

PA11按鈕事件

4. PA12中斷響應(yīng)

PA12引腳的下降沿觸發(fā)將會(huì)觸發(fā)中斷,進(jìn)入函數(shù)EXTI15_10_IRQHandler,此時(shí)在函數(shù)中調(diào)用HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12)表示查看PA12的值际长,如果符合條件婆誓,則觸發(fā)HAL_GPIO_EXTI_Callback函數(shù)。

在callback函數(shù)中也颤,將檢測標(biāo)志位置1即可被while循環(huán)中的if識別并輸出洋幻。代碼如下。


// ---------- stm32f1xx_it.c ---------- 
void EXTI15_10_IRQHandler(void){
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
}

//  ---------- main.c ---------- 
void NVIC_Init(){
    // 使能中斷
    HAL_NVIC_SetPriority(EXTI15_10_IRQn,0,0);
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
}

int PA12count = 0, PA12flag = 0;

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    if (GPIO_Pin == GPIO_PIN_12){
        PA12flag = 1;
        PA12count ++;
    }else{
        UNUSED(GPIO_Pin);
    }
}

int main(void) {
    int total, bitcount;
    char str[64];
    int send = 0;
    NVIC_Init();
......
    while (1) {
        int cnt;
......
        if (PA12flag == 1){
            PA12flag = 0;
            cnt = sprintf(str, "Press 12 %d times\r\n", PA12count);
            HAL_UART_Transmit(&UartHandle, (uint8_t*)str, cnt, 500);    
        }
    }
}

void MX_GPIO_Init(void) {
......  
  GPIO_InitStruct.Pin = GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
......
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
中斷響應(yīng)

5. 定時(shí)器中斷

定時(shí)器中斷的實(shí)現(xiàn)思路與引腳涉及的中斷基本一致翅娶。不同的是需要設(shè)置中斷觸發(fā)的時(shí)間文留。因?yàn)椴煌谕獠恐袛啵瑫r(shí)鐘中斷是內(nèi)部觸發(fā)竭沫,所以需要預(yù)先設(shè)定好觸發(fā)時(shí)間燥翅。

而后,同樣的蜕提,需要覆寫中斷觸發(fā)函數(shù)TIM3_IRQHandler森书,而后在其中對時(shí)鐘進(jìn)行判斷后觸發(fā)HAL_TIM_PeriodElapsedCallback。并在callback中真正處理邏輯谎势。


// ---------- stm32f1xx_hal_msp.c ---------- 

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim){
    __TIM3_CLK_ENABLE();
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htime){
    __TIM3_CLK_DISABLE();
}

// main.c

void NVIC_Init(){
...
    HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM3_IRQn);
}

TIM_HandleTypeDef TIM_Handle;

int TIMflag = 0;
void TIM3_IRQHandler(void){
    HAL_TIM_IRQHandler(&TIM_Handle);
}

void TIM_Init(){
    TIM_Handle.Instance = TIM3;
    TIM_Handle.Init.Prescaler = 8000;
    TIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    TIM_Handle.Init.Period = 199;
    HAL_TIM_Base_Init(&TIM_Handle);
    HAL_TIM_Base_Start_IT(&TIM_Handle);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
    TIMflag = 1;
}

int main(void){
......
    total = 0; bitcount = MAX_BITCOUNT;
    while (1) {
        int cnt;
        GPIO_PinState state;

        HAL_Delay(CHECK_DELAY);
        state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
        anti_jitter(&bitcount, state);  
        if (bitcount == 0){
            if (send != 2){
                send = 1;
            }
        }else if (send == 2){
            send = 0;
        }
        if (TIMflag == 1){
            TIMflag = 0;
            if (send == 1){
                send = 2;
                total++;
                cnt = sprintf(str, "Press 11 %d times\r\n", total);
                HAL_UART_Transmit(&UartHandle, (uint8_t*)str, cnt, 500);
            }
            if (PA12flag == 1){
                PA12flag = 0;
                cnt = sprintf(str, "Press 12 %d times\r\n", PA12count);
                HAL_UART_Transmit(&UartHandle, (uint8_t*)str, cnt, 500);            
            }
        }
    }
}

定時(shí)器中斷

6. 自行車碼表

碼表有兩個(gè)模式凛膏,里程模式以及速度模式,兩個(gè)模式有區(qū)別也有聯(lián)系脏榆。

首先是最基礎(chǔ)的里程模式猖毫,該模式只對應(yīng)PA12按鈕的事件。在每次PA12被按下(輪子走了一圈)的時(shí)候算好里程即可须喂,或者使用圈數(shù)*輪子周長的方式也行吁断。在本程序中,將輪子周長表示為3.14m坞生。

其次是速度模式仔役。速度模式不能單單使用總里程/總時(shí)間,這樣得到的總速度是沒有意義的是己,而近似實(shí)時(shí)的速度計(jì)算法應(yīng)該是通過計(jì)算在一定時(shí)間內(nèi)所行駛的里程數(shù)推算出短時(shí)間內(nèi)的速度又兵。在本程序中,使用1.6s作為計(jì)算的時(shí)間長度赃泡,即8個(gè)周期寒波。

里程模式
速度模式

代碼清單
main.c


#define MAX_BITCOUNT 0xff
#define CHECK_DELAY 10
#define PERIMETER 3.14

UART_HandleTypeDef UartHandle;
TIM_HandleTypeDef TIM_Handle;
int cnt;
int total, bitcount, dispMode = 0;
int PA12count = 0, PA12flag = 0;
int TIMflag = 0, TIMcount = 0;
float RouteTick[10];
char str[64];
int send = 0;

void UART0_Init(){
    UartHandle.Instance = USART1;
    UartHandle.Init.BaudRate = 9600;
    UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
    UartHandle.Init.StopBits = UART_STOPBITS_1;
    UartHandle.Init.Parity = UART_PARITY_NONE;
    UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    UartHandle.Init.Mode = UART_MODE_TX_RX;
    
    HAL_UART_Init(&UartHandle);
}

void NVIC_Init(){
    HAL_NVIC_SetPriority(EXTI15_10_IRQn,0,0);
    HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
    HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM3_IRQn);
}

void anti_jitter(int *bitcount, int state){
    *bitcount <<= 1;
    *bitcount &= MAX_BITCOUNT;
    *bitcount += state & 1;
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    if (GPIO_Pin == GPIO_PIN_12){
        PA12flag = 1;
        PA12count ++;
    }else{
        UNUSED(GPIO_Pin);
    }
}

void EXTI15_10_IRQHandler(void){
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
}

void TIM3_IRQHandler(void){
    HAL_TIM_IRQHandler(&TIM_Handle);
}

void TIM_Init(){
    TIM_Handle.Instance = TIM3;
    TIM_Handle.Init.Prescaler = 8000;
    TIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    TIM_Handle.Init.Period = 199;
    HAL_TIM_Base_Init(&TIM_Handle);
    HAL_TIM_Base_Start_IT(&TIM_Handle);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
    TIMflag = 1;
    TIMcount++;
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
    UART0_Init();
    NVIC_Init();
    TIM_Init();
    total = 0; bitcount = MAX_BITCOUNT;
    dispMode = 0;
    while (1) {
        int cnt;
        GPIO_PinState state;
        HAL_Delay(CHECK_DELAY);
        state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
        anti_jitter(&bitcount, state);  
        if (bitcount == 0){
            send = 1;
        }else{
            if (send == 2){
                send = 0;
            }
        }
        if (send == 1){
            send = 2;
            dispMode = 1 - dispMode;
        }
        if (TIMflag == 1){
            int head = (TIMcount - 1) % 8;
            int nexHead = (head + 1) % 8;
            float route = PA12count * PERIMETER;
            RouteTick[head] = route;
            TIMflag = 0;
            if (dispMode == 0){
                cnt = sprintf(str, "You traveled %.2f m\r\n", route);
            }else{
                float inThisTime = RouteTick[head] - RouteTick[nexHead];
                cnt = sprintf(str, "You traveled in %.2f m/s\r\n", inThisTime / 1.6);
            }
            HAL_UART_Transmit(&UartHandle, (uint8_t*)str, cnt, 500);
        }
    }
}

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pins : PA11 PA12 */
  GPIO_InitStruct.Pin = GPIO_PIN_11;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
  GPIO_InitStruct.Pin = GPIO_PIN_12;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

stm32f1xx_hal_msp.c

void HAL_MspInit(void)
{
  __HAL_RCC_AFIO_CLK_ENABLE();
    
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  /* System interrupt init*/
  /* MemoryManagement_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(MemoryManagement_IRQn, 0, 0);
  /* BusFault_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(BusFault_IRQn, 0, 0);
  /* UsageFault_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(UsageFault_IRQn, 0, 0);
  /* DebugMonitor_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DebugMonitor_IRQn, 0, 0);
  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim){
    __TIM3_CLK_ENABLE();
}

void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim){
    __TIM3_CLK_DISABLE();
}

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(huart->Instance==USART1)
  {
    __HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_USART1_CLK_ENABLE();
      
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }

}

void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{

  if(huart->Instance==USART1)
  {
    __HAL_RCC_USART1_CLK_DISABLE();
    __HAL_RCC_USART1_FORCE_RESET();
    __HAL_RCC_USART1_RELEASE_RESET();
    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
  }
}

7. PA11的按鈕也采用中斷方式檢測,主程序只檢測標(biāo)識做串口發(fā)送

有了PA12的經(jīng)驗(yàn)升熊,修改PA11按鈕的檢測方式也比較容易。(假設(shè)PA11沒有抖動(dòng)問題)

首先绸栅,需要在初始化PA11的時(shí)候级野,將其設(shè)置為中斷觸發(fā),我設(shè)置的是下降沿觸發(fā)。

  GPIO_InitStruct.Pin = GPIO_PIN_11;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

而后蓖柔,在中斷處理函數(shù)內(nèi)添加對PA11的處理辰企。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
    if (GPIO_Pin == GPIO_PIN_12){
        PA12flag = 1;
        PA12count ++;
    }else if(GPIO_Pin == GPIO_PIN_11){
        PA11flag = 1;
    }else{
        UNUSED(GPIO_Pin);
    }
}

void EXTI15_10_IRQHandler(void){
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_11);
    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_12);
}

最后,只需要在主循環(huán)中對PA11flag進(jìn)行檢測即可况鸣。

        if (PA11flag == 1){
            PA11flag = 0;
            dispMode = 1 - dispMode;
        }

當(dāng)然牢贸,由于PA11flag只是涉及到狀態(tài)的改變,可以直接在中斷觸發(fā)函數(shù)中進(jìn)行模式的切換镐捧。

參考資料:

下載鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末懂酱,一起剝皮案震驚了整個(gè)濱河市竹习,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌列牺,老刑警劉巖整陌,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瞎领,居然都是意外死亡泌辫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門九默,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甥郑,“玉大人,你說我怎么就攤上這事荤西±浇粒” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵邪锌,是天一觀的道長勉躺。 經(jīng)常有香客問我,道長觅丰,這世上最難降的妖魔是什么饵溅? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮妇萄,結(jié)果婚禮上蜕企,老公的妹妹穿的比我還像新娘。我一直安慰自己冠句,他們只是感情好轻掩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著懦底,像睡著了一般唇牧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天丐重,我揣著相機(jī)與錄音腔召,去河邊找鬼。 笑死扮惦,一個(gè)胖子當(dāng)著我的面吹牛臀蛛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播崖蜜,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼浊仆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纳猪?” 一聲冷哼從身側(cè)響起氧卧,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎氏堤,沒想到半個(gè)月后沙绝,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鼠锈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年闪檬,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片购笆。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粗悯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出同欠,到底是詐尸還是另有隱情样傍,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布铺遂,位于F島的核電站衫哥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏襟锐。R本人自食惡果不足惜撤逢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望粮坞。 院中可真熱鬧蚊荣,春花似錦、人聲如沸莫杈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姓迅。三九已至敲霍,卻和暖如春俊马,著一層夾襖步出監(jiān)牢的瞬間丁存,已是汗流浹背肩杈。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留解寝,地道東北人扩然。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子捌刮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容