STM32 HAL庫編程(2)—— 外部中斷、ADC
學習外部中斷和ADC,使用戰艦mini開發板文章目錄
- STM32 HAL庫編程(2)—— 外部中斷、ADC
- 前言
- 一、新建工程
- 1. 查看手冊,看芯片型號和LED、按鍵引腳
- 2. 使用CUBEMX新建工程
- 二、配置按鍵引腳為外部中斷
- 1. 配置引腳為外部中斷
- 2. 配置中斷方式
- 3. 配置中斷優先級
- 三、代碼介紹
- 四、撰寫代碼
- 1. 中斷回呼函式
- 2. 燒錄測驗
- 五、代碼優化
- 六、串口配置
- 1. 串口介紹
- 2. 串口配置
- 3. 串口代碼介紹
- 4. 撰寫串口代碼1——發送資料
- 5. 使用printf發送資料
前言
- 外部中斷:指的是某一個引腳從低電平變高電平,或高電平變低電平而產生的中斷,區別于定時器內部中斷,這個常用于按鍵讀取,按鍵按下去之后,比如從高電平變成低電平,自動就跳到了中斷函式,如果沒有中斷函式,就需要一直在while中讀取按鍵的高低電平,這種輪詢方式效率太低,
- ADC:模數轉換,將模擬信號轉換位數字信號,STM32可以讀取的模擬電壓位0-3.3V,12位精度(即模擬信號的0-3.3 轉換為 數字信號的0-4095),
一、新建工程
1. 查看手冊,看芯片型號和LED、按鍵引腳





2. 使用CUBEMX新建工程
依照步驟:選擇CPU、選擇debug方式、配置時鐘、配置LED引腳、最后作業來進行,并且在生成的代碼上測驗LED閃爍代碼,觀察是否正常運行,
二、配置按鍵引腳為外部中斷
1. 配置引腳為外部中斷
- 根據上方的原理圖,設定三個按鍵為外部中斷方式,外部中斷的英文名為EXTI,在配置中斷時,會發現EXTI后有一個中斷號,這是與引腳號對應的,例如PA0就是EXTI0,PC5就是EXTI5,有中斷號才能判斷是哪一個引腳產生的中斷,
- 實際上,PA0,PB0,PC0等都是共用中斷EXTI0的,其他EXTI1、EXTI2等也都是這樣,這樣做的目的是減少外部中斷數量,單片機速度本來就不高,太多的中斷會降低運行效率,
- 那如果PA0、PB0都用到了中斷EXTI0,如何判斷出中斷是由哪一個引腳產生的呢?一個辦法就是在產生中斷后,在中斷函式中讀取PA0和PB0的引腳高低電平,從而判斷出哪一個引腳發生了中斷,
- 產生了中斷,代碼會自動跳到中斷函式中,需要運行的代碼就放在中斷函式中,比如轉變LED燈的亮滅,在以前的庫函式中,中斷0-4由單獨的中斷函式,中斷5-9共用一個中斷函式,中斷10-15也共用一個中斷函式,但HAL庫中,所有的外部中斷共用一個中斷函式,進入中斷函式后,首先需要通過**中斷句柄(中斷號)**判斷是哪一個中斷,

2. 配置中斷方式
- 中斷方式:上升沿中斷和下降沿中斷,最常用的兩種中斷方式,上升沿中斷就是當引腳從低電平變成高電平時,會產生一個中斷,下降沿中斷反之,比如一個按鍵,沒按的時候時低電平,按下去的時候是高電平,那我就配置這個引腳的中斷方式為上升沿中斷,
- 引腳上拉下拉:一個引腳默認既不是高電平也不是低電平,這樣就可能導致中斷例外,為穩定中斷,我們需要通過上拉或下拉的方式,讓引腳在平時的狀態下,保持高電平或低電平,原理圖中按鍵都沒有設定外部上拉或者下拉,我們需要配置KEY0和KEY1為上拉,WK_UP為下拉,
- 三個按鍵的中斷配置為:PA0:標簽WK_UP,上升沿中斷,引腳下拉;PC5:標簽KEY0,下降沿中斷,引腳上拉;PA15:標簽KEY1,下降沿中斷,引腳上拉,

配置完成后的圖如下圖:可以順帶設定LED的標簽為LED0和LED1

3. 配置中斷優先級

三、代碼介紹


- 右擊上方的中斷提交函式,點擊查看該函式的定義:


四、撰寫代碼
1. 中斷回呼函式
代碼為不同引腳讓LED燈發生變化,代碼如下,只需要將中斷回呼函式復制到放在合適的位置,每次中斷就會自動呼叫這個函式,

2. 燒錄測驗
五、代碼優化
問題:對于按鍵而言,會有按鍵抖動,即在按下去的時候,會產生多個上升沿和下降沿,導致多次產生中斷,
解決:一個是通過添加濾波電容的方式,硬體方式消去按鍵的抖動信號;另一個辦法是添加延時并判斷,軟體方式消去抖動,由于電路已經設計,這里使用軟體方式,

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == WK_UP_Pin) // 按鍵WK_UP中斷
{
HAL_Delay(20);
if(HAL_GPIO_ReadPin(WK_UP_GPIO_Port, WK_UP_Pin) == 1)
{
HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin); // 更改LED0亮滅
}
}
else if(GPIO_Pin == KEY0_Pin) // KEY0中斷
{
HAL_Delay(20);
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin) == 0)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); // 更改LED1亮滅
}
}
else if(GPIO_Pin == KEY1_Pin) // KEY1中斷
{
HAL_Delay(20);
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 0)
{
HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin); // 更改LED0亮滅
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin); // 更改LED1亮滅
}
}
}
六、串口配置
1. 串口介紹
- 串口是單片機中很常見的一種通信方式,可以與電腦通信、與傳感器通信、與其他單片機通信等,
- 異步串口(UART)是用的最多的一種串口,僅包含TX和RX兩條通信線,
2. 串口配置
- 可以看到,對于這個stm32而言,有很多個串口,這里我們選擇串口1,并配置為異步串口,波特率為115200,
- 對于一個串口,它可以映射到不同的引腳上,除了這里使用的PA9和PA10,串口1還可以使用PB6和PB7,


3. 串口代碼介紹

4. 撰寫串口代碼1——發送資料
發送資料使用以下函式進行:

在main中撰寫以下代碼,每隔1s發送hello給電腦:

uint8_t buff[10] = {"hello\r\n"};
HAL_UART_Transmit(&huart1, buff, 10, 1000);
HAL_Delay(1000);
連接USB到電腦,發開串口助手,注意選擇對應的波特率115200,
5. 使用printf發送資料
在C語言學習中,printf可以很方便的輸出內容,例如printf(“a is %d”, a)可以輸出a的值,為使用printf,需要在代碼中添加stdio.h庫和重定向函式,如下圖,

#include "stdio.h"
// 重定向函式,可以使用printf
int fputc(int ch,FILE *f)
{
uint8_t temp[1]={ch};
HAL_UART_Transmit(&huart1,temp,1,2);
}
在while中測驗printf,輸出一些內容測驗一下,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/258810.html
標籤:其他
