Stm32 探索经历 ----------------既然选择电子这条路,你就要耐得住寂寞,且码且珍惜--------------------------- 作为电子信息专业的学生,我想很多人是从51开始接触单片机的,我也不例外,我是在大三的时候开始学习51的,和同学一起在实验室里,一步一步地跟着按郭天祥的视频学习,看累了,就会一起开黑打Dota,时光如此美好,可惜不再,所以还是要往后看。后来因为要参加TI的大学生电子竞赛,接触到了430(不是dota选手430),记得是TI刚推广的g2553,16位单片机,真真切切的感受到了其时钟的强大,后来由于比赛,开发板被压在杭电,一个礼拜的430之旅到此结束。临近毕业,我必须选一条道路走,于是走上了FPGA这条路,后来由于要接手同事的项目,开始熟悉STM32。 我是从今天1月份开始接触STM32的,因为项目中用的是F207系列,所以一开始是从F207开接触STM32的。罗列下我找的资料:1)2系列的技术手册,2)数据手册,3)外设库,4)STM32F2研讨会技术培训。除了第四个要在百度上找之外,其它的都可以再ST社区中找到。接下来开始我的F207之旅,因为英文不是那么好,很多专业的名词不会,所以我会先看STM32F2研讨会技术培训PDF(如果你说4系列没有这样的,你可以看F1的中文翻译手册,很多功能类似的),然后再看英文技术手册,再然后熟悉下外设库(STM外设库中提供了很多历程,所以熟悉起来很快)。 时钟、电源可以说相当于是人体的心脏,所以我先从时钟和电源入手,因为玩过FPGA的原因,所以我喜欢用它们的原理图来分析,无非就是几个多路选择器(通过寄存器来选择),在纸上将时钟电路图拷贝下来,并跟寄存器对应起来,我觉得这样更容易帮助我理解寄存器。但是就算看了半天的RCC,后来我都没用到过哈哈,因为ST外设库中有个system_stm32f2xx.c文件,根据指定晶振默认输出最大工作时钟。因为我工程中用的是25M晶振,所以无需做修改,但是如果外部晶振不一样时,还是需要你修改的。 STM32发展迅速,网上资料满天飞,各种开发板层出不穷,我想很多人会逼自己做决定,选择用库函数开发,还是用寄存器开发。对于这点,我也犹豫过,但是后来想想是很可笑的,因为STM32的库函数,其实就是操作寄存器,只不过有些太复杂了,但是却那么的形象生动,所以在初始化外设的时候,我会用库函数来初始化,但是当初始化定时器,我却喜欢用寄存器直接操作,TIMx->ARR,TIMx->SC,因为很好理解,一个总计数值,一个时钟分频系数,所以主要还是要看个人爱好的。初始化由于跟速度无关,所以用库函数还是寄存器由你们自己喜欢来选择。但是设计到与速度相关的,我就会用寄存器来操作,比如程序中有多个中断,我就会有寄存器来判断中断标志位和清除中断标志位,比如定时器更新中断,我就会这样用:if(TIMx->SR&TIM_IT_Update){TIMx->SR&=(uint16_t}~TIM_IT_Update;至于我为什么这样写,我只不过把库函数里寄存器操作,移出来,稍微修改下而已。 要充分发挥调试器的作用,论坛上,有很多人把一大段代码贴出来,然后提问,为什么定时器进不了更新中断,为什么==,很多时候都是由于初始化外设寄存器没配置好,所以你完全可以通过调试,来查看寄存器是否设置正确,不管是KEIL,IAR都有寄存器查看窗口,而不是傻傻的坐在电脑前,等着大神回复你的提问,你要知道,大神也是很忙的,所以说要物尽其用。比如F207的ADC功能,我采用DMA方式时,AD会莫名其妙停止工作,通过查看AD寄存器,发现OVR@ADC_SR置1时(F1系列没有),发送会停止,查看了技术手册中AD章节DMA管理后,DMA模式下,如果数据丢失,DMA传输被关闭,不再响应后续DMA请求,碰到些比较棘手的问题时,还是要自己通过调试发现问题。只要是单片机,就离不开寄存器哈。 接下来讲下我在调试时候遇到的问题,首先是板间串口通信,因为接收方不知道发送方数据的个数,所以接收方使用串口空闲中断,来判断一串数据是否接收完成。所以就有一个空闲帧这一概念,但是手册写的不是很清楚,甚至还误导我,STM32F207技术手册在串口章节的串口发送操作时序中写到先发送一个空闲帧,然后再置位TE启动发送,这不是将会导致接收方准备接收数据之前就应该进入串口空闲中断吗?如果我用主机像STM32发送数据,空闲帧又是哪来的,难道在一串数据之后会发一个空闲帧吗?其实归根到底,还是因为我没好好理解空闲帧的概念,ST在描述空闲帧时,这样描述:从起始位到停止位都是高电平。并且通过实验验证并找到规律,我明白了空闲中断的意思:当串口RX从低电平拉高,并且拉高一段时间之后,就会进入串口空闲中断。所以1)当数据发送结束之后,RX线会变成高电平,达到一定时间就进入串口中断。2)如果你通过复位按钮复位发送方,你也会发现接收方照样进入空闲中断,因为复位的时候,未初始化串口外设,接收方的RX(发送发的TX)线会为低电平,初始化完成之后,就会拉高RX,所以这也是为什么发送方复位,接收方也进入了空闲中断。板间串口通信的数据,我采用的是乒乓操作,当数据接收完成之后,将串口数据拷贝到缓冲区1,然后对缓冲区1的数据进行处理,串口照样接收,接收完成之后拷贝到缓冲区2,等缓冲区1数据处理完成之后,对缓冲区2数据进行处理。提示,使用标志位。 当用到GPIO操作时,你是不是感觉ST提供的库函数,很笨,比如你不能这样子操作,LED=~LED。为了解决这种情况,STMF207中提供了位带操作(BIT-BAND),当你对别名区(alias region)进行读写操作,就相当于对位带(bit-band)中的某位进行读写操作,即相当于对寄存器或SRAM某位进行操作。STM32F207内存映射中,有两个32M的别名区分别与两个1M的位带区互相映射(图一)。 图一 地址映射后如图二所示(具体算法见外设库chm文件中的Bit-Band章节),我们可以看出,对0x22000000的地址上的数进行操作,就相当于对0x20000000的第一位进行操作。比如你要对外设中寄存器中的某位进行操作,你要对寄存器地址在0x40000000的第7位进行读写操作时,你可以对0x4200001C进行读写,* (__IO uint32_t *)0x4200001C = (uint32_t)NewState。 图二 项目中的很多外设都用到了DMA,以前接触过DMA,所以接触起来很简单,只需要CPU设置要源地址,目标地址,数据类型,传送个数,当CPU时能DMA传输后,DMA控制器就会帮你完成数据传送过程,所以当传送大块数据时,CPU几乎不参与工作,CPU只在传输数据前的参数配置和传输完成后参与工作。 很多参考书其实就是对官方的数据手册进行翻译,所以我觉得上述的四个资料够我用来学习STM32了。 在给个我对外设库#define的理解,比如USART_GetITStatus函数 #define USART_IT_PE ((uint16_t)0x0028) #define USART_IT_TXE ((uint16_t)0x0727) #define USART_IT_TC ((uint16_t)0x0626) #define USART_IT_RXNE ((uint16_t)0x0525) #define USART_IT_IDLE ((uint16_t)0x0424) #define USART_IT_LBD ((uint16_t)0x0846) #define USART_IT_CTS ((uint16_t)0x096A) #define USART_IT_ERR ((uint16_t)0x0060) #define USART_IT_ORE ((uint16_t)0x0360) #define USART_IT_NE ((uint16_t)0x0260) #define USART_IT_FE ((uint16_t)0x0160) #define USART_IT_xxxx ((uint16_t)0xABCD) B用来判断各标志位在SR寄存器中的哪一位,通过将0xABCD右移8位。 C用来判断中断标志位在哪个寄存器上,CR1,CR2,CR3.取CD:(uint8_t)0xABCD,然后右移5位得到。 <span style="mso-spacerun:'yes'; font-size:12.0000pt; font-family:'宋体'; ">D用来判断中断标志位在寄存器上的哪一位,通过0x01 |
RE:【MCU实战经验】+快速熟悉stm32
RE:【MCU实战经验】+快速熟悉stm32
RE:【MCU实战经验】+快速熟悉stm32
回复:【MCU实战经验】+快速熟悉stm32
顶起来 不错、、、、、、、、、、、、哪都有你啊