網(wǎng)頁設(shè)計秀麗南寧成都關(guān)鍵詞優(yōu)化平臺
?在開始之前記得先準備好環(huán)境:
STM32F103核心板下載教程.pdf · 林何/STM32F103C8 - 碼云 - 開源中國 (gitee.com)
一、STM32的GPIO模塊數(shù)據(jù)手冊詳解
每個GPIO端口對應16個引腳,例GPIOA(PA0~PA15)
內(nèi)核cpu就可以通過APB2總線對寄存器讀寫,完成輸出電平和讀取電平的功能
?1.GPIO和APIO
GPIO:通用輸入/輸出IO
APIO:備用輸入/輸出IO
2.GPIO功能描述
3.配置模式
【STM32】GPIO工作原理(八種工作方式超詳細分析,附電路圖)-CSDN博客
1.輸入浮動,輸入上拉,輸入下拉(數(shù)字狀態(tài))
都是數(shù)字模式,數(shù)字IO,只關(guān)心電平是1還是0
輸入浮空:就是當電平輸入進來后,直接輸入到寄存器中【不對其進行操作】
輸入上拉:在內(nèi)部有一個上拉電阻(將電平拉高),只能外部接地,才能將電平拉低,如果TTL肖特基觸發(fā)器:輸入的是高電平或者干擾信號,則會將其過濾調(diào)。
2.模擬輸入(模擬狀態(tài))
AD轉(zhuǎn)換
可以工作在模擬電路或者數(shù)字電路
3.輸出
開漏輸出
推挽輸出
4.備用
將不用的引腳配置成備用引腳(GPIO)才可以被使用
4.輸出字節(jié)數(shù)控制
1)輸出32位字:使用GPIO_CRL---效率低,但是兼容性好
2)輸入小于32位字:使用CPIOx_BSRR--效率高,但是兼容性差
5.I/O 端口位框圖
6.端口位配置表
7.輸出模式位
8.外部中斷/喚醒線
將IO口和相對應的中斷映射起來
9.GPIO寄存器描述
1. 端口配置低寄存器(GPIOx_CRL)
由于每個GPIO口需要4位來進行配置輸入輸出模式(2位配置MODE,2位配置CNF),這樣的話每組16個GPIO口則需要64位,這也就表明需要兩個32位寄存器。于是GPIOx_CRL用于配置GPIO0-GPIO7的輸入輸出模式。同理GPIOx_CRH則用于配置GPIO8-GPIO15的輸入輸出模式。
控制PX0---PX7引腳工作模式
四個位控制一個引腳
2.?端口配置高寄存器(GPIOx_CRH)
控制PX8---PX15引腳工作模式
3.端口輸入數(shù)據(jù)寄存器(GPIOx_IDR)?
4. 端口輸出數(shù)據(jù)寄存器(GPIOx_ODR)
5. 端口位設(shè)置/復位寄存器(GPIOx_BSRR)
如果想要將bit7和bit6置為0,則表示要將bit7和bit6寫為1,其他位置為0
對復位上寫1表示復位
對置位上寫1表示置為
如果置位和復位同時設(shè)置,則置位起作用。
6.端口位復位寄存器(GPIOx_BRR)
7.端口配置鎖定寄存器(GPIOx_LCKR)
8.復用功能I/O和調(diào)試配置(AFIO)
二、原理圖分析
1.硬件接線
1)杜邦線連接到P0端口到LCD的J19接口,這樣相當于8個LED分別對應PB8-PB15
2)因為GPIO接到LCD的負極,所以輸入0亮,輸入1暗
三、MDK工程建立
與前面51建立工程是一樣的
1.注意點1:
2.注意點2:
單片機中用到的c語言其實不是原始c語言,而是有點定制性c語言
之前認識:整個程序從main函數(shù)開始執(zhí)行,main執(zhí)行完整個程序就結(jié)束
起始代碼:從CPU復位開始執(zhí)行的第一句指令,到main函數(shù)之前所做的事情就是起始代碼
3.起始代碼
1)起始代碼是從哪里來的:編譯環(huán)境提高的,STM32CPU提供的
2)不同CPU的起始代碼一般是不同的
3)起始代碼是用匯編寫的
四、寫代碼控制GPIO點亮和熄滅
1.寄存器現(xiàn)象確認
我們使用的是P0端口(對應PB8-PB15),所以我們要去對應查找PB的寄存器起始地址
1)STM32 PortB的起始是0x4001 0c00
2.有可能使用到的GPIO的地址:
因為我們是PB8-PB15,所以我們只使用CRH
3.C語言操作寄存器
1)ARM是內(nèi)存與IO統(tǒng)一編址的,所以ARM中的所有外設(shè)都是通過寄存器的方式來操作的
2)每一個寄存器都有地址,c語言通過這些地址來操作這些寄存器位,用到的c語言的技巧主要是c與的位操作和c語言指針
3)常見面試題:用c語言向內(nèi)存地址0x3000 0004寫入16
? ? ? ? *(unsigned int *)0x3000 0004=16;
等價于
? ? ? ? unsigned int *p=(unsigned int *)0x3000 0004;
? ? ? ? *p=16;
4.解析寄存器
1.端口配置高寄存器(GPIOx_CRH)-高8位
//向CRH寄存器寫內(nèi)容,將GPIO_GPB15配置為輸出模式【此時高位有用】//推挽輸出模式,輸出的速率為50MHZ【0011 0011 0011 0011.。。】*((unsigned int *)GPIOB_CRH)=0x33333333;//表示將GPIO_CRH的值設(shè)置為0x33333333
2.端口輸出數(shù)據(jù)寄存器(GPIOx_ODR)
//向CRH寄存器寫內(nèi)容,將GPIO_GPB15配置為輸出模式【此時高位有用】//推挽輸出模式,輸出的速率為50MHZ【0011 0011 0011 0011.。。】*((unsigned int *)GPIOB_CRH)=0x33333333;//表示將GPIO_CRH的值設(shè)置為0x33333333
5.注意點:
記得在操作GPIO的時候要先打開時鐘
#define GPIOB_CRH 0x40010C04
#define GPIOB_ODR 0x40010C0C#define RCC_APB2ENR 0x40021018void main(void){//STM32所有外設(shè)默認關(guān)閉//所以我們在打開時鐘*((unsigned int *)RCC_APB2ENR)=0x00000008;//向CRH寄存器寫內(nèi)容,將GPIO_GPB15配置為輸出模式//推挽輸出模式,輸出的速率為50MHZ【0011 0011 0011 0011.。?!?((unsigned int *)GPIOB_CRH)=0x33333333;//表示將GPIO_CRH的值設(shè)置為0x33333333//輸出1,點亮LED//ff:對應15-8位*((unsigned int *)GPIOB_ODR)=0x0000f000;while(1);}
五、其他寄存器的測試
1.端口位設(shè)置/清除寄存器(GPIOx_BSRR)
將bit8-bit15置0(變亮),因為我們前面是使用了GPIO_GRH(所以只能控制8-15個引腳),所以此時改變0-7是無效的
//使用寄存器【GPIOB_BSRR】:將bit8-bit15置0(此時表示全亮) //*((unsigned int *)GPIOB_BSRR)=0x00000000;//因為前面我們是控制GPIOB_CRH,所以只有8-15位才起效果,0-7無論設(shè)置什么都無所謂//*((unsigned int *)GPIOB_BSRR)=0x000000ff;//此時全亮,與上面效果一樣//0101 0101//*((unsigned int *)GPIOB_BSRR)=0x00005500;//此時2,4,6,8亮//此時led1,led3不亮,其他亮//使用置位*((unsigned int *)GPIOB_BSRR)=0x00005500;//此時2,4,6,8亮//使用復位:將高4位全部復位*((unsigned int *)GPIOB_BSRR)=0xf0000000;
2.端口位清除寄存器(GPIOx_BRR)
只能操作bit0-bit15
BRR:只能用來復位,不能置位(所以只能將其置為0,而不能置為1)
//使用寄存器【GPIOB_BRR】:將bit8-bit15置0(此時表示全亮) //GPIOB_BRR:只能進行復位(意思是只能將電平置為0)//前面16-32是無效位*((unsigned int *)GPIOB_BRR)=0x00000000;//全亮*((unsigned int *)GPIOB_BRR)=0x0000ffff;//全亮//*((unsigned int *)GPIOB_BRR)=0x0000ff00;//只亮高4位(led的4-7)
六、總結(jié)
對數(shù)據(jù)操作的三種方法:
ODR:可以進行任何操作,但是只能一次性操作32位,效率低,但是移植性高【其次考慮】
BSRR:原子操作,效率高;移植性差【優(yōu)先考慮】
BRR:只能進行復位,不能置位,原子操作,效率高;移植性差
1.代碼
#define GPIOB_CRH 0x40010C04
#define GPIOB_CRL 0x40010C00
#define GPIOB_ODR 0x40010C0C
#define GPIOB_BSRR 0x40010C10
#define GPIOB_BRR 0x40010C14#define RCC_APB2ENR 0x40021018void main(void){//STM32所有外設(shè)默認關(guān)閉//所以我們在打開時鐘*((unsigned int *)RCC_APB2ENR)=0x00000008;//向CRH寄存器寫內(nèi)容,將GPIO_GPB15配置為輸出模式【此時高位有用】//推挽輸出模式,輸出的速率為50MHZ【0011 0011 0011 0011.。?!?((unsigned int *)GPIOB_CRH)=0x33333333;//表示將GPIO_CRH的值設(shè)置為0x33333333//輸出0,點亮LED//ff:對應15-8位//*((unsigned int *)GPIOB_ODR)=0x00000000;//使用寄存器【GPIOB_BSRR】:將bit8-bit15置0(此時表示全亮) //*((unsigned int *)GPIOB_BSRR)=0x00000000;//因為前面我們是控制GPIOB_CRH,所以只有8-15位才起效果,0-7無論設(shè)置什么都無所謂//*((unsigned int *)GPIOB_BSRR)=0x000000ff;//此時全亮,與上面效果一樣//0101 0101//*((unsigned int *)GPIOB_BSRR)=0x00005500;//此時2,4,6,8亮//此時led1,led3不亮,其他亮//使用置位//*((unsigned int *)GPIOB_BSRR)=0x00005500;//此時2,4,6,8亮//使用復位:將高4位全部復位//*((unsigned int *)GPIOB_BSRR)=0xf0000000;//使用寄存器【GPIOB_BRR】:將bit8-bit15置0(此時表示全亮) //GPIOB_BRR:只能進行復位(意思是只能將電平置為0)//前面16-32是無效位*((unsigned int *)GPIOB_BRR)=0x00000000;//全亮*((unsigned int *)GPIOB_BRR)=0x0000ffff;//全亮//*((unsigned int *)GPIOB_BRR)=0x0000ff00;//只亮高4位(led的4-7)while(1);}
2.對宏定義的封裝
#define GPIOB_CRH 0x40010C04
#define GPIOB_CRL 0x40010C00
#define GPIOB_ODR 0x40010C0C
#define GPIOB_BSRR 0x40010C10
#define GPIOB_BRR 0x40010C14#define RCC_APB2ENR 0x40021018#define rGPIOB_CRH (*((unsigned int *)GPIOB_CRH))
#define rGPIOB_ODR (*((unsigned int *)GPIOB_ODR))
#define rGPIOB_BSRR (*((unsigned int *)GPIOB_BSRR))
#define rGPIOB_BRR (*((unsigned int *)GPIOB_BRR))
#define rRCC_APB2ENR (*((unsigned int *)RCC_APB2ENR))void main(void){rRCC_APB2ENR = 0x00000008;rGPIOB_CRH = 0x33333333;rGPIOB_ODR = 0x0000aa00;
}