多圖殺貓。實(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安全套餐、百度全家桶等揭厚。
打開程序之后界面長這樣却特。
萌新上來什么都不懂,跟著教程直接新建工程筛圆,選擇了核心板的型號STM32F103C8之后直接點(diǎn)OK裂明。
點(diǎn)擊Project選項(xiàng)卡中的setting,進(jìn)入到項(xiàng)目設(shè)置太援。填寫完項(xiàng)目名稱闽晦、位置以及工具鏈。在圖中提岔,我選的是MDK-ARM V5仙蛉,下載列表中有相關(guān)工具下載(Keil)。
全部設(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)入庫管理界面。
此時(shí)走孽,左下角有一個(gè)** From Local ... **按鈕惧辈,將下載的V1.3.0包以及V1.3.1補(bǔ)丁順序打入即可。安裝完畢后可以看到安裝的是當(dāng)前最新版本磕瓷。
接下來為了點(diǎn)亮小燈盒齿,需要找一個(gè)引腳輸出高電平形成電流。在此困食,我選擇將PA9接口置為GPIO_Output模式边翁。多說一句,實(shí)際上這個(gè)地方的配置不是必須的硕盹,因?yàn)檫@里的配置最終也是由MX轉(zhuǎn)譯成為C的代碼符匾,而在Keil中才是真正的編譯,即可以在代碼中直接編寫相應(yīng)的流程瘩例。不過啊胶,話說回來,能自動(dòng)干的東西為啥要碼代碼仰剿。
而后创淡,點(diǎn)擊代碼生成按鈕痴晦。
生成結(jié)束后后會(huì)在項(xiàng)目的文件夾下生成一個(gè)由設(shè)置所決定的工程文件夾南吮。而Open Project目前點(diǎn)了還沒有作用,因?yàn)檫€沒有裝相應(yīng)的軟件誊酌。
至此部凑,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)行修改以滿足我們的要求即可。
由于我們在MX中已經(jīng)有進(jìn)行過設(shè)置环凿,修改了PA9為輸出引腳梧兼,在代碼中就得到了體現(xiàn)。下方即為生成的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
實(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è)模式。
配置完畢闷游,接下來是代碼生成峻汉,點(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í)間堕澄。
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é)果如下。
注意到按鈕的狀態(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é)果并不理想,由圖可以看出痊项。我依然沒有按任何的按鍵锅风,而串口卻一直有輸出。
思考了一下鞍泉,發(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í)間較短砚嘴。
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);
}
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);
}
}
}
}
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)行模式的切換镐捧。
參考資料:
- 第3次實(shí)驗(yàn)的指導(dǎo)文檔 by 楊凱
- [分享] [練習(xí)]以STM32CubeMX+Keil 成功點(diǎn)燈 -- 比較 STM32 與 Arduino 的差異
- STM32CubeMX的固件庫的離線安裝方法
- keil mdk v5.11 官方最新版 這個(gè)鏈接是為了安裝教程潜索,沒有下載過
- STM32F103 Blink LED (using Keil and STMCubeMX)
- STM32學(xué)習(xí)筆記之EXTI(外部中斷)
- stm32庫函數(shù)詳解