资源描述
,*,Click to edit Master text styles,Second Level,Third Level,Fourth Level,Fifth Level,Click to edit Master title style,第,8,章,STM32,时钟与,GPIO,设计,8.1,时钟设置与开启外设时钟,8.2 GPIO,简介,8.3,GPIO,端口配置寄存器,8.4,stm32f10 x.h,库中,GPIO,代码剖析,8.6 GPIO,控制,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,(系统时钟),=72MHz,AHB,总线时钟,(,使用,SYSCLK)=72MHz,APB1,总线时钟,(PCLK1)=36MHz,APB2,总线时钟,(PCLK2)=72MHz,PLL,时钟,=72MHz,用到的,RCC,寄存器复位值:,RCC_CR =0 x0000 xx83;,RCC_CFGR =0 x0000 0000,;,RCC_CIR =0 x0000 0000;,RCC_CFGR2=0 x0000 0000;,这些,RCC,时钟寄存器组名的宏定义与其他外设寄存器名定义都在,stm32f10 x.h,文件中。,RCC,时钟寄存器组在,stm32f10 x.h,中的定义,typedef struct,_IO uint32_t CR;,_IO uint32_t CFGR;,_IO uint32_t CIR;,_IO uint32_t APB2RSTR;,_IO uint32_t APB1RSTR;,_IO uint32_t AHBENR;,_IO uint32_t APB2ENR;,_IO uint32_t APB1ENR;,_IO uint32_t BDCR;,_IO uint32_t CSR;,#ifdef STM32F10X_CL,_IO uint32_t AHBRSTR;,_IO uint32_t CFGR2;,#endif/*STM32F10X_CL*/,#if defined,(STM32F10X_LD_VL)|defined(STM32F10X_MD_VL)|defined(STM32F10X_HD_VL),uint32_t RESERVED0;,_IO uint32_t CFGR2;,#endif/*STM32F10X_LD_VL|STM32F10X_MD_VL|STM32F10X_HD_VL*/,RCC_TypeDef;,_IO,宏定义,core_cm3.h,中:,#define,_IO,volatile,;,volatile,易变的,用变量时需到原地址重新存取。,uint32_t,定义,在,stdin.h,里。,typedef,unsigned,int,uint32_t,;,知道了结构体,首,地址就,确定,RCC,寄存器组,所有,32,位寄存器,的,地址,,,0 x04,正好是地址偏移量,所以把连续的寄存器组定义为,结构。,2,、,SetSysClock(),函数如下,此函数中选择调用确定使用频率的函数。,static void SetSysClock(void),#ifdef SYSCLK_FREQ_HSE,SetSysClockToHSE();,#elif defined SYSCLK_FREQ_24MHz,SetSysClockTo24();,#elif defined SYSCLK_FREQ_36MHz,SetSysClockTo36();,#elif defined SYSCLK_FREQ_48MHz,SetSysClockTo48();,#elif defined SYSCLK_FREQ_56MHz,SetSysClockTo56();,#elif defined SYSCLK_FREQ_72MHz/,使用此项,SetSysClockTo72();,#endif,3,、,SetSysClockTo72(),函数,各个,SetSysClockTo,XX,(void),函数,配置了具体的系统时钟,PLL,倍频以及分频系数。采用寄存器直接配置方式,如:,static void,SetSysClockTo72(void),_IO uint32_t StartUpCounter=0,HSEStatus=0;,/*SYSCLK,HCLK,PCLK2 and PCLK1 configuration*/,/*Enable HSE*/,RCC-CR|=(uint32_t)RCC_CR_HSEON);,do,HSEStatus=RCC-CR,StartUpCounter+;,while(HSEStatus=0),欲深入分析时钟配置,就仔细阅读这些最底层的库函数!,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,中对外设名进行了宏定义,看名即知设备。,#define RCC_AHBPeriph_DMA1 (uint32_t)0 x00000001),#define RCC_AHBPeriph_DMA2 (uint32_t)0 x00000002),#define RCC_AHBPeriph_SRAM (uint32_t)0 x00000004),#define RCC_AHBPeriph_FLITF (uint32_t)0 x00000010),#define RCC_AHBPeriph_CRC (uint32_t)0 x00000040),#define RCC_AHBPeriph_FSMC (uint32_t)0 x00000100),#define RCC_AHBPeriph_SDIO (uint32_t)0 x00000400),#define RCC_AHBPeriph_OTG_FS (uint32_t)0 x00001000),#define RCC_AHBPeriph_ETH_MAC (uint32_t)0 x00004000),#define RCC_AHBPeriph_ETH_MAC_Tx (uint32_t)0 x00008000),#define RCC_AHBPeriph_ETH_MAC_Rx (uint32_t)0 x00010000),挂载在,APB2,上的外设名,#define RCC_APB2Periph_AFIO (uint32_t)0 x00000001),#define RCC_APB2Periph_GPIO,A,(uint32_t)0 x00000004),#define RCC_APB2Periph_GPIO,B,(uint32_t)0 x00000008),#define RCC_APB2Periph_GPIO,G,(uint32_t)0 x00000100),#define RCC_APB2Periph_ADC1 (uint32_t)0 x00000200),#define RCC_APB2Periph_ADC2 (uint32_t)0 x00000400),#define RCC_APB2Periph_TIM1 (uint32_t)0 x00000800),#define RCC_APB2Periph_SPI1 (uint32_t)0 x00001000),#define RCC_APB2Periph_TIM8 (uint32_t)0 x00002000),#define RCC_APB2Periph_USART1 (uint32_t)0 x00004000),#define RCC_APB2Periph_ADC3 (uint32_t)0 x00008000),#define RCC_APB2Periph_TIM15 (uint32_t)0 x00010000),#define RCC_APB2Periph_TIM16 (uint32_t)0 x00020000),#define RCC_APB2Periph_TIM17 (uint32_t)0 x00040000),#define RCC_APB2Periph_TIM9 (uint32_t)0 x00080000),#define RCC_APB2Periph_TIM10 (uint32_t)0 x00100000),#define RCC_APB2Periph_TIM11 (uint32_t)0 x00200000),挂载在,APB1,上的外设名,#define RCC_APB1Periph_TIM,2,(uint32_t)0 x00000001),#define RCC_APB1Periph_TIM,3,(uint32_t)0 x00000002),#define RCC_APB1Periph_TIM,14,(uint32_t)0 x00000100),#define RCC_APB1Periph_WWDG (uint32_t)0 x00000800),#define RCC_APB1Periph_SPI2 (uint32_t)0 x00004000),#define RCC_APB1Periph_SPI3 (uint32_t)0 x00008000),#define RCC_APB1Periph_USART2 (uint32_t)0 x00020000),#define RCC_APB1Periph_USART3 (uint32_t)0 x00040000),#define RCC_APB1Periph_UART4 (uint32_t)0 x00080000),#define RCC_APB1Periph_UART5 (uint32_t)0 x00100000),#define RCC_APB1Periph_I2C1 (uint32_t)0 x00200000),#define RCC_APB1Periph_I2C2 (uint32_t)0 x00400000),#define RCC_APB1Periph_USB (uint32_t)0 x00800000),#define RCC_APB1Periph_CAN1 (uint32_t)0 x02000000),#define RCC_APB1Periph_CAN2 (uint32_t)0 x04000000),#define RCC_APB1Periph_BKP (uint32_t)0 x08000000),#define RCC_APB1Periph_PWR (uint32_t)0 x10000000),#define RCC_APB1Periph_DAC (uint32_t)0 x20000000),#define RCC_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.2 GPIO,简介,GPIO,(,General Purpose I/O,)通用型输入,/,输出,主要用于需要用到,数字量输入,/,输出,的场合。,如:,继电器、,LED,、蜂鸣器等的控制;,传感器状态、高低电平等信息的输入等。,管脚可承受最大,5V,的输入电压,电流为,4mA,,短时间极限值,40mA,;,。,GPIO,简介,GPIO,引脚又被分为,GPIOA,、,GPIOBGPIOG,不同的组,每组端口分为,015,,共,16,个引脚,不同芯片的端口组数不同。,GPIO,结构图:,端口配置寄存器,GPIO,简介,I/O,引脚可通过,端口配置寄存器,设置成不同的功能。,四种输入模式(图上半部分):,上拉输入与下拉输入:与,VDD,相连的为上拉电阻,与,VSS,相连的为下拉电阻。再经施密特触发器就把信号转化为,0,、,1,存储在输入数据寄存器。,浮空输入:不接上拉与下拉电阻,直接由触发器输入,由于其输入阻抗较大,一般把这种模式用于标准的通讯协议如,I,2,C,、,USART,的接收端。,模拟输入:把电压信号直接传送到片上外设模块,如,ADC,GPIO,简介,推挽输出模式:输出,1,时,P-MOS,导通输出高电平,1,,,0,时,N-MOS,管导通输出低电平,0,。,开漏输出模式:,只有,N-MOS,管,,外部需接上拉电阻,输出,0,时导通,为低电平,0,;输出,1,时截止,为高阻状态。,复用功能的推挽式输出模式。,复用功能的开漏输出模式。,一只三极管放大信号正半周,另一只放大负半周,故称推挽放大器,四种,输出模式,(,图下半部分,),:,GPIO,简介,STM32,P0.x,P2.x,GPIO,都可配置为中断功能,并可设置为上升沿、下降沿或边沿触发。,上升沿中断,下降沿中断,边沿中断,GPIO,中断还具,有掉电唤醒功能,8.3,GPIO,端口配置寄存器,1,、端口配置低寄存器,GPIO,x,_CR,L,(,配置,07,引脚,),x=AG,,芯片的,GPIO,端口,。,PIOx_CRL,地址偏移量:,0 x00h,,复位值:,0 x4444 4444,第,y,个引脚的模式由寄存器的,4,个位控制,,MODEy,1:0,引脚模式位,,CNFy,1:0,引脚配置位。,可配置为,4,种输入、,4,种输出模式。,GPIO,端口配置寄存器,CNFy1:0,:端口,y,配置位,输入模式,(MODE1:0=00),:,00,:模拟输入,01,:浮空输入,(,复位默认值,),10,:上拉,/,下拉输入,11,:保留,输出模式,(MODE1:000),:,00,:通用推挽输出,01,:通用开漏输出,10,:复用功能推挽输出,11,:复用功能开漏输出,MODEy,1:0,:,端口,y,模式位,输入模式,00,:复位默认值,输出模式,01,:最大,速度,10MHz,10,:最大,速度,2MHz,11,:最大,速度,50MHz,PIOx_CRL,复位值,4444 4444h,,即,CNFy1:001,、,MODEy1:000,,复位后端口配置为什么口?,2,、端口配置高寄存器,GPIO,x,_CR,H,GPIO,x,_CR,H,(,配置,815,引脚,),与端口配置低寄存器类似。,地址偏移量:,0 x04h,,复位值:,0 x4444 4444,例,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 x0000 XXXX,高位,31:16,保留,始终读为,0,。,IDRy15:0,(y=015),每个位对应,I/O,口的输入状态。,GPIOx_IDR,为只读并只能以字的形式读出。,4,、端口输出数据寄存器,GPIOx_ODR,GPIOx_ODR(x=A.E),位。写该寄存器可控制某个,IO,口的输出电平,读该寄存器可以判断,IO,口的输出状态。,地址偏移量:,0 x0Ch,,复位值:,0 x0000 0000,高位,31:16,保留,始终为,0,。,ODRy15:0,:端口输出数据,(y=015),这些位可读可写并只能以字的形式操作。,通过,GPIOx_BSRR(x=AG),,可以分别地对各个,ODR,位进行独立的置位,/,清零。,5,、端口位置位,/,清零寄存器,GPIOx_BSRR,GPIOx_BSRR(x=A.G),,对,GPIOx,的端口置位,/,清零。,地址偏移量:,0 x10,,复位值:,0 x0000 0000,位,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 x0000 0000,Bits 31:16 Reserved,位,15:0,为,BRy(y=015):,只能以字写入:,0,:对应的,ODRx,位不产生影响;,1,:对应的,ODRx,位清零;,7,、端口配置锁定寄存器,GPIOx_LCKR,端口配置锁定寄存器,(GPIOx_LCKR)(x=A.G),地址偏移量:,0 x18,,复位值:,0 x0000 0000,位,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(Bit Reset y),和,BSy(Bit Set y),,,BRy,位用于写,1,清零,使引脚输出低电平;,BSy,位用来写,1,置,1,,使引脚输出高电平。,8.4,stm32f10 x.h,库中,GPIO,代码剖析,以外设,GPIOC,为例,文件中包含如下宏定义:,#define PERIPH_BASE(uint32_t)0 x40000000),#define APB2PERIPH_BASE(PERIPH_BASE+0 x10000),#define GPIO,C,_BASE(APB2PERIPH_BASE+0 x1000),先看外设基地址宏,PERIPH_BASE,,宏展开为,uint32_t,类型,0 x4000 0000,;,总线基地址宏,APB2PERIPH_BASE,指向地址,0 x4001 0000,;,最后到了宏,GPIO,C,_BASE,为,APB2PERIPH_BASE,加上地址偏移量,0 x1000,得到了,GPIO,C,端口的寄存器组的基地址为,0 x4001 1000,。,stm32f10 x.h,中,GPIO,代码剖析,stm32f10 x.h,文件,还可以发现以下类似的宏:,#define GPIO,A,_BASE(APB2PERIPH_BASE+0 x,0800,),#define GPIO,B,_BASE(APB2PERIPH_BASE+0 x,0C00,),#define GPIO,C,_BASE(APB2PERIPH_BASE+0 x,1000,),#define GPIO,D,_BASE(APB2PERIPH_BASE+0 x,1400,),GPIOA,、,GPIOB,、,GPIOC,、,GPIOD,寄存器组的起始地址,都对应着独立的一组寄存器。,typedef struct,_IO uint32_t CRL;,_IO uint32_t CRH;,_IO uint32_t IDR;,_IO uint32_t ODR;,_IO uint32_t BSRR;,_IO uint32_t BRR;,_IO uint32_t LCKR;,GPIO_TypeDef;,#define GPIOA(GPIO_TypeDef*)GPIOA_BASE),#define GPIOB(GPIO_TypeDef*)GPIOB_BASE),(GPIO_TypeDef*),把,GPIOA_BASE,地址转换为,GPIO_TypeDef,结构体指针类型。,对每个,GPIOx,是用,结构,封装了寄存器组,stm32f10 x.h,中代码:,结构体首地址即,CRL,地址若为,0 x4001 1000,,那么第二个变量,CRH,为,0 x4001 1000+0 x04,0 x04,正好是寄存器组中的地址偏移量。所以把连续的寄存器组定义为结构。,stm32f10 x.h,中,GPIO,代码剖析,有了这样的宏,就可用以下方式来修改,GPIO,寄存器:,GPIO_TypeDef*GPIOx;,/,*,定义,GPIOx,指针变量为,GPIO_TypeDef,结构体型,GPIOx=GPIOA;,/,把指针地址设置为宏,GPIOA,地址,GPIOx-CRL=0 xFFFF FFFF;,/,“,-,”,通过指针访问并修改,GPIOA_CRL,寄存器,通过类似的方式,我们就可以给具体的寄存器写上适当的参数,控制,STM32,了。,这只是库开发的皮毛,库提供了更简单的开发方式。,使用,GPIO,1.,配置寄存器:选定,GPIO,的特定功能,最基本的如:选择作为输入还是输出端口。,2.,数据寄存器:保存了,GPIO,的输入电平 或 将要输出的电平。,3.,位控制寄存器:设置某引脚的数据 为,1,或,0,,控制输出的电平。,4.,锁定寄存器:设置某锁定引脚后,就不能修改其配置。,关于,GPIO,库函数,7.6,LED,流水灯实验,实验学习方法,先学习例程编写方法,掌握后,在实验过程中改写程序、逐渐编写程序!,想要控制,LED,灯,当然是通过控制,STM32,芯片的,I/O,引脚电平的高低来实现。,LED,流水灯实验,LED,流水灯实验,LED,实验中用到了,RCC,跟,GPIO,这两个外设。环境配置如图:,用到的源程序:,main.c,led.c,led.h,Led,流水灯主程序:,main.c,#include led.h,void Delay(_IO uint32_t nCount)/,简单延时函数,for(;nCount!=0;nCount-);,int main(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(),#include led.h,#include stm32f10 x_gpio.h,#include stm32f10 x_rcc.h,void LED_GPIO_Config(void),/*,用库,定义一个,GPIO_InitTypeDef,类型的结构体*,/,GPIO_InitTypeDef GPIO_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,/,设置引脚速率为,50MHz,GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz,;,/,端口初始化库函数,利用上面设置的参数初始化,GPIOC,GPIO_Init(GPIOC,/,引脚置位库函数,关闭,led,灯,GPIO_SetBits(GPIOC,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);,函数,LED_GPIO_Config(),实现了所有为点亮,led,的配置,led.h,头文件,#ifndef _LED_H,/,条件编译,防止头文件重复包含,#define _LED_H /,独立写头文件,方便以后扩展使用,#include stm32f10 x.h,/*the macro definition to trigger the led on or off,*0-on,*1-off,*/,#define ON 0,#define OFF 1,/*,带参宏,可像内联函数一样使用,*/,#define LED1(a)if(a)GPIO_SetBits(GPIOC,GPIO_Pin_3);,else GPIO_ResetBits(GPIOC,GPIO_Pin_3),led.h,续,#define LED2(a)if(a)GPIO_SetBits(GPIOC,GPIO_Pin_4);,else GPIO_ResetBits(GPIOC,GPIO_Pin_4),#define LED3(a)if(a)GPIO_SetBits(GPIOC,GPIO_Pin_5);,else GPIO_ResetBits(GPIOC,GPIO_Pin_5),void LED_GPIO_Config(void);,#endif,/*/,条件编译结束,_LED_H */,在编译过程,编译器会把带参宏展开,在相应的位置替换为宏展开代码。,其中的反斜杠符号“,”叫做续行符,后面不能有空格、注释等,led,用到,stm32f10 x_gpio.h,库的结构、宏定义,1,、,GPIO_InitTypeDef,结构,引脚初始化的结构,2,、,GPIO_Pin_x,引脚为,uint16_t,类型,宏定义:,#define GPIO_Pin_0(uint16_t)0 x0001)/*!Pin 0 selected*/,#define GPIO_Pin_1(uint16_t)0 x0002)/*!Pin 1 selected*/,#define GPIO_Pin_2(uint16_t)0 x0004)/*!Pin 2 selected*/,#define GPIO_Pin_3(uint16_t)0 x0008)/*!Pin 3 selected*/,GPIO_Pin_x,,,x,位为,1,其余位为,0,,在第,x,位置,1,表示,pin x,例:,GPIO_Pin_1,(,0000 0000 0000 0010,),B,led,用到,stm32f10 x_gpio.h,库的结构、宏定义,3,、,GPIOSpeed_TypeDef,定义,GPIO,的输出速率:,typedef enum,GPIO_Speed_10MHz=1,/,枚举常量值,1,,对应,10MHz,GPIO_Speed_2MHz,/,常量值为,2,,对应,2MHz,GPIO_Speed_50MHz /,常量值为,3,,对应,50MHz,GPIOSpeed_TypeDef;,所以:,GPIO_Speed_10MHz,对应,(0001)B,GPIO_Speed_2MHz,对应,(0010)B,GPIO_Speed_50MHz,对应,(0011)B,Speed,控制参数,它的宏展开低,2,位的值,正好符合,寄存器,MODEy,中,2,位的控制值,。,直接,把这个参数写入,CRL,、,CRH,配置寄存器的,MODEy,位,其中,y,由,GPIO_Pin,参数,确定第几引脚。,led,用到,stm32f10 x_gpio.h,库的结构、宏定义,4,、,GPIOMode_TypeDef,结构定义,GPIO,引脚的功能:,typedef enum,GPIO_Mode_AIN=0 x0,/,模拟输入模式,GPIO_Mode_IN_FLOATING=0 x04,/,浮空输入模式,GPIO_Mode_IPD=0 x28,/,下拉输入模式,GPIO_Mode_IPU=0 x48,/,上拉输入模式,GPIO_Mode_Out_OD=0 x14,/,开漏输出模式,GPIO_Mode_Out_PP=0 x10,/,通用推挽输出模式,GPIO_Mode_AF_OD=0 x1C,/,复用功能开漏输出,GPIO_Mode_AF_PP=0 x18 /,复用功能推挽输出,GPIOMode_TypeDef;,led,用到,stm32f10 x_gpio.h,库的结构、宏定义,四种输出模式参数中的,bit4,均为,1,,而四种输入模式中的,bit4,均为,0,。所以在代码中通过与,0 x10,作位与运算,即可区分输入和输出模式。,而,bit2,和,bit3,的参数值正好对应为,CRL,、,CRH,寄存器中的,CNFy,的,2,个控制位。确定是什么模式。,经过与,Speed,参数,MODEy,组合后,配置一个引脚的,4,位参数就确定了。,用于初始化的库函数,GPIO_Init(),通过查找库帮助文档获得,DMK,软件,BUG:error 65,创建一个,STM32F103VE,核的项目,error 65:access violation at 0 x40021000:no read permission,是,Debug,里面的设置,有缺陷,不会自动匹配:,Dialog DLL,:,DCM3.DLL,Parameter,:,-,pCM3,应,手动,改为,:,Dialog DLL,:,DARMSTM.DLL,Parameter,:,-pSTM32F103VE,逻辑分析窗口使用,再点击,Setup,,输入,LED,灯对应的三个信号,PORTB.0,、,PORTF.7,、,PORTF.8,;,Display Type,选择,bit,,然后单击,Close,关闭该对话框;,逻辑分析窗口使用,点击,运行,按钮。运行一段时间之后,点击,停止,按钮,暂停仿真回到逻辑分析窗口,,可通过,Zoom,里面的,In,按钮来放大波形,通过,Out,按钮来缩小波形,或者按,All,显示全部波形。,8.7,再论库开发方式,LED,实验中寄存器配置经历了一下四步:,1,、,led.c,代码对,GPIO_InitStructure.GPIO_Pin,结构体成员赋值为,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5,宏展开为(,0000 0000 0011 1000,),B,,表明对这三个引脚进行配置。,2,、对,.GPIO_Mode,赋值为,GPIO_Mode_Out_PP,,宏展开为(,0001 0100,),B,,表明把这三个引脚都设置为通用推挽模式。,3,、对,.GPIO_Speed,赋值为,GPIO_Speed_50MHz,,宏展开为(,0011,),B,,表明设置这三个引脚的输出最大速度为,50MHz,。,调用,GPIO_Init(),把以上参数写到配置寄存器。,再论库开发方式,附录:几个规范的位操作方法,将,char,型变量,a,的第七位,(bit6),清,0,,其它位不变。,a,/,括号内,1,左移,6,位,得二进制数:,0100 0000,/,按位取反得,1011 1111,,与,a,作”位与,&”,运算,,/a,的第,7,位(,bit6,)被置零,而其它位不变。,同理,将变量,a,的第七位,(bit6),置,1,,,a|=(16);,同理,将变量,a,的第七位,(bit6),取反,a=(1CRL=0 x44333444;,执行效率最高,确定这样的一个值,却是一件麻烦事。,配置寄存器还可以用三种位操作方式:,1.GPIOC-CRL /,清空,Pin3,的,4,个控制位,2.GPIOC-CRL|=(uint32_t)(0011CRL /,清空,Pin4,的,4,个控制位,4.GPIOC-CRL|=(uint32_t)(0011CRL /,清空,Pin5,的,4,个控制位,6.GPIOC-CRL|=(uint32_t)(00114*5);/,配置,Pin5,的,4,个控制位,修改起来比较容易,执行效率低些,本章介绍的库开发方式,调用库函数耗时,但易快速编程;,CPU,高速了,一般不必担心耗时。,课下任务,作业:,1,、试述,STM32,的系统时钟,并说明是如何设置的?,2,、举例说明,STM32,的外设时钟是如何开启与关闭的。,3,、,LED,流水灯模拟实验,实验报告(包括每个语句的解释意义)。,思考简答:,在,stm32f10 x_conf.h,这个头文件中定义的函数声明还是宏定义,怎么在其它文件中应用呢?,自学:,GPIO_Init(),函数的定义代码分析,见野火,PDF,资料,P105-106.,旧版本,BUG Error:L6218E:,Error:L6218E:Undefined symbol assert_param(referred from stm32f10 x_gpio.o).,断言机制函数,assert_param,,,STM32,的函数:,assert_param(IS_GPIO_ALL_PERIPH(GPIOx);,刚开始学习的时候都遇到编译不过去的问题,通过在文件中添加,USE_STDPERIPH_DRIVER,来解决的:,
展开阅读全文