STM32F4学习笔记之USART(使用固件库,查询方式)
- 格式:doc
- 大小:25.00 KB
- 文档页数:2
STM32L4库学习总结ST为开发者提供了非常方便的开发库。
到目前为止,有标准外设库(STD库)、HAL库、LL库三种。
前两者都是常用的库,后面的LL库是ST最近才添加,随HAL源码包一起提供,目前支持的芯片也偏少。
一般来说STD库和LL库是不兼容的。
标准外设库(Standard Peripherals Library)是对STM32芯片的一个完整的封装,包括所有标准器件外设的器件驱动器。
这应该是目前使用最多的ST库。
几乎全部使用C语言实现。
但是,标准外设库也是针对某一系列芯片而言的,没有可移植性。
标准外设库仍然接近于寄存器操作,主要就是将一些基本的寄存器操作封装成了C函数。
开发者需要关注所使用的外设是在哪个总线之上,具体寄存器的配置等底层信息。
不支持从STM32L0、L4和F7以后的芯片。
HAL是Hardware Abstraction Layer的缩写,中文名:硬件抽象层。
HAL库是ST为STM32最新推出的抽象层嵌入式软件,可以更好的确保跨STM32产品的最大可移植性。
该库提供了一整套一致的中间件组件,如RTOS,USB,TCP / IP和图形等。
HAL库是基于一个非限制性的BSD许可协议(Berkeley Software Distribution)而发布的开源代码。
ST制作的中间件堆栈(USB主机和设备库,STemWin)带有允许轻松重用的许可模式,只要是在ST公司的MCU 芯片上使用,库中的中间件(USB 主机/设备库,STemWin)协议栈即被允许随便修改,并可以反复使用。
至于基于其它著名的开源解决方案商的中间件(FreeRTOS,FatFs,LwIP和PolarSSL)也都具有友好的用户许可条款。
可以说HAL库就是用来取代之前的标准外设库的。
相比标准外设库,STM32Cube HAL库表现出更高的抽象整合水平,HAL API集中关注各外设的公共函数功能,这样便于定义一套通用的用户友好的API函数接口,从而可以轻松实现从一个STM32产品移植到另一个不同的STM32系列产品。
STM32 固件库中RCC_GetClocksFreq()函数注意事项在STM32 固件库中,当你使用RCC_GetClocksFreq()这个函数的时候,需要注意一下。
(比如,你在使用串口的USART_Init 的时候,就无形中使用到这个函数)。
当你使用外部晶振做为系统时钟的时候,而且外部晶振不是标准8MHz 的时候,你需要留意一下STM32 的固件库,里面的stm32f10x_rcc.c 这个文件,在它的RCC_GetClocksFreq()这个函数中,有这么一段voidRCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks){u32 tmp = 0, pllmull = 0, pllsource = 0, presc = 0;/* Get SYSCLK source -*/tmp = RCC->CFGR & CFGR_SWS_Mask;switch (tmp){case 0 乘以00:/* HSI used as system clock */RCC_Clocks- >SYSCLK_Frequency = HSI_Value;break;case 0 乘以04:/* HSE used as system clock */RCC_Clocks- >SYSCLK_Frequency=HSE_Value;break;case 0 乘以08:/* PLL used as system clock *//* Get PLL clock source and multiplication factor -*/pllmull = RCC->CFGR & CFGR_PLLMull_Mask;pllmull = ( pllmull >> 18) + 2;pllsource = RCC->CFGR & CFGR_PLLSRC_Mask;if (pllsource == 0 乘以00){/* HSI oscillator clock divided by 2 selected as PLL clock entry */RCC_Clocks->SYSCLK_Frequency = (HSI_Value >> 1) * pllmull;}else{/* HSE selected as PLL clock entry */if ((RCC->CFGR & CFGR_PLLXTPRE_Mask) != (u32)RESET){/* HSE oscillator clock divided by 2 */。
/******************************************************************* 文件名:书写程序中一些特别需要留意的地方文件编辑人:张恒编辑日期:15/11/23功能:快速查阅巩固知识点*******************************************************************/ 版本说明:v1.0版本:1.开始编辑书写整个文档,开始用的为TXT文档的形式,整理了部分学习到的东西和一些在书写常用程序中容易出错的地方,以及经常忽视细节而导致程序运行失败,是巩固知识点,提醒值得注意地方的工具文档。
2.添加的功能上基本涵盖了所有的模块,除了串口通信中的SPI和I2C、I2S等,应用是比较简单后续可能会添加。
3.对一些特定的功能综合应用并未加入进去,这是一个不好的地方,后续应该会随着学习总结更新,每次更新记录为一个版本。
// 2015/11/24;v1.1版本:1.将所有的TXT版本的文档全部转换为DOC模式,并且更新的加入了目录显示,显示为1级目录,方便查阅相关内容。
2.更新了SysTick书写中值得注意的地方3.更新了FSMC的一些细微操作,后续继续追捕更新书写细节。
V1.2版本:1.更新了FSMC部分功能显示,详细了FSMC的使用注意事项2.添加了RTC实时时钟的一些注意事项。
//2015/12/1;V1.3版本:1.更新RTC部分注意事项。
//2015/12/11V1.4版本:1.更新ADC校准标志部分注意事项。
2.更新了TIM1和TIM8的高级定时器特殊功能说明。
//2015/12/13V1.5版本:1.优化了部分注意事项,SysTick的写法上重新的定制写法。
2.优化了ADC在使用过程的一些细节注意地方。
3.面对最近出现的浮点数运算错误,配合AD数据进行总结。
4.RTC细节的把握-配置正确顺序的错误。
stm32f4 的 dma 中断函数STM32F4系列微控制器是ST公司推出的一款高性能、低功耗的32位ARM Cortex-M4内核微控制器。
它具有丰富的外设和强大的计算能力,广泛应用于各种嵌入式系统中。
其中,DMA(Direct Memory Access,直接存储器访问)是STM32F4中重要的特性之一,可以有效地提高数据传输的效率和性能。
DMA中断函数是在DMA传输过程中产生中断时执行的函数。
在STM32F4中,DMA控制器负责处理数据传输,而CPU可以在数据传输过程中执行其他任务。
当DMA传输完成或出现错误时,DMA控制器会触发中断,然后执行相应的中断函数。
在编写DMA中断函数之前,首先需要配置DMA控制器和相关外设。
以USART为例,下面是配置USART和DMA的简单示例代码:```c// 配置USARTUSART_InitTypeDef USART_InitStruct;USART_ART_BaudRate = 115200;USART_ART_WordLength = USART_WordLength_8b; USART_ART_StopBits = USART_StopBits_1;USART_ART_Parity = USART_Parity_No;USART_ART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_ART_Mode = USART_Mode_Tx;USART_Init(USART1, &USART_InitStruct);USART_Cmd(USART1, ENABLE);// 配置DMADMA_InitTypeDef DMA_InitStruct;DMA_InitStruct.DMA_Channel = DMA_Channel_4;DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)buffer;DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;DMA_InitStruct.DMA_BufferSize = sizeof(buffer);DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;DMA_InitStruct.DMA_Priority = DMA_Priority_High;DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;DMA_Init(DMA2_Stream7, &DMA_InitStruct);// 配置DMA中断NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = DMA2_Stream7_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStruct);```在上述代码中,首先配置了USART1的相关参数,然后配置了DMA2的Stream7通道,将USART1的数据寄存器和存储器进行连接。
STM32使⽤printf发送数据配置⽅法--串⼝UART,JTAGSWO,JLINKRTTSTM32串⼝通信中使⽤printf发送数据配置⽅法(开发环境 Keil RVMDK)在STM32串⼝通信程序中使⽤printf发送数据,⾮常的⽅便。
可在刚开始使⽤的时候总是遇到问题,常见的是硬件访真时⽆法进⼊main主函数,其实只要简单的配置⼀下就可以了。
下⾯就说⼀下使⽤printf需要做哪些配置。
有两种配置⽅法:⼀、对⼯程属性进⾏配置,详细步骤如下1、⾸先要在你的main ⽂件中包含“stdio.h” (标准输⼊输出头⽂件)。
2、在main⽂件中重定义<fputc>函数如下:// 发送数据int fputc(int ch, FILE *f){USART_SendData(USART1, (unsigned char) ch);// USART1 可以换成 USART2 等while (!(USART1->SR & USART_FLAG_TXE));return (ch);}// 接收数据int GetKey (void){while (!(USART1->SR & USART_FLAG_RXNE));return ((int)(USART1->DR & 0x1FF));}这样在使⽤printf时就会调⽤⾃定义的fputc函数,来发送字符。
3、在⼯程属性的 “Target" -> "Code Generation" 选项中勾选 "Use MicroLIB"MicroLIB 是缺省C的备份库,关于它可以到⽹上查找详细资料。
⼆、第⼆种⽅法是在⼯程中添加“Regtarge.c”⽂件1、在main⽂件中包含 “stdio.h” ⽂件2、在⼯程中创建⼀个⽂件保存为 Regtarge.c ,然后将其添加⼯程中在⽂件中输⼊如下内容(直接复制即可)#include <stdio.h>#include <rt_misc.h>#pragma import(__use_no_semihosting_swi)extern int SendChar(int ch); // 声明外部函数,在main⽂件中定义extern int GetKey(void);struct __FILE {int handle; // Add whatever you need here};FILE __stdout;FILE __stdin;int fputc(int ch, FILE *f) {return (SendChar(ch));}int fgetc(FILE *f) {return (SendChar(GetKey()));}void _ttywrch(int ch) {SendChar (ch);}int ferror(FILE *f) { // Your implementation of ferrorreturn EOF;}void _sys_exit(int return_code) {label: goto label; // endless loop}3、在main⽂件中添加定义以下两个函数int SendChar (int ch) {while (!(USART1->SR & USART_FLAG_TXE)); // USART1 可换成你程序中通信的串⼝USART1->DR = (ch & 0x1FF);return (ch);}int GetKey (void) {while (!(USART1->SR & USART_FLAG_RXNE));return ((int)(USART1->DR & 0x1FF));}⾄此完成配置,可以在main⽂件中随意使⽤ printf 。
usart_senddata函数用法USART (Universal Synchronous/Asynchronous Receiver/Transmitter) 是一种由微处理器或计算机实现的串行通信接口,用于向外界设备或其他计算机传输数据。
USART可实现异步或同步的串行传输,具有高效性、可靠性和灵活性,因此在许多计算机和嵌入式系统中广泛应用。
USART使用串行通信协议,通过发送和接收数据包,实现设备间的数据交换。
在这里,我们将介绍USART_SendData函数的用法。
USART_SendData函数是STM32微控制器的USART库函数之一,用于在USART通信中向外界设备发送数据。
通常,在发送数据之前,需要初始化USART接口,配置它的各种参数,包括波特率、数据位、停止位和校验位等。
这些参数可以通过STM32芯片上的USART寄存器进行配置。
在配置完成之后,可以使用USART_SendData函数将数据发送到USART接口。
USART_SendData函数的参数有两个,第一个是USART_TypeDef类型的指针,指向USART寄存器组。
USART_TypeDef结构体中包含了USART寄存器的各种寄存器值,包括数据寄存器、状态寄存器和控制寄存器等。
第二个参数是要发送的数据值,为unsigned short类型。
USART_SendData函数的返回值为一个标志位,标志着数据是否成功发送。
如果数据发送成功,返回值为1;如果数据发送失败,返回值为0。
USART_SendData函数的使用非常简单,只需调用函数并传递参数即可发送数据。
以下是USART_SendData函数的示例代码,它将一个8位二进制字节(0x55)发送到USART1接口:USART_SendData(USART1, 0x55);在发送数据之后,通常需要检查发送是否成功。
可以使用USART_GetFlagStatus函数来读取USART标志位状态,以确定数据是否成功发送。
32位基于ARM微控制器STM32F101xx与STM32F103xx固件函数库介绍本手册介绍了32位基于ARM微控制器STM32F101xx与STM32F103xx的固件函数库。
该函数库是一个固件函数包,它由程序、数据结构和宏组成,包括了微控制器所有外设的性能特征。
该函数库还包括每一个外设的驱动描述和应用实例。
通过使用本固件函数库,无需深入掌握细节,用户也可以轻松应用每一个外设。
因此,使用本固态函数库可以大大减少用户的程序编写时间,进而降低开发成本。
每个外设驱动都由一组函数组成,这组函数覆盖了该外设所有功能。
每个器件的开发都由一个通用API (application programming interface 应用编程界面)驱动,API对该驱动程序的结构,函数和参数名称都进行了标准化。
所有的驱动源代码都符合“Strict ANSI-C”标准(项目于范例文件符合扩充ANSI-C标准)。
我们已经把驱动源代码文档化,他们同时兼容MISRA-C 2004标准(根据需要,我们可以提供兼容矩阵)。
由于整个固态函数库按照“Strict ANSI-C”标准编写,它不受不同开发环境的影响。
仅对话启动文件取决于开发环境。
该固态函数库通过校验所有库函数的输入值来实现实时错误检测。
该动态校验提高了软件的鲁棒性。
实时检测适合于用户应用程序的开发和调试。
但这会增加了成本,可以在最终应用程序代码中移去,以优化代码大小和执行速度。
想要了解更多细节,请参阅Section 2.5。
因为该固件库是通用的,并且包括了所有外设的功能,所以应用程序代码的大小和执行速度可能不是最优的。
对大多数应用程序来说,用户可以直接使用之,对于那些在代码大小和执行速度方面有严格要求的应用程序,该固件库驱动程序可以作为如何设置外设的一份参考资料,根据实际需求对其进行调整。
此份固件库用户手册的整体架构如下:定义,文档约定和固态函数库规则。
固态函数库概述(包的内容,库的架构),安装指南,库使用实例。
STM32标准外设固件库文件结构及用途文件夹树图及文件作用详述stm32f10x_stdperiph_lib_V3.5.0--------------ST 公司针对STM32提供的函数接口├─Release_Notes.html -------------------------官方网页资源├─stm32f10x_stdperiph_lib_um.chm-------------库的帮助文档 ├─stm32f10x_stdperiph_lib_um.chw ├─htmresc -----------------------------------CMSIS 内核和ST 公司Logo │ ├─CMSIS_Logo_Final.jpg │ └─logo.bmp ├─Libraries ----------------------------------固件库 │ ├─CMSIS -Cortex Microcontroller Software Interface Standard(Cortex 内核软件接口标准) │ │ ├─CMSIS debug support.htm ------------官方网页资源 │ │ ├─CMSIS_changes.htm ------------------官方网页资源 │ │ ├─License.doc │ │ ├─CM3 固件库文件夹树形图│ │ │ ├─CoreSupport----为采用Cortex-M3核设计SOC的芯片商设计的芯片外设提供一个进入M3内核的接口│ │ │ │ ├─core_cm3.c│ │ │ │ └─core_cm3.h│ │ │ └─DeviceSupport│ │ │ └─ST│ │ │ └─STM32F10x│ │ │ ├─Release_Notes.html│ │ │ ├─stm32f10x.h --------------------定义寄存器的地址及使用的结构体封装│ │ │ ├─system_stm32f10x.c--------------设备外设访问层,主要配置时钟频率│ │ │ ├─system_stm32f10x.h--------------配置时钟频率相应的头文件│ │ │ └─startup--------由汇编编写的系统启动文件,不同的文件对应不同的芯片型号│ │ │ ├─arm-------ARM编译器启动文件│ │ │ │ ├─startup_stm32f10x_cl.s------cl:互联型产品,stm32f105/107系列│ │ │ │ ├─startup_stm32f10x_hd.s------hd:高密度产品,FLASH大于128│ │ │ │ ├─startup_stm32f10x_hd_vl.s---vl:超值型产品,stm32f100系列│ │ │ │ ├─startup_stm32f10x_ld.s------ld:低密度产品,FLASH小于64K│ │ │ │ ├─startup_stm32f10x_ld_vl.s│ │ │ │ ├─startup_stm32f10x_md.s------md:中等密度产品,FLASH=64 or 128 │ │ │ │ ├─startup_stm32f10x_md_vl.s│ │ │ │ └─startup_stm32f10x_xl.s----xl:超高密度(容量)产品,stm32f101/103系列│ │ │ ├─gcc_ride7………………GCC编译器启动文件│ │ │ ├─iar………………………………IAR编译器启动文件│ │ │ └─TrueSTUDIO……………TrueSTUDIO编译器启动文件│ │ └─Documentation│ │ └─CMSIS_Core.htm --------------CMSIS_Core网页资源│ └─STM32F10x_StdPeriph_Driver-----------CMSIS的设备外设函数,由stm32f10x_ppp.c或 stm32f10x_ppp.h ││文件组成,PPP表示外设名称。
MDK5新建⼯程MDK5使⽤技巧STM32F4在线调试建⽴相关⽂件夹如图所⽰FWLIB放官⽅固件库⽂件,HARDWARE放⾃⼰编写的.C,.H⽂件,USER放主函数⽂件,⼯程,启动⽂件等。
1,⾸先,打开 MDK(以下将 MDK5 简称为 MDK)软件。
然后点击 Project---New uVision Project ,然后保存在USER⽂件夹下,⼯程名⾃取。
2,选择 STMicroelectronics--STM32F4 Series--STM32F407--STM32F407ZGT6(如果使⽤的是其他系列的芯⽚,选择相应的型号就可以了,特别注意:⼀定要安装对应的器件 pack才会显⽰这些内容哦!!)。
3,点击 OK, MDK 会弹出 Manage Run-Time Environment 对话框。
这是 MDK5 新增的⼀个功能,在这个界⾯,我们可以添加⾃⼰需要的组件,从⽽⽅便构建开发环境,不过这⾥我们不做介绍。
所以在图 3.2.4 所⽰界⾯,我们直接点击 Cancel,即可。
得到如图所⽰界⾯:4,到这⾥,我们还只是建了⼀个框架,还需要添加启动代码,以及.c ⽂件等。
这⾥我们先介绍⼀下启动代码:启动代码是⼀段和硬件相关的汇编代码。
是必不可少的!这代码主要作⽤如下:1、堆栈(SP)的初始化;2、初始化程序计数器(PC);3、设置向量表异常事件的⼊⼝地址;4、调⽤ main 函数。
感兴趣的朋友可以⾃⼰去分析这部分代码。
ST 公司为 STM32F40x 和 STM32F41x 系列的 STM32F4 提供了⼀个共同的启动⽂件,名字为: startup_stm32f40_41xxx.s。
我们开发板使⽤的是 STM32F407ZGT6,属于 STM32F40x 系列⾥⾯的,所以直接使 startup_stm32f40_41xxx.s 这个启动⽂件即可。
不过这个启动⽂件,我们做了⼀点点修改,具体是 Reset_Handler 函数,该函数修改后代码如下:Reset_Handler PROCEXPORT Reset_Handler [WEAK];IMPORT SystemInit ;寄存器代码,不需要在这⾥调⽤ SystemInit 函数,;故屏蔽掉,库函数版本代码,可以留下;不过需要在外部实现 SystemInit 函数,否则会报错.IMPORT __mainLDR R0, =0xE000ED88 ;使能浮点运算 CP10,CP11LDR R1,[R0]ORR R1,R1,#(0xF << 20)STR R1,[R0];LDR R0, =SystemInit ;寄存器代码,未⽤到,屏蔽;BLX R0 ;寄存器代码,未⽤到,屏蔽LDR R0, =__mainBX R0ENDP这段代码,我们主要加⼊了开启 STM32F4 硬件 FPU 的代码,以使能 STM32F4 的浮点运算单元。
正点原子STM32标准库的使用模板一、前言在当今科技飞速发展的时代,嵌入式系统已经渗透到了各行各业,而STM32作为一款性能强大、功能丰富的微控制器,广泛应用于各种电子设备中。
而正点原子STM32标准库则是基于STM32的固件库,为开发者提供了一套完整的软件开发评台和丰富的外设驱动库,极大地降低了嵌入式系统开发门槛。
本文将从深度和广度两方面对正点原子STM32标准库的使用模板进行全面评估,并带您深入探讨这一主题。
二、正点原子STM32标准库的概述正点原子STM32标准库是一套专门为STM32系列单片机设计的外设固件库,提供了丰富的外设驱动程序以及丰富的例程,支持快速开发和灵活的定制,大大加速了产品的研发周期和降低了开发成本。
正点原子STM32标准库的主要特点包括:1. 完善的外设支持:库中包含了对各种外设的支持,如GPIO、USART、SPI、I2C等,方便开发者直接调用。
2. 简洁的接口设计:接口简洁清晰,易于学习和使用,降低了开发难度。
3. 兼容性强:支持多款STM32系列单片机,且易于移植和扩展。
4. 丰富的例程:提供了大量的例程供开发者参考,方便快速上手。
三、正点原子STM32标准库的使用模板1. 环境准备在使用正点原子STM32标准库前,首先需要准备好开发环境,包括开发板、Keil或者IAR等IDE环境、J-Link或ST-Link等调试工具。
确保硬件和软件环境准备就绪后,即可开始使用正点原子STM32标准库进行开发。
2. 库的下载和安装正点原子STM32标准库的下载和安装非常简单,开发者可登入正点原子全球信息站,在相应的产品页面中找到库文件的下载信息,下载后按照冠方文档进行安装和配置即可,非常方便快捷。
3. 软件应用在使用正点原子STM32标准库进行软件开发时,首先需要新建一个工程,然后在工程中引入正点原子的库文件,并在代码中进行相关的配置和程序编写。
在编写代码时,根据需要调用相应的库函数即可完成相关的功能,比如配置GPIO、初始化串口通信等。
关于STM32F4的IAP的一点点记录看了原子的STM32 的IAP 教程,一开始还以为bootloader 是啥意思,差点跟uboot 搞混淆了,其实stm32 的“bootloader”不需要自己写汇编和链接脚本,Boot 和App 都是单片机程序,只是实现的功能不同,前者是为了引导App,后者是为了实现业务逻辑。
只不过boot 是有写flash 或者sram 的功能,再加上通信口(USB/USART etc.)来接收所谓的应用程序app 代码。
然后跳转到该代码执行就好了,但是要重新设置一下中断向量表的位置,要不然两个程序的中断可能会混淆。
也就是说boot 代码的中断要进boot 代码的irq handler 而app 代码的中断要进app 代码的irq handler。
下边就以flash iap 为例来具体说说需要注意的两点:(1)boot 代码和app 代码在flash 中的位置两个代码都要正常运行那肯定不能在写入app 代码到flash 时把boot 的代码给覆盖了,要不然boot 代码就失效了。
STM32F429IG 支持三种启动方式1. FLASH 启动上电复位后PC 指针指向第一条指令位置——0x080000002. SRAM 启动上电复位后PC 指针指向第一条指令位置——0X200000003. 系统存储器启动上电复位后PC 指针指向第一条指令位置——0X1FFF0000程序的起始地址默认是被放在FLASH 的起始地址处,即0x08000000。
下图为boot 程序的flash 设置:boot 程序的地址不需要更改就是用默认的地址,理论上我们只需要确保APP起始地址在Boot 之后,并且偏移量为0X200的倍数即可。
设置boot 的占用64k(0x10000),就是0X08000000 ~0X08010000 的flash 区。
UM0427用户手册32位基于ARM微控制器STM32F101xx与STM32F103xx固件函数库介绍本手册介绍了32位基于ARM微控制器STM32F101xx与STM32F103xx的固件函数库。
该函数库是一个固件函数包,它由程序、数据结构和宏组成,包括了微控制器所有外设的性能特征。
该函数库还包括每一个外设的驱动描述和应用实例。
通过使用本固件函数库,无需深入掌握细节,用户也可以轻松应用每一个外设。
因此,使用本固态函数库可以大大减少用户的程序编写时间,进而降低开发成本。
每个外设驱动都由一组函数组成,这组函数覆盖了该外设所有功能。
每个器件的开发都由一个通用API (application programming interface 应用编程界面)驱动,API对该驱动程序的结构,函数和参数名称都进行了标准化。
所有的驱动源代码都符合“Strict ANSI—C”标准(项目于范例文件符合扩充ANSI-C标准)。
我们已经把驱动源代码文档化,他们同时兼容MISRA-C 2004标准(根据需要,我们可以提供兼容矩阵).由于整个固态函数库按照“Strict ANSI-C"标准编写,它不受不同开发环境的影响。
仅对话启动文件取决于开发环境。
该固态函数库通过校验所有库函数的输入值来实现实时错误检测.该动态校验提高了软件的鲁棒性。
实时检测适合于用户应用程序的开发和调试。
但这会增加了成本,可以在最终应用程序代码中移去,以优化代码大小和执行速度。
想要了解更多细节,请参阅Section 2.5。
因为该固件库是通用的,并且包括了所有外设的功能,所以应用程序代码的大小和执行速度可能不是最优的。
对大多数应用程序来说,用户可以直接使用之,对于那些在代码大小和执行速度方面有严格要求的应用程序,该固件库驱动程序可以作为如何设置外设的一份参考资料,根据实际需求对其进行调整.此份固件库用户手册的整体架构如下:⏹定义,文档约定和固态函数库规则.⏹固态函数库概述(包的内容,库的架构),安装指南,库使用实例。
UM0427用户手册之杨若古兰创作32位基于ARM微控制器STM32F101xx与STM32F103xx固件函数库介绍本手册介绍了32位基于ARM微控制器STM32F101xx与STM32F103xx的固件函数库.该函数库是一个固件函数包,它由程序、数据结构和宏构成,包含了微控制器所有外设的功能特征.该函数库还包含每一个外设的驱动描述和利用实例.通过使用本固件函数库,无需深入把握细节,用户也能够轻松利用每一个外设.是以,使用本固态函数库可以大大减少用户的程序编写时间,进而降低开发成本.每个外设驱动都由一组函数构成,这组函数覆盖了该外设所有功能.每个器件的开发都由一个通用API (application programming interface 利用编程界面)驱动,API对该驱动程序的结构,函数和参数名称都进行了尺度化.所有的驱动源代码都符合“Strict ANSIC”尺度(项目于范例文件符合扩充ANSIC尺度).我们曾经把驱动源代码文档化,他们同时兼容MISRAC 尺度(根据须要,我们可以提供兼容矩阵).因为全部固态函数库按照“Strict ANSIC”尺度编写,它不受分歧开发环境的影响.仅对话启动文件取决于开发环境.该固态函数库通过校验所有库函数的输入值来实理想时错误检测.该动态校验提高了软件的鲁棒性.实时检测适合于用户利用程序的开发和调试.但这会添加了成本,可以在终极利用程序代码中移去,以优化代码大小和履行速度.想要了解更多细节,请参阅Section 2.5.因为该固件库是通用的,而且包含了所有外设的功能,所以利用程序代码的大小和履行速度可能不是最优的.对大多数利用程序来说,用户可以直接使用之,对于那些在代码大小和履行速度方面有严酷请求的利用程序,该固件库驱动程序可以作为如何设置外设的一份参考材料,根据实际需求对其进行调整.此份固件库用户手册的全体架构如下:⏹定义,文档商定和固态函数库规则.⏹固态函数库概述(包的内容,库的架构),安装指南,库使用实例.⏹固件库具体描述:设置架构和每个外设的函数.STM32F101xx和STM32F103xx在全部文档中被写作STM32F101x.本用户手册和固态函数库按照以下章节所描述的规范编写.1.1缩写Table 1. 本文档所有缩写定义缩写外设/单元CAN控制器局域网模块DMA直接内存存取控制器EXTI内部间断事件控制器FLASH闪存存储器GPIO通用输入输出I2C内部集成电路IWDG独立看门狗NVIC嵌套间断向量列表控制器PWR电源/功耗控制RCC复位与时钟控制器RTC实时时钟SPI串行外设接口SysTick零碎嘀嗒定时器TIM通用定时器TIM1高级控拟定时器USART通用同步异步接收发射端1.2命名规则固态函数库服从以下命名规则:PPP暗示任一外设缩写,例如:ADC.更多缩写相干信息参阅章节1.1 缩写.零碎、源程叙文件和头文件命名都以“stm32f10x_”作为开头,例如:stm32f10x_conf.h.常量仅被利用于一个文件的,定义于该文件中;被利用于多个文件的,在对应头文件中定义.所有常量都由英文字母大写书写.寄存器作为常量处理.他们的命名都由英文字母大写书写.在大多数情况下,他们采取与缩写规范与本用户手册分歧.外设函数的命名以该外设的缩写加下划线为开头.每个单词的第一个字母都由英文字母大写书写,例如:SPI_SendData.在函数名中,只答应存在一个下划线,用以分隔外设缩写和函数名的其它部分.名为PPP_Init的函数,其功能是根据PPP_InitTypeDef中指定的参数,初始化外设PPP,例如TIM_Init.名为PPP_DeInit的函数,其功能为复位外设PPP的所有寄存器至缺省值,例如TIM_DeInit.名为PPP_StructInit的函数,其功能为通过设置PPP_InitTypeDef 结构中的各种参数来定义外设的功能,例如:USART_StructInit.名为PPP_Cmd的函数,其功能为使能或者失能外设PPP,例如:SPI_Cmd.名为PPP_ITConfig的函数,其功能为使能或者失能来自外设PPP某间断源,例如:RCC_ITConfig.名为PPP_DMAConfig的函数,其功能为使能或者失能外设PPP的DMA接口,例如:TIM1_DMAConfig.用以配置外设功能的函数,老是以字符串“Config”结尾,例如GPIO_PinRemapConfig.名为PPP_GetFlagStatus的函数,其功能为检查外设PPP某标记位被设置与否,例如:I2C_GetFlagStatus.名为PPP_ClearFlag的函数,其功能为清除外设PPP标记位,例如:I2C_ClearFlag.名为PPP_GetITStatus的函数,其功能为判断来自外设PPP的间断发生与否,例如:I2C_GetITStatus.名为PPP_ClearITPendingBit的函数,其功能为清除外设PPP间断待处理标记位,例如:I2C_ClearITPendingBit.1.3编码规则本章节描述了固态函书库的编码规则.固态函数库定义了24个变量类型,他们的类型和大小是固定的.在文件stm32f10x_type.h中我们定义了这些变量:typedef signed long s32;typedef signed short s16;typedef signed char s8;typedef signed long const sc32; /* Read Only */typedef signed short const sc16; /* Read Only */typedef signed char const sc8; /* Read Only */typedef volatile signed long vs32;typedef volatile signed short vs16;typedef volatile signed char vs8;typedef volatile signed long const vsc32; /* Read Only */typedef volatile signed short const vsc16; /* Read Only */typedef volatile signed char const vsc8; /* Read Only */typedef unsigned long u32;typedef unsigned short u16;typedef unsigned char u8;typedef unsigned long const uc32; /* Read Only */typedef unsigned short const uc16; /* Read Only */typedef unsigned char const uc8; /* Read Only */typedef volatile unsigned long vu32;typedef volatile unsigned short vu16;typedef volatile unsigned char vu8;typedef volatile unsigned long const vuc32; /* Read Only */typedef volatile unsigned short const vuc16; /* Read Only */typedef volatile unsigned char const vuc8; /* Read Only */在文件stm32f10x_type.h中,布尔形变量被定义如下:Typedef enum{FALSE = 0,TRUE = !FALSE} bool;1.3.3 标记位形态类型在文件stm32f10x_type.h中,我们定义标记位类型(FlagStatus type)的2个可能值为“设置”与“重置”(SET or RESET).typedef enum{RESET = 0,SET = !RESET} FlagStatus;1.3.4 功能形态类型在文件stm32f10x_type.h中,我们定义功能形态类型(FunctionalState type)的2个可能值为“使能”与“失能”(ENABLE or DISABLE).typedef enum{DISABLE = 0,ENABLE = !DISABLE} FunctionalState;1.3.5 错误形态类型在文件stm32f10x_type.h中,我们错误形态类型类型(ErrorStatus type)的2个可能值为“成功”与“出错”(SUCCESS or ERROR).Typedef enum{ERROR = 0,SUCCESS = !ERROR} ErrorStatus;1.3.6 外设用户可以通过指向各个外设的指针访问各外设的控制寄存器.这些指针所指向的数据结构与各个外设的控制寄存器规划逐个对应.外设控制寄存器结构文件stm32f10x_map.h包含了所有外设控制寄存器的结构,下例为SPI寄存器结构的声明:/* Serial Peripheral Interface */typedef struct{vu16 CR1;u16 RESERVED0;vu16 CR2;u16 RESERVED1;vu16 SR;u16 RESERVED2;vu16 DR;u16 RESERVED3;vu16 CRCPR;u16 RESERVED4;vu16 RXCRCR;u16 RESERVED5;vu16 TXCRCR;u16 RESERVED6;} SPI_TypeDef;寄存器命名遵守上节的寄存器缩写命名规则.RESERVEDi(i为一个整数索引值)暗示被保存区域.外设声明文件stm32f10x_map.h包含了所有外设的声明,下例为SPI外设的声明:#ifndef EXT#DefineEXT extern#endif......#define PERIPH_BASE ((u32)0x40000000)#define APB1PERIPH_BASE PERIPH_BASE#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)....../* SPI2 Base Address definition*/#define SPI2_BASE (APB1PERIPH_BASE + 0x3800)....../* SPI2 peripheral declaration*/#ifndef DEBUG......#ifdef _SPI2 #define SPI2 ((SPI_TypeDef *) SPI2_BASE)#endif /*_SPI2 */......#else /* DEBUG */…...#ifdef _SPI2EXT SPI_TypeDef *SPI2;#endif /*_SPI2 */…...#endif /* DEBUG */如果用户但愿使用外设SPI,那么必须在文件stm32f10x_conf.h中定义_SPI标签.通过定义标签_SPIn,用户可以访问外设SPIn的寄存器.例如,用户必须在文件stm32f10x_conf.h中定义标签_SPI2,否则是不克不及访问SPI2的寄存器的.在文件stm32f10x_conf.h中,用户可以按照下例定义标签_SPI 和_SPIn.#define _SPI#define _SPI1#define _SPI2每个外设都有若干寄存器专门分配给标记位.我们按照响应的结构定义这些寄存器.标记位的命名,同样遵守上节的外设缩写规范,以‘PPP_FLAG_’开始.对于分歧的外设,标记位都被定义在响应的文件stm32f10x_ppp.h中.用户想要进入除错(DEBUG)模式的话,必须在文件stm32f10x_conf.h中定义标签DEBUG.如许会在SRAM的外设结构部分创建一个指针.是以我们可以简化除错过程,而且通过转储外设获得来获得所有寄存器的形态.在所无情况下,SPI2都是一个指向外设SPI2首地址的指针.变量DEBUG可以仿照下例定义:#define DEBUG 1可以初始化DEBUG模式与文件stm32f10x_lib.c中如下:#ifdef DEBUGvoid debug(void){......#ifdef _SPI2SPI2 = (SPI_TypeDef *) SPI2_BASE;#endif /*_SPI2 */......} #endif /* DEBUG*/Note:1 当用户选择DEBUG模式,宏assert_param被扩展,同时运转时间检查功能也在固态函数库代码中被激活.2 进入DEBUG模式会增大代码的尺寸,降低代码的运转效力.是以,我们强烈建议仅仅在除错的时候使用响应代码,在终极的利用程序中,删除它们.2.固件函数库2.1紧缩包描述STM32F10x固件函数库被紧缩在一个zip文件中.解压该文件会发生一个文件夹:STM32F10xFWLib\FWLib,包含如下所示的子文件夹:Figure 1:固件函数库文件夹结构2.1.1文件夹Examples文件夹Examples,对应每一个STM32外设,都包含一个子文件夹.这些子文件夹包含了整套文件,构成典型的例子,来示范如何使用对应外设.这些文件有:readme.txt:每个例子的简单描述和使用说明.stm32f10x_conf.h:该头文件设置了所有使用到的外设,由分歧的“DEFINE”语句构成.stm32f10x_it.c:该源文件包含了所有的间断处理程序(如果未使用间断,则所有的函数体都为空).stm32f10x.it.h:该头文件包含了所有的间断处理程序的本相.main.c:例程代码.注:所有的例程的使用,都不受分歧软件开发环境的影响.2.1.2文件夹Library文件夹Library包含构成固件函数库核心的所有子文件夹和文件:子文件夹inc包含了固件函数库所需的头文件,用户无需点窜该文件夹:stm32f10x_type.h:所有其他文件使用的通用数据类型和枚举.stm32f10x_map.h:外设存储器映像和寄存器数据结构.stm32f10x_lib.h:主头文件夹,包含了其他头文件.stm32f10x_ppp.h:每个外设对应一个头文件,包含了该外设使用的函数本相,数据结构和枚举.cortexm3_macro.h:文件cortexm3_macro.s对应的头文件.子文件夹src包含了固件函数库所需的源文件,用户无需点窜该文件夹:stm32f10x_ppp.c:每个外设对应一个源文件,包含了该外设使用的函数体.stm32f10x_lib.c:初始化所有外设的指针.注:所有代码都按照Strict ANSIC尺度书写,都不受分歧软件开发环境的影响.2.1.3文件夹Project文件夹Project包含了一个尺度的程序项目模板,包含库文件的编译和所有效户可点窜的文件,可用以建立新的工程.stm32f10x_conf.h:项目配置头文件,默认为设置了所有的外设.stm32f10x_it.c:该源文件包含了所有的间断处理程序(所有的函数体默认为空).stm32f10x_it.h:该头文件包含了所有的间断处理程序的本相.main.c:主函数体文件夹EWARM,RVMDK,RIDE:用于分歧开发环境使用,概况查询各文件夹下的文件readme.txt.2.2固件函数库文件描述Table 2列举和描述了固件函数库使用的所有文件.固件函数库的体系和文件彼此包含的联系暗示在Figure 2中.每一个外设都有一个对应的源文件:stm32f10x_ppp.c和一个对应的头文件:stm32f10x_ppp.h.文件stm32f10x_ppp.c包含了使用外设PPP所需的所有固件函数.提供所有外设一个存储器映像文件stm32f10x_map.h.它包含了所有寄存器的声明,既可以用于Debug模式也能够用于release模式.头文件stm32f10x_lib.h包含了所有外设头文件的头文件.它是独逐个个用户须要包含在本人利用中的文件,起到利用和库之间界面的感化.文件stm32f10x_conf.h是独逐个个须要由用户点窜的文件.它作为利用和库之间的界面,指定了一系列参数.Table 2. 固件函数库文件描述文件名描述参数设置文件,起到利用和库之间界面的感化.用户必须在运转本人的程序前点窜该文件.用户可以利用模板使能或者失能外设.也能够点窜内部晶振的参数.也能够是用该文件在编译前使能Debug或者release模式.主函数体示例.外设间断函数文件.用户可以加入本人的间断程序代码.对于指向同一个间断向量的多个分歧间断请求,可以利用函数通过判断外设的间断标记位来确定精确的间断源.固件函数库提供了这些函数的名称.包含了所有外设的头文件的头文件.它是独逐个个用户须要包含在本人利用中的文件,起到利用和库之间界面的感化.Debug模式初始化文件.它包含多个指针的定义,每个指针指向特定外设的首地址,和在Debug模式被使能时,被调用的函数的定义.该文件包含了存储器映像和所有寄存器物理地址的声明,既可以用于Debug模式也能够用于release模式.所有外设都使用该文件.通用声明文件.包含所有外设驱动使用的通用类型和常数.由C说话编写的外设PPP的驱动源程叙文件.外设PPP的头文件.包含外设PPP函数的定义,和这些函数使用的变量.CortexM3内核特殊指令的指令包装.Figure 2. 固件函数库文件体系结构2.3 外设的初始化和设置本节按步调描述了如何初始化和设置任不测设.这里PPP代表任不测设.1.在主利用文件中,声明一个结构PPP_InitTypeDef,例如:PPP_InitTypeDef PPP_InitStructure;这里PPP_InitStructure是一个位于内存中的工作变量,用来初始化一个或者多个外设PPP.2.为变量PPP_InitStructure的各个结构成员填入答应的值.可以采取以下2种方式:a)按照如下程序设置全部结构体PPP_InitStructure.member1=val1;PPP_InitStructure.member2 = val2;PPP_InitStructure.memberN = valN;/* where N is the number of the structure members */以上步调可以合并在同一行里,用以优化代码大小:PPP_InitTypeDef PPP_InitStructure = { val1, val2,.., valN}b)仅设置结构体中的部分成员:这类情况下,用户该当首先调用函数PPP_SturcInit(..)来初始化变量PPP_InitStructure,然后再点窜其中须要点窜的成员.如许可以包管其他成员的值(多为缺省值)被精确填入.PPP_StructInit(&PPP_InitStructure);PP_InitStructure.memberX = valX;PPP_InitStructure.memberY = valY;/*where X and Y are the members the user wants to configure*/3. 调用函数PPP_Init(..)来初始化外设PPP.4. 在这一步,外设PPP已被初始化.可以调用函数PPP_Cmd(..)来使能之.PPP_Cmd(PPP, ENABLE);可以通过调用一系列函数来使用外设.每个外设都具有各自的功能函数.更多细节参阅Section3 外设固件概述.注:1.在设置一个外设前,必须调用以下一个函数来使能它的时钟:RCC_AHBPeriphClockCmd(RCC_AHBPeriph_PPPx,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_PPPx, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_PPPx, ENABLE);2. 可以调用函数PPP_Deinit(..)来把外设PPP的所有寄存器复位为缺省值:PPP_DeInit(PPP)3.在外设设置完成当前,继续点窜它的一些参数,可以参照如下步调:PPP_InitStucture.memberX = valX;PPP_InitStructure.memberY = valY; /* where X and Y are the onlymembers that user wants to modify*/PPP_Init(PPP, &PPP_InitStructure);2.4 位段(BitBanding)Cortex™M3存储器映像包含两个位段(bitband)区.这两个位段区将别号存储器区中的每个字映照到位段存储器区的一个位,在别号存储区写入一个字具有对位段区的目标位执行读改写操纵的不异后果.所有STM32F10x外设寄存器都被映照到一个位段(bitband)区.这个特性在各个函数中对单个比特进行置1/置0操纵时被大量使用,用以减小和优化代码尺寸.Section 2.4.1和Section 2.4.2给出了外设固件函数库中如何实现位段访问的描述.2.4.1 映照公式映照公式给出了别号区中的每个字是如何对应位带区的响应位的,公式如下:bit_word_offset = (byte_offset x 32) + (bit_number × 4)bit_word_addr = bit_band_base + bit_word_offset其中:bit_word_offset是目标位在存取器位段区中的地位.bit_word_addr 是别号存储器区中字的地址,它映照到某个目标位.bit_band_base 是别号区的起始地址.byte_offset 是包含目标位的字节在位段里的序号.bit_number 是目标位所在地位(031).2.4.2 利用实例下例揭示了如何把寄存器RCC_CR的PLLON[24]位,映照到别号区:/* Peripheral base address in the bitband region */#define PERIPH_BASE ((u32)0x40000000)/* Peripheral address in the alias region */#define PERIPH_BB_BASE ((u32)0x42000000)/* RCC registers bit address in the alias region */#define RCC_OFFSET (RCC_BASE PERIPH_BASE)/* CR Register *//* Alias word address of PLLON bit */#define CR_OFFSET (RCC_OFFSET + 0x00)#define PLLON_BitNumber 0x18#define CR_PLLON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32 (PLLON_BitNumber * 4))编写一个使能/失能PLL的函数,步调如下:...#define CR_PLLON_Set ((u32)0x01000000)#define CR_PLLON_Reset ((u32)0xFEFFFFFF)...void RCC_PLLCmd(FunctionalState NewState){if (NewState != DISABLE){ /* Enable PLL */RCC>CR |= CR_PLLON_Set;}else{ /* Disable PLL */RCC>CR &= CR_PLLON_Reset;}}Using bitband access this function will be coded as follows:void RCC_PLLCmd(FunctionalState NewState){*(vu32 *) CR_PLLON_BB = (u32)NewState;}2.5 运转时间检测固件函数库通过检查库函书的输入来实现运转时间错误侦测.通过使用宏assert_param来实现运转时间检测.所有请求输入参数的函数都使用这个宏.它可以检查输入参数是否在答应的范围以内.例:函数PWR_ClearFlagstm32f10x_pwr.c:void PWR_ClearFlag(u32 PWR_FLAG){/* Check the parameters */assert_param(IS_PWR_CLEAR_FLAG(PWR_FLAG));PWR>CR |= PWR_FLAG << 2;}stm32f10x_pwr.h:/* PWR Flag */#define PWR_FLAG_WU ((u32)0x00000001)#define PWR_FLAG_SB ((u32)0x00000002)#define PWR_FLAG_PVDO ((u32)0x00000004)#define IS_PWR_CLEAR_FLAG(FLAG) ((FLAG == PWR_FLAG_WU) || (FLAG == PWR_FLAG_SB)如果传给宏assert_param的参数为false,则调用函数assert_failed并返回被错误调用的函数所在的文件名和行数.如果传给宏assert_param的参数为true,则无返回值.宏assert_param编写于文件stm32f10x_conf.h中:/* Exported macro */#ifdef DEBUG/******************************************************************* ************ * * Macro Name : assert_param* Description : The assert_param macro is used for function's parameters check.* It is used only if the library is compiled in DEBUG mode.* Input : expr: If expr is false, it calls assert_failed function.* which reports the name of the source file and the source* line number of the call that failed.* If expr is true, it returns no value.* Return : None******************************************************************* ************/#define assert_param(expr) ((expr) ? (void)0 : assert_failed((u8 *)__FILE__,__LINE__))/* Exported functions */void assert_failed(u8* file, u32 line);#else#define assert_param(expr) ((void)0)#endif /* DEBUG */函数assert_failed编写于文件main.c或者其他用户C文件:#ifdef DEBUG/****************************************************************** * Function name : assert_failed* Description : Reports the name of the source file and the source line number.* where the assert_param error has occurred.* Input : file: pointer to the source file name* line: assert_param error line source number* Output : None* Return : None******************************************************************/ void assert_failed(u8* file, u32 line){/* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* Infinite loop */while (1){}}#endif注:运转时间检查,即宏assert_param该当只在库在Debug模式下编译时使用.建议在用户利用代码的开发和调试阶段使用运转时间检查,在终极的代码中去掉它们以改进代码尺寸和速度.如果用户仍然但愿在终极的代码中保存这项功能,可以在调用库函数前,从头使用宏assert_param来测试输入参数.3. 外设固件概述本节零碎描述了每一个外设固件函数库.完好地描述所有相干函数并提供如何使用他们的例子.函数的描述按如下格式进行:函数名外设函数的名称输入参数{x}输入参数描述输出参数{x}输出参数描述返回值函数的返回值4. 模拟/数字转换器4.1 ADC寄存器结构4.2 ADC库函数5. 备份寄存器(BKP)5.1 BKP寄存器结构5.2 BKP库函数6控制器局域网(CAN)6.1 CAN寄存器结构6.2 CAN库函数7 DMA控制器(DMA)7.1 DMA寄存器结构7.2 DMA库函数8 内部间断/事件控制器(EXTI)8.1 EXTI寄存器结构8.2 EXTI库函数9 FLASH存储器(FLASH)9.1 FLASH寄存器结构9.2 FLASH库函数10 通用输入/输出(GPIO)GPIO驱动可以用作多个用处,包含管脚设置,单位设置/重置,锁定机制,从端口管脚读入或者向端口管脚写入数据.Section 10.1 GPIO寄存器结构描述了固件函数库所使用的数据结构,Section 10.2 固件库函数介绍了函数库里的所有函数.10.1 GPIO寄存器结构GPIO寄存器结构,GPIO_TypeDef和AFIO_TypeDef,在文件“stm32f10x_map.h”中定义如下:typedef struct{vu32 CRL;vu32 CRH;vu32 IDR;vu32 ODR;vu32 BSRR;vu32 BRR;vu32 LCKR;} GPIO_TypeDefTypedef struct{vu32 EVCR;vu32 MAPR;vu32 EXTICR[4];} AFIO_TypeDef;Table 178.例举了GPIO所有寄存器.Table 178. GPIO寄存器IDR端口输入数据寄存器ODR端口输出数据寄存器BSRR端口位设置/复位寄存器BRR端口位复位寄存器LCKR端口配置锁定寄存器EVCR事件控制寄存器MAPR复用重映照和调试I/O配置寄存器EXTICR内部间断线路015配置寄存器五个GPIO外设声明于文件“stm32f10x_map.h”:...#define PERIPH_BASE ((u32)0x40000000)#define APB1PERIPH_BASE PERIPH_BASE#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)...#define AFIO_BASE (APB2PERIPH_BASE + 0x0000)#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) #define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00) #define GPIOC_BASE (APB2PERIPH_BASE + 0x1000) #define GPIOD_BASE (APB2PERIPH_BASE + 0x1400) #define GPIOE_BASE (APB2PERIPH_BASE + 0x1800) #ifndef DEBUG...#ifdef _AFIO#define AFIO ((AFIO_TypeDef *) AFIO_BASE)#endif /*_AFIO */#ifdef _GPIOA#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)#endif /*_GPIOA */#ifdef _GPIOB#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)#endif /*_GPIOB */#ifdef _GPIOC#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)#endif /*_GPIOC */#ifdef _GPIOD#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)#endif /*_GPIOD */#ifdef _GPIOE#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)#endif /*_GPIOE */...#else /* DEBUG */...#ifdef _AFIOEXT AFIO_TypeDef *AFIO;#endif /*_AFIO */#ifdef _GPIOAEXT GPIO_TypeDef *GPIOA;#endif /*_GPIOA */#ifdef _GPIOBEXT GPIO_TypeDef *GPIOB;#endif /*_GPIOB */#ifdef _GPIOCEXT GPIO_TypeDef *GPIOC;#endif /*_GPIOC */#ifdef _GPIODEXT GPIO_TypeDef *GPIOD;#endif /*_GPIOD */#ifdef _GPIOEEXT GPIO_TypeDef *GPIOE;#endif /*_GPIOE */...#endif使用Debug模式时,初始化指针AFIO, GPIOA, GPIOB, GPIOC, GPIOD 和GPIOE 于文件“stm32f10x_lib.c”:#ifdef _GPIOAGPIOA = (GPIO_TypeDef *) GPIOA_BASE;#endif /*_GPIOA */#ifdef _GPIOBGPIOB = (GPIO_TypeDef *) GPIOB_BASE;#endif /*_GPIOB */#ifdef _GPIOCGPIOC = (GPIO_TypeDef *) GPIOC_BASE;#endif /*_GPIOC */#ifdef _GPIODGPIOD = (GPIO_TypeDef *) GPIOD_BASE;#endif /*_GPIOD */#ifdef _GPIOEGPIOE = (GPIO_TypeDef *) GPIOE_BASE;#endif /*_GPIOE */#ifdef _AFIOAFIO = (AFIO_TypeDef *) AFIO_BASE;#endif /*_AFIO */为了访问GPIO寄存器,, _GPIO, _AFIO, _GPIOA, _GPIOB, _GPIOC, _GPIOD和_GPIOE必须在文件“stm32f10x_conf.h”中定义如下:#define _GPIO#define _GPIOA#define _GPIOB#define _GPIOC#define _GPIOD#define _GPIOE#define _AFIO10.2 GPIO库函数Table 179. 例举了GPIO的库函数Table 179. GPIO库函数GPIO_Init根据GPIO_InitStruct中指定的参数初始化外设GPIOx寄存器GPIO_ReadInputData读取指定的GPIO端口输入GPIO_ReadOutputDataBit读取指定端口管脚的输出GPIO_ReadOutputData读取指定的GPIO端口输出GPIO_SetBits设置指定的数据端口位GPIO_ResetBits清除指定的数据端口位GPIO_WriteBit设置或者清除指定的数据端口位GPIO_Write向指定GPIO数据端口写入数据GPIO_PinLockConfig锁定GPIO管脚设置寄存器GPIO_EventOutputConfig选择GPIO管脚用作事件输出GPIO_EventOutputCmd使能或者失能事件输出10.2.1 函数GPIO_DeInitTable 180. 描述了函数GPIO_DeInit函数名GPIO_DeInit输入参数GPIOx:x可所以A,B,C,D或者E,来选择GPIO外设输出参数无返回值无例:/* Resets the GPIOA peripheral registers to their default resetvalues */GPIO_DeInit(GPIOA);10.2.2 函数GPIO_AFIODeInitTable 181. 描述了函数GPIO_AFIODeInitTable 181. 函数GPIO_AFIODeInit函数名GPIO_AFIODeInit输入参数无输出参数无返回值无先决条件无例:/* Resets the Alternate functions registers to their default resetvalues */GPIO_AFIODeInit();10.2.3 函数GPIO_InitTable 182. 描述了函数GPIO_InitTable 182. 函数GPIO_InitGPIO_Init输入参数1GPIOx:x可所以A,B,C,D或者E,来选择GPIO外设输入参数2GPIO_InitStruct:指向结构GPIO_InitTypeDef的指针,包含了外设GPIO的配相信息参阅Section:GPIO_InitTypeDef查阅更多该参数答应取值范围输出参数无返回值无先决条件无被调用函数无GPIO_InitTypeDef structureGPIO_InitTypeDef定义于文件“stm32f10x_gpio.h”:typedef struct{u16 GPIO_Pin;GPIOSpeed_TypeDef GPIO_Speed;GPIOMode_TypeDef GPIO_Mode;} GPIO_InitTypeDefGPIO_Pin该参数选择待设置的GPIO管脚,使用操纵符“|”可以一次选中多个管脚.可以使用下表中的任意组合.Table 183. GPIO_Pin值GPIO_Pin_1选中管脚1GPIO_Pin_2选中管脚2GPIO_Pin_3选中管脚3GPIO_Pin_4选中管脚4GPIO_Pin_5选中管脚5GPIO_Pin_6选中管脚6GPIO_Pin_7选中管脚7GPIO_Pin_8选中管脚8GPIO_Pin_9选中管脚9GPIO_Pin_10选中管脚10GPIO_Pin_11选中管脚11GPIO_Pin_12选中管脚12GPIO_Pin_15选中管脚15GPIO_Pin_All选中全部管脚GPIO_SpeedGPIO_Speed GPIO_Speed用以设置选中管脚的速率.Table 184. 给出了该参数可取的值.Table 184. GPIO_Speed值GPIO_SpeedGPIO_Mode用以设置选中管脚的工作形态.Table 185. 给出了该参数可取的值. Table 185. GPIO_Mode值GPIO_Mode_IPD下拉输入GPIO_Mode_IPU上拉输入GPIO_Mode_Out_OD开漏输出GPIO_Mode_Out_PP推挽输出GPIO_Mode_AF_OD复用开漏输出GPIO_Mode_AF_PP复用推挽输出留意:⏹当某管脚设置为上拉或者下拉输入模式,使用寄存器Px_BSRR和PxBRR ⏹GPIO_Mode答应同时设置GPIO方向(输入/输出)和对应的输入/输出设置,:位[7:4]对应GPIO方向,位[4:0]对应配置.GPIO方向有如下索引GPIO输入模式= 0x00GPIO输出模式= 0x01Table 186. 给出了所有GPIO_Mode的索引和编码Table 186. GPIO_Mode的索引和编码GPIO方向索引模式设置模式代码GPIO Input0x00 GPIO_Mode_AIN 0x00 0x00GPIO_Mode_IN_FLOATING 0x04 0x04GPIO_Mode_IPD 0x08 0x28GPIO_Mode_IPU 0x08 0x48GPIO Output0x01 GPIO_Mode_Out_OD 0x04 0x14GPIO_Mode_Out_PP 0x00 0x10GPIO_Mode_AF_OD 0x0C 0x1CGPIO_Mode_AF_PP 0x08 0x18例:/* Configure all the GPIOA in Input Floating mode */GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);10.2.4 函数GPIO_StructInitTable 187. 描述了函数GPIO_StructInitTable 187. 函数GPIO_StructInit函数名GPIO_StructInit输入参数GPIO_InitStruct:指向结构GPIO_InitTypeDef的指针,待初始化输出参数无返回值无先决条件无Table 188. 给出了GPIO_InitStruct各个成员的缺省值Table 188. GPIO_InitStruct缺省值成员缺省值例:/* Initialize the GPIO Init Structure parameters */GPIO_InitTypeDef GPIO_InitStructure;GPIO_StructInit(&GPIO_InitStructure);10.2.5 函数GPIO_ReadInputDataBitTable 189. 描述了函数GPIO_ReadInputDataBitTable 189. 函数GPIO_ReadInputDataBit函数名GPIO_ReadInputDataBit输入参数1GPIOx:x可所以A,B,C,D或者E,来选择GPIO外设输入参数2GPIO_Pin:待读取的端口位参阅Section:GPIO_Pin查阅更多该参数答应取值范围先决条件无被调用函数无例:/* Reads the seventh pin of the GPIOB and store it in ReadValue variable */u8 ReadValue;ReadValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7);10.2.6 函数GPIO_ReadInputDataTable 190. 描述了函数GPIO_ReadInputDataTable 190. 函数GPIO_ReadInputData函数名GPIO_ReadInputData输入参数GPIOx:x可所以A,B,C,D或者E,来选择GPIO外设输出参数无返回值GPIO输入数据端口值先决条件无例:/*Read the GPIOC input data port and store it in ReadValuevariable*/u16 ReadValue;ReadValue = GPIO_ReadInputData(GPIOC);10.2.7 函数GPIO_ReadOutputDataBitTable 191. 描述了GPIO_ReadOutputDataBitTable 191. 函数GPIO_ReadOutputDataBit函数名GPIO_ReadOutputDataBit输入参数1GPIOx:x可所以A,B,C,D或者E,来选择GPIO外设输入参数2GPIO_Pin:待读取的端口位参阅Section:GPIO_Pin查阅更多该参数答应取值范围返回值输出端口管脚值先决条件无被调用函数无例:/* Reads the seventh pin of the GPIOB and store it in ReadValue variable */u8 ReadValue;ReadValue = GPIO_ReadOutputDataBit(GPIOB, GPIO_Pin_7);10.2.8 函数GPIO_ReadOutputDataTable 192. 描述了函数GPIO_ReadOutputDataTable 192. 函数GPIO_ReadOutputData函数名GPIO_ReadOutputData输入参数GPIOx:x可所以A,B,C,D或者E,来选择GPIO外设输出参数无返回值GPIO输出数据端口值先决条件无例:/* Read the GPIOC output data port and store it in ReadValue variable */u16 ReadValue;ReadValue = GPIO_ReadOutputData(GPIOC);10.2.9 函数GPIO_SetBitsTable 193. 描述了GPIO_SetBitsTable 193. 函数GPIO_SetBits函数名GPIO_SetBits输入参数1GPIOx:x可所以A,B,C,D或者E,来选择GPIO外设输入参数2GPIO_Pin:待设置的端口位该参数可以取GPIO_Pin_x(x可所以015)的任意组合参阅Section:GPIO_Pin查阅更多该参数答应取值范围返回值无先决条件无被调用函数无例:/* Set the GPIOA port pin 10 and pin 15 */GPIO_SetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15);10.2.10 函数GPIO_ResetBitsTable 194. 描述了GPIO_ResetBitsTable 194. 函数GPIO_ResetBits函数名GPIO_ResetBits输入参数1GPIOx:x可所以A,B,C,D或者E,来选择GPIO外设输入参数2GPIO_Pin:待清除的端口位该参数可以取GPIO_Pin_x(x可所以015)的任意组合参阅Section:GPIO_Pin查阅更多该参数答应取值范围输出参数无返回值无先决条件无被调用函数无例:/* Clears the GPIOA port pin 10 and pin 15 */GPIO_ResetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15);10.2.11 函数GPIO_WriteBitTable 195. 描述了GPIO_WriteBitTable 195. 函数GPIO_WriteBit函数名GPIO_WriteBit输入参数1GPIOx:x可所以A,B,C,D或者E,来选择GPIO外设输入参数2GPIO_Pin:待设置或者清除指的端口位该参数可以取GPIO_Pin_x(x可所以015)的任意组合参阅Section:GPIO_Pin查阅更多该参数答应取值范围输入参数3BitVal: 该参数指定了待写入的值该参数必须取枚举BitAction的其中一个值Bit_RESET: 清除数据端口位Bit_SET: 设置数据端口位输出参数无返回值无先决条件无/* Set the GPIOA port pin 15 */GPIO_WriteBit(GPIOA, GPIO_Pin_15, Bit_SET);10.2.12 函数GPIO_WriteTable 196. 描述了GPIO_WriteTable 196. 函数GPIO_Write函数名GPIO_Write输入参数1GPIOx:x可所以A,B,C,D或者E,来选择GPIO外设输入参数2PortVal: 待写入端口数据寄存器的值输出参数无返回值无先决条件无被调用函数无例:/* Write data to GPIOA data port */GPIO_Write(GPIOA, 0x1101);10.2.13 函数GPIO_PinLockConfigTable 197. 描述了GPIO_PinLockConfigTable 197. 函数GPIO_PinLockConfig函数名GPIO_PinLockConfig输入参数2GPIO_Pin:待锁定的端口位该参数可以取GPIO_Pin_x(x可所以015)的任意组合参阅Section:GPIO_Pin查阅更多该参数答应取值范围输出参数无返回值无先决条件无被调用函数无例:/* Lock GPIOA Pin0 and Pin1 */GPIO_PinLockConfig(GPIOA, GPIO_Pin_0 | GPIO_Pin_1);10.2.14 函数GPIO_EventOutputConfigTable 198. 描述了GPIO_EventOutputConfigTable 198. 函数GPIO_EventOutputConfig函数名GPIO_EventOutputConfig输入参数1GPIO_PortSource: 选择用作事件输出的GPIO端口参阅Section:GPIO_PortSource查阅更多该参数答应取值范围输入参数2GPIO_PinSource:事件输出的管脚该参数可以取GPIO_PinSourcex(x可所以015)输出参数无返回值无先决条件无被调用函数无GPIO_PortSourceGPIO_PortSource用以选择用作事件输出的GPIO端口.Table 199. 给出了该参数可取的值Table 199. GPIO_PortSource值GPIO_PortSource描述GPIO_PortSourceGPIOC选择GPIOCGPIO_PortSourceGPIOD选择GPIOD/* Selects the GPIOE pin 5 for EVENT output */GPIO_EventOutputConfig(GPIO_PortSourceGPIOE, GPIO_PinSource5);10.2.15 函数GPIO_EventOutputCmdTable 200. 描述了GPIO_EventOutputCmdTable 200. 函数GPIO_EventOutputCmd函数名GPIO_EventOutputCmd输入参数1NewState: 事件输出的新形态这个参数可以取:ENABLE或者DISABLE输出参数无返回值无先决条件无例:/* Enable Event Ouput to the GPIOC pin 6 */GPIO_EventOutputConfig(GPIO_PortSourceGPIOC, GPIO_PinSource6);GPIO_EventOutputCmd(ENABLE);10.2.16 函数GPIO_PinRemapConfigTable 201. 描述了GPIO_ PinRemapConfigTable 201. 函数GPIO_ PinRemapConfig函数名GPIO_ PinRemapConfig函数本相void GPIO_PinRemapConfig(u32 GPIO_Remap, FunctionalStateNewState)功能描述改变指定管脚的映照输入参数1GPIO_Remap: 选择重映照的管脚参阅Section:GPIO_Remap查阅更多该参数答应取值范围输入参数2NewState: 管脚重映照的新形态这个参数可以取:ENABLE或者DISABLE输出参数无返回值无先决条件无被调用函数无GPIO_RemapGPIO_Remap用以选择用作事件输出的GPIO端口.Table 202. 给出了该参数可取的值Table 202. GPIO_Remap值GPIO_Remap描述GPIO_Remap_USART1USART1复用功能映照GPIO_PartialRemap_USART3USART2复用功能映照GPIO_FullRemap_USART3USART3复用功能完好映照GPIO_PartialRemap_TIM1USART3复用功能部分映照GPIO_FullRemap_TIM1TIM1复用功能完好映照GPIO_PartialRemap1_TIM2TIM2复用功能部分映照1GPIO_PartialRemap2_TIM2TIM2复用功能部分映照2GPIO_FullRemap_TIM2TIM2复用功能完好映照GPIO_PartialRemap_TIM3TIM3复用功能部分映照GPIO_FullRemap_TIM3TIM3复用功能完好映照GPIO_Remap_TIM4TIM4复用功能映照GPIO_Remap1_CAN CAN复用功能映照1GPIO_Remap2_CAN CAN复用功能映照2GPIO_Remap_PD01PD01复用功能映照GPIO_Remap_SWJ_NoJTRST除JTRST外SWJ完好使能(JTAG+SWDP)GPIO_Remap_SWJ_JTAGDisable JTAGDP失能 + SWDP使能例:/* I2C1_SCL on PB.08, I2C1_SDA on PB.09 */GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);10.2.17 函数GPIO_EXTILineConfigTable 203. 描述了GPIO_EXTILineConfigTable 203. 函数GPIO_EXTILineConfig函数名GPIO_EXTILineConfig输入参数1GPIO_PortSource: 选择用作内部间断线源的GPIO端口参阅Section:GPIO_PortSource查阅更多该参数答应取值范围输入参数2GPIO_PinSource:待设置的内部间断线路该参数可以取GPIO_PinSourcex(x可所以015)输出参数无返回值无先决条件无被调用函数无例:/* Selects PB.08 as EXTI Line 8 */。
1.使能对应USART模块时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USARTx, ENABLE) for USART1 and USART6
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USARTx, ENABLE) for USART2, USART3, UART4 or
UART5.
2.使能对应GPIO的时钟
RCC_AHB1PeriphClockCmd() function. (The I/O can be TX, RX, CTS, or/and SCLK).
3.配置对应引脚的复用功能
GPIO_PinAFConfig(GPIOx, GPIO_PinSourcex, GPIO_AF_USARTx); //引脚映射
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 设置为推挽输
出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用模式
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_x | GPIO_Pin_x; //引脚选择
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_xxMHz; //速度选择
GPIO_Init(GPIOx, &GPIO_InitStructure); //写入
配置信息
4.配置USART信息
USART_InitStructure.USART_BaudRate = xxx; //波特率
USART_InitStructure.USART_WordLength = USART_WordLength_xb;//字长
USART_InitStructure.USART_StopBits = USART_StopBits_x; //停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //校验
位,USART_Parity_Even,USART_Parity_Odd
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;//硬件流控
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //工作模
式
USART_Init(USARTx, &USART_InitStructure); //写入配
置信息
USART_Cmd(USARTx, ENABLE);
//使能串口模块
5.发送
USART_SendData(USARTx, char xx); //发
送字符
while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);//等待发送
完成
6.接收
if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET) //查询是否接收到数据
xxx=USART_ReceiveData(USARTx) //读
取接收到的数据
程序举例:
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl =
USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
while (1)
{
if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == SET)
{
USART_SendData(USART1, USART_ReceiveData(USART1));
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
}
}
}