原创 STM32学习笔记(10)-修修改改玩串口

2010-7-19 12:34 8798 12 13 分类: MCU/ 嵌入式


还是原来的风格,找个例子来玩,这回要玩的东西在这里(见下图)。


b09f7a66-f224-4462-b6ce-1ba6bee53b17.gif


但是这次的printf这个例子有点不一样,它依赖于ST自己的EV板子,所以要用到的东西多一些了。除了上图所示的文件以外,还要把


22cdfb2a-6341-4fc4-b8ba-4df81fd04904.gif


这里的stm32_eval.c,stm32_eval.h文件,以及图中所示三个文件夹中任意一个文件夹中的部分文件复制到第一个图所示的文件夹中去,这里我们选择stm3210e_eval这个文件夹。


4c44a12e-008f-431c-b17d-6842f41be9e3.gif



需要复制的文件是stm3210e_eval.h


如同前面一样建立工程,并且注意修改stm32_eval.h的内容


97f7e46f-3e54-4b27-a8c2-e5f81533f490.gif



将//#define USE_STM3210E_EVAL 前的#去掉。


这样,就可以编译并通过文件,用软件仿真,在usart #1窗口显示出


USART Printf Example: retarget the C library printf function to the USART


这样一行字了。


显然,对这样的玩法不令人满意,下面试着去掉与stm32e_eval等相关文件,把这里面需要用到的函数直接复制到main中去,同时,也了解一些串口设置的知识。


学到这里,多少有点明白了,STM提供的库为了达到通用性的要求,用了很多的符号来替代常量,然后七转八拐,有时不知要转多少个弯才能找到最终对寄存器操作的代码。这时,keil提供的符号浏览就很有用处了。方法是在将光标移到需要查看的符号上面,按下F12即可,通常可以直接跳转到所需查看到的符号的出处。如下图


0c01878c-e711-4c06-a517-80f9fb368cae.gif



将光标移到USART_BaudRate处,按下F12,即跳转到stm32f10x_uart.h文件中相应的定义处:


2164ff7b-30fc-4549-8c17-74717c970e35.gif



如果stm32f10x_uart.h文件没有打开,那么这个动作会自动打开这个文件。


下面我们将eval板相关的函数复制到main函数中,以便丢掉与eval板相关的文件。


(1)打开stm32_eval.h文件,将


typedef enum


{


  COM1 = 0,


  COM2 = 1


} COM_TypeDef;


复制到main.c中,这是用来选择哪一个串口的,因为我的板子上也有2个串口,所以就把它复制过来,也省得对函数作较大的修改了。


(2)打开stm32_eval.c文件,有一个


void STM_EVAL_COMInit(COM_TypeDef COM, USART_InitTypeDef* USART_InitStruct)


的函数,是用来初始化端口的,我们把它复制到main.c中,并且把它改名为


void STM_COMInit(COM_TypeDef COM, USART_InitTypeDef* USART_InitStruct)


去掉中间的eval。


当然,在main函数中调用这个函数的地方也要做相应的修改。


 e0fd8c1f-97d1-4e3b-8f25-aec53849b16d.gif



这个函数中用到了如上图中蓝色框中的一些符号,又是一系列的转换,用刚才所说的跟踪方法,找到这些符号的原始出处,作出修改,最后得到的STM_COMInit函数如下:


void STM_COMInit(COM_TypeDef COM, USART_InitTypeDef* USART_InitStruct)


{


  GPIO_InitTypeDef GPIO_InitStructure;


 


  /* 打开UART所用到的GPIO引脚的时钟*/


  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);


  /* 打开UART的时钟*/


  if (COM == COM1)


  {


RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);


  }


  else     //COM=COM2


  {


    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);


  }


 


  /* 配置TX引脚为推挽式输出 */


  if(COM==COM1)


      GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_9 ;


  else


       GPIO_InitStructure.GPIO_Pin =   GPIO_Pin_2;     


  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;


  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


  GPIO_Init(GPIOA, &GPIO_InitStructure);


                                                      


  /* 配置RX引脚为浮动输入(高阻?) */


 if(COM==COM1)


      GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10 ;


  else


       GPIO_InitStructure.GPIO_Pin =   GPIO_Pin_3;     


  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;


  GPIO_Init(GPIOA, &GPIO_InitStructure);


 


  /* 串行口配置*/


  if(COM==COM1)


      USART_Init(USART1, USART_InitStruct);


  else


       USART_Init(USART2, USART_InitStruct);     


 


  /* 串口允许*/


  if(COM==COM1)


      USART_Cmd(USART1, ENABLE);


  else


      USART_Cmd(USART2, ENABLE);    


}


至此,修改基本结束,在工程中移去stm32_eval相关的各个文件,在APP文件夹中将这些文件删除,关闭工程,再重新打开工程,编译通过,运行通过。


下面对上述初始化工作做一些解读,当然,少不了要数据手册的帮忙了。


(1)UART1的时钟来源和其他串口的时钟来源不同,UART1的时钟来源是:APB2,其他串口的时钟来源:APB1。


(2)用于UART通信的引脚不会自动配置,需要手工配置。其中用于输出信号的引脚TX必须配置成为推挽式输出,而RX引脚则配置成浮动型输入。


(3)串口波特率、停止位等参数由库提供的stm32f10x_usart.c中的


void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)


函数来设定。


观察这个函数的执行,可以看到函数通过对CR2寄存器的操作来设定停止位,如下图蓝色框中所示。


657e0e85-60b0-433a-93c6-58395a56fc9e.gif



通过对CR1寄存器的设定来确定数据位/奇偶校验位等,这些都只需要找到相应的符号,就能顺利地进行设置,找到符号的方法,当然还是上面的按F12浏览的方法。


还有一个重要的工作是波特率的计算,且看这里是如何来做的。


下面这一段是波特率设置的代码


9a4b79e7-0431-4efe-b474-6adc502026fe.gif



首先根据usartxbase的值来确定需要配置的是USART1还是USART2


 usartxbase = (uint32_t)USARTx;


而USARTx是传入这个函数的一个参数。


然后据此来得到用于USART的时钟频率,这个频率值被变量apbclock记录。


dd6839ac-ed76-4a9f-840c-c0c65308ad30.gif



从上面变量的跟踪可以看到apbclock的值是0x44aa200即72000000,也就是72MHz。


接下来的一系列计算式就是根据波特率的值来计算应该传入BRR寄存器的值了,偷点懒,这里就不对算式进行一一分析了(我认为暂时没有这个必要)。


至此,USART的设置工作完成,即完成了其数据位、停止位、奇偶校验位、波特率的设置工作。异步通信的配置工作完成。当然,细细分析,可以发现,初始还按默认方式处理了硬件握手等的处理工作。


除了使用库函数提供的printf等函数外,我们在单片机开发中还经常使用直接对数据寄存器赋值的方法来使用串口。STM32串口的数据寄存器名为DR,因此,我试着在main函数中写入这样一行:


While1()


{     USART1->DR=0x55;


}


一试成功,软件仿真时,在串行窗口出现了大串的字符55.


好了,串口暂时告一段落。


 


 

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户425423 2012-9-11 20:59

图片不能下载?确认好多次邮箱了,还是提示要确认邮箱,怒了!!
相关推荐阅读
teach51_109853927 2015-10-25 22:37
带“锁定输出”的数控稳压电源(二)
3.控制程序编写        硬件电路设计完成后,就要编写软件了。软件基本上可以分为键盘驱动,PWM生成,功能实现等部分。 3.1 键盘处理程序        STC单片机的引脚可以...
teach51_109853927 2014-03-02 12:17
带“锁定输出”的数控稳压电源(一)
本文是探索“开源培训”思想的作品。 所谓“开源培训”是指在某个社区,各志愿者提供有一定实用价值和教学价值的作品,同时详细说明制作过程,并提供制作所需的各类资源,帮助入门者快速找到适合自己的项目...
teach51_109853927 2014-02-22 21:15
《单片机项目教程》、《单片机项目教程C语言版》电子课件
《单片机项目教程》电子课件 http://pan.baidu.com/s/1kT2Yb6f 《单片机项目教程C语言版》电子课件 http://pan.baidu.com/s/1gd5O...
teach51_109853927 2014-02-22 21:05
《单片机应用与接口技术》相关资源
单片机应用与接口技术    机械工业出版社出版,江苏省教育厅推荐教材 《单片机应用与接口技术》课件 http://pan.baidu.com/s/1c0kpzUg 《单片机应用与接...
teach51_109853927 2014-02-22 15:25
便携式无线抢答器
本产品专门为开展活动时需要用到抢答器的场合设计,已制作成品,读者可以参考作为练手之用。 如图1所示左边为信号接收装置(主持人用),右边两个为发射装置(比赛选手用)。都只需要使用干电池供电即可。...
teach51_109853927 2014-02-22 15:22
Modbus通讯协议
Modbus协议最初由Modicon公司开发出来,在1979年末该公司成为施耐德自动化(Schneider Automation)部门的一部分,现在Modbus已经是工业领域全球最流行的协议。此协...
EE直播间
更多
我要评论
1
12
关闭 站长推荐上一条 /3 下一条