【速成】蓝桥杯嵌入式省一教程:(十一)UART串口通信

news2024/11/18 6:34:44

与I2C、SPI一样,UART是一种通信协议,设备之间依靠Rx(Receive)与Tx(Transmit)两条线进行数据传输。一个单片机通常内置有多个UART,而这些UART通常都与单片机上的USB接口连接在一起,因此只需要将单片机通过数据线与电脑相连,即可实现单片机与电脑的UART串口通信。

下面我们就来看看如何实现串口通信功能。首先配置好Cube中有关UART的设置:

首先选择USART1/2/3/UART4中的任意一个(USART与UART的区别是USART可以进行同步通信,UART只能进行异步通信),将Mode设置为Asynchronous(异步),将Baud Rate(波特率)设置为9600。同步是指通信设备之间使用同一个时钟信号传输数据,而异步是指使用约定的波特率(即数据传输速率)进行数据传输与接收。 

打开中断:

在这里中断是用于接收。我们只能控制发送的时间,却不能控制接收的时间,因为不知道对方什么时候会发送数据,因此我们使用接收中断,当接收到数据时进入中断函数进行处理。

首先我们来看看如何用单片机向电脑发送信息,这需要用到HAL库的UART发送函数:

/**
  * @brief Send an amount of data in blocking mode.
  * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
  *         the sent data is handled as a set of u16. In this case, Size must indicate the number
  *         of u16 provided through pData.
  * @note When FIFO mode is enabled, writing a data in the TDR register adds one
  *       data to the TXFIFO. Write operations to the TDR register are performed
  *       when TXFNF flag is set. From hardware perspective, TXFNF flag and
  *       TXE are mapped on the same bit-field.
  * @param huart   UART handle.
  * @param pData   Pointer to data buffer (u8 or u16 data elements).
  * @param Size    Amount of data elements (u8 or u16) to be sent.
  * @param Timeout Timeout duration.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)

与LCD显示一样,这个函数用于发送一个字符串。我们同样可以通过sprintf函数为字符串赋值:

char str[40];
int year = 2024;
sprintf(str, "%d lanqiao\r\n", year);                           //\r\n表示换行
HAL_UART_Transmit(&huart1, (uint8_t *)str, strlen(str), 50);    //50为超时时间,通常可以设定一个很大的值

打开选手资源数据包中的串口助手“ComAssistant”,将波特率设定为9600,选择对应的端口(不知道是哪个就一个一个试,不对的会提示无法打开),然后点击打开串口,运行程序,就可以在串口助手上看到2024 lanqiao的文字了:

下面我们来编写接收的程序。和其他中断一样,我们首先要在初始化中开启UART接收中断:

uint8_t rx;
HAL_UART_Receive_IT(&huart1, &rx, 1);    //1表示每次接收一个字节

HAL_UART_Receive_IT函数定义如下:

/**
  * @brief Receive an amount of data in interrupt mode.
  * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
  *         the received data is handled as a set of u16. In this case, Size must indicate the number
  *         of u16 available through pData.
  * @param huart UART handle.
  * @param pData Pointer to data buffer (u8 or u16 data elements).
  * @param Size  Amount of data elements (u8 or u16) to be received.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

同样,要编写UART接收中断回调函数(函数名和形参不能修改!!!可按下图进行查找)

void HAL_UART_RxCpltCallback(UART_HandleTypedef *huart)   //UART接收完成(Cplt(Complete))中断
{
    if (huart->Instance == USART1)              //USART1触发的中断
    {
        HAL_UART_Receive_IT(&huart1, &rx, 1);   //由于此中断回调函数会关闭中断,因此要重新打开
    }
}

想要验证程序的正确与否,只需要将接收到的数据通过串口再发送出去,或使用LCD显示出来即可。

通常,由于不同设备向单片机发送的数据不同、格式不同,有的可能还会含有帧头、帧尾等防错位措施,UART接收需要根据实际需求进行编写。下面我们以第十三届省赛题为例,讲讲如何根据实际情况书写UART中断函数:

题目要求可以通过串口修改密码,修改的格式为当前密码-新密码(共7个字符),且当前密码需要输入正确。这里隐含了两个判断条件:格式要求正确,如123-789;当前密码要求正确只有满足这两个条件,才进行下一步处理——修改密码。

char pswd[3] = {'1','2','3'};
char rx_data[100];
int rx_data_i = 0;                    //用于判断接收位数
bool flag = 0;                        //用于判断格式与密码是否正确

void HAL_UART_RxCpltCallback(UART_HandleTypedef *huart)
{
    if (huart->Instance == USART1)
    {
        rx_data[rx_data_i++] = rx;    //将接收到的数据放进数组中,方便后续判断
        HAL_UART_Receive_IT(&huart1, &rx, 1);
    }
}

void change_pswd(void)
{
    //第一个判断条件:输入字符恰为7个
    if (rx_data_i == 7)
    {
        //第二个判断条件:输入格式正确,为3个数字-3个数字
        for (int i=0; i<3; i++)
        {
            if ((rx_data[i]>'0'&&rx_data[i]<'9') && (rx_data[i+4]>'0'||rx_data[i+4]<'9') && rx_data[3]=='-')    flag = 1;
            else
            {
                flag = 0;
                break;
            }
        }

        if (flag)
        {
            //第三个判断条件:当前密码正确
            for (int i=0; i<3; i++)
            {
                if (rx_data[i] == pswd[i])    flag = 1;
                else
                {
                    flag = 0;
                    break;
                }
            }
        }

        //前三个判断条件均成立,才能走到这一步
        if (flag)
        {
            for (int i=0; i<3; i++)    pswd[i] = rx_data[i+4];    //修改密码
        }
    }

    rx_data_i = 0;              //判断接收位数的变量清零
    memset(rx_data, 0, 100);    //存储接收数据的数组清零,需要调用string.h
    flag = 0;                   //判断格式与密码的标志位清零
}

在主循环中,需要判断是否接收到,且接收是否完成,才能进行修改密码的操作:

while (1)
{
    if (rx_data_i != 0)
    {
        int temp = rx_data_i;
        HAL_Delay(1);    //延时1ms,若仍在进入中断,rx_data_i会改变,说明接收未完成
        if (temp == rx_data_i)    change_pswd();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/928518.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CK-GW06-E03与汇川PLC的EtherNet/IP通信

准备阶段&#xff1a; CK-GWO6-E03网关POE交换机网线汇川PLC编程软件汇川AC801-0221-U0R0型号PLC 1.打开汇川PLC编程软件lnoProShop(V1.6.2)SP2 新建工程&#xff0c;选择对应的PLC型号&#xff0c;编程语言选择为“结构化文本&#xff08;ST&#xff09;语言”&#xff0c;然…

数据库连接池druid 的jar包官网下载-最新版下载

进入官网Central Repository: com/alibaba/druid 往下滑 找到最新版点击进入 找到该jar包 点击即可下载

树状表格父节点选择 - 在Vue.js中实现仅选择父节点的树状表格功能

功能介绍 本文介绍了如何在Vue.js框架下实现一个树状表格&#xff0c;其中只支持选择父节点的复选框。通过这个功能&#xff0c;用户可以方便地选择表格中的父节点&#xff0c;而无需关心子节点的选择。代码示例和详细的实现步骤将展示如何使用Vue.js的相关特性和组件实现这个功…

WPF基础入门-Class3-WPF数据模板

WPF基础入门 Class3&#xff1a;WPF数据模板 1、先在cs文件中定义一些数据 public partial class Class_4 : Window{public Class_4(){InitializeComponent();List<Color> test new List<Color>();test.Add(new Color() { Code "Yellow", Name &qu…

Robotframework 的简介及其工作原理~

下面通过官网和网上资料来简单介绍下Robotframework及其工作原理。 官方说明&#xff1a; Robot Framework is a generic test automation framework for acceptance testing and acceptance test-driven development (ATDD). It has easy-to-use tabular test data syntax a…

Redis 执行 RDB 快照期间,主进程可以正常处理命令吗?

执行了 save 命令&#xff0c;会在主进程生成 RDB 文件&#xff0c;由于和执行操作命令在同一个线程&#xff0c;所以如果写入 RDB 文件的时间太长&#xff0c;会阻塞主进程。 执行 bgsave 过程中&#xff0c;由于是交给子进程来构建 RDB 文件&#xff0c;主进程还是可以继续工…

[SQLITE_ERROR] SQL error or missing database (near “=“: syntax error)【已解决】

这个报的错误是语法错误&#xff0c;但是我并没有看出来这行代码有什么错。 通过排除掉下边两个问题解决的 从增加记录方法复制的下来的代码&#xff0c;只删除了关闭自动提交事务&#xff0c;但是connection.commit忘记删除executeQuery和executeUpdate方法的用法忘记了&…

SQL视图

一、视图概念 1.为什么使用视图 简化复杂的查询&#xff1a;视图是一个虚拟表&#xff0c;它可以由一个或多个表的数据以某种特定的查询方式组合而来。通过创建视图&#xff0c;可以将复杂的查询逻辑抽象为一个简单的视图查询&#xff0c;使得查询更加直观和易于理解。 数据安…

u盘 pe系统;widnows cmd命令后台运行;c盘桌面文件默认路径保存到其他盘

1、u盘 pe系统 参考&#xff1a; https://www.wepe.com.cn/download.html https://m.52nxs.com/jiaocheng/soft/49535.html ##u盘 微pe工具箱步骤 u盘启动pe&#xff0c;开启狂按F10&#xff0c;选择u盘启动即可进入pe系统 2、widnows cmd命令后台运行 start ssh -CNR 99…

portainer初体验

官方文档 安装 docker 这里采用的的是国内汉化的一个镜像&#xff0c;版本号2.16.2。 地址 docker run -d --restartalways --name"portainer" -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock 6053537/portainer-ce体验 访问9000端口。 尝试&#x…

java八股文面试[JVM]——JVM调优

知识来源&#xff1a; 【2023年面试】JVM性能调优实战_哔哩哔哩_bilibili

Ubuntu20.04配置mysql配置主从复制

ubuntu20.04&#xff1a;mysql主库 sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf # 修改完毕重启 sudo service mysql stop sudo service mysql start主库mysqld.cnf配置 [mysqld] ... # bind-address>->--- 127.0.0.1 # 注释掉&#xff0c;允许外部连接 # mysqlx-b…

国际旅游网络的大数据分析(数学建模练习题)

题目&#xff1a;国际旅游网络的大数据分析 伴随着大数据时代的到来,数据分析已经深入到现代社会生活中的各个方面。 无论是国家政府部门、企事业单位还是个人&#xff0c;数据分析工作都是进行决策之前的 重要环节。 山东省应用统计学会是在省民政厅注册的学术类社会组织&…

轻量化的赛博朋克游戏本:微星星影15 Air开学季好选择

又是一年的开学季&#xff0c;如何选购一台适合自己的笔记本&#xff0c;对于高校生非常重要。特别是如今笔记本产品越来越细分&#xff0c;反而会遇到“选择困难症”纠结一番。微星笔记本的产品系列也很丰富&#xff0c;但还是要问下学生朋友们&#xff1a;我们主要选购笔记本…

七夕特别篇 | 浪漫的Bug

文章目录 前言一、迷失的爱情漩涡&#xff08;多线程中的错误同步&#xff09;1.1 Bug 背景1.2 Bug 分析1.3 Bug 解决 二、心形积分之恋&#xff08;心形面积计算中的数值积分误差&#xff09;1.1 Bug 背景1.1.1 背景1.1.2 数学模型 1.2 Bug 分析1.2.1 初始代码1.2.2 代码工作流…

华为OD机试 - 字符串筛选排序 - 数组(Java 2022 Q4 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…

性能测试告诉你 mysql 数据库存储引擎该如何选?

简介 数据库存储引擎&#xff1a;是数据库底层软件组织&#xff0c;数据库管理系统&#xff08;DBMS&#xff09;使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能&#xff0c;使用不同的存储引擎&#xff0c;还可以…

辛苦拍摄的视频画面有多个杂物,教你一分钟快速去除

短视频在我们生活中已经成为了人们记录生活、分享生活的重要方式之一。然而&#xff0c;在我们辛苦拍摄的同时难免也会遇到拍摄画面中出现杂物、多余的物体或者是不相干的对象的问题。想要无痕去除的话&#xff0c;随着人工智能的快速发展&#xff0c;AI智能抠像技术为解决这一…

【C语言】16-函数-2

1. 函数的嵌套调用 C 语言的函数定义是互相平行、独立的,也就是说,在定义函数时,一个函数内不能再定义另一个函数,即不能嵌套定义,但可以嵌套调用函数,即在调用一个函数的过程中又调用另一个函数,如下图所示: 其执行的流程为: 执行 main 函数的开头部分遇函数调用语句…

Hbase--技术文档--单机docker基础安装(非高可用)

环境准备-docker 配置Linux服务器华为云耀云服务器之docker安装&#xff0c;以及环境变量安装 java &#xff08;虚拟机一样适用&#xff09;_docker配置java环境变量_一单成的博客-CSDN博客 说明&#xff1a; 本文章安装方式为学习使用的单体hbase项目。主要是学习&#xff…