STM32學(xué)習(xí)筆記(二)——STM32的GPIO和AFIO
一、STM32芯片引腳分布
1.1 特殊功能引腳和普通功能引腳
STM32F103C8T6共有48個引腳
- 特殊功能引腳(11個)
- Vdd+Vss給芯片供電引腳 共三隊,六個
- VDDA+VSSA模擬電壓 兩個(A~Analog模擬的)
- BOOT0啟動方式選擇引腳 一個
- VBAT備用電池引腳(Battery)一個
- NRST復(fù)位引腳 一個
- 普通IO口引腳(37個)
其中特殊功能引腳是為了維持芯片的運(yùn)行,所以被特殊化了
普通IO引腳是我們可以去應(yīng)用的
1.2 STM32芯片IO引腳復(fù)用
IO復(fù)用:IO引腳身兼數(shù)職的現(xiàn)象叫IO復(fù)用
- 如:下圖的PA9和PA10
- 不僅可以做普通IO口,
- 還能做串口通信的發(fā)送端口和接收端口,
- 還能做定時器的通道引腳
- 作為芯片設(shè)計人員,希望STM32芯片的功能越強(qiáng)大越好
- 所以設(shè)計人員向STM32芯片內(nèi)加了各種外設(shè)模塊,來執(zhí)行各種功能,比如ADC模塊,用來做模數(shù)轉(zhuǎn)換;I2C模用來通信等,詳見下圖
- 每一個模塊都能執(zhí)行特定的功能,每一個模塊也會占用不同的引腳資源,芯片的引腳資源明顯不夠,所以必須讓同一個引腳去身兼數(shù)職
1.3 引腳的通用功能和復(fù)用功能辨析
通用功能(普通IO):我們通過編程讓CPU直接通過GPIO模塊對對應(yīng)的IO引腳進(jìn)行直接的控制
復(fù)用功能:我們通過編程讓CPU控制串口模塊,串口模塊自動的去控制GPIO模塊,跟外接進(jìn)行通信
總結(jié):
通用功能:我們直接對IO引腳進(jìn)行控制
復(fù)用功能:通過控制其他外設(shè),間接對IO口進(jìn)行控制,復(fù)用功能可有多個
1.4 IO引腳的重映射
IO重映射就說,將某個片上外設(shè)的復(fù)用功能,移動到其它的IO引腳上
- 若我們想用PA9和PA10的串口功能,又想用PA9和PA10的定時器功能,就會產(chǎn)生沖突,這時我們可以將串口功能重映射到其它引腳上,避免了沖突
1.5 最小系統(tǒng)板引腳圖
B站UP鐵頭山羊老師整理的,清晰的很
- 如,PA9和PA10,可以當(dāng)作通用IO,也可以復(fù)用定時器和串口
- 當(dāng)既想用PA9、PA10的串口和定時器時,查重映射部分,看到串口可重映射到PB6和PB7
1.6 C8T6引腳功能總結(jié)
二、STM32的GPIO
2.1 GPIO簡介
- STM32的CPU通過控制片上外設(shè)來執(zhí)行相應(yīng)的功能
![]()
- 其中有一種外設(shè)叫GPIO,GPIO根據(jù)CPU的指令去控制對應(yīng)的引腳,進(jìn)行讀寫操作
![]()
2.2 GPIO的寄存器組
寄存器組概念
- CPU控制GPIO這個片上外設(shè)模塊,執(zhí)行引腳的讀寫操作
- 可CPU怎么控制GPIO這個片上外設(shè)呢,他們之間怎么通信呢?
- CPU通過寄存器組去控制GPIO外設(shè)
![]()
寄存器組的組成
- 一個寄存器組由若干個寄存器組成
- 一個GPIO外設(shè),可以控制16個IO口
- GPIO寄存器組由以下組成
- 配置寄存器
- 輸入數(shù)據(jù)寄存器
- 輸出數(shù)據(jù)寄存器
2.3 GPIO的8種工作模式
- GPIO的工作模式有以下8種
![]()
- 中文之華美,我們將名稱拆開理解
- 輸入輸出
- 輸入:單片機(jī)IO口讀取到連接的設(shè)備的電平
- 輸出:單片機(jī)IO口向連接的設(shè)備發(fā)送電平
- 通用復(fù)用
- 通用:CPU直接控制GPIO
- 復(fù)用:CPU控制片上外設(shè),片上外設(shè)控制GPIO,間接控制
- 只有輸出才有通用、復(fù)用功能區(qū)分
- 輸入只是讀取外部電平,無論是CPU讀取,還是片上外設(shè)讀取都一樣,都是那個電平信號
- 推挽開漏
- IO引腳內(nèi)部由2個MOS管組成
- 推挽模式:通過電壓控制MOS交替導(dǎo)通,輸出高、低電壓
- 開漏模式: 可以輸出低電平,和高阻抗
![]()
- 上拉下拉(針對輸入模式)
- 如果IO引腳工作在輸入模式,IO引腳內(nèi)阻會無窮大,輸入是測電壓的,可以想象成萬用表,萬用表測量電阻兩端電壓時,是并聯(lián)的,萬用表的內(nèi)存是無窮大的
- 當(dāng)輸入高低電壓時一切正常,但若懸空時,這時IO引腳會類似于天線,接收外界電磁波,產(chǎn)生干擾
- 解決辦法,就說加 上拉電阻或下拉電阻
- 當(dāng)接上拉電阻時:引腳懸空時,引腳會被拉高到高電平;引腳正常輸入高低電平時,一切正常
- 當(dāng)接下拉電阻時:引腳懸空時,引腳會被拉到低電平; 引腳正常輸入高低電平時,一切正常
![]()
2.4 IO口的最大輸出速度
最大輸出速度:IO允許輸出電平的最大切換頻率
- 受控于上升時間和下降時間,若頻率太快,保持時間就會很小,輸出不了有效的電平
![]()
STM32C8T6的最大輸出速度分為三擋
- 2MHZ:每秒鐘切換200萬次
- 10MHZ:每秒鐘切換1000萬次
- 50MHZ:每秒鐘切換5000萬次
選擇原則:選擇滿足要求的最小值,以此降低功耗
-
2.5 GPIO內(nèi)部結(jié)構(gòu)
B站鐵頭山羊:2.2節(jié) 10:42
三、是的終于到了-----點(diǎn)燈
單純點(diǎn)燈方法應(yīng)用程序: 點(diǎn)我點(diǎn)我點(diǎn)我
3.1 學(xué)會看原理圖
PC13是我們要控制的引腳,當(dāng)PC13為低電平時,LED導(dǎo)通,點(diǎn)亮;當(dāng)PC13為高電平時,LED不導(dǎo)通,不亮。
我們要去看想要控制的器件的原理圖,了解是什么電平,什么方式驅(qū)動這個想要控制的器件的
3.2 新建工程
- “工程是包含了我們所有編寫的代碼的東西”
- 我們用到的代碼,包括,從網(wǎng)上找到的函數(shù)庫+自己編寫的功能代碼
- 從標(biāo)準(zhǔn)庫建立一個工程挺復(fù)雜的(想學(xué)習(xí)的可以去看正點(diǎn)原子的前幾節(jié)課),避免重復(fù)造輪子,我們引入工程模板的概念,將常用的庫函數(shù)功能,集成到一個模板里,而后只需要調(diào)用我們所需的庫函數(shù),專注于編寫我們自己的功能代碼即可
- 網(wǎng)上已經(jīng)有很多大神,幫我們建立了工程模板,如正點(diǎn)原子的,洋桃電子的,海創(chuàng)電子的,鐵頭山羊的,因?yàn)樽罱诤丸F老師學(xué)習(xí),我們接下來用鐵老師的模板。
3.3 工程模板結(jié)構(gòu)
- User:用戶自己編寫的代碼
- Startup:單片機(jī)上電后,會先執(zhí)行啟動文件里的程序,而后執(zhí)行主函數(shù)里的程序
- PAL庫:對標(biāo)準(zhǔn)庫的補(bǔ)充
- 標(biāo)注庫:ST提供的官方庫函數(shù)
3.4 GPIO的標(biāo)準(zhǔn)庫編程接口
標(biāo)準(zhǔn)庫的編程接口,是和寄存器一一對應(yīng)的
3.4 開始編程
3.4.1 IO引腳初始化
初始化:使用IO引腳前做一些參數(shù)配置的工作
IO引腳初始化步驟:
- 使能GPIO端口時鐘
- 選擇模式和其它參數(shù)(如:推挽輸出?最大傳輸速度?)
![]()
一、啥是使能GPIO端口時鐘 ??????
為啥要使能時鐘啊 ???
- CPU控制的片上外設(shè),都為時序電路,時序電路需要時鐘
- 默認(rèn)狀態(tài),片上外設(shè)的時鐘,都是關(guān)閉的,為了省電
- 所以用到哪個片上外設(shè),就要開啟它對應(yīng)的時鐘
![]()
不是,那咋使能時鐘啊 ???
- 我們需要向RCC外設(shè)的寄存器里寫值(忽略)
- 我們只需要調(diào)用對應(yīng)的函數(shù)即可
![]()
二、GPIO_Init咋用????????
GPIO_Init簡介:
- 用于初始化單個IO引腳
- 使用時填入兩個參數(shù)
- 參數(shù)1:選擇想要初始化引腳的端口號,如出書畫PC13,參數(shù)填GPIOC
- 參數(shù)2:初始化各種參數(shù),為結(jié)構(gòu)體類型的指針。庫函數(shù)幫我們聲明好了結(jié)構(gòu)體類型,這個結(jié)構(gòu)體類型名稱叫GPIO_InitTypeDef,也就是它給了一張表格,表格叫GPIO_InitTypeDef,你需要將你用的參數(shù),填寫到表格中。
![]()
結(jié)構(gòu)體知識補(bǔ)充:
- 聲明結(jié)構(gòu)體類型,再定義結(jié)構(gòu)體變量
- 類比:結(jié)構(gòu)體類型=int類型
- 類比:定義結(jié)構(gòu)體類變量=定義整形變量。
- 類比:GPIO_InitTypeDef a = int a
具體操作步驟
將庫函數(shù)給你表格,寫上你自己的名字,也就是定義結(jié)構(gòu)體類型變量GPIO_InitTypeDef GPIOInitStruct(名稱自定義);
填寫結(jié)構(gòu)體變量的參數(shù):
- 端口C一共有16個引腳,用的哪一個引腳?
- GPIO的模式是啥?推挽輸出,輸入上拉?
- 若是輸出,輸出的最大速度是啥?
調(diào)用GPIO_Init()函數(shù),填入兩個參數(shù)
3.4.2 ODR的寫入和讀取
ODR(Output Data Register)輸出數(shù)據(jù)寄存器
- 此寄存器可以寫入也可以讀取
- 寫入:控制MOS管通斷
- 讀?。鹤x出上次寫入ODR的值
3.4.3 IDR的讀取
IDR(Intput Data Register)輸入數(shù)據(jù)寄存器
3.4.4 IO的翻轉(zhuǎn)
IO翻轉(zhuǎn):先讓燈亮,延時一會,再讓燈滅,在延時一會,以此循環(huán)
編程實(shí)現(xiàn):
- 實(shí)現(xiàn)延時功能:庫函數(shù)中沒有這個功能,引入PAL庫
- 引入頭文件#include “stm32f10x_pal.h”
- 對PAL 庫初始化 PAL_Init()
- 使用PAL庫中的延時函數(shù) PAL_Delay() 單位ms
方案1的實(shí)現(xiàn):
#include "stm32f10x.h"
#include "stm32f10x_pal.h"
int main(void)
{
GPIO_InitTypeDef GPIOInitStruct;
PAL_Init();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能GPIO外設(shè)時鐘
GPIOInitStruct.GPIO_Pin = GPIO_Pin_13;
GPIOInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//輸出開漏
GPIOInitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC,&GPIOInitStruct);//初始化GPIO外設(shè)C組
while(1)
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,0);//給PC13引腳寫0,點(diǎn)亮燈
PAL_Delay(100);//延時100ms
GPIO_WriteBit(GPIOC,GPIO_Pin_13,1);//給PC13引腳寫0,熄滅燈
PAL_Delay(100);//延時100ms
}
}
方案2的實(shí)現(xiàn):
方案2中的翻轉(zhuǎn)是如何做到的呢?
- ODR寄存器的可以讀取上次寫入的值
- 我們只需要讀取上次寫的是0還是1,若是1 這次寫0;若是0,這次寫1,就可以實(shí)現(xiàn)翻轉(zhuǎn)的功能
![]()
#include "stm32f10x.h"
#include "stm32f10x_pal.h"
int main(void)
{
GPIO_InitTypeDef GPIOInitStruct;
PAL_Init();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能GPIO外設(shè)時鐘
GPIOInitStruct.GPIO_Pin = GPIO_Pin_13;
GPIOInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;//輸出開漏
GPIOInitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC,&GPIOInitStruct);//初始化GPIO外設(shè)C組
GPIO_WriteBit(GPIOC,GPIO_Pin_13,0);//給PC13引腳寫0,點(diǎn)亮燈
while(1)
{
PAL_Delay(100);//延時100ms
//翻轉(zhuǎn)代碼
if(GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_13) == 0)
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,1);
}
else
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,0);
}
}
}
四、按鍵編程
單純按鍵應(yīng)用程序: 點(diǎn)我點(diǎn)我點(diǎn)我
4.1 按鍵的電路設(shè)計
外接上拉電阻:
- 按鍵打開,IO口讀取到的是高電平
- 按鍵閉合,IO口讀取到的是低電平
內(nèi)部上拉電阻
- 由于單片機(jī)內(nèi)部本來就有兩個電阻
- 可設(shè)置輸入模式,來啟用內(nèi)部的上拉電阻,這樣按鍵電路,節(jié)省了一個電阻
按鍵電路:連接時,連接1-3端 或者2-4端
4.2 按鍵編程的原理
當(dāng)按鍵按下時,IO口讀取到的是低電平 當(dāng)按鍵松開時,IO口讀取到的值是高電平,我們可以不斷的讀取IO引腳的值,來檢測按鍵的狀態(tài)
但我們習(xí)慣于捕捉,按鍵按下或者松開那一瞬間的值,因?yàn)橹挥性诎存I狀態(tài)變化的瞬間才去切換LED的亮滅
- 如:電腦的鼠標(biāo)左鍵,當(dāng)我們按下按鍵時,鼠標(biāo)不會有反映,只有當(dāng)我們松開按鍵的瞬間,鼠標(biāo)才完成了點(diǎn)擊這個動作,所以我們捕捉的是按鍵發(fā)生變化的瞬間。
- 方法:我們聲明兩個變量
- previous 上次
- current 當(dāng)前
- 若上次讀到IDR寄存器里值是1,當(dāng)前IDR寄存器是0,表示按鍵按下的瞬間
*若讀到從0到1,是松開按鍵的瞬間
1.先定義兩個變量,存儲上一次讀取到的值,和這一次讀取到的值
2.然后將當(dāng)前值,賦給上一次值
3.在讀取當(dāng)前值
4.若當(dāng)前值和上一次值不想等,則代表,按鍵狀態(tài)發(fā)生了變化
5.那是按下的變化,還是松開的變化呢
6.只需要判斷當(dāng)前值,當(dāng)前值是0,則是按下的瞬間
7.當(dāng)前值是1,則是松開的瞬間
4.3 按鍵控制燈的亮滅代碼實(shí)現(xiàn)
1.PC13連接的是燈 要把PC13初始化為輸出開漏模式
2.PA0連接的按鍵 初始化為輸入上拉模式
3.讀取PA0的電平,看其是否是按鍵按下后又松開那個瞬間,若是
4.編寫燈翻轉(zhuǎn)程序
#include "stm32f10x.h"
#include "stm32f10x_pal.h"
int main(void)
{
uint8_t current = 1;
uint8_t previous = 1;
GPIO_InitTypeDef GPIOInitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//開啟GPIOC時鐘
PAL_Init();
GPIOInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
GPIOInitStruct.GPIO_Pin = GPIO_Pin_13;
GPIOInitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC,&GPIOInitStruct);//初始化GPIOC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//開啟GPIOA時鐘
GPIOInitStruct.GPIO_Mode = GPIO_Mode_IPU;//代碼一行一行執(zhí)行,所以直接給結(jié)構(gòu)體變量直接賦值就行
GPIOInitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA,&GPIOInitStruct);//初始化GPIOA
while(1)
{
previous = current ;
current = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);
if(current != previous)
{
if(current == 0)//按鍵按下
{
}
else
{
//切換燈的亮滅狀態(tài)
if( GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_13) == 0 )
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,1);
}
else
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,0);
}
}
}
}
}
4.4 按鍵消抖
4.4.1 按鍵抖動產(chǎn)生原因
- 按鍵按下時,彈簧片與另一個引腳連通,不按下時不連通,
- 因?yàn)槠湮锢斫Y(jié)構(gòu),會產(chǎn)生抖動
- IO引腳會捕獲這種抖動,從而對實(shí)驗(yàn)產(chǎn)生干擾
4.4.2 按鍵消抖方法
硬件電路時固定的,我們考慮用軟件消抖方法。
由于抖動的時間不會超過10ms,所以我們可以等待10ms,直到按鍵電平穩(wěn)定的時候,再去判斷其電平狀態(tài)
代碼實(shí)現(xiàn)如下
- 采集當(dāng)前值和上一次值,如果當(dāng)前值不等于上次的值
- 那么,等待10ms
- 再次采集當(dāng)前值,如果當(dāng)前值,還是不等于上次值
- 那么執(zhí)行對應(yīng)的程序
#include "stm32f10x.h"
#include "stm32f10x_pal.h"
int main(void)
{
uint8_t current = 1;
uint8_t previous = 1;
GPIO_InitTypeDef GPIOInitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//開啟GPIOC時鐘
PAL_Init();
GPIOInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
GPIOInitStruct.GPIO_Pin = GPIO_Pin_13;
GPIOInitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC,&GPIOInitStruct);//初始化GPIOC
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//開啟GPIOA時鐘
GPIOInitStruct.GPIO_Mode = GPIO_Mode_IPU;//代碼一行一行執(zhí)行,所以直接給結(jié)構(gòu)體變量直接賦值就行
GPIOInitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA,&GPIOInitStruct);//初始化GPIOA
while(1)
{
previous = current ;
current = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);//第一次讀取
if(current != previous)//第一次檢測 不相等
{
PAL_Delay(10);//延時10ms
current = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);//再次讀取
if(current != previous)//再次檢測
{
if(current == 0)//按鍵按下
{
}
else
{
//切換燈的亮滅狀態(tài)
if( GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_13) == 0 )
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,1);
}
else
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,0);
}
}
}
}
}
}
4.4.3 大佬的肩膀-PAL庫按鍵消抖
大佬的庫中,關(guān)于按鍵的函數(shù)有兩條
使用方法:
使用方法詳細(xì)介紹:
- 引用頭文件:#include “stm32f10x_pal_button.h”
- 聲明句柄:PalButton_HandleTypeDef hbutton1;//button1的句柄變量,(最好寫主函數(shù)外面)
- 填寫按鍵初始化參數(shù)
- 哪個引腳組
- 哪個引腳
- 外部上拉電阻 還是內(nèi)部上拉電阻
- 編寫按鍵按下執(zhí)行的功能函數(shù),并將函數(shù)名,填寫到句柄回調(diào)函數(shù)參數(shù)中
- 調(diào)用初始化函數(shù)PAL_Button_Init( )
- 在While中寫執(zhí)行函數(shù)PAL_Button_Proc( )
標(biāo)準(zhǔn)庫和PAL庫對比
代碼:
#include "stm32f10x.h"
#include "stm32f10x_pal.h"
#include "stm32f10x_pal_button.h"
PalButton_HandleTypeDef hbutton1;//button1的句柄變量
static void OnButtonlRealeased(void)
{
//對PC13亮滅切換
if(GPIO_ReadOutputDataBit(GPIOC,GPIO_Pin_13) == 0)
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,1);
}
else
{
GPIO_WriteBit(GPIOC,GPIO_Pin_13,0);
}
}
int main(void)
{
GPIO_InitTypeDef GPIOinitStruct;
PAL_Init();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIOinitStruct.GPIO_Pin = GPIO_Pin_13;
GPIOinitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
GPIOinitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC,&GPIOinitStruct);
//設(shè)置按鍵PA0 內(nèi)部上拉
hbutton1.Init.GPIOx = GPIOA;
hbutton1.Init.GPIO_Pin = GPIO_Pin_0;
hbutton1.Init.Button_Mode = Button_Mode_IPU;
hbutton1.Init.ButtonReleasedCallback = OnButtonlRealeased;
PAL_Button_Init(&hbutton1);
while(1)
{
PAL_Button_Proc(&hbutton1);
}
}
4.4.3 補(bǔ)充 句柄
句柄:
- 編程=數(shù)據(jù)結(jié)構(gòu)+算法
- 如:描述人要有年齡,身高,性別(數(shù)據(jù)結(jié)構(gòu))+行為,走,跑,跳(算法)
- 句柄就說一種數(shù)據(jù)結(jié)構(gòu),用來存儲,表示這個實(shí)體的所有數(shù)據(jù)
- 而函數(shù),算法,是對句柄里的數(shù)據(jù)執(zhí)行的某種操作
例子: 現(xiàn)在創(chuàng)建一個句柄,也就是描述一個茶壺的信息,
有總?cè)莘e,當(dāng)前水量
然后對這個茶壺進(jìn)行三種操作
- 創(chuàng)建一個10L的空茶壺:其實(shí)就是對茶壺這個數(shù)據(jù)結(jié)構(gòu)進(jìn)行操作
- 向茶壺中注入水:其實(shí)就是對茶壺這個數(shù)據(jù)結(jié)構(gòu)進(jìn)行操作
- 將茶壺中水倒出:其實(shí)就是對茶壺這個數(shù)據(jù)結(jié)構(gòu)進(jìn)行操作
4.4.3 補(bǔ)充 回調(diào)函數(shù)(HAL庫編程也會用到)
什么是回調(diào)函數(shù):
將我們定義的函數(shù)名稱告訴給PAL庫,這樣PAL庫將在適當(dāng)?shù)臅r機(jī)調(diào)用這個函數(shù)(自動調(diào)用,我搞不懂怎么調(diào)用的)
但是用法是,將想要在按鍵松開時執(zhí)行的程序,自己封裝成一個自定義函數(shù),然后把函數(shù)名傳遞給句柄中的一個參數(shù)
例:我們將切換PC13亮滅狀態(tài)的代碼,封裝成一個函數(shù) void OnButtonlPressed()
我們希望按鍵松開時執(zhí)行這個函數(shù),這樣我們把我們定義的函數(shù)名,給到PAL庫,也就是給到這個句柄中的一個參數(shù)
五、AFIO
5.1 AFIO簡介
- IO引腳可以進(jìn)行復(fù)用,
- IO復(fù)用,就說同一個IO引腳身兼數(shù)職,有多個功能
- IO引腳直接被CPU控制–通用
- IO引腳被片上外設(shè)進(jìn)行控制–復(fù)用,同一個IO引腳復(fù)用功能有多個
- 如下圖,若我們想同時使用,片上外設(shè)1和片上外設(shè)2,那么引腳就沖突了,這是我們需要復(fù)用功能重映射來解決這個問題,也就是左圖黃色的小框框,
- 這個小框框,將某一個開關(guān)的引腳,重映射到別的位置,這個方式就說復(fù)用功能的重映射
- AFIO也是一個片上外設(shè)
![]()
5.2 IO復(fù)用功能重映射表
官方編程手冊8.3小節(jié)
B站UP鐵頭山羊:2.5節(jié) 14:00
B站UP鐵頭山羊: 2.5AFIO
5.3 AFIO編程
標(biāo)準(zhǔn)庫接口位置:和GPIO外設(shè)在一起
有四個編程接口:
使用方法:
調(diào)用上圖函數(shù),第一參數(shù)填寫要重映射外設(shè)功能的名稱,開啟重映射
如:
重映射外設(shè)USART1
重映射外設(shè)TIM1文章來源:http://www.zghlxwxcb.cn/news/detail-811905.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-811905.html
到了這里,關(guān)于STM32學(xué)習(xí)筆記(二)——STM32的GPIO和AFIO的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!