日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32F103五分钟入门系列(一)跑马灯(库函数+寄存器)+加编程模板+GPIO总结

發(fā)布時間:2023/12/10 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32F103五分钟入门系列(一)跑马灯(库函数+寄存器)+加编程模板+GPIO总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

摘自:STM32F103五分鐘入門系列(一)跑馬燈(庫函數(shù)+寄存器)+加編程模板+GPIO總結(jié)
作者:自信且愛笑‘
發(fā)布時間: 2021-04-28 21:17:40
網(wǎng)址:https://blog.csdn.net/Curnane0_0/article/details/116158776

學(xué)習(xí)板:STM32F103ZET6

跑馬燈實驗

  • 前言
  • 一、GPIO
    • 1、GPIO種類
    • 2、GPIO輸入輸出的8種模式:
    • 3、模式用途
  • 二、點亮LED(庫函數(shù)版)
    • 1、庫函數(shù)的由來
    • 2、點亮LED庫函數(shù)版編寫順序
      • 1、GPIO_Init()
      • 2、RCC_APB2PeriphClockCmd()
      • 3、將配置函數(shù)放在led.c和led.h文件
  • 三、點亮LED(寄存器版本)
    • 1、新建工程、添加led文件
    • 2、配置時鐘
    • 3、GPIO配置
    • 4、主函數(shù)代碼編寫
  • 附1 PXout()與PXin()

前言

本來準(zhǔn)備先總結(jié)一下GPIO、幾種輸入輸出模式以及配置方法、寄存器種類、時鐘及分頻等,但是想了想,還是算了,一步步的來,到時候用到再總結(jié)吧 ,不然前面總結(jié)了,后面用到還得回顧。

至于前面的安裝庫、安裝軟件、Keil中添加文件等,就不在總結(jié)了,因為這些根本并不需要記的,新手可以去跟著視頻走一遍。學(xué)習(xí)過程中,不用每次都自己去新建工程,直接將官方給的模板拷過來,修改一下文件夾名稱即可。

一、GPIO

1、GPIO種類

本博板子STM32F103ZET6共有7組IO口,每組16個,共16×7=112個,分別為:
GPIOA——>PA0、PA1、PA2…PA15
GPIOB——>PB0、PB1、PB2…PB15
.
.
.
GPIOG——>PG0、PG1、PG2、…PG15

2、GPIO輸入輸出的8種模式:

程序中標(biāo)識模式
GPIO_Mode_AIN模擬輸入
GPIO_Mode_IN_FLOATING浮空輸入
GPIO_Mode_IPD下拉輸入
GPIO_Mode_IPU上拉輸入
GPIO_Mode_Out_OD開漏輸出
GPIO_Mode_Out_PP推挽輸出
GPIO_Mode_AF_OD復(fù)用開漏輸出
GPIO_Mode_AF_PP復(fù)用推挽輸出

3、模式用途

1、 GPIO_Mode_AIN :模擬輸入
一般用于ADC模擬輸入

2、GPIO_Mode_IN_FLOATING :浮空輸入
可用于按鍵KEY實驗、發(fā)送接收信號RX、TX等,不過這些實驗可以不用浮空輸入,如KEY用到上拉和下拉

3、GPIO_Mode_IPD:下拉輸入
4、GPIO_Mode_IPU:上拉輸入
IO內(nèi)部上拉電阻、下拉電組輸入,使情況而定,比如剛剛說的key按鍵實驗,原理圖如下:

可以看到KEY_UP按下后,IO口應(yīng)該是3V3電平輸入,未按下時為懸空狀態(tài),而懸空狀態(tài)IO輸入是未知的,所以為了防止程序跑飛,采用下拉輸入,在懸空狀態(tài)下,使IO輸入下拉到低電平。這樣,在懸空狀態(tài)下,IO檢測到的是低電平,不會去執(zhí)行key_up按下后的程序。

KEY0~2按下后,IO口是低電平輸入。按下時為懸空狀態(tài),而懸空狀態(tài)IO輸入是未知的,所以為了防止程序跑飛,采用上拉輸入,在懸空狀態(tài)下,使IO輸入上拉到高電平。這樣,在懸空狀態(tài)下,IO檢測到的是高電平,不會去執(zhí)行KEY0 ~2按下后的程序。

5、GPIO_Mode_Out_OD:開漏輸出
IO 輸出 0 接 GND,IO 輸出 1,懸空,需要外接上拉電阻,才能實現(xiàn)輸出 高電平。當(dāng)輸出為 1 時,IO 口的狀態(tài)由上拉電阻拉高電平,但由于是開漏輸出模式,這樣 IO 口也就可以 由外部電路改變?yōu)榈碗娖交虿蛔儭T撃J竭m合做電流型的驅(qū)動,吸收電流能力比較強(qiáng)。

6、GPIO_Mode_Out_PP:推挽輸出
可以輸出高、低電平。導(dǎo)通損耗小、效率高。既提高電路的負(fù)載能力,又提高開關(guān)速度。廣泛各種實驗,比如接下來要總結(jié)的LED。

7、GPIO_Mode_AF_OD:復(fù)用開漏輸出
當(dāng)GPIO為復(fù)用IO時的開漏輸出模式,一般用于外設(shè)功能,如TX1

8、GPIO_Mode_AF_PP:復(fù)用推挽輸出
當(dāng)GPIO為復(fù)用IO時的推挽輸出模式,一般用于外設(shè)功能,如I2C

二、點亮LED(庫函數(shù)版)

1、庫函數(shù)的由來

在學(xué)習(xí)庫函數(shù)之前,應(yīng)該明白,STM32F1用的是Cortex-M3芯片,是由ARM公司設(shè)計的。所以芯片的標(biāo)準(zhǔn)是由ARM公司制定的,芯片內(nèi)核架構(gòu)有ARM公司提供。而我們現(xiàn)在用的STM32由ST公司生產(chǎn),所以關(guān)系是:ARM制定內(nèi)核架構(gòu),ST等芯片公司根據(jù)ARM公司的標(biāo)準(zhǔn)設(shè)計了芯片。ST等公司設(shè)計的芯片,不同的是存儲容量、外設(shè)、串口數(shù)量等等。

以本博的學(xué)習(xí)板STM32F103ZET6為例,固件庫(庫函數(shù)的集合)是由官方提供的,這個官方是ST公司,而不是正點原子官方。也就是說不僅僅這一型號單片機(jī),ST系列其他型號的單片機(jī)庫函數(shù)依舊可以適用。所以不必?fù)?dān)心更換板子后不知如何去編程。

ST公司推出官方固件庫,將底層寄存器操作都封裝起來,形成一套接口(API)供我們使用,大多數(shù)情況下我們不必去考慮底層寄存器。比如本博的LED,只需調(diào)用GPIO配置函數(shù)、時鐘配置函數(shù),然后主函數(shù)初始化后,直接給引腳賦值就可以實現(xiàn)LED的亮滅,而不用去考慮寄存器如何工作的。當(dāng)然本博會把寄存器版的LED也總結(jié)一下。畢竟想要真正理解單片機(jī),還得去真正理解寄存器,庫函數(shù)版只是讓我們停留在“會使用”。當(dāng)然,對應(yīng)大多數(shù)人來講,“會使用”已經(jīng)完全足夠了。

2、點亮LED庫函數(shù)版編寫順序

1、設(shè)置時鐘
2、設(shè)置GPIO

只要這兩步的配置,再在主函數(shù)中給對應(yīng)引腳傳輸高低電平即可。

打開原理圖文件(下圖我打開了6個文件,都是需要的,而且大部分情況下,有這6個文件足以。都在板子附帶資料的文件夾里

從原理圖中得到以下信息:

①DS0 LED0陽極接+,陰極接PB5;DS1 LED1陽極接+,陰極接PE5。

②SYS LED由名稱“PWR”顧名思義,為電源指示燈,所以單片機(jī)接通電源后,電源指示燈常亮。

③芯片的PB5引腳軟件置0后,LED0亮;PE5引腳軟件置0后,LED1亮。

所以要配置GPIOB(因為PB5)和GPIOE(因為PE5)。

然后是時鐘設(shè)置,只要是對GPIO操作,就必須進(jìn)行時鐘配置(而且時鐘配置在前)。GPIO是掛載在APB2總線上的外設(shè),所以在對GPIO的時鐘進(jìn)行設(shè)置時,通過函數(shù)RCC_APB2PeriphClockCmd()來實現(xiàn)。

下面進(jìn)入實戰(zhàn):

打開模板文件:(時間久遠(yuǎn)了,不知道模板文件原來放哪個文件夾下,找不到的話可以把LED官方例程打開,關(guān)于LED的.c和.h文件刪掉,主函數(shù)清空,就可以當(dāng)以后的模板來用了,不用每次都創(chuàng)建工程)

首先查看GPIO配置函數(shù),既然是GPIO,那么先找一下頭文件,在main.c下找GPIO頭文件,并點擊進(jìn)入。

找到對應(yīng)函數(shù):(下一博客總結(jié)所有GPIO函數(shù)的用法、以及延時函數(shù))

上圖標(biāo)注,GPIO_Init()函數(shù)初始化,進(jìn)行設(shè)置GPIO,GPIO_SetBits()函數(shù)給對應(yīng)引腳置1,GPIO_ReSetBits()函數(shù)給對應(yīng)引腳置0。

1、GPIO_Init()

右鍵選中函數(shù),點擊【Go to Definition of …】,進(jìn)入函數(shù)詳細(xì)說明

可以看到,函數(shù)的形參有兩個,而且都是指針。進(jìn)入第一個形參“類型”


看到GPIOx指針是指向上圖這個結(jié)構(gòu)體的,也就是每組GPIO都包含的7個寄存器。

比如LED實驗,傳遞GPIOB(PB5)過來后,*GPIOB就指向這七個寄存器,初始化函數(shù)就是對七個寄存器的操作,不過被庫函數(shù)封裝起來了,emmmm…說太多了,只要知道GPIO_Init()傳過來的第一個參數(shù)表示對該組GPIO配置就行了。

察看第二組形參“類型”



看到第二個形參也是結(jié)構(gòu)體指針,指向的結(jié)構(gòu)體含有三個參數(shù)GPIO_Pin、GPIO_Speed、GPIO_Mode

到這里就可以用C++語法來說明了。比如第二個形參是a(注意是指針),那么:
a.GPIO_Pin=…
a.GPIO_Speed=…
a.GPIO_Mode=…
就完成了對參數(shù)GPIO參數(shù)的設(shè)置。

接下來我們再看看上面三個賦值語句的右邊究竟是什么東西:
轉(zhuǎn)回到初始化函數(shù):


1表示第二個形參
2表示對 GPIO_Init()的第一個形參的處理(就是那個結(jié)構(gòu)體里有7個寄存器的東西)
3表示mode的配置
4表示pin的配置
5表示速speed的配置。

點開GPIO_Mode設(shè)置函數(shù):

可以看到就是我們第一大部分總結(jié)的8中輸入輸出模式

點開pin設(shè)置函數(shù)

可以看到pin是我們第一大部分總結(jié)的一組GPIO的15個IO口

點開速度設(shè)置函數(shù)

可以看到速度可設(shè)置的值:


到這里,GPIO的設(shè)置函數(shù)應(yīng)該會寫了:

第一步:設(shè)置形參1和形參2
第二步:上面那三個賦值語句的設(shè)置
第三步:運行GPIO_Init()函數(shù)

程序:(先在主函數(shù)中書寫,.c文件中書寫接下來會總結(jié)

GPIO_TypeDef GPIO_B;//形參1GPIO_InitTypeDef GPIO_InitStruct;//形參2GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//形參2.mode=推挽輸出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//形參2.pin=5GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//形參2.speed=50MHZGPIO_Init(&GPIO_B,&GPIO_InitStruct);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

注意GPIO_Init()傳遞的是指針,所以應(yīng)該用取地址符“&”。

上面的程序還是有問題的,因為定義了GPIO_B為第一個參數(shù),但是程序并不知道GPIO_B是對GPIOB的操作,所以在 GPIO_Init(&GPIO_B,&GPIO_InitStruct);語句中,“&GPIO_B”應(yīng)該是真正的、物理上的地址,而不能像參數(shù)2一樣,只是程序定義參數(shù)時分配的地址。

輸入“GPIOB”,并進(jìn)入

發(fā)現(xiàn)官方真的定義了GPIOB,而且還是真正的、物理層的地址

所以之前程序中的GPIO_B可以刪掉了,不是物理層的地址,定義了、傳遞給GPIO_Init()函數(shù)也沒用。

正確完整程序:

//GPIO_TypeDef GPIO_B;//形參1GPIO_InitTypeDef GPIO_InitStruct;//形參2GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//形參2.mode=推挽輸出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//形參2.pin=5GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//形參2.speed=50MHZGPIO_Init(GPIOB,&GPIO_InitStruct);//注意GPIOB是地址!GPIO_InitStruct是指針,傳遞過去后的倆個實參數(shù)都是指針。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

以上配置了GPIOB是為了點亮LED0,現(xiàn)配置LED1(PE5)的GPIO,參考上面的程序:

GPIO_InitTypeDef GPIO_InitStruct;//形參2GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//形參2.mode=推挽輸出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//形參2.pin=5GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//形參2.speed=50MHZGPIO_Init(GPIOB,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;GPIO_Init(GPIOE,&GPIO_InitStruct);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

因為之前設(shè)置了mode和speed,而實參2是沒有指向的,即并不能知道實參2屬于實參1,所以哪怕再重新定義一個GPIOE的實參2,重新定義mode和speed也沒有意義,所以就可以省略了。

接下來可以將LED引腳置高電平,熄滅LED。使初始狀態(tài)下LED是滅的。

int main(void){ GPIO_InitTypeDef GPIO_InitStruct;//形參2GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//形參2.mode=推挽輸出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//形參2.pin=5GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//形參2.speed=50MHZGPIO_Init(GPIOB,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;GPIO_Init(GPIOE,&GPIO_InitStruct);GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_SetBits(GPIOE, GPIO_Pin_5);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2、RCC_APB2PeriphClockCmd()

之前說過,GPIO是掛載在APB2總線上的外設(shè),所以在對GPIO的時鐘進(jìn)行設(shè)置時,通過函數(shù)RCC_APB2PeriphClockCmd()來實現(xiàn)。打開RCC.h頭文件,找到時鐘函數(shù)

同樣的方法確定形參類型

形參1:

形參2:

所以程序:(注意時鐘配置函數(shù)應(yīng)該放在最前面

GPIO_InitTypeDef GPIO_InitStruct;//形參2RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOE , ENABLE);GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//形參2.mode=推挽輸出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//形參2.pin=5GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//形參2.speed=50MHZGPIO_Init(GPIOB,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;GPIO_Init(GPIOE,&GPIO_InitStruct);GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_SetBits(GPIOE, GPIO_Pin_5);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

加入延時函數(shù),形成流水燈:(只在Main.c文件編程)
其中GPIO_SetBits(GPIOB, GPIO_Pin_5)是將PB5引腳置1;GPIO_ReSetBits(GPIOB, GPIO_Pin_5)是將PB5引腳置0
(是通過庫函數(shù)對BSRR和BRR寄存器操作完成置0置1,下一博客會涉及到)

#include "stm32f10x.h" #include "delay.h"int main(void){ GPIO_InitTypeDef GPIO_InitStruct;//形參2RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOE , ENABLE);GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//形參2.mode=推挽輸出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//形參2.pin=5GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//形參2.speed=50MHZGPIO_Init(GPIOB,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;GPIO_Init(GPIOE,&GPIO_InitStruct);GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_SetBits(GPIOE, GPIO_Pin_5);delay_init(); //延時函數(shù)初始化 while(1){GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_SetBits(GPIOE, GPIO_Pin_5);delay_ms(1000); //注意包含頭文件delay.h,這個好像是正點原子官方寫的GPIO_ResetBits(GPIOB, GPIO_Pin_5);GPIO_ResetBits(GPIOE, GPIO_Pin_5);delay_ms(1000); }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

3、將配置函數(shù)放在led.c和led.h文件

在LED使用的工程文件夾新建一個LED文件夾

進(jìn)行下一步驟:


創(chuàng)建一個text文件,命名為led.h,保存在LED group中

將頭文件添加進(jìn)來


同理。新建一個led.c文件,將.c文件也添加進(jìn)來

上述步驟是創(chuàng)建一個LED Group,現(xiàn)在將頭文件添加進(jìn)來:


找到剛剛創(chuàng)建的文件夾并添加


上述步驟是為了之后調(diào)用里面生成的led.c和led.h

編輯頭文件:
固定格式:

#ifndef 一個未定義字符串 #define 一個未定義字符串#include ... #include ... //各種需要在本.h文件中用到的頭文件 ... ...//一些函數(shù)聲明、甚至定義 #endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

本實驗led.h文件可這樣寫:

#ifndef __LED_H //led.h文件 #define __LED_H void LED_Init(void);//初始化 #endif
  • 1
  • 2
  • 3
  • 4

接下來編輯led.c文件
需要有本.c文件用到的頭文件,如果要用到別的文件中定義的變量,可以采用外部聲明重新聲明該變量。在.c文件實現(xiàn).h文件聲明的函數(shù)

將我們之前main函數(shù)中關(guān)于GPIO配置和時鐘聲明的函數(shù)移植過來得到完整的LED程序:

/**led.h**/ #ifndef __LED_H //led.h文件 #define __LED_H void LED_Init(void);//初始化 #endif/**led.c**/ #include "led.h" #include "stm32f10x.h" void LED_Init(void) {GPIO_InitTypeDef GPIO_InitStruct;//形參2RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOE , ENABLE);GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//形參2.mode=推挽輸出GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;//形參2.pin=5GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//形參2.speed=50MHZGPIO_Init(GPIOB,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;GPIO_Init(GPIOE,&GPIO_InitStruct);GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_SetBits(GPIOE, GPIO_Pin_5); }/**main.c**/ #include "stm32f10x.h" #include "delay.h" #include "led.h"int main(void){ LED_Init();delay_init(); //延時函數(shù)初始化 while(1){GPIO_SetBits(GPIOB, GPIO_Pin_5);GPIO_SetBits(GPIOE, GPIO_Pin_5);delay_ms(1000); //注意包含頭文件delay.h,這個好像是正點原子官方寫的GPIO_ResetBits(GPIOB, GPIO_Pin_5);GPIO_ResetBits(GPIOE, GPIO_Pin_5);delay_ms(1000); }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

三、點亮LED(寄存器版本)

1、新建工程、添加led文件

畢竟是32系列第一個博客,還是希望詳細(xì)一點,之后的實驗就會慢慢省略一部分東西,寄存器版本完整來一遍

打開模板文件,如果沒有,就把LED庫函數(shù)例程打開,刪掉led.c和led.h,當(dāng)做以后所有實驗的模板就行了。

一般情況下,應(yīng)該【HARDWARE】中創(chuàng)建.c文件。也可以在文件【HARDWARE】之外建,看個人習(xí)慣。

如果懶得去搞模板,就用我這個吧

先將模板文件拷過來,在HARDWARE文件夾下創(chuàng)建LED文件夾

打開模板文件

新建兩個text文件,保存在剛剛創(chuàng)建的LED文件夾下,并改名為led.c、led.h

將led.c文件添加進(jìn)工程

將LED文件目錄添加進(jìn)來



現(xiàn)在進(jìn)入實戰(zhàn)

led.h編輯,之前庫函數(shù)版本講過了,直接附代碼:

#ifndef LED_H //led.h文件 #define LED_H int LED_Init(void); #endif
  • 1
  • 2
  • 3
  • 4

led.c文件編輯
開始還是老規(guī)矩:

#include "led.h" #include "stm32F10x.h"int LED_Init(void) {}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2、配置時鐘

打開《STM32中文參考手冊》7.3.7 APB2外設(shè)時鐘使能寄存器(RCC_APB2ENR)

寄存器下一博客總結(jié),現(xiàn)在只需知道,APB2外設(shè)時鐘使能寄存器的第3位和第6位分別對應(yīng)GPIOB(LED0、DS0)和GPIOE(LED1、DS1)

時鐘使能代碼如下:

RCC->APB2ENR|=1<<3; RCC->APB2ENR|=1<<6;
  • 1
  • 2

解釋一下:

首先RCC->APB2ENR是對外設(shè)時鐘使能寄存器的訪問

RCC->APB2ENR|=1的意思是:RCC->APB2ENR=RCC->APB2ENR|0x00000001(32位寄存器),也就是說將該寄存器的第0位軟件置1,其它位保持不變。"<<3"是將剛剛設(shè)置的那個第0位的1左移3位,也就是此時第3位為1.同理“<<6”是將第6位設(shè)置為1;此時就使能了GPIOB和GPIOE的時鐘

3、GPIO配置

用到端口配置寄存器,由于是對PB5、PE5的配置,是低位IO口(Px0~Px7是低位、Px8 ~Px15是高位),所以用到端口配置低寄存器GPIOx_CRL

打開《STM332中文參考手冊》

看到第21、20位控制模式和速度,為50M輸出,所以這兩位是11;23 、22控制哪種輸出,為推挽輸出,所以這兩位為00,所以GPIOx_CRL的狀態(tài)值為:0x00300000;程序如下:

GPIOB->CRL&=0xff0fffff; //PB5GPIOB->CRL|=0x00300000;GPIOE->CRL&=0xff0fffff; //PE5GPIOE->CRL|=0x00300000;
  • 1
  • 2
  • 3
  • 4
  • 5

解釋一下:

GPIOB->CRL&=0xff0fffff 是將GPIOB的20、21、22、23這四位置0,其它位保持不變;

GPIOB->CRL|=0x00300000是將GPIOB的20、21、22、23這四位置1,其它位保持不變;

此時配置好了,然后可以給IO口賦初值,如開始時讓LED處于熄滅狀態(tài),則PB5、PE5均置1。用到的寄存器:端口輸出數(shù)據(jù)寄存器GPIOx_ODR

代碼:

GPIOB->ODR|=1<<5;GPIOE->ODR|=1<<5;
  • 1
  • 2

led.c文件完整代碼:

#include "led.h" //led.c文件 #include "stm32F10x.h" int LED_Init(void) {RCC->APB2ENR|=1<<3;RCC->APB2ENR|=1<<6;GPIOB->CRL&=0xff0fffff; //PB5GPIOB->CRL|=0x00300000;GPIOE->CRL&=0xff0fffff; //PE5GPIOE->CRL|=0x00300000;GPIOB->ODR|=1<<5;GPIOE->ODR|=1<<5; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

4、主函數(shù)代碼編寫

進(jìn)入主函數(shù)后,首先應(yīng)調(diào)用剛剛寫的LED初始化函數(shù),完成GPIO配置;程序會用到延時函數(shù),將延時函數(shù)也初始化,代碼:(頭文件包含led.h)

#include "sys.h"#include "delay.h"#include "led.h"int main(void){ LED_Init();delay_init();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

然后在死循環(huán)中,對PB5和PE5 IO口賦值就行了,還是用到端口輸出數(shù)據(jù)寄存器GPIOx_ODR

不過給IO口置0時,需要注意,應(yīng)該和0xffffffdf進(jìn)行與運算

GPIOB->ODR&=0xffffffdf;//置0GPIOE->ODR&=0xffffffdf;//置0
  • 1
  • 2

或者移位運算,將第0位置0再向左移5位

GPIOB->ODR&=0xfffffffe<<5;GPIOE->ODR&=0xfffffffe<<5;
  • 1
  • 2

給IO口置1就和0x00000020進(jìn)行或運算

GPIOB->ODR|=0x00000020;GPIOE->ODR|=0x00000020;
  • 1
  • 2

或者直接位移運算,先和0x00000001進(jìn)行或運算,使第0位置1,再將第0位向左移動5,代碼:

GPIOB->ODR|=1<<5;GPIOE->ODR|=1<<5;
  • 1
  • 2

main.c文件完整程序:

#include "sys.h" //main.c文件 #include "delay.h" #include "led.h"int main(void){ LED_Init();delay_init();while(1){GPIOB->ODR&=0xffffffdf;//置0GPIOE->ODR&=0xffffffdf;//置0//GPIOB->ODR&=0xfffffffe<<5;//GPIOE->ODR&=0xfffffffe<<5;delay_ms(1000);GPIOB->ODR|=0x00000020;GPIOE->ODR|=0x00000020;//GPIOB->ODR|=1<<5;//GPIOE->ODR|=1<<5;delay_ms(1000);}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

附1 PXout()與PXin()

打開sys.h頭文件


定義了PXout()與PXin()函數(shù),用法為:

點亮熄滅DS0、DS1,只需:

PBout(5)=0;//點亮 PEout(5)=0;//點亮 delay_ms(1000); PBout(5)=1;//熄滅 PEout(5)=1;//熄滅 delay_ms(1000);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

或者定義:

#define LED0 PBout(5) #define LED1 PEout(5)LED0=0;//點亮 LED1=0;//點亮 delay_ms(1000); LED0=1;//熄滅 LED1=1;//熄滅 delay_ms(1000);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

總結(jié)

以上是生活随笔為你收集整理的STM32F103五分钟入门系列(一)跑马灯(库函数+寄存器)+加编程模板+GPIO总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。