STM32时钟与GPIO设计_第1页
STM32时钟与GPIO设计_第2页
STM32时钟与GPIO设计_第3页
STM32时钟与GPIO设计_第4页
STM32时钟与GPIO设计_第5页
已阅读5页,还剩50页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

EmbeddedSystemDevelopment,嵌入式系统与应用,第8章STM32时钟与GPIO设计,8.1时钟设置与开启外设时钟8.2GPIO简介8.3GPIO端口配置寄存器8.4stm32f10 x.h库中GPIO代码剖析8.6GPIO控制LED灯实验,8.1系统时钟配置与外设时钟开启,在startup_stm32f10 x_hd.s启动文件中,调用_main函数之前先调用了SystemInit()初始化函数,其中系统时钟SYSCLK设置:时钟源、倍频、分频等控制参数。,SystemInit()定义在system_stm32f10 x.c文件中,其他的配置主要在stm32f10 x_rcc.c中。使用外设时,配置初始化后,必须也要开启外设时钟。,8.1.1时钟设置解析,系统时钟SYSCLK是SystemInit()先将配置时钟相关的寄存器都复位为默认值,再调用SetSysClock()选择使用频率,而具体设置是通过宏定义设置的。函数调用顺序:启动文件SystemInit()SetSysClock()SetSysClockTo72()。,1、SystemInit(),STM32时钟系统的SystemInit()中设置:SYSCLK(系统时钟)=72MHzAHB总线时钟(使用SYSCLK)=72MHzAPB1总线时钟(PCLK1)=36MHzAPB2总线时钟(PCLK2)=72MHzPLL时钟=72MHz用到的RCC寄存器复位值:RCC_CR=0 x0000 xx83;RCC_CFGR=0 x00000000;RCC_CIR=0 x00000000;RCC_CFGR2=0 x00000000;这些RCC时钟寄存器组名的宏定义与其他外设寄存器名定义都在stm32f10 x.h文件中。,RCC时钟寄存器组在stm32f10 x.h中的定义,typedefstruct_IOuint32_tCR;_IOuint32_tCFGR;_IOuint32_tCIR;_IOuint32_tAPB2RSTR;_IOuint32_tAPB1RSTR;_IOuint32_tAHBENR;_IOuint32_tAPB2ENR;_IOuint32_tAPB1ENR;_IOuint32_tBDCR;_IOuint32_tCSR;#ifdefSTM32F10X_CL_IOuint32_tAHBRSTR;_IOuint32_tCFGR2;#endif/*STM32F10X_CL*/#ifdefined(STM32F10X_LD_VL)|defined(STM32F10X_MD_VL)|defined(STM32F10X_HD_VL)uint32_tRESERVED0;_IOuint32_tCFGR2;#endif/*STM32F10X_LD_VL|STM32F10X_MD_VL|STM32F10X_HD_VL*/RCC_TypeDef;,_IO宏定义core_cm3.h中:#define_IOvolatile;volatile,易变的,用变量时需到原地址重新存取。uint32_t定义在stdin.h里。typedefunsignedintuint32_t;知道了结构体首地址就确定RCC寄存器组所有32位寄存器的地址,0 x04正好是地址偏移量,所以把连续的寄存器组定义为结构。,2、SetSysClock()函数如下,此函数中选择调用确定使用频率的函数。staticvoidSetSysClock(void)#ifdefSYSCLK_FREQ_HSESetSysClockToHSE();#elifdefinedSYSCLK_FREQ_24MHzSetSysClockTo24();#elifdefinedSYSCLK_FREQ_36MHzSetSysClockTo36();#elifdefinedSYSCLK_FREQ_48MHzSetSysClockTo48();#elifdefinedSYSCLK_FREQ_56MHzSetSysClockTo56();#elifdefinedSYSCLK_FREQ_72MHz/使用此项SetSysClockTo72();#endif,3、SetSysClockTo72()函数,各个SetSysClockToXX(void)函数,配置了具体的系统时钟,PLL倍频以及分频系数。采用寄存器直接配置方式,如:staticvoidSetSysClockTo72(void)_IOuint32_tStartUpCounter=0,HSEStatus=0;/*SYSCLK,HCLK,PCLK2andPCLK1configuration*/*EnableHSE*/RCC-CR|=(uint32_t)RCC_CR_HSEON);doHSEStatus=RCC-CR欲深入分析时钟配置,就仔细阅读这些最底层的库函数!,8.1.2开启关闭外设时钟,外设都是挂在AHB、APB1、APB2总线上,要想使用某个外设,必须初始化外设后,再开启使用开启外设的时钟,不用时再关闭外设时钟,从而降低STM32的整体功耗。stm32f10 x_rcc.c文件中有开启和关闭外设时钟的库函数,如下:RCC_AHBPeriphClockCmd(外设名,ENABLE|DISABLE)挂在AHB总线外设的开启与关闭函数,ENABLE开启,DISABLE关闭外设时钟;RCC_APB1PeriphClockCmd(外设名,ENABLE|DISABLE)挂在APB1总线外设的开启与关闭函数;RCC_APB2PeriphClockCmd(外设名,ENABLE|DISABLE)挂在APB2总线外设的开启与关闭函数;,挂载在AHB的外设名,stm32f10 x_rcc.h中对外设名进行了宏定义,看名即知设备。#defineRCC_AHBPeriph_DMA1(uint32_t)0 x00000001)#defineRCC_AHBPeriph_DMA2(uint32_t)0 x00000002)#defineRCC_AHBPeriph_SRAM(uint32_t)0 x00000004)#defineRCC_AHBPeriph_FLITF(uint32_t)0 x00000010)#defineRCC_AHBPeriph_CRC(uint32_t)0 x00000040)#defineRCC_AHBPeriph_FSMC(uint32_t)0 x00000100)#defineRCC_AHBPeriph_SDIO(uint32_t)0 x00000400)#defineRCC_AHBPeriph_OTG_FS(uint32_t)0 x00001000)#defineRCC_AHBPeriph_ETH_MAC(uint32_t)0 x00004000)#defineRCC_AHBPeriph_ETH_MAC_Tx(uint32_t)0 x00008000)#defineRCC_AHBPeriph_ETH_MAC_Rx(uint32_t)0 x00010000),挂载在APB2上的外设名,#defineRCC_APB2Periph_AFIO(uint32_t)0 x00000001)#defineRCC_APB2Periph_GPIOA(uint32_t)0 x00000004)#defineRCC_APB2Periph_GPIOB(uint32_t)0 x00000008)#defineRCC_APB2Periph_GPIOG(uint32_t)0 x00000100)#defineRCC_APB2Periph_ADC1(uint32_t)0 x00000200)#defineRCC_APB2Periph_ADC2(uint32_t)0 x00000400)#defineRCC_APB2Periph_TIM1(uint32_t)0 x00000800)#defineRCC_APB2Periph_SPI1(uint32_t)0 x00001000)#defineRCC_APB2Periph_TIM8(uint32_t)0 x00002000)#defineRCC_APB2Periph_USART1(uint32_t)0 x00004000)#defineRCC_APB2Periph_ADC3(uint32_t)0 x00008000)#defineRCC_APB2Periph_TIM15(uint32_t)0 x00010000)#defineRCC_APB2Periph_TIM16(uint32_t)0 x00020000)#defineRCC_APB2Periph_TIM17(uint32_t)0 x00040000)#defineRCC_APB2Periph_TIM9(uint32_t)0 x00080000)#defineRCC_APB2Periph_TIM10(uint32_t)0 x00100000)#defineRCC_APB2Periph_TIM11(uint32_t)0 x00200000),挂载在APB1上的外设名,#defineRCC_APB1Periph_TIM2(uint32_t)0 x00000001)#defineRCC_APB1Periph_TIM3(uint32_t)0 x00000002)#defineRCC_APB1Periph_TIM14(uint32_t)0 x00000100)#defineRCC_APB1Periph_WWDG(uint32_t)0 x00000800)#defineRCC_APB1Periph_SPI2(uint32_t)0 x00004000)#defineRCC_APB1Periph_SPI3(uint32_t)0 x00008000)#defineRCC_APB1Periph_USART2(uint32_t)0 x00020000)#defineRCC_APB1Periph_USART3(uint32_t)0 x00040000)#defineRCC_APB1Periph_UART4(uint32_t)0 x00080000)#defineRCC_APB1Periph_UART5(uint32_t)0 x00100000)#defineRCC_APB1Periph_I2C1(uint32_t)0 x00200000)#defineRCC_APB1Periph_I2C2(uint32_t)0 x00400000)#defineRCC_APB1Periph_USB(uint32_t)0 x00800000)#defineRCC_APB1Periph_CAN1(uint32_t)0 x02000000)#defineRCC_APB1Periph_CAN2(uint32_t)0 x04000000)#defineRCC_APB1Periph_BKP(uint32_t)0 x08000000)#defineRCC_APB1Periph_PWR(uint32_t)0 x10000000)#defineRCC_APB1Periph_DAC(uint32_t)0 x20000000)#defineRCC_APB1Periph_CEC(uint32_t)0 x40000000),开启外设时钟举例:,GPIO的C口挂在APB2总线,所用的时钟PCLK2为72MHz。开启GPIOC外设时钟:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE)如用到I/O引脚复用功能,还要开启其复用功能时钟。如GPIOC的Pin4还可作为ADC1的输入引脚,把它作为ADC1来用,除开启GPIOC时钟,还要开启ADC1时钟:RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE)RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE)开启关闭外设时钟的三个函数,内部对外设时钟的使能寄存器操作,达到开启和关闭的目的。,8.2GPIO简介,GPIO(GeneralPurposeI/O)通用型输入/输出,主要用于需要用到数字量输入/输出的场合。如:继电器、LED、蜂鸣器等的控制;传感器状态、高低电平等信息的输入等。管脚可承受最大5V的输入电压,电流为4mA,短时间极限值40mA;。,GPIO简介,GPIO引脚又被分为GPIOA、GPIOBGPIOG不同的组,每组端口分为015,共16个引脚,不同芯片的端口组数不同。GPIO结构图:,端口配置寄存器,GPIO简介,I/O引脚可通过端口配置寄存器设置成不同的功能。四种输入模式(图上半部分):上拉输入与下拉输入:与VDD相连的为上拉电阻,与VSS相连的为下拉电阻。再经施密特触发器就把信号转化为0、1存储在输入数据寄存器。浮空输入:不接上拉与下拉电阻,直接由触发器输入,由于其输入阻抗较大,一般把这种模式用于标准的通讯协议如I2C、USART的接收端。模拟输入:把电压信号直接传送到片上外设模块,如ADC,GPIO简介,推挽输出模式:输出1时P-MOS导通输出高电平1,0时N-MOS管导通输出低电平0。开漏输出模式:只有N-MOS管,外部需接上拉电阻,输出0时导通,为低电平0;输出1时截止,为高阻状态。复用功能的推挽式输出模式。复用功能的开漏输出模式。,一只三极管放大信号正半周,另一只放大负半周,故称推挽放大器,四种输出模式(图下半部分):,GPIO简介,GPIO都可配置为中断功能,并可设置为上升沿、下降沿或边沿触发。,GPIO中断还具有掉电唤醒功能,8.3GPIO端口配置寄存器,1、端口配置低寄存器GPIOx_CRL(配置07引脚)x=AG,芯片的GPIO端口。PIOx_CRL地址偏移量:0 x00h,复位值:0 x44444444,第y个引脚的模式由寄存器的4个位控制,MODEy1:0引脚模式位,CNFy1:0引脚配置位。可配置为4种输入、4种输出模式。,GPIO端口配置寄存器,CNFy1:0:端口y配置位输入模式(MODE1:0=00):00:模拟输入01:浮空输入(复位默认值)10:上拉/下拉输入11:保留输出模式(MODE1:000):00:通用推挽输出01:通用开漏输出10:复用功能推挽输出11:复用功能开漏输出,MODEy1:0:端口y模式位输入模式00:复位默认值输出模式01:最大速度10MHz10:最大速度2MHz11:最大速度50MHz,PIOx_CRL复位值44444444h,即CNFy1:001、MODEy1:000,复位后端口配置为什么口?,2、端口配置高寄存器GPIOx_CRH,GPIOx_CRH(配置815引脚)与端口配置低寄存器类似。地址偏移量:0 x04h,复位值:0 x44444444例1:GPIOx_CRH寄存器的第28至29位设置为11,并在第30至31位设置为00:答:则把x端口第15个引脚的模式配置成了:输出的最大速度为50MHz的通用推挽输出模式。例2:上题反过来。,3、端口输入数据寄存器GPIOx_IDR,端口输入数据寄存器(GPIOx_IDR)(x=A.G),读该寄存器可看某个IO口的输入状态。地址偏移量:0 x08h,复位值:0 x0000XXXX高位31:16保留,始终读为0。IDRy15:0(y=015)每个位对应I/O口的输入状态。GPIOx_IDR为只读并只能以字的形式读出。,4、端口输出数据寄存器GPIOx_ODR,GPIOx_ODR(x=A.E)位。写该寄存器可控制某个IO口的输出电平,读该寄存器可以判断IO口的输出状态。地址偏移量:0 x0Ch,复位值:0 x00000000高位31:16保留,始终为0。ODRy15:0:端口输出数据(y=015)这些位可读可写并只能以字的形式操作。通过GPIOx_BSRR(x=AG),可以分别地对各个ODR位进行独立的置位/清零。,5、端口位置位/清零寄存器GPIOx_BSRR,GPIOx_BSRR(x=A.G),对GPIOx的端口置位/清零。地址偏移量:0 x10,复位值:0 x00000000,位31:16为BRy(y=015),清零,只能以字写入:0:对应的ODRx位不产生影响;1:对应的ODRx位清零;位15:0为BSy(y=015),置位,只能以字写入:0:对对应的ODRx位不产生影响;1:对应的ODRx位置位;注:如果同时设置BSy和BRy的对应位,BSx位起作用。,6、端口位清零寄存器(GPIOx_BRR),GPIOx_BRR(x=A.G)对GPIOx的端口清零。注意:相当于GPIOx_BSRR寄存器的清零功能。地址偏移量:0 x14,复位值:0 x00000000,Bits31:16Reserved位15:0为BRy(y=015):只能以字写入:0:对应的ODRx位不产生影响;1:对应的ODRx位清零;,7、端口配置锁定寄存器GPIOx_LCKR,端口配置锁定寄存器(GPIOx_LCKR)(x=A.G)地址偏移量:0 x18,复位值:0 x00000000,位16(LCKK):当执行正确的写序入列(写1-写0-写1-写0-写1),置1下次系统复位前该寄存器被锁住。位15:0:在LCKK位为0时:LCKy写1锁定对应端口y脚配置寄存器(CRL或CRH)中相应的4个位;LCKy写0不锁;,例:,要控制引脚电平高低,需要对寄存器进行什么操作?一个引脚y的输出数据由GPIOx_BSRR寄存器位的2个位来控制分别为BRy(BitResety)和BSy(BitSety),BRy位用于写1清零,使引脚输出低电平;BSy位用来写1置1,使引脚输出高电平。,8.4stm32f10 x.h库中GPIO代码剖析,以外设GPIOC为例,文件中包含如下宏定义:#definePERIPH_BASE(uint32_t)0 x40000000)#defineAPB2PERIPH_BASE(PERIPH_BASE+0 x10000)#defineGPIOC_BASE(APB2PERIPH_BASE+0 x1000)先看外设基地址宏PERIPH_BASE,宏展开为uint32_t类型0 x40000000;总线基地址宏APB2PERIPH_BASE指向地址0 x40010000;最后到了宏GPIOC_BASE为APB2PERIPH_BASE加上地址偏移量0 x1000得到了GPIOC端口的寄存器组的基地址为0 x40011000。,stm32f10 x.h中GPIO代码剖析,stm32f10 x.h文件,还可以发现以下类似的宏:#defineGPIOA_BASE(APB2PERIPH_BASE+0 x0800)#defineGPIOB_BASE(APB2PERIPH_BASE+0 x0C00)#defineGPIOC_BASE(APB2PERIPH_BASE+0 x1000)#defineGPIOD_BASE(APB2PERIPH_BASE+0 x1400)GPIOA、GPIOB、GPIOC、GPIOD寄存器组的起始地址,都对应着独立的一组寄存器。,typedefstruct_IOuint32_tCRL;_IOuint32_tCRH;_IOuint32_tIDR;_IOuint32_tODR;_IOuint32_tBSRR;_IOuint32_tBRR;_IOuint32_tLCKR;GPIO_TypeDef;,#defineGPIOA(GPIO_TypeDef*)GPIOA_BASE)#defineGPIOB(GPIO_TypeDef*)GPIOB_BASE)(GPIO_TypeDef*)把GPIOA_BASE地址转换为GPIO_TypeDef结构体指针类型。,对每个GPIOx是用结构封装了寄存器组,stm32f10 x.h中代码:,结构体首地址即CRL地址若为0 x40011000,那么第二个变量CRH为0 x40011000+0 x04,0 x04正好是寄存器组中的地址偏移量。所以把连续的寄存器组定义为结构。,stm32f10 x.h中GPIO代码剖析,有了这样的宏,就可用以下方式来修改GPIO寄存器:GPIO_TypeDef*GPIOx;/*定义GPIOx指针变量为GPIO_TypeDef结构体型GPIOx=GPIOA;/把指针地址设置为宏GPIOA地址GPIOx-CRL=0 xFFFFFFFF;/“-”通过指针访问并修改GPIOA_CRL寄存器通过类似的方式,我们就可以给具体的寄存器写上适当的参数,控制STM32了。这只是库开发的皮毛,库提供了更简单的开发方式。,使用GPIO,1.配置寄存器:选定GPIO的特定功能,最基本的如:选择作为输入还是输出端口。2.数据寄存器:保存了GPIO的输入电平或将要输出的电平。3.位控制寄存器:设置某引脚的数据为1或0,控制输出的电平。4.锁定寄存器:设置某锁定引脚后,就不能修改其配置。,关于GPIO库函数,7.6LED流水灯实验,实验学习方法,先学习例程编写方法,掌握后,在实验过程中改写程序、逐渐编写程序!想要控制LED灯,当然是通过控制STM32芯片的I/O引脚电平的高低来实现。,LED流水灯实验,LED流水灯实验,LED实验中用到了RCC跟GPIO这两个外设。环境配置如图:用到的源程序:main.cled.cled.h,Led流水灯主程序:main.c,#includeled.hvoidDelay(_IOuint32_tnCount)/简单延时函数for(;nCount!=0;nCount-);intmain(void)LED_GPIO_Config();/函数在led.c中定义while(1)LED1(ON);/函数在头文件led.h中定义Delay(0 x0FFFFF);LED1(OFF);LED2(ON);Delay(0 x0FFFFF);LED2(OFF);LED3(ON);Delay(0 x0FFFFF);LED3(OFF);,led.c-初始化函数LED_GPIO_Config(),#includeled.h#includestm32f10 x_gpio.h#includestm32f10 x_rcc.hvoidLED_GPIO_Config(void)/*用库定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDefGPIO_InitStructure;/*开启GPIOC的外设时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);/*选择要控制的GPIOC引脚GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;/*设置引脚模式为通用推挽输出*/GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;,led.c,/设置引脚速率为50MHzGPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;/端口初始化库函数,利用上面设置的参数初始化GPIOCGPIO_Init(GPIOC,函数LED_GPIO_Config()实现了所有为点亮led的配置,led.h头文件,#ifndef_LED_H/条件编译,防止头文件重复包含#define_LED_H/独立写头文件,方便以后扩展使用#includestm32f10 x.h/*themacrodefinitiontotriggertheledonoroff*0-on*1-off*/#defineON0#defineOFF1/*带

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论