STM32学习笔记及勘误手册.docx
- 文档编号:14681601
- 上传时间:2023-06-26
- 格式:DOCX
- 页数:34
- 大小:919.75KB
STM32学习笔记及勘误手册.docx
《STM32学习笔记及勘误手册.docx》由会员分享,可在线阅读,更多相关《STM32学习笔记及勘误手册.docx(34页珍藏版)》请在冰点文库上搜索。
STM32学习笔记及勘误手册
/*******************************************************************
文件名:
书写程序中一些特别需要留意的地方
文件编辑人:
张恒
编辑日期:
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/11
V1.4版本:
1.更新ADC校准标志部分注意事项。
2.更新了TIM1和TIM8的高级定时器特殊功能说明。
//2015/12/13
V1.5版本:
1.优化了部分注意事项,SysTick的写法上重新的定制写法。
2.优化了ADC在使用过程的一些细节注意地方。
3.面对最近出现的浮点数运算错误,配合AD数据进行总结。
4.RTC细节的把握-配置正确顺序的错误。
//2015/12/20
V1.6版本:
1添加USART的一些使用细节。
2.更新TIM的PWM输入和输出以及主从模式的使用。
3.添加了小技巧类的程序检查调试方案。
4.添加了I2C通信协议方式STM32版使用事项。
//2015/12/23
V1.7版本:
1.更新了高级TIM定时器的注意事项。
//2015/12/25
V1.8版本:
1.更新了RTC的一些注意事项。
2.更新了GPIO端口部分重映射和重映射使用注意说明,及一些特殊引脚默认功能的附表,一些端口默认下并不是IO口功能的特殊说明。
//2015/12/28
V1.9版本:
1.更新添加了特别篇:
小技巧的用法使用说明。
//2015/12/29
V2.0版本:
1.更新了部分模块使用的一些详细说明。
2.添加了高级TIM输出PWM的控制说明。
//2015/1/13
V2.1版本:
1.添加了printf的重定向内容程序部分。
2.(下阶段进军实体化例子制作)。
//2015/1/14
V2.2版本:
1.补充了ADC中容易忽视的读取数值位数小马虎。
2.技巧篇补充对实际运行的考虑来优化代码。
//2016/3/3
V2.3版本:
1.补充高级定时器PWM输出的使用注意。
2.添加高级定时器死区和互补输出题目(未补充)。
3.对定时器添加了一些独立使用描述。
//2016/3/9
V2.4版本:
1.补充了特别技巧篇:
替换法查错。
2.对版本说明进行适当修正,查找出每个版本更新的不同。
3.添加更新了状态机的语句使用。
//2016/3/10
V2.5版本:
1.对DMA进行详尽的功能描述和使用说法。
//2016/3/16
V2.6版本:
1.对TIM定时器的输出比较模式Toogle总结
//2016/3/19
V2.7版本:
1.对FSMC控制下的5310TFTLCD进行窗口配置总结
//2016/4/2
V2.8版本:
1.更新TIM的BDTR功能描述,包括5位控制位
2.更新TIM_Toggle模式操作说明,在V2.6中的进行补充
3.更新TIM的注意事项
4.添加程序调试添加小技巧
5.添加程序优化、快速替换等小技巧
//2016/5/25
V2.9版本:
1.更新了非常主要的TIM捕获比较中断概念点
//2016/5/26
查阅目录(简制版)
1、对于GPIO和Remap的使用4
2、外部中断EXTI配置使用5
3、在使用DMA时需要注意5
4、ADC在使用的时候5
5、NVIC中断优先级控制器6
6、TIMx定时器在进行配置使用的时候6
7、DAC的使用过程需要注意的地方7
8、SysTick滴答定时器7
9、FSMC外扩展技术的配置函数8
10、在使用RTC的时候8
11、在使用USART时的注意事项11
12、使用中的printf重定向功能11
13、I2C通信协议方式事项12
特别篇:
程序检查调试小技巧方案14
特别篇:
程序写作小技巧方案16
1、对于GPIO和Remap的使用
1>当使用GPIO时,如果是其复位的默认功能,需要打开IO时钟(APB2Clock)。
2>如果在使用复用功能时,需要在打开IO时钟的基础上打开AFIO时钟,它表示复用功能开启。
3>如果使用的是IO的重定义功能,AFIO和GPIORemap函数都要进行配置开启,否则出错。
4>对于STM32的芯片来说典型的三条AHB\APB1\APB2时钟线,它们每个总线下都挂载了许多的外设,这些外设使用时都需要配置时钟,相应需要GPIO的外设还需要进行GPIO的Mode配置,注意:
不同的外设需求的GPIO类型Mode是不一样的,在使用这个外设时一定要注意按照DataSheet中的外设GPIO_Mode配置方式进行配置。
以下为外设的GPIO配置要求图:
详见datasheet8.1.11
表内仅是部分数据,详细信息查阅datasheet8.1.11。
5>大部分的引脚功能都默认的是第一功能IO口,然而有一些引脚它们的第一功能并不是作为GPIO使用(复位后的默认功能不是GPIO),这里要注意的是:
使用这些引脚的时候,如果作为GPIO使用,需要进行配置,打开AFIO和Remap函数。
以下是一些特殊注意的引脚图:
以上引脚参考图为STM32F103RBT6的芯片,更高级的芯片或许此类引脚更多,使用时注意它们的使用方式,可以看出MainFunction并不是GPIO的功能。
使用之前切记配置!
2、外部中断EXTI配置使用
1>当使用外部中断EXTI时,一共19根EXTI线,需要在配置EXTI之前进行EXTIconfig函数设置具体使用的是那个EXTIx。
GPIO_EXTILineConfig(GPIO_PortSourceGPIOG,GPIO_PinSource8);//配置函数
3、在使用DMA时需要注意
1>DMA的使能命令DMA_Cmd开启DMA,但是开启了DMA之后如果不是连续的搬运模式,就会在DMAcounter数据为0时表示数据搬运完毕,而且开启DMA将无法重新加载搬运的数量函数:
DMA_SetCurrDataCounter函数。
因此必须要先关闭DisableDMA之后再写加载数量函数,然后再开启,重复运行,就可以多次不间断搬运数据。
2>DMA的时钟也需要开启,且DMA的时钟是挂载在了AHB的总线上,因此要注意使能。
DMA和M3的内核共用数据总线的,当它们同时访问数据的时候,DMA会暂停CPU访问若干周期。
3>DMA初始换函数里面有2个地址,一个是DataAddr一个是PeriAddr,要注意它们表示的是目的地址和源地址,使能DMA是即会自动在它们之间进行数据的传送(但要注意1>
4>外设可以使用DMA通道的,都会有一个DMA使能位(DMAEN位),当我们打开DMA使能和外设的DMA使能时数据就会自动传输。
4、ADC在使用的时候
1>STM32内部的ADC是需要在一定的时钟频率下工作的最大不超过14M,因此在使用ADC是除了要进行ADC的时钟开启(APB2Clock),还要首先设定ADC工作频率,它的频率是靠函数:
RCC_ADCCLKConfig(RCC_PCLK2_Divx);来写,在使能ADC之前必须先进行时钟分频开启,因为ADC最大14M而APB2时钟PCLK2系统配置的是72M因此这个函数必须一定要写,根据具体的需要来写出相应的分频数。
2>ADC在首次启动的时候是需要进行ADC校准的,需要用到2个函数和2个校准状态函数,这里一般使用时都要开启,因此非常重要,注意是在ADC_Cmd命令使能以后才进行校准。
也需要注意的是:
复位校准和开始校准操作是有校准标志的,1表示正在校准;0表示校准完成,在写法上:
while(ADC_GetResetCalibrationStatus(ADC1)!
=RESET);类似于这个。
3>在需要使用内部的温度传感器和基准电压时,是需要对它们进行使能,打开相应的AD采集通道16和17,使能函数写在ADC使能命令左右(先于或后于都可以),具体的使能函数:
ADC_TempSensorVrefintCmd();
4>ADC里面的ADC_NbrOfChannel(初始化结构体里面)表示规则组数量,多通道时一般写上相应的组数,这里重要的是在配置规则组通道具体排序时:
在ADC_RegularChannelConfig规则组配置函数中,注意要分开独立的写每一个组内的通道,每一个通道都专用一个单独的配置函数来配置,该函数中uint8_tRank参数表示的是该通道是组内第几个,是第几就写入相应的数,例如Rank=2表示为第2个通道。
在书写规范上,往往容易出现当函数配置时将配置顺序写错而导致的错误,这类错误是最难发现的也是最不好掌握的,只能多做总结。
在ADC配置顺序上尤其要注意通道配置函数:
ADC_RegularChannelConfig,这个函数的配置顺序是在ADC_Cmd函数之前就需要配置完成,否则无法进行AD转换。
5>ADC的ADC_Cmd命令是开启ADC并非直接进行转换。
ADC_SoftwareStart才是ADC转换开始的命令,它会在转换完成后自动清除。
6>最近出现的浮点数运算问题中,体现出了细节,不照顾细节也很容易出现一些让人摸不着头脑的错误。
整型数在运算的时候是没有小数部分,所以不管进行什么操作其结果都是整型,如果要求显示小数部分,则必须要使用浮点类型:
float和double。
但是往往在进行整型到浮点转化的过程会出现错误,这里需要注意的是:
如需要小数部分,则最好不要用整型计算过的数,而在计算过程上就使用强制转化。
另外:
在转化时从整型跳变到浮点数是个难处,反过来却很容易,所以在整型转化浮点数时注意不要直接转化结果,一定要在过程中转化。
注意上面temp=(float)adcx*(3.3/4096)和temp=(float)(adcx*(3.3/4096))的差别。
它们2个写法很像但是却有区别。
7>ADC在使用过程中因为有取数据的步骤,除了在数据的运算时要注意类型,防止对数据的破坏,还要注意一点小马虎,ADC的数据需要至少u16的数据量才可以,所以容易犯错就是ADC的数据赋值成了u8,导致一直没有结果的显示,或者结果显示的很小。
5、NVIC中断优先级控制器
1>中断优先级控制器NVIC在使用之前需要进行分组配置NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);这个是分组配置函数,务必要写入NVIC初始化配置之前。
2>每个中断都需要配置NVIC寄存器,因此只要有中断就必须一定要写NVIC函数。
6、TIMx定时器在进行配置使用的时候
6.1通用定时器TIM2/3/4/5
1>进行输入捕获上下双沿的时候,要注意一般初始化会给定一个上或下降沿,在触发输入捕获中断时,一般是因为触发的边沿中断,检测到了上或下降沿,在中断函数中就要再改变其边沿从而实现双沿捕获,而库函数里面并没IC类名函数,用的是OC的函数:
TIM_OC1PolarityConfig(TIM5,TIM_ICPolarity_Rising)这个函数在输出时是OC的极性设置,在输入的时候是IC的上下沿降,这里要注意不要找不到了。
2>在配置OC输出的初始化配置时,注意Purse表示的是预装载的捕获/比较值,初始可以写0x000~0xFFFF之间,系统默认为:
0x0000。
3>在使用输出PWM时(Toggle模式下除外),需要注意,PWM需要开启自动装载和影子寄存器,所以对应的会有2个函数:
TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable);和TIM_ARRPreloadConfig(TIM2,ENABLE);如果不使能这2个函数,则会导致结过错误。
4>定时器TIMx下的输出比较模式中有一个特别的反转模式:
TIM_OCMode_Toggle,,这个模式的一般作用是达到比较值之后进行电平的反转。
较为特殊的一种方式是溢出PWM的方式:
在PWM的TIM_OCMode_Toggle模式下初始化 TIM1_PWM_Init(719,0);可知其计数值为0,则进行溢出操作,每溢出一次就反转一次电平(比较值=0=溢出),但是注意的是它的频率不是分频之后的频率:
溢出取反后,每溢出一次取反一次,取2次反则为一个波形,因此它的频率需要除以2。
推导可知:
Toggle的频率是反转两次的总计数为一个完整的周期波形,计算频率要用完整的周期波形计算。
另外一点:
使用TIM_OCMode_Toggle反转模式下,必须要关闭通道的自动装载使能TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);需要打开TIM的捕获/比较通道的中断才可以使用。
5>定时器时钟注意事项(本项采自俊名QQ空间资料):
定时器关闭了但是并不关闭定时器时钟(APB)的话,定时器其实还在运行/跑,而且关闭CCRx时钟也会继续跑,所以要完全关闭定时器一般是关闭APB定时器时钟,这一点在更改定时器工作模式时为了保证运行不会出错,选择先关闭APB定时器时钟,再进行模式修改等操作。
(这一点想一想是有问题的,基于时间关系并没有验证,有待考究)。
6>(非常重要)TIM定时器一共有7个中断操作,常用的是Update、CCx、Trigger等中断。
在这些中断内,CCx中断应该特别注意:
CCx中断全称是捕获/比较中断,所以CCx中断包含捕获中断和比较中断两个中断,注意不是一个捕获中断,非常容易混淆!
CCx具体是怎么样的中断需要查看当前捕获/比较通道设置的是输出比较模式还是输入捕获模式。
详细情况可以查看datasheet中的以下描述:
可以看出CCx输出时表示值匹配中断,输入时表示捕获值中断,在使用过程中要特别注意!
6.2高级定时器TIM1/8
1>高级定时器具有重复计数功能可以进行多次的计数溢出之后在发生更新。
在高级定时器基本初始化时会比通用定时器多一个repetion参数,此项表示多次计数的次数,注意使用和其空间为8位(单向256,中央128)。
2>高级定时器的互补PWM,所谓互补就是0/1之间的相反互补。
在OC初始化设置里面比通用定时器多了CCxN的一项,注意填写。
在TIM寄存器中有相应的CCxE和CCxNE可以加入死区控制互补和非死区互补。
3>无论是高级定时器还是基本定时器在输出PWM上都要使能两个位(Toggle模式除外),而且一定要使能,否则将不会输出,一个是影子寄存器预装载寄存器ARR使能位,另一个是输出比较通道OCx的自动装载使能位。
一共是两个函数:
TIM_ARRPreloadConfig(TIMx,ENABLE);
TIM_OCxPreloadConfig(TIMx,TIM_OCPreload_Enable);
4>高级定时器TIM1和TIM8中要使CHX和CHNX输出PWM波形必须打开控制输出的MOE位(BDTR寄存器的最高位),还需要进行一个配置,其配置函数为:
TIM_CtrlPWMOutputs(TIM1,ENABLE);如果不打开这一位则无法输出PWM波形。
5>高级定时器PWM输出时,使能信号TIM_CtrlPWMOutputs(TIM1,ENABLE)可以重复读取从而不影响结果。
但是使用TIM_Cmd(TIM1,ENABLE)时,就会出现没有PWM信号的问题,因此当要求PWM信号可控制停止和启动的时候不可用定时器使能命令。
6>寄存器BDTR涵盖死区DT设置和刹车BREAK设置,DT和BREAK的设置主要与5个控制位有关:
MOE、OISx、OISxN、OSSI、OIIR。
它们的主要作用可以参考datasheet和参考手册。
DT的设置需要注意的是要根据死区时间长短选取不同的公式计算,而BREAK主要是打开使能和极性。
7>无论是高级定时器还是通用定时器,它们之间都是完全独立的,不相互共享任何资源,因此它们可以同时启动,同步运行。
8>
7、DAC的使用过程需要注意的地方
1>DAC在使用时因为DAC一共有2个且每个DAC都可以单独输出,因此一共2个输出引脚,重要的是它们是模拟量输出,而STM32的引脚一般使用是数字量。
这里需要熟记:
当DAC在配置输出GPIO引脚输出时,要将此输出引脚配置成模拟输入模式GPIO_Mode_AIN,这样可以大幅的避免因为模拟量的原因而造成的干扰。
8、SysTick滴答定时器
1>SysTick滴答定时器(24位计数/定时)是捆绑在NVIC里面的,在M3指南中查看NVIC可以找到SysTick,这是因为SysTick是M3内核里面的东西,主要的结构体和寄存器定义在:
core_cm3.h的头文件中,注意查找,另外由于是M3的内核所以大部分的板子都是可以兼容的!
在是用滴答定时器的时候要注意SysTick的时钟可以是AHB时钟也可以是AHB时钟的9分频,配置函数可以在misc.h文件中找到:
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);需要事先启用时钟。
2>SysTick的写法是兼容的,固然很重要,而且计时很准确,但要注意的是它是一个24位的计数器,一般在9MHz的频率下,所以最大计时时间为1.86s左右,因此计时2秒以上是不可能的,需要多次书写函数。
3>程序书写上,先配时钟,在依次写LOAD、VAL、CTRL寄存器,结束时依次写CTRL、VAL寄存器,注意顺序!
官方延时循环部分:
比较好用的循环部分:
4>SysTick的寄存器一共有4个但是校准寄存器一般不会使用,寄存器里面由于不方便查找每一位的信息所以就在此写了一下方便查阅,CTRL寄存器的第0位为启动位,第16位为计数到0位,当SysTick定时器计数到0时该为硬件置1,读取则会清除标志位。
VAL和LOAD看名字就知道功能不再多说。
9、FSMC外扩展技术的配置函数
1>FSMC的时钟是挂载在AHB总线上的,因此在使用FSMC之前一定要使能AHBClock的时钟RCC_AHBPeriph_FSMC。
2>FSMC中需要注意的地方是它一共有25根地址线16根数据线,要选择行进行设置连接,且所有的FSMC数据和地址线都是引脚复用的,注意打开AFIO时钟和进行相关GPIO配置。
3>在FSMC配置拓展外部NOR/PSRAM/SRAM时一共有四种模式(参考Intel8080接口线)选择:
1、2、A、B,使用过程中要注意它们之间的区别,1模式下读写线都分别占用,属于不是相互独立读写,A模式和1模式区别是A模式的读写线不会占用,因此A模式下读写是相互独立的,2/B模式下根1/A模式下差不多,但是2/B模式有一个NADV位控制线。
4>注意FSMC映射1G的地址空间,其中0x60000000~0x6fffffff为第一大块区域属于NOR/PSRAM的扩展控制区;0x70000000~0x7fffffff|0x80000000~0x8fffffff两个区域为第二、三大块区域,属于NAND扩展控制区,0x90000000~0x9fffffff为第四大块区域,属于PC扩展控制区。
它们每个大块还可分为四小块,使用时要注意地址。
详情查看datasheet。
5>FSMC下的TFTLCD配置ID为5310,这里需要注意的是竖屏和横屏的切换:
TFTLCD默认的是竖屏的分辨率,以5310为例,竖屏的分辨为320(宽)×480(高),在切换的时候仅仅更改扫描方式和显示坐标是不行的,因为默认的竖屏分辨为320×480所以就算更改成横屏扫描,其结果还是对320×480的区域进行填充,导致横屏切换错误。
要更改为横屏显示,必须要对默认的分辨率进行修改,修改为横屏的分辨480(长)×320(宽),这样才会对这个区域进行填充,数据才不会出错!
以下为更改分辨的参考代码:
其中的2B和2A分别表示Y和X的地址寄存器,可以看出这里将分辨进行了重新配置。
320和480为设置的X和Y。
10、在使用RTC的时候
1>RTC有2个独立分离的时钟在内:
一个是RTC一个是PCLK1因此要注意时钟使能。
这里详细说明一下,RTC和PCLK1的时钟不一个时钟,RTC时钟在未接LSE的情况下是内部的LSI时钟,大约是40K左右,而接了外部晶振,LSE时钟就是32.768KHz经过15次分频之后(2^15)刚好是1S的周期,所以这里要注意。
PCLK1就是APB1总线上的时钟36MHz,它不对RTC进行直接操作,而是用一些控制寄存器来间接控制RTC。
这些控制寄存器虽然在PCLK1时钟下,但是出于后备电源区域,平时是保护状态,要打开保护进行修改(操作详见参见2>),双时钟的模块(这里是控制状态下的要注意和BKP、PWR两个时钟相互区别)。
2>RTC的计时时钟是处于RCC配置的后备区域,RTC的时钟配置需要通过这个后备区域BKP进行配置。
当系统复位的时候,为了防止误操作RTC,RTC的所有时钟配置值将禁止被操作。
因此要想进行时钟配置操作必须要使能BKP、PWR,这里十分重要。
RTC的2个复位系统说明:
系统复位不能对RTC造成影响,而软件复位RTC则会重新计时。
3>RTC的读写操作不能进行嵌套,每次只能执行一个读或写操作,因此为了防止读写操作的冲突导致数据错误,我们在读写操作之前要进行标志查询RTOFF,如果查询得知上次的操组已经完成,则还需要使能读写操作CNF位,才能进行相关读写操作,读写操作完毕后要关闭CNF位和查询读写是否完毕。
相关函数:
RTC_WaitForLastTask();
4>参见2>可知,RTC在对计时时钟操作的时候要注意一定要使能PWR和BKP的时钟,打开PWR的后备区域通道保护,才可进行对RTC的CONT和ALR寄存器进行赋值,达到设置时间和闹钟的目的。
这里要注意一定不可在重新使能(这里是软复位)复位BKP时钟了,下面是例程代码:
(注释部分需要知道)
以上是在设置定时的时候,万不可直接写出函数:
RTC_SetAlarm();要记得它们被保护着,参考以上写法就可以。
在一种特殊情况下可以直接设置RTC_SetAlarm();而不需要打开保护状态,就是当不使用后备电源的时候,因为时钟不需要后备电源供电,断电就不能继续计时,而每次上电都会打开保护,所以每次只要上电,初始化保护是打开的,就不需要在一一向上面那个图一样进行打开保护写入时间,直接赋值时间
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- STM32 学习 笔记 勘误 手册