1. 简介

串口全称:Universal synchronous asynchronous receiver transmitter,中文名称:通用同步异步串行接收发送器。串口可用于接收和发送数据,可以用作跟其他设备通讯,如蓝牙模块、GSM模块、GPS模块等。
串口中最常见的是RS-232,共有9根线用于通讯,但常用的仅3根线:RXD、TXD、GND。其中RXD用于接收,TXD用于发送,GND为信号地线,两个通讯设备之间的收发信号(RXD与TXD)应交叉相连。

2. 基本概念

  • 波特率:串口异步通讯中由于没有时钟信号,所以两个通讯设备之间需要约定好波特率,即每个码元的长度,以便对信号进行解码,常见的波特率为4800、9600、115200 等。波特率越高传输速度越快,但出错的概率要更大。
  • 通讯的起始和停止信号:串口通讯的一个数据包从起始信号开始,直到停止信号结束。数据包的起始信号由一个逻辑 0 的数据位表示,而数据包的停止信号可由 0.5、1、1.5或 2个逻辑 1的数据位表示,只要双方约定一致即可。
  • 有效数据:在数据包的起始位之后紧接着的就是要传输的主体数据内容,也称为有效数据,有效数据的长度常被约定为 5、6、7或 8位长。
  • 数据校验:在有效数据之后,有一个可选的数据校验位。由于数据通信相对更容易受到外部干扰导致传输数据出现偏差,可以在传输过程加上校验位来解决这个问题。校验方法有奇校验(odd)、偶校验(even)、0校验(space)、1校验(mark)以及无校验(noparity)。奇校验要求有效数据和校验位中“1”的个数为奇数,偶校验与奇校验要求刚好相反,要求帧数据和校验位中“1”的个数为偶数,0校验是不管有效数据中的内容是什么,校验位总为“0”,1校验是校验位总为“1”。
  • 常用的设置:波特率9600,8位数据位,1位停止位,无校验位,无硬件流控。

串口USART分为两部分,初始化和处理。

1. 初始化分三步:GPIO、通用中断、USART。

1.1. GPIO:时钟、引脚、输入输出模式、端口初始化

  • 时钟:需要同时使能GPIO时钟
  • 引脚:需要选择指定的引脚
  • 输入输出模式:TX引脚选择复用推挽模式,RX引脚选择浮空输入模式
  • 端口初始化:初始化指定的端口

1.2. 通用中断:优先级分组、中断源、优先级、使能

  • 优先级分组:设定合适的优先级分组
  • 中断源:选择指定的中断源:USART1_IRQn
  • 优先级:设定合适的优先级
  • 使能:调用库函数即可,可选择使能多个中断,一般情况下只使能接收中断。

1.3. USART:时钟、波特率、数据字长、停止位、校验位、硬件流控制、工作模式、初始化、使能。

  结构体

typedef struct {
uint32_t USART_BaudRate;
uint16_t USART_WordLength;
uint16_t USART_StopBits;
uint16_t USART_Parity;
uint16_t USART_Mode;
uint16_t USART_HardwareFlowControl;
} USART_InitTypeDef;

  • 时钟:需要使能USART1时钟

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

  • 波特率:一般可选的设置项包括4800、9600、115200等,常用的波特率为9600。

USART_InitStructure.USART_BaudRate = 9600;

  • 数据字长:可选8位或9位,常用的是8位。

USART_InitStructure.USART_BaudRate = 9600;

  • 停止位:可选0.5、1、1.5、2个,常用的是1个停止位。

USART_InitStructure.USART_BaudRate = 9600;

  • 奇偶校验:可选无校验、奇校验和偶校验,常用的是无校验。

USART_InitStructure.USART_Parity = USART_Parity_No;

  • 模式:可选发送、接收,或者同时启用,一般都是同时启用。

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  • 硬件流控:可选有使能RTS、使能CTS、同时使能、不使能,一般选择不使能。

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  • 初始化配置

USART_Init(USART1, &USART_InitStructure);

  • 使能

USART_Cmd(USART1, ENABLE);

2. 处理

处理分为接收和发送。
接收处理通常放在中断中,中断服务函数名称为USART1_IRQHandler(),调用库函数USART_ReceiveData()得到接收的数据,并自动清除接收中断标志位;
发送直接调用库函数USART_SendData()即可,发送完成之后会调用函数来获取相应标志来实现发送完成等待功能,即USART_SendData()函数返回时,相应的数据已经确保发送完成,并可发送下一个数据,发送不同类型的数据可以封装成不同的函数,但最终都是调用USART_SendData()函数。

接收:

// 串口中断服务函数
void USART1_IRQHandler(void)
{uint8_t ucTemp;if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET){    ucTemp = USART_ReceiveData(USART1);}
}

发送:

//发送一个字节
void Usart_SendByte(USART_TypeDef * pUSARTx, uint8_t ch)
{//发送一个字节数据到USARTUSART_SendData(pUSARTx,ch);//等待发送数据寄存器为空,即发送完成while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}
//发送一个数组
void Usart_SendArray(USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
//发送字符串
void Usart_SendString(USART_TypeDef * pUSARTx, char *str)

完整代码(仅自己编写的部分)

void NVIC_Configuration(void)
{NVIC_InitTypeDef NVIC_InitStructure;/* 嵌套向量中断控制器组选择 */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);/* 配置USART为中断源 */NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;/* 抢断优先级*/NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;/* 子优先级 */NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;/* 使能中断 */NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;/* 初始化配置NVIC */NVIC_Init(&NVIC_InitStructure);
}void USART_Config(uint32_t baudrate)
{GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;// 打开串口GPIO的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 打开串口外设的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);// 将USART Tx的GPIO配置为推挽复用模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 将USART Rx的GPIO配置为浮空输入模式GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置串口的工作参数// 配置波特率USART_InitStructure.USART_BaudRate = baudrate;// 配置 帧数据字长USART_InitStructure.USART_WordLength = USART_WordLength_8b;// 配置停止位USART_InitStructure.USART_StopBits = USART_StopBits_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;// 完成串口的初始化配置USART_Init(USART1, &USART_InitStructure);// 串口中断优先级配置NVIC_Configuration();// 使能串口接收中断USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);// 使能串口USART_Cmd(USART1, ENABLE);
}//发送一个字节
void Usart_SendByte(USART_TypeDef * pUSARTx, uint8_t ch)
{//发送一个字节数据到USARTUSART_SendData(pUSARTx,ch);//等待发送数据寄存器为空,即发送完成while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}//发送数组
void Usart_SendArray(USART_TypeDef * pUSARTx, uint8_t *array, uint16_t num)
{uint8_t i;for(i = 0; i < num; i++){/* 发送一个字节数据到USART */Usart_SendByte(pUSARTx, array[i]);}/* 等待发送完成 */while(USART_GetFlagStatus(pUSARTx, USART_FLAG_TC)==RESET);
}//发送字符串
void Usart_SendString(USART_TypeDef * pUSARTx, char *str)
{uint32_t k = 0;do{Usart_SendByte(pUSARTx, *(str + k));k++;} while(*(str + k)!='0');/* 等待发送完成 */while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET);
}//发送16位数
void Usart_SendHalfWord(USART_TypeDef * pUSARTx, uint16_t ch)
{uint8_t temp_h, temp_l;/* 取出高八位 */temp_h = (ch & 0xFF00) >> 8;/* 取出低八位 */temp_l = ch & 0xFF;/* 发送高八位 */USART_SendData(pUSARTx, temp_h);while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);/* 发送低八位 */USART_SendData(pUSARTx, temp_l);while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
}// 串口中断服务函数
void USART1_IRQHandler(void)
{uint8_t ucTemp;if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){ucTemp = USART_ReceiveData(USART1);USART_SendData(USART1, ucTemp);}
}int main(void)
{USART_Config(9600);Usart_SendString(USART1, "Hello World!n");while(1){}
}

仿真结果

1. 发送

编译完成后,点击

开始仿真,点击

,打开串口监视串口(点击右侧的箭头可以选择第几个串口),然后运行程序,可以在串口监视窗口看到串口发送的信息。

2. 接收

如果想要仿真串口接收,需要使用虚拟串口软件vspd,下载安装完成后,运行该软件:

可以看到左侧有COM1-5共 5个物理串口,点击右侧的添加端口,可以添加COM6和COM7两个虚拟串口,并自动连接这两个串口。

此时可以打开2个串口工具,分别设置为COM6和COM7,并分别发送数据,看看对方是否能够正常接收,如果可以,表示虚拟串口添加并连接成功,此时在串口工具中关闭COM6。

运行KEIL,并开始仿真后,在COMMAND串口中输入
MODE COM6 9600,0,8,1
ASSIGN COM6 <S1IN> S1OUT
第一条命令设置COM6波特率9600,无校验位,8个数据位,1个停止位,注意这里的设置应该与程序中串口的设置保持一致。
第二条命令将COM6和单片机的第一个串口进行绑定,即单片机第一个串口的收发数据通过计算机的COM6进行收发。
此时在串口工具打开COM7,并通过串口工具发送数据,程序即可接收到发送的数据。

从上图可以看到从COM7发送了一个A给单片机,单片机接收到了A,并将A又发送出去,COM7接收到了A。
因此,通过虚拟串口软件,即可在无开发板、无串口线、无串口设备的情况下,通过串口工具即可调试串口接收及发送程序,实现纯软件环境调试。

学习资料分享交流群:1093776732 入群有全套学习视频资料电子书免费赠送!

参考资料:

嵌入式开发直播课 - STM32 USART串口的应用​www.makeru.com.cn

物联网开发入门直播课 - 基于STM32讲解串口操作​www.makeru.com.cn

物联网开发入门直播课 - 通过Z-stack协议栈实现串口透传​www.makeru.com.cn嵌入式开发直播课 - 带你揭晓STM32定时器深藏不露的绝技​www.makeru.com.cn

物联网STM32入门 - 带你揭晓STM32定时器深藏不露的绝技​www.makeru.com.cn

vc++ cserialport 打开多个串口_STM32之USART串口相关推荐

  1. windows通信端口初始化失败_STM32实例——USART串口通信实验(二)

    USART 串口通信配置步骤 在上面的介绍中,可能有的朋友很不理解,不过没有关系,下面我们讲解如何使用库函数对 USART 进行配置.这个也是在编写程序中必须要了解的.具体步骤如下:(USART 相关 ...

  2. USART串口协议和USART串口外设(USART串口发送串口发送和接收)

    1.通信接口 A.基本概念 • 通信的目的:将一个设备的数据传送到另一个设备,扩展硬件系统 • 通信协议:制定通信的规则,通信双方按照协议规则进行数据收发  异步:需要双方约定一个频率 B.数据通信方 ...

  3. linux 串口 dma,STM32 USART串口DMA 接收和发送流程详解

    1.dma发送流程 1.配置DMA发送中断 - NVIC_Init 2.配置串口中断 - NVIC_Init 3.GPIO配置 - GPIO_Init 4.DMA发送配置 -DMA_Init  DMA ...

  4. 17、江科大stm32视频学习笔记——USART串口协议和USART串口外设

    目录 1.通信接口 2. 硬件电路 3.电平标准 4.串口参数及时序 5.USART简介 6.USART工作 (1)写操作 (2)读操作 (3)帧头和帧尾的添加和除由电路自动执行 (4)硬件数据控制流 ...

  5. 10 vm 添加串口_STM32的串口通信

    在基础实验成功的基础上,对串口的调试方法进行实践.硬件代码顺利完成之后,对日后调试需要用到的printf重定义进行调试,固定在自己的库函数中. b) 初始化函数定义: void USART_Confi ...

  6. 串口通信模块2:串口通信编程基础(打开、配置)

    有两种方式可以操作串口:同步操作方式和异步操作方式(即重叠操作方式).同步操作时,API函数会阻塞直到操作完成以后才能返回(在多线程方式中,虽然不会阻塞主线程,但是仍然会阻塞监听线程):而异步操作方式 ...

  7. 串口输出换行_stm32初学者必会操作----usart串口调试工具

    stm32初学者必会操作----usart串口调试工具 今天笔者介绍stm32初学者必会的工具 usart的串口设备. usart很重要,可以传输数据,可以检查代码的错误位置,查看输出数据. 下图就是 ...

  8. 基于STM32安装Stm32CubeMX,配合Keil完成LED流水灯和USART串口通讯程序,及其管脚的时序波形观察

    目录 一.使用HAL库完成LED流水灯 (一).用STM32CUBEMX生成工程文件 (二).用Keil仿真调试并生成hex文件 (三).用STM32串口烧录程序 (四).实物连接 二.使用HAL库完 ...

  9. 串口通信模块5:串口操作自定义类(2)

    1.ProcessErrorMessage()函数的实现: ProcessErrorMessage()函数负责处理并提示错误信息,其实现过程如下: void CMySerial::ProcessErr ...

最新文章

  1. python的官方网站地址是什么-python赋值和地址
  2. [云炬创业学笔记]第二章决定成为创业者测试11
  3. CSDN专访云信阙杭宁:以16年技术积累打造稳定IM云服务
  4. 量数据导出Excel 之 多重影分身之术
  5. abb机器人指令手册_「ABB」ABB机器人指令模块介绍与开发过程
  6. access字段类型varchar_数据库即将被淘汰的几种数据类型,烦恼还是解脱?
  7. 花里胡哨的c语言程序,通达信花里胡哨主图公式源码
  8. 上粱正,下粱不歪——网吧母盘制作流程(转)
  9. 参考 雷霄骅https://blog.csdn.net/leixiaohua1020/article/list/28
  10. Python OpenCV实现身份证号码识别
  11. 数据分析师系列课程 统计学基础1
  12. 什么是Instagram直播购物?如何设置Instagram 直播购物?
  13. 【学习总结】标准日本语(陈述句)
  14. Mybatis Generator最完整配置详解 叩丁狼教育
  15. 低价云 主机虚拟云服务器,低价云 主机虚拟云服务器
  16. 吴恩达课程作业中的lr_utils下载
  17. 详解“辗转相除法”(如何求最大公约数)
  18. 概率统计Python计算:离散型随机变量分布(bernoulli geom)
  19. jmp指令(0903)
  20. hp服务器 linux,在Linux中监控HP和Dell的服务器(SNMP,Cacti)

热门文章

  1. 深度搜索问题c语言,C语言实现的图的深度搜索与广度搜索程序.doc
  2. matlab arima模型定阶,ARIMA模型预测问题
  3. J-Link该如何升级固件?
  4. 看技术笔记,提高嵌入式基础
  5. 我的特长是复制、粘帖
  6. 什么?物联网方向也能发论文了?
  7. mysql 更新索引_MySQL索引优化
  8. 字典与集合_月隐学python第8课
  9. android申请权限一次性申请多个,Android 批量申请权限
  10. python大数据后期教学_大数据处理之道(十分钟学会Python)