stm32 的 io 採用分組管理(gpioa、gpiob…),每組 16 個 io…對應的列舉型別定義:
typedef enumgpiomode_typedef;
每個 io 口可以自由程式設計, 但 io 口暫存器必須要按 32 位字被訪問。
void gpio_init(gpio_typedef* gpiox, gpio_inittypedef* gpio_initstruct);
typedef structgpio_inittypedef;
乙個例子:
gpio_inittypedef gpio_initstructure;
gpio_initstructure.gpio_pin = gpio_pin_5; //led0-->pb.5 埠配置
gpio_initstructure.gpio_mode = gpio_mode_out_pp; //推挽輸出
gpio_initstructure.gpio_speed = gpio_speed_50mhz; //速度 50mhz
gpio_init(gpiob, &gpio_initstructure); //根據設定引數配置 gpio
其中 gpio 的速度也是通過列舉型別定義:
typedef enumgpiospeed_typedef;
uint8_t gpio_readinputdatabit(gpio_typedef* gpiox, uint16_t gpio_pin)
函式的引數同上,無需多說。
乙個例子,需要讀gpioa pin_5的電平狀態,就可以這樣做:
gpio_readinputdatabit(gpioa, gpio_pin_5);
返回值是 1(bit_set)或 0(bit_reset)
void gpio_write(gpio_typedef* gpiox, uint16_t portval);
該函式一般用來一次性設定乙個gpio的多個埠值。
void gpio_setbits(gpio_typedef* gpiox, uint16_t gpio_pin);
void gpio_resetbits(gpio_typedef* gpiox, uint16_t gpio_pin)
stm32 有很多的內建外設,這些外設的外部引腳都是與 gpio 復用的乙個 gpio 如果可以復用為內建外設的功能引腳, 那麼當這個 gpio 作為內建外設使用的時候,就叫做復用。
例如, stm32f103zet6 有 5 個串列埠, 串列埠 1 的引腳對應的 io 為 pa9, pa10。pa9, pa10 預設功能是 gpio, 所以當 pa9, pa10 引腳作為串列埠 1 的 tx, rx 引腳使用的時候,那就是埠復用。
為了使不同器件封裝的外設 io 功能數量達到最優,可以把一些復用功能重新對映到其他一些引腳上。每個內建外設都有若干個輸入輸出引腳,一般這些引腳的輸出埠都是固定不變的,為了讓設計工程師可以更好地安排引腳的走向和功能,在 stm32 中引入了外設引腳重對映的概念,即乙個外設的引腳除了具有預設的埠外,還可以通過設定重對映暫存器的方式,把這個外設的引腳對映到其它的埠。
由上表可知,預設情況下串列埠 1 復用的是 pa9,pa10。假設在某個專案中這兩個引腳已經被占用,但又要用到串列埠 1 ,此時就可以將 tx 和 rx 重新對映到引腳 pb6 和 pb7 上去。
注意,使用重對映功能時,需要額外使能afio功能時鐘,然後呼叫重對映函式。
使能 afio 時鐘:
rcc_apb2periphclockcmd(rcc_apb2periph_afio, enable);
開啟重對映:
gpio_pinremapconfig(gpio_remap_usart1, enable);
位帶操作簡單來說就是把每個位元膨脹為乙個 32 位的字, 當訪問這些字的時候就達到了訪問位元的目的。 假設乙個暫存器有 32 位,那麼可以把每乙個位元位對映到乙個 32 位位址上。這樣,當我們訪問其中的位址時就達到訪問對應位元位的目的。當我們需要往乙個位元位寫 1 時,只需要往其對應的位址寫 1 即可。
正點原子幫我們實現了一種…
#define bitband(addr, bitnum) ((addr & 0xf0000000)+0x2000000+((
addr &0xfffff)<<5)+(bitnum<<2))
#define mem_addr(addr) *((volatile unsigned long *)(addr))
#define bit_addr(addr, bitnum) mem_addr(bitband(addr, bitnum))
//io 口位址對映
#define gpioa_odr_addr (gpioa_base+12) //0x4001080c
#define gpiob_odr_addr (gpiob_base+12) //0x40010c0c
#define gpioc_odr_addr (gpioc_base+12) //0x4001100c
#define gpiod_odr_addr (gpiod_base+12) //0x4001140c
#define gpioe_odr_addr (gpioe_base+12) //0x4001180c
#define gpiof_odr_addr (gpiof_base+12) //0x40011a0c
#define gpiog_odr_addr (gpiog_base+12) //0x40011e0c
#define gpioa_idr_addr (gpioa_base+8) //0x40010808
#define gpiob_idr_addr (gpiob_base+8) //0x40010c08
#define gpioc_idr_addr (gpioc_base+8) //0x40011008
#define gpiod_idr_addr (gpiod_base+8) //0x40011408
#define gpioe_idr_addr (gpioe_base+8) //0x40011808
#define gpiof_idr_addr (gpiof_base+8) //0x40011a08
#define gpiog_idr_addr (gpiog_base+8) //0x40011e08
//io 口操作,只對單一的 io 口!
//確保 n 的值小於 16!
#define paout(n) bit_addr(gpioa_odr_addr, n) //輸出
#define pain(n) bit_addr(gpioa_idr_addr, n) //輸入
#define pbout(n) bit_addr(gpiob_odr_addr, n) //輸出
#define pbin(n) bit_addr(gpiob_idr_addr, n) //輸入
#define pcout(n) bit_addr(gpioc_odr_addr, n) //輸出
#define pcin(n) bit_addr(gpioc_idr_addr, n) //輸入
#define pdout(n) bit_addr(gpiod_odr_addr, n) //輸出
#define pdin(n) bit_addr(gpiod_idr_addr, n) //輸入
#define peout(n) bit_addr(gpioe_odr_addr, n) //輸出
#define pein(n) bit_addr(gpioe_idr_addr, n) //輸入
#define pfout(n) bit_addr(gpiof_odr_addr, n) //輸出
#define pfin(n) bit_addr(gpiof_idr_addr, n) //輸入
#define pgout(n) bit_addr(gpiog_odr_addr, n) //輸出
#define pgin(n) bit_addr(gpiog_idr_addr, n) //輸入
有了以上**就可以很方便的使用 io 口了。當我們需要讓 gpioa 的第 6 個 io 輸出高, 就可以這樣:
paout(5) = 1; //0-> 第乙個 io 口, 5->第六個 io 口;
當我們要獲得 gpioa 的第 6 個 io 口的狀態時,就可以直接讀取 pain(5)。
if(pain(5) == 1)
位帶操作pbin(n)等同於庫函式 gpio_readinputdatabit(gpiob, gpio_pin_n)。用庫函式實現的好處是在各個 stm32 晶元上面的移植性非常好, 不需要修改任何**。 用位帶操作的好處是簡潔。
重對映我們同樣要使能復用功能的時候講解的 2 個時鐘外,還要使能 afio 功能時鐘,然後要呼叫重對映函式。
注:本文參考正點原子《stm32f1 開發指南(精英版)-庫函式版本_v1.0》
STM32輸入捕獲簡介
輸入捕獲模式可以用來測量脈衝寬度或者測量頻率。stm32的定時器,除了tim6和tim7,其他定時器都有輸入捕獲功能。stm32的輸入捕獲,簡單的說就是通過檢測timx chx上的邊沿訊號,在邊沿訊號發生跳變 比如上公升沿 下降沿 的時候,將當前定時器的值 timx cnt 存放到對應的通道的捕獲 ...
STM32輸入捕獲簡介
輸入捕獲模式可以用來測量脈衝寬度或者測量頻率。stm32的定時器,除了tim6和tim7,其他定時器都有輸入捕獲功能。stm32的輸入捕獲,簡單的說就是通過檢測timx chx上的邊沿訊號,在邊沿訊號發生跳變 比如上公升沿 下降沿 的時候,將當前定時器的值 timx cnt 存放到對應的通道的捕獲 ...
STM32基礎學習
最近在學stm32,遇到了一些問題,也解決了一些,望大家糾正。韌體庫外設驅動檔案引入方法 1 加入你要加入的.c檔案 2 在path中加入你的相對應的.h 3 就是一定要將stm32f10x conf.h配置中的相對應的標頭檔案取消注釋。暫存器版本的error l6218e undefined sy...