学习是一个简单的过程,只要有善于发掘的眼睛,总能学到新知识,然而如何坚持不懈的学习却很困难,对我亦如此,生活中有太多的诱惑,最后只想说一句勿忘初心。闲话不多扯,本篇讲诉的是异步串行口的输入输出,串口在外设中属于比较简单的通讯模式,但是在大型项目调试中又十分重要,理解该外设模块对于以后的通讯协议学习以及软件调试都有重要意义。

  通讯协议是指双方实体完成通信或服务所必须遵循的规则和约定,对于串口来说,包含波特率,数据位长度,停止位和数据校验位,当stm32芯片和客户端具有相同的协议约定时即能够正确的接收数据,因此串口外设的配置正是这些参数的设定。通过前面章节的学习,以USART1为例,在外设设置之前,我们应该有大致流程:

1. 串口外设外设和其占用的GPIO端口都要配置,且占用的GPIO端口为PA9(USART1_TX), PA10(USART1_RX).

2. 外设对应时钟都要配置,且要在初始化外设和GPIO端口配置之前

3. USART外设的配置主要是协议相关参数配置

串口外设配置

至于GPIO端口配置的参数参考<stm32F系列微控制器参考手册>(以后以手册简称)110页表21如下图

至于外设所在时钟区域,请参考RCC章节,如此外设的初始化如下:

头文件定义:

#define RCC_USART1           RCC_APB2Periph_GPIOA      \
|RCC_APB2Periph_USART1 \
|RCC_APB2Periph_AFIO
#define USART1_RX GPIOA
#define USART1_TX GPIOA
#define USART1_RX_Pin   GPIO_Pin_10
#define USART1_TX_Pin GPIO_Pin_9

初始化代码:

  USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_DeInit(USART1); RCC_APB2PeriphClockCmd(RCC_USART1, ENABLE); GPIO_InitStructure.GPIO_Pin = USART1_TX_Pin;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //配置串口1输出端为复用推挽输出
GPIO_Init(USART1_TX,&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = USART1_RX_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //配置串口1输入端为浮空输入
GPIO_Init(USART1_RX, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = ; //设置串口波特率为9600
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //输入/输出8位数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1; //设置停止位为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; //串口1启动输入输出 USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE); //使能串口

如此,便完成了外设的初始化。

这里有几个知识点要讲:

1.波特率  每秒发送的bit个数。对于一定长度的数据,在已知配置的情况下传输时间计算:

(以2k数据b,每帧8位数据,1位停止位,波特率9600,传输完成花费时间)

T = 2*1024*(8+1)/9600*8 = 0.24s

虽然用库函数可以直接设置波特率,但stm32的波特率如何通过寄存器计算还是很重要的,参考公式配置USART->BRR(手册542页):  

公式:

其中fck为串口所在区域外设时钟,如USART即为PCLK2时钟,USARTDIV即为要设置参数:

以波特率115200,PCLK等于系统时钟SYSTICk(48MHZ)算,USARTDIV设置为48M/(16*115200),转成二进制为0x1a0

2. 奇偶校验位

因为奇偶校验位的参与,接收到的数据帧有以下四种格式:

因此客户端接收时也要数据位要设定为实际数据长度,不然接收到数据会是乱码。

3. 硬件流控制

用于数据流控制,通讯的双方由此交换是否停止后继续接收信息,避免因处理数据速度问题而出现的缓存溢出,导致数据的丢失

CTS只有CTS输入信号有效(低电平)时才能发送数据。如果在数据传输的过程中,CTS信号变成无效,那么发完这个数据后,传输就停止下来。如果当CTS为无效时,向数据寄   存器里写数据,则要等到CTS有效时才会发送这个数据。

RTS只有接收缓冲区内有空余的空间时才请求下一个数据。当前数据发送完成后,发送操作就需要暂停下来。如果可以接收数据了,将RTS输出置为有效(拉至低电平)。

ps:本例中没有使用,具体详情参考手册537页

串口输入输出实现

串口的输出是通过printf函数的,其包含在stdio.h头文件内部。此外printf还需要retarget处理,具体代码如下:

retarget.h头文件添加:

  #ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (
option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

retarget.c文件添加:

PUTCHAR_PROTOTYPE
{
/*将1字节数据发往串口寄存器 */
USART_SendData(USART1, (uint8_t) ch); /*等待传输结束*/
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
{} return ch;
}

之后就可以用printf函数发送数据了,至于接收则采用缓存模式,将接受数据存储到数组中,接收到\n时结束并发送:

u8 i = ;
do
{
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
{
}
USART_STORE[i] = USART1->DR;
if(USART_STORE[i] == '\n')
{
break;
}
i++;
if(i >= USART_ISL)
{
i = ;
printf("you input is overlength");
break;
}
}while(); if(i < USART_ISL)
{
//printf("you input is ");
printf("\n%s",USART_STORE);
}

如此就完成了USART外设的配置和输入输出轮询实现。

具体代码参考:http://files.cnblogs.com/files/zc110747/3.USART%28%E8%BD%AE%E8%AF%A2%E6%A8%A1%E5%BC%8F%29.7z

STM32学习笔记(五) USART异步串行口输入输出(轮询模式)的更多相关文章

  1. 【STM32学习笔记】USART 硬件流控

    流控的概念源于 RS232 这个标准,在 RS232 标准里面包含了串口.流控的定义.大家一定了解,RS232 中的"RS"是Recommend Standard 的缩写,即&qu ...

  2. STM32学习笔记(二):GPIO口工作原理

    STM32每个IO口具有7个寄存器来控制,每个IO口都可以自由进行编程控制,我们编程实际上控制的是通过控制那7个寄存器来控制我们的IO口,我们可以通过编程控制IO口,把IO口配置成如下八种模式: 1. ...

  3. python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍

    python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍 IDLE默认不能显示行号,使用ALT+G 跳到对应行号,在右下角有显示光标所在行.列.pycharm免费社区版.Su ...

  4. STM32学习笔记——USART

    STM32的USART组件支持异步.同步.单线半双工.多处理器.IrDA.LIN.SmartCard等模式,本文介绍的是异步即UART模式. 总线通信有三种模型:轮询.中断和DMA.DMA对我来说是陌 ...

  5. STM32学习笔记(四)——串口控制LED(中断方式)

    目录: 一.时钟使能,包括GPIO的时钟和串口的时钟使能 二.设置引脚复用映射 三.GPIO的初始化配置,注意要设置为复用模式 四.串口参数初始化配置 五.中断分组和中断优先级配置 六.设置串口中断类 ...

  6. STM32学习笔记——OLED屏

    STM32学习笔记--OLED屏 OLED屏的特点: 1.  模块有单色和双色可选,单色为纯蓝色,双色为黄蓝双色(本人选用双色): 2.  显示尺寸为0.96寸 3.  分辨率为128*64 4.   ...

  7. C#可扩展编程之MEF学习笔记(五):MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  8. stm32学习笔记----双串口同时打开时的printf()问题

    stm32学习笔记----双串口同时打开时的printf()问题 最近因为要使用串口2外接PN532芯片实现通信,另一方面,要使用串口1来将一些提示信息输出到上位机,于是重定义了printf(),使其 ...

  9. 【转载】salesforce 零基础开发入门学习(五)异步进程介绍与数据批处理Batchable

    salesforce 零基础开发入门学习(五)异步进程介绍与数据批处理Batchable   本篇知识参考:https://developer.salesforce.com/trailhead/for ...

随机推荐

  1. 微信浏览器禁止页面下拉查看网址(不影响页面内部scroll)

    此类事件是手机touchmove默认事件行为,可以通过js代码隐藏事件: $(‘body’).on(‘touchmove’, function (event) {event.preventDefaul ...

  2. http://www.cnblogs.com/ACMer/p/5170255.html

    http://www.cnblogs.com/ACMer/p/5170255.html

  3. 以Debug模式启动JBoss

    JBoss服务器的启动方法: 假设JBoss的安装目录为$JBOSS_HOME,Windows以及Linux环境下的Debug模式的启动方法分别为:Windows环境:找到Windows下的JBoss ...

  4. win7系统如何安装SQL Server 2005

    Microsoft Windows 7 旗舰版(32位) SQL Server 2005 简体中文开发板 方法/步骤   1 首先为了保证数据库的顺利安装,先启用IIS服务吧!Win7比XP好的一点是 ...

  5. Windows7中IIS简单安装与配置(详细图解)

    最近工作需要IIS,自己的电脑又是Windows7系统,找了下安装的方法,已经安装成功.在博客里记录一下,给需要的朋友,也是给自己留个备份,毕竟我脑子不是很好使. 一.首先是安装IIS.打开控制面板, ...

  6. SQL Nexus

    在前面的SQLdiag系列中有提到SQLNexus,当时我们用SQLNexus查看了Perfmon Summary(性能计数器).ReadTrace Reports(跟踪文件)两项报表.SQLNexu ...

  7. Windows Server 2008 R2 创建辅助DNS服务器并接管主要DNS服务器

    公司需求: Zhuyu公司局域网有一台主要DNS服务器,经领导讨论需要规划安装一台辅助DNS服务器备用. 功能需求: 当主要DNS服务器宕机或系统崩溃,辅助DNS服务器能接管主要DNS服务器工作,并且 ...

  8. 将编码从GB2312转成UTF-8的方法汇总(从前台、程序、数据库)

    这篇文章主要介绍了将编码从GB2312转成UTF-8的方法汇总(从前台.程序.数据库),需要的朋友可以参考下 一个网站如果需要国际化,就需要将编码从GB2312转成UTF-8,其中有很多的问题需要注意 ...

  9. SpringMVC源码剖析(一)- 从抽象和接口说起

    SpringMVC作为Struts2之后异军突起的一个表现层框架,正越来越流行,相信javaee的开发者们就算没使用过SpringMVC,也应该对其略有耳闻.我试图通过对SpringMVC的设计思想和 ...

  10. [Android Tips] 13. How to Detect Tablet

    /** * 判断是否是平板 * @param context * @return */ public static boolean isTablet(Context context) { return ...