版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
第十一章
STM32單片機的使用電子設計基礎與創(chuàng)新實踐教程01STM32單片機概述PARTONESTM32系列MCU是意法半導體(ST)公司推出的基于ARM內核的32位微控制器,包括主流MCU、高性能MCU、超低功耗MCU、無線MCU等。
以STM32F407xx為例,它包含高速存儲器(1MB的Flash,最高可達192KB的SRAM、最高可達4KB的備份SRAM)、3個12位ADC、2個DAC、2個通用32位定時/計數(shù)器、1個真實隨機數(shù)發(fā)生器(RNG),并且提供各類標準及高級通信接口(最多3個IIC、3個SPI/IIS接口、4個USART接口、2個CAN總線接口、1個SDIO/MMC接口、1個全速USBOTG接口和1個高速USBOTG接口、網(wǎng)口及相機接口等);在-40~+105℃的溫度范圍內工作,電源電壓為1.8~3.6V,當設備使用外部電源監(jiān)控器在0~70℃的溫度范圍內運行時,電源電壓可降至1.7V,并且擁有一套全面的節(jié)能模式,以滿足低功耗應用設計要求。STM32系列單片機介紹及選型
STM32系列單片機引腳定義我們可以通過數(shù)據(jù)手冊(Datasheet)及參考手冊獲取引腳定義,其引腳定義的說明如圖所示。STM32系列單片機總線架構及存儲器映射1.STM32F407xx總線架構STM32F407xx存儲系統(tǒng)由32位多層AHB總線矩陣組成,連接了:(1)8個主控單元。? I-總線,D-總線和S-總線;? DMA1存儲器總線;? DMA2存儲器總線;? DMA3存儲器總線;? 以太網(wǎng)DMA總線;? USBOTGHSDMA總線。(2)7個從單元。? 內部FlashICODE總線;? 內部FlashDCODE總線;? 主要內部SRAM1(112KB);? 輔助內部SRAM2(16KB);? 輔助內部SRAM3(64KB);? AHB1外設;? AHB2外設;? FSMC。2.STM32F407xx存儲器映射存儲器本身不具有地址,給存儲器分配地址的過程就是存儲器映射,STM32F407xx的存儲器映射。STM32的地址線是32位的,對應4GB的存儲空間,被分為8塊(Block),每塊為512MB。我們重點介紹Block2,它被分配給外設,根據(jù)總線分為APB1、APB2、AHB1、AHB2,具體劃分如表11-1-3所示。它以4字節(jié)(32位)為一個寄存器單元,C語言中通過指針來訪問這些寄存器。STM32系列單片機總線架構及存儲器映射3.STM32F407外設地址映射①總線:STM32F407連接有4條總線,不同總線掛載不同的外設,APB掛載低速外設,AHB掛載高速外設??偩€的最低地址稱為該總線的基地址,總線基地址如表所示。②外設:總線上掛著各種各樣的外設,這些外設也被分配不同的地址,具體外設的邊界地址參考STM32F407參考手冊中的存儲器映射部分,以GPIO為例,GPIO是掛在AHB1總線上的外設,其基地址如表所示。③外設寄存器:每個外設都有多個不同功能的寄存器,每個寄存器占4字節(jié)(32位),每個寄存器都會被分配不同的地址,以GPIOF端口為例,其寄存器地址如表所示,編寫C語言程序時通過“外設基地址+偏移”來描述寄存器的地址。STM32系列單片機總線架構及存儲器映射STM32系列單片機總線架構及存儲器映射通過“AHB1基地址+相對AHB1總線基地址的偏移+相對GPIOF地址的偏移”可以獲取GPIOF的相關寄存器地址,例如0x40020000+0x00001400+0x00=0x40021400,可獲取GPIOF_MODER的地址。4.C語言對寄存器的封裝①封裝總線和外設基地址。為方便理解和記憶,通過宏定義方式進行封裝。程序清單11-1-1 stm32f4xx.h程序/*!<Defines'read/write'permissions*/#define__IOvolatile
/*!<Peripheralbaseaddressinthealiasregion*/#definePERIPH_BASE((uint32_t)0x40000000)/*!<Peripheralmemorymap*/#defineAPB1PERIPH_BASEPERIPH_BASE#defineAPB2PERIPH_BASE(PERIPH_BASE+0x00010000)#defineAHB1PERIPH_BASE(PERIPH_BASE+0x00020000)#defineAHB2PERIPH_BASE(PERIPH_BASE+0x10000000)/*!<AHB1peripherals*/#defineGPIOA_BASE(AHB1PERIPH_BASE+0x0000)#defineGPIOB_BASE(AHB1PERIPH_BASE+0x0400)#defineGPIOC_BASE(AHB1PERIPH_BASE+0x0800)#defineGPIOD_BASE(AHB1PERIPH_BASE+0x0C00)#defineGPIOE_BASE(AHB1PERIPH_BASE+0x1000)#defineGPIOF_BASE(AHB1PERIPH_BASE+0x1400)#defineGPIOG_BASE(AHB1PERIPH_BASE+0x1800)#defineGPIOH_BASE(AHB1PERIPH_BASE+0x1C00)#defineGPIOI_BASE(AHB1PERIPH_BASE+0x2000)#defineGPIOJ_BASE(AHB1PERIPH_BASE+0x2400)#defineGPIOK_BASE(AHB1PERIPH_BASE+0x2800)②封裝寄存器列表。GPIOA~GPIOK都有一組功能相同的寄存器,它們只是地址不同,為方便訪問,通過結構體進行封裝。程序清單11-1-2 stm32f4xx.h程序STM32系列單片機總線架構及存儲器映射typedefstruct{__IOuint32_tMODER;/*!<GPIOportmoderegister,Addressoffset:0x00*/__IOuint32_tOTYPER;/*!<GPIOportoutputtyperegister,Addressoffset:0x04*/__IOuint32_tOSPEEDR;/*!<GPIOportoutputspeedregister,Addressoffset:0x08*/__IOuint32_tPUPDR;/*!<GPIOportpull-up/pull-downregister,Addressoffset:0x0C*/__IOuint32_tIDR;/*!<GPIOportinputdataregister,Addressoffset:0x10*/__IOuint32_tODR;/*!<GPIOportoutputdataregister,Addressoffset:0x14*/__IOuint16_tBSRRL;/*!<GPIOportbitset/resetlowregister,Addressoffset:0x18*/__IOuint16_tBSRRH;/*!<GPIOportbitset/resethighregister,Addressoffset:0x1A*/__IOuint32_tLCKR;/*!<GPIOportconfigurationlockregister,Addressoffset:0x1C*/__IOuint32_tAFR[2];/*!<GPIOalternatefunctionregisters,Addressoffset:0x20-0x24*/}GPIO_TypeDef;這段代碼用typedef關鍵字聲明了名為GPIO_TypeDef的結構體類型,內有10個變量。結構體內變量的存儲空間是連續(xù)的,32位變量占4字節(jié),16位變量占2字節(jié)。結構體各個變量相對結構體首地址的偏移與GPIO各個寄存器地址的偏移一致,只要給結構體設置好首地址,就可以確定各個寄存器的地址,然后通過結構體指針訪問寄存器。程序清單11-1-3 stm32f4xx.h程序STM32系列單片機總線架構及存儲器映射/*使用GPIO_TypeDef把地址強制轉換成指針*/#defineGPIOA((GPIO_TypeDef*)GPIOA_BASE)#defineGPIOB((GPIO_TypeDef*)GPIOB_BASE)#defineGPIOC((GPIO_TypeDef*)GPIOC_BASE)#defineGPIOD((GPIO_TypeDef*)GPIOD_BASE)#defineGPIOE((GPIO_TypeDef*)GPIOE_BASE)#defineGPIOF((GPIO_TypeDef*)GPIOF_BASE)#defineGPIOG((GPIO_TypeDef*)GPIOG_BASE)#defineGPIOH((GPIO_TypeDef*)GPIOH_BASE)#defineGPIOI((GPIO_TypeDef*)GPIOI_BASE)#defineGPIOJ((GPIO_TypeDef*)GPIOJ_BASE)#defineGPIOK((GPIO_TypeDef*)GPIOK_BASE)#defineCRC((CRC_TypeDef*)CRC_BASE)#defineRCC((RCC_TypeDef*)RCC_BASE)這段代碼使用GPIO_TypeDef把地址強制轉換成指針,這樣可以使用定義好的宏直接訪問GPIOF端口的寄存器。時鐘是單片機的“心臟”,是單片機的驅動源,由于STM32有很多外設,每個外設需要的時鐘頻率不同,所以需要多個時鐘源。使用任何一個外設都必須打開相應的時鐘,當不使用某個外設的時候,就把它的時鐘關掉,從而降低系統(tǒng)的功耗。STM32F407xx系列單片機時鐘樹如圖所示,它有5個重要的時鐘源:高速內部時鐘(HSI)、高速外部時鐘(HSE)、低速內部時鐘(LSI)、低速外部時鐘(LSE)、鎖相環(huán)時鐘(PLL)。(1)HSI是一個RC振蕩電路,頻率為16MHz,可以作為系統(tǒng)時鐘或者PLL的輸入。(2)HSE可以外接晶振或者外部時鐘,頻率范圍為4MHz~26MHz,可以作為系統(tǒng)時鐘或者PLL的輸入。(3)LSI是一個RC振蕩電路,頻率為32kHz,為看門狗和自動喚醒單元提供時鐘。(4)LSE外接頻率為32.768kHz的晶振,主要作為RTC的時鐘源。(5)STM32F407xx系列單片機有兩個PLL:①主PLL由HSE或者HSI提供時鐘信號,并具有兩個不同的輸出時鐘。第一個輸出PLLCLK用于生成高速的系統(tǒng)時鐘(最高168MHz);第二個輸出PLL48CK用于生成USBOTGFS的時鐘(48MHz)、隨機數(shù)發(fā)生器的時鐘和SDIO時鐘。②專用PLL(PLLIISCLK)用于生成精確時鐘,從而在IIS接口實現(xiàn)高品質音頻性能。STM32系列單片機時鐘控制STM32系列單片機時鐘控制時鐘設置函數(shù)如下。程序清單11-1-4 sys.c程序//時鐘設置函數(shù)//Fvco=Fs*(plln/pllm);//Fsys=Fvco/pllp=Fs*(plln/(pllm*pllp));//Fusb=Fvco/pllq=Fs*(plln/(pllm*pllq));//Fvco:VCO頻率//Fsys:系統(tǒng)時鐘頻率//Fusb:USB,SDIO,RNG等的時鐘頻率//Fs:PLL輸入時鐘頻率,可以是HSI,HSE等//plln:主PLL倍頻系數(shù)(PLL倍頻),取值范圍:64~432//pllm:主PLL和音頻PLL分頻系數(shù)(PLL之前的分頻),取值范圍:2~63//pllp:系統(tǒng)時鐘的主PLL分頻系數(shù)(PLL之后的分頻),取值范圍:2,4,6,8.(僅限這4個值!)STM32系列單片機時鐘控制//pllq:USB/SDIO/隨機數(shù)發(fā)生器等的主PLL分頻系數(shù)(PLL之后的分頻),取值范圍:2~15//外部晶振頻率為8MHz的時候,推薦值:plln=336,pllm=8,pllp=2,pllq=7.//得到:Fvco=8*(336/8)=336MHz//Fsys=336/2=168MHz//Fusb=336/7=48MHz//返回值:0,成功;1,失敗。u8Sys_Clock_Set(u32plln,u32pllm,u32pllp,u32pllq){u16retry=0;u8status=0;RCC->CR|=1<<16; //HSE開啟while(((RCC->CR&(1<<17))==0)&&(retry<0X1FFF))retry++;//等待HSERDYif(retry==0X1FFF)status=1; //HSE無法就緒else{RCC->APB1ENR|=1<<28; //電源接口時鐘使能PWR->CR|=3<<14; //高性能模式,時鐘頻率可達168MHzRCC->CFGR|=(0<<4)|(5<<10)|(4<<13);//HCLK不分頻;APB14分頻;APB22分頻RCC->CR&=~(1<<24); //關閉主PLLRCC->PLLCFGR=pllm|(plln<<6)|(((pllp>>1)-1)<<16)|(pllq<<24)|(1<<22); //配置主PLL,PLL時鐘源來自HSESTM32系列單片機時鐘控制RCC->CR|=1<<24; //打開主PLLwhile((RCC->CR&(1<<25))==0); //等待PLL準備好FLASH->ACR|=1<<8; //指令預取使能FLASH->ACR|=1<<9; //指令cache使能FLASH->ACR|=1<<10; //數(shù)據(jù)cache使能FLASH->ACR|=5<<0; //5個CPU等待周期RCC->CFGR&=~(3<<0); //清零RCC->CFGR|=2<<0; //選擇主PLL作為系統(tǒng)時鐘while((RCC->CFGR&(3<<2))!=(2<<2));//等待主PLL作為系統(tǒng)時鐘成功}returnstatus;}在Sys_Clock_Set函數(shù)中,設置了APB1為4分頻,APB2為2分頻,HCLK不分頻,同時選擇PLLCLK作為系統(tǒng)時鐘。該函數(shù)有4個參數(shù),具體意義和計算方法見函數(shù)前面的說明。一般推薦設置為Sys_Clock_Set(336,8,2,7),即可設置STM32F407運行在168MHz的頻率下,APB1時鐘頻率為42MHz,APB2時鐘頻率為84MHz,USB/SDIO/隨機數(shù)發(fā)生器時鐘頻率為48MHz。02STM32單片機軟件開發(fā)PARTONEGPIO口結構及寄存器配置圖示為STM32的GPIO口的基本結構,其可通過軟件配置成8種模式:輸入浮空、輸入上拉、輸入下拉、模擬輸入/輸入、開漏輸出、推挽輸出、復用功能的推挽輸出、復用功能的開漏輸出。每個通用I/O口包括4個32位配置寄存器(GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR和GPIOx_PUPDR)、2個32位數(shù)據(jù)寄存器(GPIOx_IDR和GPIOx_ODR)、1個32位置位/復位寄存器(GPIOx_BSRR)、1個32位鎖定寄存器(GPIOx_LCKR)和2個32位復用功能選擇寄存器(GPIOx_AFRH和GPIOx_AFRL)。GPIO口的每個位均可自由編程,但I/O口寄存器必須按32位字、半字或字節(jié)進行訪問。1.配置寄存器GPIOx_MODER0寄存器用于選擇I/O方向(輸入、輸出、AF、模擬)。GPIOx_OTYPER和GPIOx_OSPEEDR寄存器分別用于選擇輸出類型(推挽或開漏)和速度,GPIOx_PUPDR寄存器用于選擇上拉/下拉。其I/O口位配置表如表所示。GPIO口結構及寄存器配置①GPIOportmoderegister(GPIO口模式寄存器)(GPIOx_MODER)(x=A,B,…,I,J,K)。Addressoffset(偏移地址):0x00。GPIO口結構及寄存器配置MODERy[1:0](y=0,1,2,…,15):端口x配置位,用于配置I/O口的方向。00:輸入。01:通用輸出。10:復用功能。11:模擬信號輸入/輸出。②GPIOportoutputtyperegister(GPIO口輸出類型寄存器)(GPIOx_OTYPER)(x=A,B,…,I,J,K)Addressoffset(偏移地址):0x04。OTy(y=0,1,2,…,15):端口x配置位,用于配置I/O口的輸出類型。0:輸出推挽。1:輸出開漏。③GPIOportoutputspeedregister(GPIO口輸出速度寄存器)(GPIOx_OSPEEDR)(x=A,B,…,I,J,K)。Addressoffset(偏移地址):0x08。OSPEEDRy[1:0](y=0,1,…,15):端口x配置位,用于配置I/O口的速度。00:低速。01:中速。10:高速。11:超高速。GPIO口結構及寄存器配置④GPIOportpull-up/pull-downregister(GPIO口上拉/下拉寄存器)(GPIOx_PUPDR)(x=A,B,…,I,J,K)。Addressoffset(偏移地址):0x0C。PUPDRy[1:0](y=0,1,…,15):端口x配置位,用于配置I/O口的上拉和下拉。00:無上拉或下拉。01:上拉。10:下拉。11:保留。GPIO口結構及寄存器配置①GPIOportinputdataregister(GPIO口輸入數(shù)據(jù)寄存器)(GPIOx_IDR)(x=A,B,…,I,J,K)。Addressoffset(偏移地址):0x10。IDRy(y=0,1,…,15):端口x輸入數(shù)據(jù)位,這些位是只讀位,并且只能在word模式下訪問,儲存的是相應I/O口的輸入值。②GPIOportoutputdataregister(GPIO口輸出數(shù)據(jù)寄存器)(GPIOx_ODR)(x=A,B,…,I,J,K)。Addressoffset(偏移地址):0x14。ODRy(y=0,1,…,15):端口x輸出數(shù)據(jù)位,這些位可讀寫,并且可以進行位操作。2.數(shù)據(jù)寄存器
每個GPIO口都具有2個16位數(shù)據(jù)寄存器:輸入數(shù)據(jù)寄存器(GPIOx_IDR)和輸出數(shù)據(jù)寄存器(GPIOx_ODR)。GPIOx_ODR用于存儲待輸出數(shù)據(jù),可對其進行讀/寫訪問。通過I/O口輸入的數(shù)據(jù)會存儲到輸入數(shù)據(jù)寄存器(GPIOx_IDR)中,它是一個只讀寄存器。GPIO口結構及寄存器配置通過對以上6個寄存器的介紹,我們結合實例來講解下STM32F407的I/O口設置,熟悉這幾個寄存器的使用。例如,設置PORTC的第12個I/O口(PC11)為推挽輸出,速度為100MHz,不帶上下拉電阻,并輸出高電平。代碼如下:RCC->AHB1ENR|=1<<2; //使能PORTC時鐘GPIOC->MODER&=~(3<<(11*2)); //先清除PC11原來的設置GPIOC->MODER|=1<<(11*2); //設置PC11為輸出模式GPIOC->OTYPER&=~(1<<11); //清除PC11原來的設置GPIOC->OTYPER|=0<<11; //設置PC11為推挽輸出GPIOC->OSPEEDR&=~(3<<(11*2)); //先清除PC11原來的設置GPIOC->OSPEEDR|=3<<(11*2); //設置PC11輸出速度為100MHzGPIOC->PUPDR&=~(3<<(11*2)); //先清除PC11原來的設置GPIOC->PUPDR|=0<<(11*2); //設置PC11不帶上下拉電阻GPIOC->ODR|=1<<11; //設置PC11輸出1(高電平)GPIO口結構及寄存器配置經(jīng)過以上介紹,我們便可以設計一個通用的GPIO設置函數(shù)來設置STM32F407的I/O口,即GPIO_Set函數(shù),該函數(shù)代碼如下:GPIO口結構及寄存器配置//GPIO通用設置//GPIOx:GPIOA~GPIOI.//BITx:0X0000~0XFFFF,位設置,每個位代表一個I/O口,第0位代表Px0,第1位代表Px1,依此類推.比如0X0101,代表同時設置Px0和Px8.//MODE:0~3;模式選擇,0,輸入(系統(tǒng)復位默認狀態(tài));1,普通輸出;2,復用功能;3,模擬輸入.//OTYPE:0/1;輸出類型選擇,0,推挽輸出;1,開漏輸出.//OSPEED:0~3;輸出速度設置,0,2MHz;1,25MHz;2,50MHz;3,100MHz.//PUPD:0~3:上下拉設置,0,不帶上下拉電阻;1,上拉電阻;2,下拉電阻;3,保留.//注意:在輸入模式(普通輸入/模擬輸入)下,OTYPE和OSPEED參數(shù)無效!!voidGPIO_Set(GPIO_TypeDef*GPIOx,u32BITx,u32MODE,u32OTYPE,u32OSPEED,u32PUPD){u32pinpos=0,pos=0,curpin=0;for(pinpos=0;pinpos<16;pinpos++){pos=1<<pinpos; //一個個位檢查curpin=BITx&pos; //檢查引腳是否要設置if(curpin==pos) //需要設置{GPIOx->MODER&=~(3<<(pinpos*2)); //先清除原來的設置GPIOx->MODER|=MODE<<(pinpos*2); //設置新的模式GPIO口結構及寄存器配置if((MODE==0X01)||(MODE==0X02)) //如果是輸出模式/復用功能模式{GPIOx->OSPEEDR&=~(3<<(pinpos*2)); //清除原來的設置GPIOx->OSPEEDR|=(OSPEED<<(pinpos*2)); //設置新的速度值
GPIOx->OTYPER&=~(1<<pinpos); //清除原來的設置GPIOx->OTYPER|=OTYPE<<pinpos; //設置新的輸出模式}GPIOx->PUPDR&=~(3<<(pinpos*2)); //先清除原來的設置GPIOx->PUPDR|=PUPD<<(pinpos*2); //設置新的上下拉模式}}}GPIO口結構及寄存器配置該函數(shù)支持對STM32F407的任何I/O口進行設置,并且支持同時設置多個I/O口(功能一致時),有了這個函數(shù),我們就可以大大簡化STM32F407的I/O口設置過程,比如同樣設置PC11為推挽輸出,還可利用GPIO_Set函數(shù)實現(xiàn),代碼如下:RCC->AHB1ENR|=1<<2; //使能PORTC時鐘GPIO_Set(PORTC,1<<11,1,0,3,0); //設置PC11推挽輸出,100MHz,不帶上下拉電阻GPIOC->ODR|=1<<11; //設置PC11輸出1(高電平)并且,開發(fā)板廠商為GPIO_Set定義了一系列的宏,這些宏在sys.h里面,如果全換成宏,則有GPIO_Set(PORTC,1<<11,1,0,3,0);可以寫成:GPIO_Set(PORTC,PIN11,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_NONE);這樣,雖然看起來長了一點,但是一眼便知參數(shù)設置的意義,具有很好的可讀性。3.置位/復位寄存器置位/復位寄存器(GPIOx_BSRR)是一個32位寄存器,它允許應用程序在輸出數(shù)據(jù)寄存器(GPIOx_ODR)中對各個單獨的數(shù)據(jù)位執(zhí)行置位和復位操作。置位/復位寄存器的大小是GPIOx_ODR的兩倍。GPIOx_ODR中的每個數(shù)據(jù)位對應于GPIOx_BSRR中的兩個控制位:BSRR(i)和BSRR(i+Size)。當寫入1時,BSRR(i)位會置位對應的ODR(i)位,BSRR(i+Size)位會清零ODR(i)對應的位。在GPIOx_BSRR中向任何位寫入0都不會對GPIOx_ODR中的對應位產(chǎn)生任何影響。如果在GPIOx_BSRR中同時嘗試對某個位執(zhí)行置位和清零操作,則置位操作優(yōu)先。GPIOportbitset/resetregister(GPIO口置位/復位寄存器)(GPIOx_BSRR)(x=A,B,…,I,J,K)。Addressoffset:0x18。Bits[31:16]BRy(y=0,1,…,15):端口x復位位,用于配置I/O口的輸出類型。0:無影響。1:對相應的ODRx位進行復位。Bits[15:0]BSy(y=0,1,…,15):端口x置位位,用于配置I/O口的輸出類型。0:無影響。1:對相應的ODRx位進行置位。GPIO口結構及寄存器配置4.復用功能寄存器復用功能寄存器GPIOx_AFRL和GPIOx_AFRH用來在每個GPIO口上復用多個可用的外設功能,可為每個I/O口選擇一個可用功能,其中AFRL控制0~7這8個I/O口,AFRH控制8~15這8個I/O口。①GPIOalternatefunctionlowregister(GPIO復用功能低位寄存器)(GPIOx_AFRL)(x=A,B,…,I,J,K)。Addressoffset(偏移地址):0x20。
Bits[31:0]AFRLy(y=0,1,…,7):端口x位y的復用功能選擇,用于配置I/O口的復用功能。0000:AF0。0001:AF1?!?111:AF15。GPIO口結構及寄存器配置4.復用功能寄存器②GPIOalternatefunctionhighregister(GPIO復用功能高位寄存器)(GPIOx_AFRH)(x=A,B,…,I,J,K)。Addressoffset(偏移地址):0x24。Bits[31:0]AFRLy(y=8,9,…,15):端口x位y的復用功能選擇,用于配置I/O口的復用功能。0000:AF0。0001:AF1?!?111:AF15。STM32F407xx系列單片機I/O口復用功能選擇如圖所示。GPIO口結構及寄存器配置例如,要用PC11復用的功能為SDIO_D3。因為引腳11是由AFRH[15:12]控制的,且屬于SDIO功能復用,所以要選擇AF12,即設置AFRH[15:12]=AF12,代碼如下:RCC->AHB1ENR|=1<<2; //使能PORTC時鐘GPIO_Set(PORTC,PIN11,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //設置PC11復用輸出,100MHz,上拉GPIOC->AFR[1]&=~(0X0F<<12); //清除PC11原來的設置GPIOC->AFR[1]|=12<<12; //設置PC11為AF12注意,在MDK里面,AFRL和AFRH被定義成AFR[0]和AFR[1]。經(jīng)過以上設置,我們就將PC11設置為復用功能輸出,且復用功能選擇SDIO_D3。同樣,我們將AFRL和AFRH的設置封裝成函數(shù),即GPIO_AF_Set函數(shù),該函數(shù)代碼如下://GPIO復用設置//GPIOx:GPIOA~GPIOI.//BITx:0~15,代表I/O引腳編號.//AFx:0~15,代表AF0~AF15.voidGPIO_AF_Set(GPIO_TypeDef*GPIOx,u8BITx,u8AFx){GPIOx->AFR[BITx>>3]&=~(0X0F<<((BITx&0X07)*4));GPIOx->AFR[BITx>>3]|=(u32)AFx<<((BITx&0X07)*4);}GPIO口結構及寄存器配置同樣,我們將AFRL和AFRH的設置封裝成函數(shù),即GPIO_AF_Set函數(shù),該函數(shù)代碼如下://GPIO復用設置//GPIOx:GPIOA~GPIOI.//BITx:0~15,代表I/O引腳編號.//AFx:0~15,代表AF0~AF15.voidGPIO_AF_Set(GPIO_TypeDef*GPIOx,u8BITx,u8AFx){GPIOx->AFR[BITx>>3]&=~(0X0F<<((BITx&0X07)*4));GPIOx->AFR[BITx>>3]|=(u32)AFx<<((BITx&0X07)*4);}GPIO口結構及寄存器配置通過該函數(shù),我們就可以很方便地設置任何一個I/O口的復用功能了。下面通過該函數(shù)設置PC11為SDIO_D3,代碼如下:RCC->AHB1ENR|=1<<2; //使能PORTC時鐘GPIO_Set(PORTC,PIN11,GPIO_MODE_AF,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU); //設置PC11復用輸出,100MHz,上拉GPIO_AF_Set(GPIOC,11,AF12); //設置PC11為AF12其中,PIN11和AF12是在sys.h里面定義好的宏。另外,需要注意GPIO_AF_Set函數(shù)每次只能設置1個I/O口的復用功能,如果有多個I/O口要設置,那么需要多次調用該函數(shù)。新建工程(寄存器版)以跑馬燈為例,通過Keil5新建工程。STM32F407ZGT6最小系統(tǒng)板與LED的連接原理圖如圖所示,在PF9、PF10端口上分別接了兩個LED小燈。步驟1:在TEST文件夾下新建一個HARDWARE文件夾,用來存放與硬件有關的文件;然后在HARDWARE文件夾下新建一個LED文件夾,用來存放與LED相關的代碼。在USER文件夾下找到工程文件test.uvprojx并打開,新建一個led.c文件,保存在HARDWARE-LED文件夾下面,在文件中輸入如下代碼。程序清單11-2-1 led.c(寄存器版)程序#include"led.h"http://初始化PF9和PF10為輸出口,并使能這兩個口的時鐘 //LEDI/O口初始化voidLED_Init(void){ RCC->AHB1ENR|=1<<5;//使能PORTF時鐘GPIO_Set(GPIOF,PIN9|PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_100M,GPIO_PUPD_PU);//PF9,PF10設置
LED0=1;//LED0關閉
LED1=1;//LED1關閉}通常購買系統(tǒng)板時,廠家都會提供基本的工程文件,可以將其復制到我們的工程文件夾TEST中直接使用,通常包括表11-2-2所示文件。新建工程(寄存器版)該代碼里面就包含了一個函數(shù)voidLED_Init(void),該函數(shù)的功能就是配置PF9和PF10為推挽輸出。I/O口配置采用GPIO_Set函數(shù)實現(xiàn)。這里需要注意的是:在配置STM32F407外設的時候,要先使能該外設的時鐘。RCC_AHB1ENR是AHB總線上的外設時鐘使能寄存器,其各位的描述如下。Addressoffset(偏移地址):0x30。Access(訪問):nowaitstate,word,half-wordandbyteaccess.(無等待周期,按字、半字和字節(jié)訪問)。我們要使能PORTF的時鐘,則只要將該寄存器的bit5置1就可以。配置完時鐘之后,LED_Init調用GPIO_Set函數(shù)完成對PF9和PF10模式的配置,然后熄滅LED0、LED1。步驟2:按同樣的方法,新建一個led.h文件,也保存在LED文件夾下面。在led.h中輸入如下代碼并保存。程序清單11-2-2led.h(寄存器版)程序#ifndef__LED_H#define__LED_H #include"sys.h"http://LED端口定義#defineLED0PFout(9) //DS0#defineLED1PFout(10) //DS1 voidLED_Init(void); //初始化 #endif這里使用位帶操作來操作某個I/O口。在M3/M4中,有兩個區(qū)可以實現(xiàn)位帶操作,其中一個是SRAM區(qū)的最低1MB范圍(0x20000000~0x200FFFFF),第二個則是片內外設區(qū)的最低1MB范圍(0x40000000~0x400FFFFF),稱為位帶區(qū)。這兩個區(qū)中的存儲器除了可以像普通的RAM一樣訪問使用,M3/M4還將這部分存儲器的每一位重映射為另外一個獨立的存儲空間——位帶別名區(qū)的一個字(32位),通過訪問這些獨立的存儲空間,就可以達到訪問原始存儲器每一位的目的,映射關系如圖所示。新建工程(寄存器版)SRAM位帶區(qū)字節(jié)地址為A的第n(0≤n≤7)位,對應的位帶別名區(qū)地址為:AliasAddr=0x22000000+((A-0x20000000)*8+n)*4=0x22000000+(A-0x20000000)*32+n*4片上外設位帶區(qū)字節(jié)地址為A的第n(0≤n≤7)位,對應的位帶別名區(qū)地址為:AliasAddr=0x42000000+((A-0x40000000)*8+n)*4=0x42000000+(A-0x40000000)*32+n*4上式中,“*4”表示一個字有4字節(jié),“*8”表示一字節(jié)有8位。位帶操作程序代碼如下://位帶操作,實現(xiàn)51單片機類似的GPIO控制功能//具體實現(xiàn)思想,參考<<Cortex-M3權威指南>>(中文)第五章(87頁~92頁).M4同M3類似,只是寄存器地址變了//I/O口操作宏定義#defineBITBAND(addr,bitnum)((addr&0xF0000000)+0x2000000+((addr&0xFFFFF)<<5)+(bitnum<<2))#defineMEM_ADDR(addr)*((volatileunsignedlong*)(addr))#defineBIT_ADDR(addr,bitnum)MEM_ADDR(BITBAND(addr,bitnum))#definePFout(n)BIT_ADDR(GPIOF_ODR_Addr,n)//輸出#definePFin(n)BIT_ADDR(GPIOF_IDR_Addr,n)//輸入新建工程(寄存器版)步驟3:在Target目錄樹上右擊,選擇“ManageProjectItems”,出現(xiàn)圖示的對話框,在Groups下面單擊“New(Insert)”按鈕,新建一個HARDWARE組,并把led.c添加到這個組里。新建工程(寄存器版)新建工程(寄存器版)步驟4:回到主界面,在main函數(shù)中編寫如下代碼。程序清單11-2-3test.c(寄存器版)程序#include"sys.h"#include"delay.h"#include"led.h"intmain(void){{LED0=0; //DS0亮
LED1=1; //DS1滅
delay_ms(500);LED0=1; //DS0滅
LED1=0; //DS1亮
delay_ms(500);}}單擊按鈕,出現(xiàn)圖11-2-7所示的“OptionsforTarget”對話框,選擇“C/C++”選項卡,把led.h的路徑添加進編譯文件,如圖11-2-8所示。然后單擊按鈕,編譯工程,生成.hex文件,安裝J-LINK驅動程序,單擊按鈕下載到目標板中,即可驗證程序。Stm32_Clock_Init(336,8,2,7); //設置時鐘,168MHzdelay_init(168); //初始化延時函數(shù)
LED_Init(); //初始化LED時鐘
while(1)在51單片機的開發(fā)中我們通過直接操作寄存器來實現(xiàn)控制,例如要控制I/O口的狀態(tài),我們直接操作寄存器:P0=0x11;而在STM32的開發(fā)中,同樣可以操作寄存器:GPIOF->BSRRL=0x0001;這種通過寄存器的控制需要開發(fā)者根據(jù)參考手冊查找每個寄存器對各個位的定義,再進行配置,由于STM32有數(shù)量龐大的寄存器,因此配置過程中容易出錯且不利于維護。ST公司推出了官方固件庫,固件庫將這些寄存器底層操作都封裝起來,提供一整套接口(API)供開發(fā)者調用。大多數(shù)場合下,開發(fā)者不需要知道操作的是哪個寄存器,只需要知道調用哪些函數(shù)即可。例如,上面通過控制BSRRL寄存器實現(xiàn)I/O口狀態(tài)的控制,官方固件庫就封裝了一個函數(shù):
GPIO相關庫函數(shù)介紹voidGPIO_SetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin){GPIOx->BSRRL=GPIO_Pin;只需要了解函數(shù)的入口參數(shù)及調用方法就可以實現(xiàn)控制了。一句話可以概括:固件庫就是函數(shù)的集合,固件庫函數(shù)的作用是向下控制寄存器,向上提供用戶函數(shù)調用的接口。通常系統(tǒng)板廠商會提供庫函數(shù)工程模板,工程模板文件夾內容清單如表所示。固件庫中,GPIO口的相關函數(shù)及定義放在文件stm32f4xx_gpio.h和stm32f4xx_gpio.c中。對于GPIO口的4個32位寄存器(GPIOx_MODER、GPIOx_OTYPER、GPIOx_OSPEEDR和GPIOx_PUPDR)的配置是通過GPIO口初始化函數(shù)完成的:voidGPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef*GPIO_InitStruct);這個函數(shù)有兩個參數(shù),第一個參數(shù)用來指定需要初始化的GPIO組,取值范圍為GPIOA~GPIOK。第二個參數(shù)為初始化參數(shù)結構體指針,結構體類型為GPIO_InitTypeDef。找到FWLIB組下面的stm32f4xx_gpio.c文件,定位到GPIO_Init函數(shù)體處,雙擊入口參數(shù)類型GPIO_InitTypeDef后右擊,選擇“Gotodefinitionof...”,可以查看結構體的定義。typedefstruct{uint32_tGPIO_Pin;GPIOMode_TypeDefGPIO_Mode;GPIOSpeed_TypeDefGPIO_Speed;GPIOOType_TypeDefGPIO_OType;GPIOPuPd_TypeDefGPIO_PuPd;}GPIO_InitTypeDef;下面通過一個GPIO初始化實例來講解這個結構體的成員變量的含義,例如:GPIO_InitTypeDefGPIO_InitStructure;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9 //GPIOF9GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT; //普通輸出模式GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz; //100MHzGPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽輸出GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; //上拉GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化GPIO
GPIO相關庫函數(shù)介紹結構體GPIO_InitStructure的第一個成員變量GPIO_Pin用來設置要初始化哪個或者哪些I/O口;第二個成員變量GPIO_Mode用來設置對應I/O口的輸入輸出模式,這個值實際上就是配置的GPIO的MODER寄存器的值,在MDK中是通過一個枚舉類型定義的,我們只需要選擇對應的值即可。typedefenum{GPIO_Mode_IN=0x00, /*!<GPIOInputMode*/GPIO_Mode_OUT=0x01, /*!<GPIOOutputMode*/GPIO_Mode_AF=0x02, /*!<GPIOAlternatefunctionMode*/GPIO_Mode_AN=0x03 /*!<GPIOAnalogMode*/}GPIOMode_TypeDef;
GPIO相關庫函數(shù)介紹GPIO_Mode_IN用來設置輸入模式,GPIO_Mode_OUT表示通用輸出模式,GPIO_Mode_AF表示復用功能模式,GPIO_Mode_AN表示模擬輸入模式。GPIO_Speed用于設置I/O口的輸出速度,有四個可選值。實際上這就是配置的GPIO的OSPEEDR寄存器的值。在MDK中同樣是通過枚舉類型定義的:/*Addlegacydefinition*/#defineGPIO_Speed_2MHzGPIO_Low_Speed#defineGPIO_Speed_25MHzGPIO_Medium_Speed#defineGPIO_Speed_50MHzGPIO_Fast_Speed#defineGPIO_Speed_100MHzGPIO_High_Speedtypedefenum{GPIO_Low_Speed=0x00, /*!<Lowspeed*/GPIO_Medium_Speed=0x01, /*!<Mediumspeed*/GPIO_Fast_Speed=0x02, /*!<Fastspeed*/GPIO_High_Speed=0x03 /*!<Highspeed*/}GPIOSpeed_TypeDef;我們的輸入可以是GPIOSpeed_TypeDef枚舉類型中GPIO_High_Speed枚舉類型值,也可以是GPIO_Speed_100MHz這樣的值,實際上GPIO_Speed_100MHz就是通過define宏定義標識符“define”定義出來的,它跟GPIO_High_Speed是等同的。GPIO_OType用來設置GPIO的輸出類型,實際上就是設置GPIO的OTYPER寄存器的值。在MDK中同樣是通過枚舉類型定義的:typedefenum{GPIO_OType_PP=0x00,GPIO_OType_OD=0x01}GPIOOType_TypeDef;如果需要設置為推挽輸出模式,那么設置其值為GPIO_OType_PP,如果需要設置為輸出開漏模式,那么設置其值為GPIO_OType_OD。GPIO_PuPd用來設置I/O口的上下拉電阻,實際上就是設置GPIO的PUPDR寄存器的值。同樣通過一個枚舉類型列出:
GPIO相關庫函數(shù)介紹typedefenum{GPIO_PuPd_NOPULL=0x00,GPIO_PuPd_UP=0x01,GPIO_PuPd_DOWN=0x02}GPIOPuPd_TypeDef;這三個值的意思很好理解,GPIO_PuPd_NOPULL為不使用上下拉電阻,GPIO_PuPd_UP為上拉,GPIO_PuPd_DOWN為下拉。我們根據(jù)需要設置相應的值即可。在固件庫中通過函數(shù)GPIO_Write來設置ODR寄存器的值,從而控制I/O口的輸出狀態(tài):voidGPIO_Write(GPIO_TypeDef*GPIOx,uint16_tPortVal);該函數(shù)一般用來一次性給GPIO的所有端口賦值。
GPIO相關庫函數(shù)介紹讀ODR寄存器還可以讀出I/O口的輸出狀態(tài),庫函數(shù)為:uint16_tGPIO_ReadOutputData(GPIO_TypeDef*GPIOx);uint8_tGPIO_ReadOutputDataBit(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);這兩個函數(shù)的功能類似,只不過前面的函數(shù)用來一次讀取一組I/O口的輸出狀態(tài),后面的函數(shù)用來一次讀取一組I/O口中一個或者幾個I/O口的輸出狀態(tài)。讀取某個I/O口的電平的相關庫函數(shù)為:uint8_tGPIO_ReadInputDataBit(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);uint16_tGPIO_ReadInputData(GPIO_TypeDef*GPIOx);前面的函數(shù)用來讀取一組I/O口中一個或者幾個I/O口的輸入電平,后面的函數(shù)用來一次讀取一組I/O口的輸入電平。也可通過庫函數(shù)操作BSRR寄存器來設置I/O口的電平,相關庫函數(shù)為:voidGPIO_SetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);voidGPIO_ResetBits(GPIO_TypeDef*GPIOx,uint16_tGPIO_Pin);函數(shù)GPIO_SetBits用來設置一組I/O口中的一個或者多個I/O口為高電平。GPIO_ResetBits用來設置一組I/O口中一個或者多個I/O口為低電平。比如,我們要設置GPIOB.5輸出高電平,方法為:GPIO_SetBits(GPIOB,GPIO_Pin_5); //GPIOB.5輸出高電平設置GPIOB.5輸出低電平,方法為:GPIO_ResetBits(GPIOB,GPIO_Pin_5); //GPIOB.5輸出低電平以跑馬燈為例,通過系統(tǒng)板廠商提供的庫函數(shù)工程模板來建立自己項目的工程。步驟1:單擊工程模板USER目錄下的工程文件Template.uvproj(也可重命名為LED.uvproj)。在工程根目錄文件夾下新建一個HARDWARE文件夾,用來存放與硬件相關的代碼。然后在HARDWARE文件夾下新建一個LED文件夾,用來存放與LED相關的代碼。新建一個文本文件led.c,保存在LED文件夾下,在led.c中輸入如下代碼。程序清單11-2-4led.c(庫函數(shù)版)程序#include"led.h"
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025便利店商品采購與配送合同范本3篇
- 二零二五年度家居裝飾材料區(qū)域代理采購合同3篇
- 2025年度10架AC311A直升機購銷與地面服務保障合同3篇
- 二零二四年度三方貸款資金管理合同3篇
- 二零二五版高端裝備制造工廠生產(chǎn)承包合同書模板3篇
- 年度智慧停車戰(zhàn)略市場規(guī)劃報告
- 2025年蔬菜大棚農業(yè)科技研發(fā)與創(chuàng)新合作合同2篇
- 年度丙二酮戰(zhàn)略市場規(guī)劃報告
- 二零二五版?zhèn)€人短期租房合同補充協(xié)議2篇
- 2024-2025學年高中歷史第8單元20世紀下半葉世界的新變化第21課世界殖民體系的瓦解與新興國家的發(fā)展課時作業(yè)含解析新人教版必修中外歷史綱要下
- 第12講 語態(tài)一般現(xiàn)在時、一般過去時、一般將來時(原卷版)
- 2024年采購員年終總結
- 2024年新疆區(qū)公務員錄用考試《行測》試題及答案解析
- 肺動脈高壓的護理查房課件
- 2025屆北京巿通州區(qū)英語高三上期末綜合測試試題含解析
- 公婆贈予兒媳婦的房產(chǎn)協(xié)議書(2篇)
- 煤炭行業(yè)智能化煤炭篩分與洗選方案
- 2024年機修鉗工(初級)考試題庫附答案
- Unit 5 同步練習人教版2024七年級英語上冊
- 矽塵對神經(jīng)系統(tǒng)的影響研究
- 分潤模式合同模板
評論
0/150
提交評論