USART—串口通讯
本章中主要讲解的是串口异步通讯,异步通讯中由于没有时钟信号, 所以两个通讯设备之间需要约定好波特率,即每个码元的长度,以便对信号进行解码 。
串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一
个逻辑 0 的数据位表示,而数据包的停止信号可由 0.5、 1、 1.5 或 2 个逻辑 1 的数据位表示,
只要双方约定一致即可。
STM32 芯片具有多个 USART 外设用于串口通讯,它是 Universal Synchronous
Asynchronous Receiver and Transmitter 的缩写,即通用同步异步收发器可以灵活地与外部设
备进行全双工数据交换。有别于 USART,它还有具有 UART 外设(Universal Asynchronous
Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。
简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基
本都是 UART。
STM32 的 USART 输出的是 TTL 电平信号,若需要 RS-232 标准的信号可使用
MAX3232 芯片进行转换。
①功能引脚
TX:发送数据输出引脚。
RX:接收数据输入引脚。
SW_RX:数据接收引脚,只用于单线和智能卡模式,属于内部引脚,没有具体外部引
脚。
nRTS:请求以发送(Request To Send), n 表示低电平有效。如果使能 RTS 流控制,当
USART 接收器准备好接收新数据时就会将 nRTS 变成低电平;当接收寄存器已满时,
nRTS 将被设置为高电平。该引脚只适用于硬件流控制。
nCTS:清除以发送(Clear To Send), n 表示低电平有效。如果使能 CTS 流控制,发送
器在发送下一帧数据之前会检测 nCTS 引脚,如果为低电平,表示可以发送数据,如果为
高电平则在发送完当前数据帧之后停止发送。该引脚只适用于硬件流控制。
SCLK:发送器时钟输出引脚。这个引脚仅适用于同步模式。
USART 引脚在 STM32F429IGT6 芯片具体发布见表 20-3。
应用型编程,先会使用,有需要再去解析内部实现:
- int main(void)
- {
- /*初始化USART 配置模式为 115200 8-N-1,中断接收*/
- Debug_USART_Config();
- /* 发送一个字符串 */
- Usart_SendString( DEBUG_USART,"这是一个串口中断接收回显实验\n");
- printf("这是一个串口中断接收回显实验\n");
- while()
- {
- }
- }
- void Debug_USART_Config(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
- RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK|DEBUG_USART_TX_GPIO_CLK,ENABLE);
- /* 使能 USART 时钟 */
- RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);
- /* GPIO初始化 */
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- /* 配置Tx引脚为复用功能 */
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_PIN ;
- GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
- /* 配置Rx引脚为复用功能 */
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_PIN;
- GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
- /* 连接 PXx 到 USARTx_Tx*/
- GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,DEBUG_USART_RX_SOURCE,DEBUG_USART_RX_AF);
- /* 连接 PXx 到 USARTx__Rx*/
- GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,DEBUG_USART_TX_SOURCE,DEBUG_USART_TX_AF);
- /* 配置串DEBUG_USART 模式 */
- /* 波特率设置:DEBUG_USART_BAUDRATE */
- USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
- /* 字长(数据位+校验位):8 */
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- /* 停止位:1个停止位 */
- USART_InitStructure.USART_StopBits = USART_StopBits_1;
- /* 校验位选择:不使用校验 */
- USART_InitStructure.USART_Parity = USART_Parity_No;
- /* 硬件流控制:不使用硬件流 */
- USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- /* USART模式控制:同时使能接收和发送 */
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- /* 完成USART初始化配置 */
- USART_Init(DEBUG_USART, &USART_InitStructure);
- /* 嵌套向量中断控制器NVIC配置 */
- NVIC_Configuration();
- /* 使能串口接收中断 */
- USART_ITConfig(DEBUG_USART, USART_IT_RXNE, ENABLE);
- /* 使能串口 */
- USART_Cmd(DEBUG_USART, ENABLE);
- }
从上面的红色部分我们可以知道,和往常一样,开启时钟是第一步,尤其注意的是引脚复用调用的函数,注意是GPIO_Pinsource而不是GPIO_Pin.
在编写程序的时候,首先参考官方固件库,然后谨记编程要点,比如什么时钟应该开启,引脚功能如何配置,是否有复用模式,中断是否需要配置。这需要我们熟悉外设挂载在哪个总线上,已及总线的最高时钟,这些都知道以后,固件库编程是很快速的。至于固件库的具体实现,也是很有参考价值的,但是如果你手上还有很多需要学习的东西,可以暂时不管固件库底层如何实现,先完成基本设计,再慢慢深入。这是一个长期累积的过程。
串口调试助手,不勾选发送模式,默认是以字符的方式发送。
编程时需要用到的固件库函数
要使用printf重定向,需要重写fputc函数,并且在keil中勾选使用微库。
NOTE:
STM32默认就是小端模式:
The processor can access data words in memory in little-endian format or big-endian
format. It always accesses code in little-endian format.
Note:
Little-endian is the default memory format for ARM processors.
在发送一个字节8位模式时,是从高位开始向低位传输的:
但是,要是我们想要发送一个16位的数据,是先发送高8位呢还是低8位?通过参考历程可以看出,是先发送的高8位,再发送低8位。
那么为什么要先发送高8位再发送底八位呢?
例如一个16位数据0x1234;在寄存器中是高位在前,低位在后的(stm32默认小端模式)。
二进制 0001 0010 0011 0100;
要想把这一串二进制以8位一次的方式发送,如果我们先发送低8位,再发送高8位,最后出来将会是0x3412,所以,我们应该先发送高位再发送低位。
重要寄存器,解释为什么发送接收库函数要那么去写:
//接收库函数
//发送库函数
首先,这是中断服务函数调用的,首先调用接收函数,能进接收中断,所以肯定有数据发来单片机接收到了,此时把DR寄存器的值得低9位(在我们的历程中使用的8位,到底是9位还是8位要看M的设置),这个值返回出来,确实应该是接收函数。但是,为什么像DR中写入数据,就是发送了?刚开始我也不理解,但是参看参考手册之后,发现,写数据倒DR寄存器中会硬件触发标志,这样,内核可以知道你是接收还是发送。
发送端:
7. 在 USART_DR 寄存器中写入要发送的数据(该操作将清零 TXE 位)。为每个要在单缓
冲区模式下发送的数据重复这一步骤。
8. 向 USART_DR 寄存器写入最后一个数据后,等待至 TC=1。这表明最后一个帧的传送已
完成。禁止 USART 或进入暂停模式时需要此步骤,以避免损坏最后一次发送。
接收端:
这样,读DR寄存器,会产生一些硬件标志置位,所以内核可以知道是否接收完成,向DR寄存器写数据,也会产生一些硬件标志位,这样内核就知道是否发送发送完成。
嵌入式开发,离不开和芯片手册折腾,但是这又是必备技能,而且这里STMF4还是中文参考手册,更多时候,我们开发是英文手册,更加困难,所以,软件程序员,必须熟练运用英语和数学。
USART—串口通讯的更多相关文章
- 第20章 USART—串口通讯—零死角玩转STM32-F429系列
第20章 USART—串口通讯 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...
- 第20章 USART—串口通讯
本章参考资料:<STM32F76xxx参考手册>USART章节. 学习本章时,配合<STM32F76xxx参考手册>USART章节一起阅读,效果会更佳,特别是涉及到寄存器说明的 ...
- STM32F10x 学习笔记6(USART实现串口通讯 2)
这次讲讲利用串口收发中断来进行串口通讯.STM32 上为每个串口分配了一个中断.也就是说无论是发送完成还是收到数据或是数据溢出都产生同一个中断.程序需在中断处理函数中读取状态寄存器(USART_SR) ...
- STM32F10x 学习笔记5(USART实现串口通讯 1)
STM32F10x 系列单片机中都包含了USART 模块,所谓USART,就是通用同步异步收发器.通用同步异步收发器(USART)提供了一种灵活的方法与使用工业标准NRZ异步串行数据格式的外部设备之间 ...
- 串口(USART)通信-串口通讯协议简介
物理层:规定通讯系统中具有机械.电子功能部分的特性,确保原始数据在物理媒体的传输.其实就是硬件部分. 协议层:协议层主要规定通讯逻辑,统一收发双方的数据打包.解包标准.其实就是软件部分. 简单来说物理 ...
- CC2530学习路线-基础实验-串口通讯发送字符串(4 未完待续)
目录 1. 前期预备知识 1.1 串口通讯电路图 1.2 实验相关寄存器 1.2 常用波特率设置 本章未完待续..... 原来写的文章已经丢失了,只能找到这一小部分,看什么时候有时间再补上. 1. 前 ...
- Arduino 串口通讯参考笔记 - Serial 类库及相关函数介绍
声明: 本ID发布的所有文章及随笔均为原创,可随意转载,单转载文章必须注明作者 aiyauto 及包含原文出处地址 http://www.cnblogs.com/aiyauto/p/7071712.h ...
- 【STM32H7教程】第29章 STM32H7的USART串口基础知识和HAL库API
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第29章 STM32H7的USART串口基础知识和 ...
- STM32—串口通讯详解
串口通讯目录 物理层 协议层 USART简介 开发板与上位机的连接 代码讲解: 一.初始化结构体 二.NVIC配置中断优先级 三.USART配置函数讲解 四.传输数据的函数: 1.发送一个字节 2.发 ...
随机推荐
- Neural Networks for Machine Learning by Geoffrey Hinton (4)
一种能够学习家谱关系的简单神经网络 血缘一共同拥有12种关系: son, daughter, nephew, niece, father, mother, uncle, aunt, brother, ...
- scikit-learn(window,linux)安装
scikit-learn是python的机器学习库 记录下载window中和linux中如何下载scikit-learn 方法一 直接下载Anaconda 这是一个非常齐全的python发行版本,里面 ...
- Qunit的使用
1.新建一个html页面,如下 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "ht ...
- TensorFlow------单层(全连接层)实现手写数字识别训练及测试实例
TensorFlow之单层(全连接层)实现手写数字识别训练及测试实例: import tensorflow as tf from tensorflow.examples.tutorials.mnist ...
- 【Linux】Shell三类变量的作用域——linux shell “永久环境变量”、“临时环境变量”和"普通变量"之完全解读
2015-05-08 00:15 3896人阅读 评论(10) 收藏 举报 本文章已收录于: 分类: 软件开发进阶(419) 作者同类文章X Unix/Linux杂项(118) 作者同类文章X ...
- PHP和数据访问之(插入。删除。和更新数据)
插入: <?php $conn=@new mysqli('localhost','root','123','mytestdb'); $q_str=<<<EOM insert i ...
- struts2 ValueStack的作用
Value Stack的作用: 1. 可以作为一个数据中转站 2. 用于在前台-后台之间传递数据,最典型的做法就是struts2标签也ognl表达式的结合.我用得最多的就是数据 ...
- 准备你的Adempiere开发环境(2)- 安装
1. 用pgAdmin III创建用户adempiere/adempiere:2. 创建adempiere360数据库:3. 导入<ADEMPIERE_HOME>\data\Adempie ...
- PHP-客户端的IP地址伪造、CDN、反向代理、获取的那些事儿
外界流传的JAVA/PHP服务器端获取客户端IP都是这么取的: 伪代码: 1)ip = request.getHeader("X-FORWARDED-FOR") 可伪造,参 ...
- 资源管理器也玩多标签:QT TabBar v1.5.0.0a3
http://zmingcx.com/explorer-also-play-more-tags-qt-tabbar-v1-5-0-0a3.html浏览器中的标签浏览功能非常受欢迎,安装QT TabBa ...