企業(yè)獨(dú)立官方網(wǎng)站網(wǎng)址怎么做百度搜索官方網(wǎng)站
目錄
簡介:
GPIO輸出的八種模式
STM32的GPIO工作方式
GPIO支持4種輸入模式:
GPIO支持4種輸出模式:
浮空輸入模式
上拉輸入模式
下拉輸入模式
模擬輸入模式:
開漏輸出模式:(PMOS無效,就是開漏輸出,)
開漏復(fù)用輸出模式 (P-MOS和N-MOS都有效)
推挽輸出模式
推挽復(fù)用輸出模式
根據(jù)八種模式在keil5上配置好相應(yīng)的代碼
GPIO的相關(guān)寄存器?
1.GPIO的輸出
? ? ? ?1.1LED閃爍
1.2LED流水燈
1.3:蜂鳴器
簡介:
下面都是理論知識,可以稍微看一看,
GPIO的基本結(jié)構(gòu):
GPIO位結(jié)構(gòu):
電路圖說明:
??????????????保護(hù)二極管:IO 引腳上下兩邊兩個二極管用于防止引腳外部過高、過低的電壓輸入。當(dāng)引腳電壓高于 VDD 時,上方的二極管導(dǎo)通;當(dāng)引腳電壓低于VSS時,下方的二極管導(dǎo)通,防止不正常電壓引入芯片導(dǎo)致芯片燒毀。但是盡管如此,還是不能直接外接大功率器件,須加大功率及隔離電路驅(qū)動,防止燒壞芯片或者外接器件無法正常工作。
P-MOS管和N-MOS管:由P-MOS管和N-MOS管組成的單元電路使得GPIO具有“推挽輸出”和“開漏輸出”的模式。這里的電路會在下面很詳細(xì)地分析到。
TTL肖特基觸發(fā)器:信號經(jīng)過觸發(fā)器后,模擬信號轉(zhuǎn)化為0和1的數(shù)字信號。但是,當(dāng)GPIO引腳作為ADC采集電壓的輸入通道時,用其“模擬輸入”功能,此時信號不再經(jīng)過觸發(fā)器進(jìn)行TTL電平轉(zhuǎn)換。ADC外設(shè)要采集到的原始的模擬信號。
下面介紹一下我們需要的LED,蜂鳴器:
GPIO輸出的八種模式
?GPIO的模式:
STM32的GPIO工作方式
GPIO支持4種輸入模式:???????
-
浮空輸入(GPIO_Mode_IN_FLOATING)
-
上拉輸入(GPIO_Mode_IPU)
-
下拉輸入(GPIO_Mode_IPD)
-
模擬輸入(GPIO_Mode_AIN)
GPIO支持4種輸出模式:
-
開漏輸出(GPIO_Mode_Out_OD)
-
開漏復(fù)用輸出(GPIO_Mode_AF_OD)
-
推挽輸出(GPIO_Mode_Out_PP)
-
推挽復(fù)用輸出(GPIO_Mode_AF_PP)
同時,GPIO 還支持三種最大翻轉(zhuǎn)速度(2MHz、10MHz、50MHz)。每個I/O口可以自由編程,但 I/O 口寄存器必須按32位字訪問。?
需要注意,在查看《STM32中文參考手冊V10》中的GPIO的表格時,會看到有“FT”一列,這代表著這個GPIO口是兼容3.3V和5V的;如果沒有標(biāo)注“FT”,就代表著不兼容5V。
浮空輸入模式
浮空輸入模式下,I/O端口的電平信號直接進(jìn)入輸入數(shù)據(jù)寄存器。也就是說,I/O的電平狀態(tài)是不確定的,完全由外部輸入決定;如果在該引腳懸空(在無信號輸入)的情況下,讀取該端口的電平是不確定的。
上拉輸入模式
上拉輸入模式下,I/O 端口的電平信號直接進(jìn)入輸入數(shù)據(jù)寄存器。但是在 I/O 端口懸空(在無信號輸入)的情況下,輸入端的電平可以保持在高電平;并且在 I/O 端口輸入為低電平的時候,輸入端的電平也還是低電平。?
下拉輸入模式
???????
下拉輸入模式下,I/O 端口的電平信號直接進(jìn)入輸入數(shù)據(jù)寄存器。但是在 I/O 端口懸空(在無信號輸入)的情況下,輸入端的電平可以保持在低電平;并且在 I/O 端口輸入為高電平的時候,輸入端的電平也還是高電平。
模擬輸入模式:
?模擬輸入可以說是ADC模數(shù)轉(zhuǎn)換器的專屬配置。
模擬輸入模式下,I/O 端口的模擬信號(電壓信號,而非電平信號)直接模擬輸入到片上外設(shè)模塊,比如 ADC 模塊等等。
開漏輸出模式:(PMOS無效,就是開漏輸出,)
開漏輸出模式下,通過設(shè)置位設(shè)置/清除寄存器或者輸出數(shù)據(jù)寄存器的值,途經(jīng) N-MOS 管,最終輸出到I/O端口。這里要注意 N-MOS 管,當(dāng)設(shè)置輸出的值為高電平的時候,N-MOS 管處于關(guān)閉狀態(tài),此時I/O端口的電平就不會由輸出的高低電平?jīng)Q定,而是由 I/O 端口外部的上拉或者下拉決定;當(dāng)設(shè)置輸出的值為低電平的時候,N-MOS 管處于開啟狀態(tài),此時 I/O 端口的電平就是低電平。同時,I/O 端口的電平也可以通過輸入電路進(jìn)行讀取;注意,I/O 端口的電平不一定是輸出的電平。
開漏復(fù)用輸出模式 (P-MOS和N-MOS都有效)
開漏復(fù)用輸出模式,與開漏輸出模式很是類似。只是輸出的高低電平的來源,不是讓CPU直接寫輸出數(shù)據(jù)寄存器,取而代之利用片上外設(shè)模塊的復(fù)用功能輸出來決定的。
推挽輸出模式
推挽輸出模式下,通過設(shè)置位設(shè)置/清除寄存器或者輸出數(shù)據(jù)寄存器的值,途經(jīng) P-MOS 管和 N-MOS 管,最終輸出到 I/O 端口。這里要注意 P-MOS 管和 N-MOS管,當(dāng)設(shè)置輸出的值為高電平的時候,P-MOS管處于開啟狀態(tài),N-MOS管處于關(guān)閉狀態(tài),此時I/O端口的電平就由P-MOS管決定:高電平;當(dāng)設(shè)置輸出的值為低電平的時候,P-MOS管處于關(guān)閉狀態(tài),N-MOS管處于開啟狀態(tài),此時I/O端口的電平就由N-MOS管決定:低電平。同時,I/O端口的電平也可以通過輸入電路進(jìn)行讀取;注意,此時I/O端口的電平一定是輸出的電平。
推挽復(fù)用輸出模式
???????推挽復(fù)用輸出模式,與推挽輸出模式很是類似。只是輸出的高低電平的來源,不是讓CPU 直接寫輸出數(shù)據(jù)寄存器,取而代之利用片上外設(shè)模塊的復(fù)用功能輸出來決定的。
?
根據(jù)八種模式在keil5上配置好相應(yīng)的代碼
現(xiàn)在的很多單片機(jī)在GPIO配置的時候,除了配置輸入輸出類型、速度以外,還需要配置一下模式,即GPIO_Mode。以STM32為例,有輸入浮空、輸入上拉、輸入下拉、模擬輸入、開漏輸出、推挽式輸出、 推挽式復(fù)用功能、開漏復(fù)用功能。?下面我們舉一種例子來講一下如何配置,
也為我們點(diǎn)亮LED燈做準(zhǔn)備。
第一步:選擇時鐘寄存器,
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//配置寄存器的時鐘使能//自己可以在keil5上跳轉(zhuǎn)到他的函數(shù)定義,看看他要什么參數(shù),我這里使用的是GPIOA,你也可以用//其他的,第一個參數(shù)變成RCC_APB2Periph_GPIOB,就是使用B寄存器
上面配置好了就可以為寄存器輸入時鐘,當(dāng)然,時鐘也有很多個,我這里選擇的是RCC這個,
第二步:
建立一個數(shù)組:為啥要建立數(shù)組呢?要配置輸入輸出類型、速度,還有上面一直介紹的八種模式。
存放不同類型的變量C語言是用數(shù)組存放的。
?GPIO_InitTypeDef GPIO_InitStructure; ?//定義一個結(jié)構(gòu)體結(jié)構(gòu)體有下面三個參數(shù)
第三部:設(shè)定好我們要的輸出類型嗎,速度,模式。
下面就是八種模式存放在函數(shù)的,以枚舉類型賦給了相應(yīng)的值,這樣我們就不需要直接給相應(yīng)的寄存器復(fù)制,直接調(diào)用這個函數(shù)即可:對應(yīng)的英文如下
-
浮空輸入(GPIO_Mode_IN_FLOATING)
-
上拉輸入(GPIO_Mode_IPU)
-
下拉輸入(GPIO_Mode_IPD)
-
模擬輸入(GPIO_Mode_AIN)
-
開漏輸出(GPIO_Mode_Out_OD)
-
開漏復(fù)用輸出(GPIO_Mode_AF_OD)
-
推挽輸出(GPIO_Mode_Out_PP)
-
推挽復(fù)用輸出(GPIO_Mode_AF_PP)
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
//選擇什么模式,上述八種模式的一種GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
//我用A0這個I/O口GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
//速度選擇50Mhz
GPIO_Init(GPIOA,&GPIO_InitStructure);//初始化
?OK,這樣的話,我們就已經(jīng)選擇了GPIO的模式,速度,和哪一個引腳。已經(jīng)擁有了I/O口的使用權(quán)。上面這些需要的參數(shù)都是可以跳轉(zhuǎn)到函數(shù)定義去看看它需要啥的,直接復(fù)制粘貼即可
最后就是操作寄存器給0或1就可以輸出和讀入了,當(dāng)然,我們還是直接操作相應(yīng)的函數(shù)給他1和0.
GPIO的相關(guān)寄存器?
下面GPIO配置寄存器,每一個端口的模式由四位進(jìn)行配置。16個端口需要64位,(基本很少直接配置寄存器,庫函數(shù)已經(jīng)配置好了,我們直接了解庫函數(shù)的使用,直接調(diào)用即可)?
所以配置寄存器有兩個,一個是端口配置低寄存器,一個是端口配置高寄存器。
?端口數(shù)據(jù)寄存器:
低16位對應(yīng)16個引腳,高16位沒有使用。
端口輸出寄存器:
低16位是進(jìn)行設(shè)置的,高16位是進(jìn)行清除的。?
與上面寄存器高16位是一樣的功能。為了方便操作設(shè)置的,如果你想單一的進(jìn)行位設(shè)置或者清除。多個端口同時進(jìn)行設(shè)置和位清除,使用8.2.5寄存器就OK了,這樣可以保證位設(shè)置和位清除的同步性,
可以對端口的配置進(jìn)行鎖定,防止意外更改,
?下面是八種模式,函數(shù)已經(jīng)把我們定義好了。我們依次講一下。
1.GPIO的輸出
? ? ? ?1.1LED閃爍
如圖所示連接面包板。我使用的是A0這個GPIO,可能圖看不太清楚。
代碼如下:(基于庫函數(shù)的工程已經(jīng)建好的情況下)
這里主要使用main.c函數(shù)
main.c
當(dāng)然,置1還是置0的函數(shù)也有很多個
下面四個,具體參數(shù)可以轉(zhuǎn)到相應(yīng)的函數(shù)定義去看看它具體要啥。
?
#include "stm32f10x.h" //32的頭文件
#include "Delay.h" //延時的文件int main()
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//配置寄存器的時鐘使能//自己可以在keil5上跳轉(zhuǎn)到他的函數(shù)定義,看看他要什么參數(shù),我這里使用的是GPIOA,你也可以用//其他的,第一個參數(shù)變成RCC_APB2Periph_GPIOB,就是使用B寄存器GPIO_InitTypeDef GPIO_InitStructure; //定義一個結(jié)構(gòu)體結(jié)構(gòu)體有下面三個參數(shù)GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//選擇什么模式,上述八種模式的一種GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);// GPIO_SetBits(GPIOA,GPIO_Pin_0);//選擇A0這個I/O口,置1操作 // GPIO_ResetBits(GPIOA,GPIO_Pin_0);//選擇A0這個I/O口,置0操作while(1){GPIO_ResetBits(GPIOA,GPIO_Pin_0);//選擇A0這個I/O口,置0操作Delay_ms(100); GPIO_SetBits(GPIOA,GPIO_Pin_0);//選擇A0這個I/O口,置1操作 Delay_ms(100);}
}
Delay函數(shù)可以自己找一個,江科大就有,在工程里面建一個文件夾,放在工程里面。最后拿進(jìn)來就OK了,當(dāng)然還要很多注意操作事項,我就不展示了。
怎么點(diǎn)亮看自己連接的引腳圖。0點(diǎn)亮還是1點(diǎn)亮,具體由自己決定。
我上面連接的電路圖是二極管長接正,短接A0口,所以,只有A0口接0就會亮。所以我是0點(diǎn)亮。當(dāng)然看你的模式是啥,推挽輸出的話:二極管長接A0口,短接負(fù)極,好像也是可以點(diǎn)亮的,跟它的工作方式有關(guān),自己可以試試。但是開漏輸出不行,說明開漏輸出沒有高電平驅(qū)動能力的
1.2LED流水燈
有了上面LED閃爍的例子,其實(shí)LED流水燈也很容易。
只不過我們多要操作7個I/O口:初始化部分麻煩了點(diǎn)。
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;對引腳的初始化可以這樣,為什么呢?
我們右擊下圖所示,轉(zhuǎn)到定義。
通過這幅圖可以看到,pin0對應(yīng)的數(shù)據(jù)是0x01,pin1為0x02........
轉(zhuǎn)為16進(jìn)制是不是 0000 0000 0000 0001(pin0)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 0000 0000 0000 0010? ?(pin1)........
按位或就是? ? ? ? ? ? 0000 0000 0000 0011? 這樣就把兩個端口全部選上了。
當(dāng)然最下面還有個GPIO_pin_All,就是把所有引腳全部選上了。
其實(shí)時鐘控制的那一項,也是可以通過按位或的操作來進(jìn)行多個選擇的,同理,右鍵
GPIO_SetBits的參數(shù)也是可以設(shè)置多個引腳的。?
OK,有了上述知識,我就點(diǎn)亮四個燈,來實(shí)現(xiàn)流水燈,插入哪一個引腳看自己的選擇,我選擇
A0,1,2,3.這四個引腳。代碼如下:
#include "stm32f10x.h" //32的頭文件
#include "Delay.h" //延時的文件int main()
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//配置寄存器的時鐘使能//自己可以在keil5上跳轉(zhuǎn)到他的函數(shù)定義,看看他要什么參數(shù),我這里使用的是GPIOA,你也可以用//其他的,第一個參數(shù)變成RCC_APB2Periph_GPIOB,就是使用B寄存器GPIO_InitTypeDef GPIO_InitStructure; //定義一個結(jié)構(gòu)體結(jié)構(gòu)體有下面三個參數(shù)GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//選擇什么模式,上述八種模式的一種GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);// GPIO_SetBits(GPIOA,GPIO_Pin_0);//選擇A0這個I/O口,置1操作 // GPIO_ResetBits(GPIOA,GPIO_Pin_0);//選擇A0這個I/O口,置0操作while(1){GPIO_ResetBits(GPIOA,GPIO_Pin_0);//選擇A0這個I/O口,置0操作Delay_ms(500); GPIO_SetBits(GPIOA,GPIO_Pin_0);//選擇A0這個I/O口,置1操作 Delay_ms(500);GPIO_ResetBits(GPIOA,GPIO_Pin_1);Delay_ms(500); GPIO_SetBits(GPIOA,GPIO_Pin_1);//選擇A0這個I/O口,置1操作 Delay_ms(500);GPIO_ResetBits(GPIOA,GPIO_Pin_2);//選擇A0這個I/O口,置0操作Delay_ms(500); GPIO_SetBits(GPIOA,GPIO_Pin_2);//選擇A0這個I/O口,置1操作 Delay_ms(500);GPIO_ResetBits(GPIOA,GPIO_Pin_3);//選擇A0這個I/O口,置0操作Delay_ms(500); GPIO_SetBits(GPIOA,GPIO_Pin_3);//選擇A0這個I/O口,置1操作 Delay_ms(500);}
}
當(dāng)然,也可以使用?GPIO_Write函數(shù)。
GPIO_Write(GPIOA,~0x0001);//0000 0000 0000 0001
Delay_ms(100);
GPIO_Write(GPIOA,~0x0002);//0000 0000 0000 0010
Delay_ms(100);
GPIO_Write(GPIOA,~0x0004);//0000 0000 0000 0100
Delay_ms(100);
GPIO_Write(GPIOA,~0x0008);//0000 0000 0000 1000
Delay_ms(100);
1.3:蜂鳴器
這一部分留給自己操作吧,應(yīng)該也是很簡單的,跟上面的代碼差不多。
.