一、GPIO 8種工作模式
輸入模式:
1. GPIO_Mode_AIN 模擬輸入
2. GPIO_Mode_IN_FLOATING 浮空輸入
3. GPIO_Mode_IPD 下拉輸入
4. GPIO_Mode_IPU 上拉輸入
輸出模式:
5. GPIO_Mode_Out_OD 開漏輸出
6. GPIO_Mode_Out_PP 推挽輸出
7. GPIO_Mode_AF_OD 復用開漏輸出
8. GPIO_Mode_AF_PP 復用推挽輸出

施密特觸發器:當輸入電壓高於正向閾值電壓,輸出為高;當輸入電壓低於負向閾值電壓,輸出為低;當輸入在正負向閾值電壓之間,輸出不改變,只有當輸入電壓發生足夠的變化時,輸出才會變化
GPIO_Mode_IN_FLOATING 浮空輸入

外部通過IO口輸入電平,傳輸到施密特觸發器(此時施密特觸發器為打開狀態),直接進入輸入數據寄存器,CPU通過讀輸入數據寄存器實現讀取外部輸入電平值,在輸入浮空模式下可以讀取外部輸入電平。如果在該引腳懸空(在無信號輸入)的情況下,讀取該端口的電平是不確定的。
GPIO_Mode_IPU 上拉輸入

上拉電阻的開關閉合,上拉電阻連接到VDD,在I/O端口懸空(在無信號輸入)的情況下,外部輸入通過上拉電阻,施密特觸發器存入輸入數據寄存器,被CPU讀取出高電平,當I/O端口輸入為低電平的時候,施密特觸發器觸發存入輸入數據寄存器,CPU讀取出低電平;
GPIO_Mode_IPD 下拉輸入

下拉電阻的開關閉合,在I/O端口懸空(在無信號輸入)的情況下,下拉電阻連接到VSS,外部輸入通過下拉電阻,施密特觸發器存入輸入數據寄存器,被CPU讀取出低電平,當I/O端口輸入為高電平的時候,下拉電阻處的電壓為高電平,施密特觸發器觸發存入數據寄存器,CPU讀取出高電平
GPIO_Mode_AIN 模擬輸入

模擬輸入通道的配置則更加簡單,信號從左邊編號1的端口進入,從右邊編號2的一端直接模擬輸入至片上外設模塊。上拉、下拉電阻和施密特觸發器,均處於斷開狀態,IO口外部電壓為模擬量,電壓形式為非電平形式。
GPIO_Mode_Out_OD 開漏輸出

開漏輸出模式下,通過設置 位設置/清除寄存器或者輸出數據寄存器的值,途經N-MOS管,最終輸出到I/O端口。這里要注意N-MOS管,當設置輸出的值為高電平的時候,N-MOS管處於截止狀態,此時I/O端口的電平就不會由輸出的高低電平決定,而是由I/O端口外部的上拉或者下拉決定;當設置輸出的值為低電平的時候,N-MOS管處於導通狀態,此時I/O端口的電平就是低電平。同時,I/O端口的電平也可以通過輸入電路進行讀取;注意,I/O端口的電平不一定是輸出的電平。
GPIO_Mode_Out_PP 推挽輸出

推挽電路(push-pull)就是兩個不同極性晶體管間連接的輸出電路。推挽電路采用兩個參數相同的MOSFET管,電路工作時,兩只對稱的功率開關管每次只有一個導通,所以導通損耗小效率高。當設置輸出的值為為高電平時,P-MOS導通,N-MOS截止,此時I/O端口的電平就由P-MOS管決定為高電平;當設置輸出的值為低電平的時候,P-MOS管處於截止狀態,N-MOS管處於導通狀態,此時I/O端口的電平就由N-MOS管決定為低電平,同時IO口輸出的電平可以通過輸入電路讀取,此時I/O端口的電平一定是輸出的電平。
GPIO_Mode_AF_OD 復用開漏輸出

與開漏輸出模式唯一區別在於輸出控制電平之前電平的來源,開漏輸出模式的輸出電平是由CPU寫入輸出數據寄存器控制的,開漏復用輸出模式的輸出電平是由復用功能外設輸出決定的。其他與開漏輸出相似。
控制電路輸出高電平:N-MOS截止,IO口電平由外部上拉/下拉決定
控制電路輸出低電平:N-MOS開啟,IO口輸出低電平
GPIO_Mode_AF_PP 復用推挽輸出

與推挽輸出模式唯一區別在於輸出控制電路之前電平的來源。開漏輸出模式的輸出電平是CPU寫入輸出數據寄存器的,推挽復用輸出模式的輸出電平是由復用功能外設輸出決定的。
應用場合
模擬輸入:應用ADC模擬輸入,或者低功耗下省電
浮空輸入:可以做KEY識別,外部按鍵輸入,IO的電平狀態是不確定,完全由外部輸入決定
下拉輸入:IO內部下拉電阻輸入
上拉輸入:IO內部上拉電阻輸入
推挽輸出(Push-Pull):可以輸出高、低電平,連接數字器件
開漏輸出(Open-Drain):開漏引腳不連接外部的上拉電阻時,只能輸出低電平;如果需要同時具備輸出高電平的功能,則需要接上拉電阻。
對於相應的復用模式(復用輸出來源片上外設),則是根據GPIO的復用功能來選擇,如GPIO的引腳用作串口的輸出(USART/SPI/CAN),則使用復用推挽輸出模式。如果用在I2C、SMBUS這些需要線與功能的復用場合,就使用復用開漏模式。
二、中斷
中斷簡而言之是暫時中止當前的工作,而去處理更為急需處理的事情,把急需處理的事情處理完畢之后,再回頭來繼續原來的事情。
stm32的中斷分為搶占優先級和響應優先級。搶占優先級高的中斷,可以打斷搶占優先級低的中斷。搶占優先級相同的中斷,響應優先級高的可以優先執行。
中斷向量表:中斷向量是中斷服務程序的入口地址,在計算機中中斷向量的地址存放一條跳轉到中斷服務程序的跳轉指令。中斷地址是存儲中斷向量的內存單元。中斷向量表是用來存放中斷向量
嵌套中斷:中斷系統正在執行一個中斷服務時,有另一個優先級更高的中斷提出中斷請求,這時會暫時終止當前正在執行的級別較低的中斷源的服務程序,去處理級別更高的中斷源,待處理完畢,再返回到被中斷了的中斷服務程序繼續執行,這個過程就是中斷嵌套。如果中斷里調用HAL_Delay就會停在那里,因為根本不會進入那個級別更低的中斷。CUBE生成的程序中, SysTick是中斷型延時,SysTick是內核中斷,優先級別默認最低。
三、STM32按鍵

按鍵需要上拉電阻,當按鍵按下時接到地,CPU讀取出低電平知道按鍵按下。




Priority Group默認為4,搶占優先權有2^4(0~15)可選而響應優先權只能是0;為3時,搶占優先權有2^3(0~7)可選,響應優先權只有2^1(0,1)可選,其他同理,根據自己的需求選擇
配置使能MCU外部晶振:

配置MCU工作主頻為80MHz

接着就生成代碼
在MDK-ARM目錄下面可以找到中斷向量表,在(startup_stm32l433xx.s)其中標明了中斷處理函數的名稱,不能隨意定義。

先是內核中斷(異常)

有Reset復位,NMI不可屏蔽中斷,HardFault硬件錯誤等。
接着是外部中斷,顯而易見EXTI0的中斷服務函數的函數名是:EXTI0_IRQHandler

EXTI0~EXTI4是獨立的,9~5共用中斷源,15~10共用中斷源,9~5和15~10的中斷需要在中斷函數中判斷是哪個中斷引腳。

異常和中斷向量表只能用匯編語言編寫
在生成的代碼gpio.c里有中斷的設置

HAL_NVIC_SetPriority();設置中斷優先級
HAL_NVIC_EnableIRQ();使能中斷

為防止抖動產生的下降沿誤觸進入中斷需要加個延時消抖,前面說過如果中斷里調用HAL_Delay就會停在那里,中斷不會進入級別更低的中斷。所以需要讀取SysTick產生延時函數(下面函數是網上找的)
void delay_ms(int32_t nms)
{
int32_t temp;
SysTick->LOAD = 8000*nms;
SysTick->VAL=0X00;//清空計數器
SysTick->CTRL=0X01;//使能,減到零是無動作,采用外部時鍾源
do
{
temp=SysTick->CTRL;//讀取當前倒計數值
}
while((temp&0x01)&&(!(temp&(1<<16))));//等待時間到達
SysTick->CTRL=0x00; //關閉計數器
SysTick->VAL =0X00; //清空計數器
}
找到HAL_GPIO_EXTI_IRQHandler()函數


HAL_GPIO_EXTI_IPQHandler()里,如果GPIO引腳還是低電平,清除狀態位然后調用回調函數,回調函數HAL_GPIO_EXTI_Callback()是個虛函數,需要重新寫,改寫回調函數為你想要的中斷功能。
