




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
EmbeddedSystemDevelopment聊城大学理工学院曹银杰caoyinjie@
嵌入式系统与应用
第7章CMSIS架构与STM32库开发方式7.1STM32库简介7.2STM32结构及库层次关系7.3库文件及使用简介7.4GPIO7.5stm32f10x.h中GPIO代码剖析7.6GPIO控制LED灯实验7.7时钟设置与开启外设时钟7.1STM32库简介STM32外设资源丰富,寄存器的数量多、设置复杂度高,直接配置寄存器方式开发程序效率低。STM32库是由ST公司针对STM32提供的函数接口,即API(ApplicationProgramInterface),库是架设在寄存器与用户驱动层之间的代码,向下处理与寄存器直接相关的配置,向上为用户提供配置寄存器的接口。STM32库简介开发者可调用这些函数接口来配置STM32的寄存器,开发快速,易于阅读,维护成本低等优点。事实上,库函数的底层实现恰恰是直接配置寄存器方式的最佳例子,想深入了解芯片是如何工作的话,只要追踪到库的最底层实现就能理解。想修炼C语言,就从ST的库开始。7.2STM32结构及库层次关系解决不同的芯片厂商生产的Cortex微控制器软件的兼容性问题,ARM与芯片厂商建立了一个软件抽象层。CMSIS标准:CortexMicroControllerSoftwareInterfaceStandard。CMSIS架构STM32结构及库层次关系CMSIS标准中最主要的为CMSIS核心层,它包括了:
内核函数层:其中包含用于访问内核寄存器的名称、地址定义,主要由ARM公司提供。
设备外设访问层:提供了片上的核外外设的地址和中断定义,主要由芯片生产商提供可见CMSIS层位于硬件层与操作系统或用户层之间,提供了与芯片生产商无关的硬件抽象层,可以为接口外设、实时操作系统提供简单的处理器软件接口,屏蔽了硬件差异,这对软件的移植是有极大的好处的。STM32的库,就是按照CMSIS标准建立的。7.3库文件及使用简介新建工程---选择芯片后—选择运行环境、用的库、驱动文件、RTX等—编译时自动添加其他用的库文件库文件及使用简介ARM公司提供的:如
core_cm3.h、及core_前缀的头文件,核内设备函数层,进入M3内核的接口。
stdin.h头文件,这是一个ANSIC文件,是独立于处理器之外的,就像我们熟知的C语言头文件stdio.h文件一样。misc.h和misc.c是和CM3内核有关的NVIC和SysTick的驱动代码。自行添加到工程。ST公司提供的:stm32f10x.h重要文件,定义寄存器地址、寄存器数据结构、中断向量表。stm32f10x_adc.c、stm32f10x_adc.h,针对模数转换(ADC)外设,还有很多其他设备外设的驱动程序。每个外设对应一个.c和.h后缀的文件。库文件及使用简介startup_stm32f10x_xx.s
启动文件,作用是:1.初始化堆栈指针SP;2.初始化程序计数器指针PC;3.设置堆、栈的大小;4.设置异常向量表的入口地址;5.配置外部SRAM作为数据存储器(这个由用户配置,一般的开发板可没有外部SRAM);6.设置C库的分支入口__main(最终调用main函数);7.启动文件还调用了在system_stm32f10x.c文件中的SystemIni()函数配置系统时钟。system_stm32f10x.c文件提供了两个函数和一个全局变量库文件及使用简介stm32f10x.h头文件中重要的内容就是把STM32的所有寄存器进行地址映射。如同51单片机的<reg52.h>头文件一样,stm32f10x.h像一个大表格,我们在使用的时候就是通过宏定义进行类似查表的操作。没有这个文件的话,怎样访问STM32的寄存器,有什么缺点?1、需要查手册来确定哪个地址对应哪个寄存器。2、地址易写错、可读性差、易出错、开发效率低。库文件及使用简介库函数,就是STM32的库文件中为我们编写好的函数接口,调用这些库函数,就可以对STM32进行配置。我们可以不知道库函数是如何实现的,但必须要知道函数的功能、可传入的参数及其意义、和函数的返回值。库函数很多,学会查阅库帮助文档就行!库帮助文档:stm32f10x_stdperiph_lib_um.chm层层打开文档的目录标签即可。在用库函数的地方,直接从库帮助文档复制即可。思考题:1、没有stm32f10x.h头文件的话,怎样访问STM32的寄存器,有什么缺点?2、从STM32库的实现原理上解答库到底是什么?为什么要用库?用库函数与直接配置寄存器的区别等问题。7.4GPIOGPIO(GeneralPurposeI/O)通用型输入/输出,主要用于需要用到数字量输入/输出的场合。如:继电器、LED、蜂鸣器等的控制;传感器状态、高低电平等信息的输入等。1、GPIO简介大部分GPIO为推挽输出,具有完整I2C功能的是开漏结构;正常拉出灌入电流为4mA,短时间极限值40mA;管脚可承受最大5V的输入电压。GPIO寄存器位于AHB总线上,可以进行高性能的CPU快速访问,支持Cortex-M3位带操作。GPIO允许进行DMA数据操作。GPIO简介GPIO引脚又被分为GPIOA、GPIOB…GPIOG不同的组,每组端口分为0~15,共16个不同的引脚,不同芯片的端口组数不同。GPIO结构图:端口配置寄存器GPIO简介I/O引脚可通过端口配置寄存器设置成不同的功能。四种输入模式(结构图上半部分):上拉输入与下拉输入:与VDD相连的为上拉电阻,与VSS相连的为下拉电阻。再经施密特触发器就把信号转化为0、1存储在输入数据寄存器。浮空输入:不接上拉与下拉电阻,直接由触发器输入,由于其输入阻抗较大,一般把这种模式用于标准的通讯协议如I2C、USART的接收端。模拟输入:把电压信号直接传送到片上外设模块,如ADC。GPIO简介结构图下半部分为输出模式结构:推挽输出模式:在输出高电平时,P-MOS导通,低电平时,N-MOS管导通。开漏输出模式:输出0时为低电平,1为高阻状态。在使用任何一种开漏模式,都需要接上拉电阻。GPIO简介
STM32P0.xP2.xGPIO都可配置为中断功能,并可设置为上升沿、下降沿或边沿触发。上升沿中断下降沿中断
边沿中断
GPIO中断还具有掉电唤醒功能2、GPIO端口配置寄存器端口配置低寄存器GPIOx_CRL(配置0~7引脚),端口配置高寄存器GPIOx_CRH(配置8~15引脚)
(x=A…G)。可将I/O口配置为输入、输出或模拟模式;PIOx_CRL复位值:44444444h,偏移地址:00h。每个引脚的模式由寄存器的4个位控制,又分引脚配置(CNFy[1:0]),引脚的模式(MODEy[1:0]),其中y表示第y个引脚。GPIOx_CRLGPIO端口配置寄存器例:CRH高寄存器的配置PIOx_CRH复位值:44444444h,偏移地址:04h。例:GPIOx_CRH寄存器的第28至29位设置为11,并在第30至31位设置为00答:则把x端口第15个引脚的模式配置成了:输出的最大速度为50MHz的通用推挽输出模式。3、端口输入数据寄存器GPIOx_IDR端口输入数据寄存器(GPIOx_IDR)(x=A..E)复位值:44444444h,地址偏移:08h高位31:16保留,始终读为0。IDRx[15:0]:端口输入数据(x=0…15)这些位为只读并只能以字的形式读出。读出的值为对应I/O口的状态。4、端口输出数据寄存器GPIOx_ODR端口输出数据寄存器(GPIOx_ODR)(x=A..E)设置I/O口的方向输入还是输出。复位值:44444444h,地址偏移:0Ch高位31:16保留,始终为0。ODRx[15:0]:端口输出数据方向(x=0…15)这些位可读可写并只能以字的形式操作。通过GPIOx_BSRR(x=A…E),可以分别地对各个ODR位进行独立的置位/清零。5、端口置位/清零寄存器GPIOx_BSRR端口置位/清零寄存器(GPIOx_BSRR)(x=A..E)复位值:44444444h,地址偏移:10h6、端口位复位寄存器(GPIOx_BRR)端口位复位寄存器(GPIOx_BRR)(x=A..E)复位值:44444444h,地址偏移:14h7、端口配置锁定寄存器GPIOx_LCKR端口配置锁定寄存器(GPIOx_LCKR)(x=A..E)复位值:44444444h,地址偏移:14h当执行正确的写序列设置了位16(LCKK)时,该寄存器用来锁定端口位的配置。位[15:0]用于锁定GPIO端口的配置。在规定的写入操作期间,不能改变LCKP[15:0]。当对相应的端口位执行了LOCK序列后,在下次系统复位之前将不能再更改端口位的配置。每个锁定位锁定控制寄存器(CRL,CRH)中相应的4个位。例:要控制引脚电平高低,需要对寄存器进行什么操作?一个引脚y的输出数据由GPIOx_BSRR寄存器位的2个位来控制分别为BRy(BitResety)和BSy(BitSety),BRy位用于写1清零,使引脚输出低电平;BSy位用来写1置1,使引脚输出高电平。8、GPIO输入输出演示GPIOx_IDR10BRy写1Bsy写1INOUT10GPIOx_ODRGPIOx_PUPDRvccGPIOGPIOx_CRL
设置引脚为GPIO功能
1
配置引脚模式
2
设置GPIO的方向
3
设置GPIO输出电平4
GPIO输入GPIO输出1高电平1输出操作流程输入操作流程1
读取GPIO引脚电平
4
GPIOx_BSRR7.5stm32f10x.h库中GPIO代码剖析以外设GPIOC为例,文件中包含如下宏定义:#defineGPIOC_BASE(APB2PERIPH_BASE+0x1000)#defineAPB2PERIPH_BASE(PERIPH_BASE+0x10000)#definePERIPH_BASE((uint32_t)0x40000000)首先看外设基地址PERIPH_BASE这个宏,宏展开为0x40000000,并把它强制转换为uint32_t类型数据;总线基地址宏APB2PERIPH_BASE指向地址0x40010000;最后到了宏GPIOC_BASE为APB2PERIPH_BASE加上偏移量0x1000得到了GPIOC端口的寄存器组的基地址。stm32f10x.h中GPIO代码剖析stm32f10x.h文件,还可以发现以下类似的宏:#defineGPIOA_BASE(APB2PERIPH_BASE+0x0800)#defineGPIOB_BASE(APB2PERIPH_BASE+0x0C00)#defineGPIOC_BASE(APB2PERIPH_BASE+0x1000)#defineGPIOD_BASE(APB2PERIPH_BASE+0x1400)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是用结构封装了寄存器组,stm32f10x.h中代码:GPIO_TypeDef,这个结构体的首地址(变量CRL的地址)若为0x40011000,那么结构体中第二个变量(CRH)地址为0x40011000+0x04,加上的这个0x04,正是4字节地址偏移量。stm32f10x.h中GPIO代码剖析有了这样的宏,就可用以下方式来修改GPIO寄存器:GPIO_TypeDef*GPIOx;//定义一个GPIO_TypeDef型结构体指针GPIOxGPIOx=GPIOA;
//把指针地址设置为宏GPIOA地址GPIOx->CRL=0xffffffff;
//通过指针访问并修改GPIOA_CRL寄存器通过类似的方式,我们就可以给具体的寄存器写上适当的参数,控制STM32了。这只是库开发的皮毛,库提供了更简单的开发方式。GPIO1.配置寄存器:选定GPIO的特定功能,最基本的如:选择作为输入还是输出端口。2.数据寄存器:保存了GPIO的输入电平或将要输出的电平。3.位控制寄存器:设置某引脚的数据为1或0,控制输出的电平。4.锁定寄存器:设置某锁定引脚后,就不能修改其配置。C语言程序举例:TESTc.C#defineuint32 unsignedint#defineN 10uint32sum;//使用加法运算来计算1+2+3+...+(N-1)+N的值。(N>0)intmain(void){uint32i;sum=0;for(i=0;i<=N;i++){ sum+=i;}}GPIO库函数7.6LED流水灯实验想要控制LED灯,当然是通过控制STM32芯片的I/O引脚电平的高低来实现。LED流水灯实验LED流水灯实验1.GPIO端口引脚多-->就要选定需要控制的特定引脚2.GPIO功能如此丰富-->配置需要的特定功能3.控制LED的亮和灭-->设置GPIO输出电压的高低与GPIO相关的寄存器了,可以通过《STM32参考手册》来查看LED流水灯实验LED实验中用到了RCC跟GPIO这两个外设。环境配置如图:main.cled.cled.hLed流水灯主程序:main.c#include"led.h"voidDelay(__IOuint32_tnCount)//简单延时函数{ for(;nCount!=0;nCount--);}intmain(void){LED_GPIO_Config(); while(1) {LED1(ON); Delay(0x0FFFFF); LED1(OFF); LED2(ON); Delay(0x0FFFFF); LED2(OFF); LED3(ON); Delay(0x0FFFFF); LED3(OFF); } }初始化LED函数led.c#include"led.h"#include"stm32f10x_gpio.h"#include"stm32f10x_rcc.h"voidLED_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函数led.c/*设置引脚速率为50MHz*/GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;/*调用库函数,初始化GPIOC*/GPIO_Init(GPIOC,&GPIO_InitStructure);//关闭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"stm32f10x.h"/**themacrodefinitiontotriggertheledonoroff*1-off*0-on*/#defineON0#defineOFF1/*带参宏,可像内联函数一样使用*/#defineLED1(a) if(a)\ GPIO_SetBits(GPIOC,GPIO_Pin_3);\ else \ GPIO_ResetBits(GPIOC,GPIO_Pin_3)led.h续#defineLED2(a) if(a)\ GPIO_SetBits(GPIOC,GPIO_Pin_4);\ else \ GPIO_ResetBits(GPIOC,GPIO_Pin_4)#defineLED3(a) if(a)\ GPIO_SetBits(GPIOC,GPIO_Pin_5);\ else \ GPIO_ResetBits(GPIOC,GPIO_Pin_5)voidLED_GPIO_Config(void);#endif/*__LED_H*/在编译过程,编译器会把带参宏展开,在相应的位置替换为宏展开代码。其中的反斜杠符号“\”叫做续行符,后面不能有空格、注释等led用到stm32f10x_gpio.h库的结构、宏定义1、GPIO_InitTypeDef结构,引脚初始化的结构2、GPIO_Pin_x引脚为uint16_t类型,宏定义:1.#defineGPIO_Pin_0((uint16_t)0x0001)/*!<Pin0selected*/2.#defineGPIO_Pin_1((uint16_t)0x0002)/*!<Pin1selected*/3.#defineGPIO_Pin_2((uint16_t)0x0004)/*!<Pin2selected*/4.#defineGPIO_Pin_3((uint16_t)0x0008)/*!<Pin3selected*/例:GPIO_Pin_0(0000000000000001)BGPIO_Pin_1(0000000000000010)B
led用到stm32f10x_gpio.h库的结构、宏定义3、GPIOSpeed_TypeDef定义GPIO的输出速率:typedefenum{GPIO_Speed_10MHz=1,//枚举常量值1,对应10MHzGPIO_Speed_2MHz,//常量值为2,对应2MHzGPIO_Speed_50MHz//常量值为3,对应50MHz}GPIOSpeed_TypeDef;GPIO_Speed_10MHz对应(0001)BGPIO_Speed_2MHz对应(0010)BGPIO_Speed_50MHz对应(0011)BSpeed控制参数,它的宏展开低2位的值,正好符合寄存器MODEy中2位的控制值。直接把这个参数写入CRL、CRH配置寄存器的MODEy位,其中y由GPIO_Pin参数确定第几引脚。
led用到stm32f10x_gpio.h库的结构、宏定义4、GPIOMode_TypeDef结构定义GPIO引脚的功能:typedefenum{GPIO_Mode_AIN=0x0,//模拟输入模式GPIO_Mode_IN_FLOATING=0x04,//浮空输入模式GPIO_Mode_IPD=0x28,//下拉输入模式GPIO_Mode_IPU=0x48,//上拉输入模式
GPIO_Mode_Out_OD=0x14,//开漏输出模式GPIO_Mode_Out_PP=0x10,//通用推挽输出模式GPIO_Mode_AF_OD=0x1C,//复用功能开漏输出GPIO_Mode_AF_PP=0x18//复用功能推挽输出}GPIOMode_TypeDef;用于初始化的库函数GPIO_Init()通过查找库帮助文档获得Error:L6218E:Error:L6218E:Undefinedsymbolassert_param(referredfromstm32f10x_gpio.o).断言机制函数assert_param,STM32的函数:assert_param(IS_GPIO_ALL_PERIPH(GPIOx));刚开始学习的时候都遇到编译不过去的问题,通过在文件中添加USE_STDPERIPH_DRIVER来解决的:error65:创建一个STM32F103VE核的项目error65:accessviolationat0x40021000:no'read'permission是Debug里面的设置有缺陷,不会自动匹配:DialogDLL:DCM3.DLLParameter:-pCM3应手动改为:DialogDLL:DARMSTM.DLLParameter:-pSTM32F103VE逻辑分析窗口使用再点击Setup,输入LED灯对应的三个信号PORTB.0、PORTF.7、PORTF.8;DisplayType选择bit,然后单击Close关闭该对话框;逻辑分析窗口使用点击运行按钮。运行一段时间之后,点击停止按钮,暂停仿真回到逻辑分析窗口,可通过Zoom里面的In按钮来放大波形,通过Out按钮来缩小波形,或者按All显示全部波形。7.7时钟设置与开启外设时钟外设初始化后,必须要开启外设时钟。开启外设时钟之前,首先要配置好系统时钟SYSCLK。在startup_stm32f10x_hd.s启动文件中,调用main函数之前就先调用了SystemInit()函数,就是设置系统时钟SYSCLK:时钟来源、倍频、分频等控制参数。这个函数的定义在system_stm32f10x.c文件之中。时钟设置与开启外设时钟voidSystemInit(void)函数的执行流程是先将与配置时钟相关的寄存器都复位为默认值,复位寄存器后,调用了另外一个函数SetSysClock(),其代码:在system_stm32f10x.c文件的开头,有条件编译定义。选择相应的时钟。时钟设置与开启外设时钟GPIO所用的时钟PCLK2我们采用默认值,也为72MHz。开启和关闭外设时钟也有封装好的库函数RCC_APB2PeriphClockCmd()。在led.c文件中调用了这个函数。
/*开启GPIOC外设时钟,参数DISABLE为关闭*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);如用到I/O引脚复用功能,还要开
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 佛山市道广体育初级游泳救生培训试题复习测试卷含答案
- 互联网营销师五级练习测试题附答案
- 2025年触电救援考试试题及答案
- 2025年口腔医学三基试题及答案
- 2025年山东合格考历史试题及答案
- 2025年防排烟自考试题及答案
- 2025年交往能力测试题型及答案
- 2025年专注力灯光测试题及答案
- 2025年戏导考试的表演试题及答案
- 2025年吸气挑战测试题及答案
- 丽江悦榕庄案例分析
- 小学语文中高年级单元整体教学设计的实践研究(中期报告)
- 国家安全教育国土安全
- 七年级下册《5.4 平移》课件
- 机电系统综合调试方案
- 《合理调节情绪-做自己情绪的主人》班会课件
- 中国高等教育的历史演进课件
- 2024年徐州地铁集团有限公司招聘笔试参考题库含答案解析
- 脑心健康管理工作总结
- 村委会会议签到表
- 001 220kV升压站事故油池施工方案
评论
0/150
提交评论