草庐IT

十三届蓝桥杯嵌入式串口

我和你拼了\' 2023-07-28 原文

目录

串口简介

区分UART、TTL、RS-232、RS-422、RS-485(客观题会考)

CUBMAX初始化

库函数讲解:(下面的好像是从b站小蜜蜂的视频里面截取下来的图片)

代码讲解: 

中断接收函数:

阻塞发送函数:

一些复杂一点的串口数据处理:

串口接收不定长数据

问题和注意事项:


串口简介

    串行通讯接口,简称串口。即数据在通信线上一次传输一位,按先后一定顺序传输。我们通常所说的单片机串口准确来说应该是串行异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART),使用TTL电平。常用两根数据线,即TXD和RXD,配合GND至少需要三根线即可进行通信。以下除特殊说明,串口均指代单片机UART串口

    串口信息以数据线上的高低电平表示,高电平为1,低电平为0

图1 串口时序图

    图1为数据线上典型时序图,数据线空闲时为高电平,以一位低电平最为起始(除特殊说明,串口大部分都是一位起始位),而后以先传输低位,再传输高位的方式发送数据位,最后以高电平为数据停止位(常用1位停止位,也有2位和1.5位等)。数据位长度此处为8位,但不一定是8位,也会有7位、9位等,有时也会包含有奇偶校验位(校验位实际上就是数据的最后一位,但通常不算在数据位里)。上图所示即我们常用的8位数据位,无校验,一位停止位的串口格式

    最为异步通信接口,串口不具有时钟线,所以需要在通信双方设置数据位长度,即电平持续时间,其倒数为电平转换的频率,这一参数即为波特率(但注意,波特的概念并不是位的概念,此处按下不表)。例9600波特率即为电平改变频率为9600Hz,电平持续时间1/9600秒,则一秒最多传输9600/(1+8+1)=960个字节(不严谨,但差不多)

    因串口发送数据线与接收数据线分离,其为全双工接口,串口最少使用三根线即可完成通讯,但除这三根线外还可以有硬件流控RTS、CTS等,我没用到过,具体我也不是很清楚

区分UART、TTL、RS-232、RS-422、RS-485(客观题会考)

    UART即使用TTL电平的串口,TTL是电平形式,通常低于0.8V为低电平,高于2.4V为高电平,不是协议格式,但我们有时也常说TTL串口,以区分RS-232串口

    RS-232串口数据格式与上文介绍的UART串口基本一致,但是电平不一样,通常以-3V至-15V为逻辑1,3V-15V为逻辑0,与UART不可混接,有烧板子的风险

    RS-422常用4线制和2线制,4线制发送和接收均有两根线,两根线上为差分信号,增加传输距离,全双工。2线制的两根线上为差分信号,同时只能做为发或者收,半双工

    RS-485为422的改进版本,最少可用两根线通信,因为使用差分信号,不使用地线也可正常通信,但不建议,半双工

CUBMAX初始化

 串口需要配置的地方不多,Mode中间设置成异步通信,在配置一下波特率,停止位,效验位。一般来说只需要配置波特率就ok。

库函数讲解:(下面的好像是从b站小蜜蜂的视频里面截取下来的图片)

 *pData:发送的数据的地址

Size:发送的数据的大小

Timeout:发送数据最大时间

上图中是发送完成一半中断回调函数,不是一般。 

代码讲解: 

编写代码之前先讲几个我们需要用到的c函数;

sscanf:解析链接        可以将串口接收到的数据变成你想要的格式、样式

strcmp:解析链接        可以比较两个字符串是否一样(两个字符串自左向右逐个字符相比(按 ASCII 值大小相比较),直到出现不同的字符或遇 \0 为止,所以最后需要流出一个空来告诉函数停止比较。)

memset:解析链接      可以用于将一个数组清除,比如串口接收缓存,我们接收结束就可以将他全部置0;

sprintf:解析链接          可以格式化输出

中断接收函数:

HAL_UART_Receive_IT(&huart1,Rx_Data,5);
开启中断接收函数,参数: *pData:接收的数据的存放地址        Size:接收的数据的大小
每当串口接收到Size个数据就会显示接收完成,进入中断。


unsigned char Rx_Data[20];
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	sprintf((char *)LCD_dispaly,"%5s",Rx_Data);
	 LCD_DisplayStringLine(Line4,LCD_dispaly);	
	HAL_UART_Receive_IT(&huart1,Rx_Data,5);
}

阻塞发送函数:

HAL_UART_Receive_IT(&huart1,Rx_Data,10);



unsigned char Tx_Data[20];
unsigned char Rx_Data[20];

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	sprintf((char *)LCD_dispaly,"%5s",Rx_Data);
	LCD_DisplayStringLine(Line4,LCD_dispaly);	
	
	sprintf((char *)Tx_Data,"%10s",Rx_Data);
	HAL_UART_Transmit(huart,Tx_Data,10,20);
	
	
	HAL_UART_Receive_IT(&huart1,Rx_Data,10);
}

将串口接收的数据发送到PC机

一些复杂一点的串口数据处理:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	sprintf((char *)LCD_dispaly,"%s",Rx_Data);
	LCD_DisplayStringLine(Line4,LCD_dispaly);	
	
	sscanf((char *)Rx_Data,"%3s%3s%4s",Tx_Data1,Tx_Data2,Tx_Data3);

//使用sscanf将串口接收到的数据Rx_Data里面的数据分配给Tx_Data1,Tx_Data2,Tx_Data3
//在第十二届主观题串口接收到车牌,停车时间这样多个内容的情况下就可以使用sscanf将内容分配给其他数组
	sprintf((char *)Tx_Data,"%s\r\n",Tx_Data1);
	HAL_UART_Transmit(huart,Tx_Data,5,20);
//将Tx_Data1的数据加上\r\n换行后发送到pc机,对应的Tx_Data1的数据也要加2.
	sprintf((char *)Tx_Data,"%s\r\n",Tx_Data2);
	HAL_UART_Transmit(huart,Tx_Data,5,20);
	sprintf((char *)Tx_Data,"%s\r\n",Tx_Data3);
	HAL_UART_Transmit(huart,Tx_Data,6,20);
	
	
	HAL_UART_Receive_IT(&huart1,Rx_Data,10);
}

如果我们需要连续发送数据,但是怕上一次发送的数据在Rx_Data里面残留着,会影响下一次的数据。我们就可以调用函数memset将Rx_Data清空置0;

memset(Rx_Data,0,sizeof(Rx_Data));

如果我们需要比较两个字符串的内容是否一样就可以调用strcmp函数;具体代码看上面的链接,十二届主观题比较车牌号是否一样。

需要注意的是两个字符串自左向右逐个字符相比(按 ASCII 值大小相比较),直到出现不同的字符或遇 \0 为止,所以最后需要流出一个空来告诉函数停止比较。

比如串口第一次接收到一个字符串为“ASCLL”,我们将它放到数组Rx_Data1里面,串口第一次接收到一个字符串为“world”,我们将它放到数组Rx_Data2里面,我们需要比较两个数组是不是一样的,我们需要定义数组Rx_Data1和Rx_Data2的大小是多少呢,不是5,是6。最后需要流出一个空来告诉函数停止比较。

如果我们需要对串口接收到的数字进行运算

串口接收到的数字是以ASCLL码的方式显示的,我们接收到’0‘,进行’0‘*3的时候,实际进行的操作是0x30*3。所以我们需要对接收到的数据进行处理。

u8 Data=Rx_Data[0]-'0';

对接收到的数字减去符号’0‘,得到的就是数字0~9; 

串口接收不定长数据

1.定时器

2.空闲中断+DMA

问题和注意事项:

串口接收到的数据是以askll码表示出来的

有关十三届蓝桥杯嵌入式串口的更多相关文章

  1. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  2. 蓝桥杯备赛(二) - 2

    目录前言: 一、ASC分析代码实现二、 卡片分析代码实现三、 直线分析代码实现四、货物摆放分析代码实现小结:前言:  在刷题的过程中,发现蓝桥杯的题目和力扣的差别很大。让人有一种不一样的感觉,蓝桥杯题目偏向对于实际问题用编程去的解决,而力扣给人感觉很锻炼自己的编程思维,逻辑能力。两者结合去刷,相信会有不一样的收获。 一、ASC  已知大写字母A的ASCII码为65,请问大写字母L的ASCII码是多少?分析  这道题目看上去很简单,我们需确定自己计算的准确,所以我建议用编程去解决。代码实现publicclassTest8{publicstaticvoidmain(String[]args){Sy

  3. 蓝桥杯C/C++VIP试题每日一练之报时助手 - 2

    ?作者主页:静Yu?简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者?社区地址:前端知识交流社区?博主的个人博客:静Yu的个人博客?博主的个人笔记本:前端面试题个人笔记本只记录前端领域的面试题目,项目总结,面试技巧等等。接下来会更新蓝桥杯官方系统基础练习的VIP试题,依然包括解题思路,源代码等等。问题描述:给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是:  如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“threeo’clock”。  如果m不为0,则将时读出来,然后将分读出来,如5

  4. 1个串口用1根线实现多机半双工通信+开机控制电路 - 2

    功能需求:主机使用一个串口,与两个从机进行双向通信,主机向从机发送数据,从机能够返回数据,由于结构限制,主机与从机之间只有3根线(电源、地、数据线),并且从机上没有设物理的电源开关,需要通过与主机连接的数据线来控制开机,总结如下:1、数据线只有1根2、能够双向通信3、主机能够控制从机开机4、主机可以单独向1个从机发数据,也可以同时向两个从机发送数据根据需求,设计出如下电路:工作原理分析:VCC_24V_IN、GND、LINE_L(LINE_R)三根线接线连接到从机,电源开启电路是从机内部的电源控制。开机的逻辑:*主机先上电,LINE_L因为主机的R1上拉而有高电平,使Q6导通,Q5的G极电压被

  5. ruby-on-rails - 如何在 RoR 中使用 content_tag 嵌入标签? - 2

    我有这个可以为我生成一个超链接:我希望它显示在td标签中,所以我想使用这个content_tag来帮助我:"example")%>我想要我的td中的超链接,所以我有这样的东西:,:class=>"example")%>但是我收到语法错误,我该怎么办? 最佳答案 内联:'example')%>或block形式:'example')do%> 关于ruby-on-rails-如何在RoR中使用content_tag嵌入标签?,我们在StackOverflow上找到一个类似的问题:

  6. 十四届蓝桥青少组模拟赛Python-20221108 - 2

    十四届蓝桥青少组模拟赛Python-20221108T1.二进制位数十进制整数2在十进制中是1位数,在二进制中对应10,是2位数。十进制整数22在十进制中是2位数,在二进制中对应10110,是5位数。请问十进制整数2022在二进制中是几位数?print(len(bin(2022))-2)#运行结果:11T2.晨跑小蓝每周六、周日都晨跑,每月的1、11、21、31日也晨跑。其它时间不晨跑。已知2022年1月1日是周六,请问小蓝整个2022年晨跑多少天?#样例代码1ls=[0,31,28,31,30,31,30,31,31,30,31,30,31]ans=0k=6foriinrange(1,13)

  7. 蓝桥杯 stm32 MCP4017 - 2

    本文代码使用HAL库。文章目录前言一、MCP4017的重要特性二、MCP4017计算RBW阻值三、MCP4017地址四、MCP4017读写函数五、CubeMX创建工程(利用ADC测量MCP4017电压)、对应代码:总结前言一、MCP4017的重要特性蓝桥杯板子上的是MCP4017T-104ELT,如图1。MCP4017是一个可编程电阻,通过写入的数值可以改变电阻的大小。重点在于6引脚(W),5引脚(B&#

  8. [蓝桥杯单片机]学习笔记——串口通信的基本原理与应用 - 2

    目录一、原理部分1、什么是串行通信(1)并行通信与串行通信(2)串行通信的制式(3)串行通信的主要方式  2、配置串口(1)SCON和PCON:串行口1的控制寄存器(2)SBUF:串行口数据缓冲寄存器 (3)AUXR:辅助寄存器​编辑(4)ES、PS:与串行口1中断相关的寄存器(5)波特率设置  3、串口框架编写二、程序案例一、原理部分1、什么是串行通信(1)并行通信与串行通信微控制器与外部设备的数据通信,根据连线结构和传送方式的不同,可以分为两种:并行通信和串行通信。并行通信:数据的各位同时发送与接收,每个数据位使用一条导线,这种方式传输快,但是需要多条导线进行信号传输。串行通信:数据一位一

  9. ruby - Ruby 是否有任何可嵌入的键值存储? - 2

    我需要快速可靠的Ruby键值存储。有没有类似的东西?要求它完全在Ruby进程内运行,不需要任何外部进程。它可能在显式磁盘刷新的内存中。它需要具有最小的键值检索时间,写入时间可能不太好。存储的数据量不会很糟糕,大约几十万个键,每个键都有~1kb的文本值。 最佳答案 事实证明,对我来说最好的选择是使用纯Hash和Marshal将其序列化到磁盘。对于那么多的对象,YAML肯定太慢了。感谢@ian-armit加强了我对核心Ruby库的信任。 关于ruby-Ruby是否有任何可嵌入的键值存储?,我

  10. ruby - mongoid 文档 to_json 包括所有嵌入的文档,每个文档都没有 ':include' - 2

    给定一个任意的mongoid文档,我如何将其转换为JSON并包含任何嵌入式结构,而不是在我的to_json语句中特别包含这些结构。例如:#!/usr/bin/envrubyrequire'mongoid'require'json'require'pp'classDocincludeMongoid::DocumentincludeMongoid::Timestampsfield:doc_specific_info,type:Stringembeds_many:personsendclassPersonincludeMongoid::Documentfield:role,type:Stri

随机推荐