设计与开发

单片机阻塞 STM32单片机从零开始使用教程(三) 阻塞模式串口的简单应用

小编 2024-10-09 设计与开发 23 0

STM32单片机从零开始使用教程(三) 阻塞模式串口的简单应用

之前跑马灯的时候已经生成过了一次keil工程,不过只是简单地编译下载,这次来仔细看一下工程中都有什么。

顺便体验一下快捷的串口设置。

与之前类似,这次需要配置一下串口

模式就用异步,毕竟我们懒得提供额外的同步时钟。

波特率115200,字长8位。

ok,闲话不多说,打开keil!

认识keil工程

工程目录

在keil的project树中可以看到有四大目录

其中Application/MDK-ARM目录下的startup_stm32f103xb.s文件为启动文件(其在资源管理器的目录就是工程目录下的MDK-ARM),打开后可以发现全是晦涩的汇编代码。我们只需要知道它负责我们单片机的启动,进行堆栈指针、程序计数器指针、堆栈大小、异常向量表、C的分支入口等初始化的工作,有兴趣可以针对stm32启动文件深入了解。

Application/User/Core目录下的内容则是用户的源代码,是我们要操作的地方,其在资源管理器下的路径就是工程目录下的Core。

Driver路径下的HAL类似于标准外设库,是Hardware Abstraction Layer(硬件抽象层),不过比标准库的集成度还要再高一些。这是STMcube帮助我们生成的,目前来讲不要随便修改它

另外一股CMSIS则是CMSIS微控制器软件接口标准,我们也不会动它。

代码内容

我们现在应该主要研究的就是User/Core目录下的内容

首先是main.c

开头生成了一段简介,以及他们ST的版权声明

USER CODE BEGIN Header和USER CODE END Header

意味着我们可以把自己的说明插入到这一块。

在几个头文件引用之后,又出现了很多段的ben和end

理论上来讲,我们这些全局变量的定义啊,宏的定义啊什么的其实怎么来都行,你觉得舒服然后能跑起来不报错就没问题。但是对于工程产出而言,能够条理规范地写清楚代码也十分的重要,因此不妨按照人家的模板分门别类的把自己的代码安放到合适的地方。

接下来看Main函数,在无限while循环之前有几个初始化函数

此处的HAL_Init()对所有外设进行初始化,包括flash接口和systick

在进行系统时钟配置后开始初始化我们配置的外设

这里就和Cube工程里面的设置有关了,比如说我打开了GPIO和USART1,那么这里就会有对应的初始化函数。

串口程序

咱们来分析一下串口的相关代码

go to definition可以找到串口初始化代码的原型

其内容就是给一个叫huart1的结构体的成员进行赋值,从这些命名看大概就可以知道分别是实例、波特率、字长等等

在初始化赋值后查询一下初始化是否成功,失败就进入错误处理。

huart1是这样的一个结构体类型,也可以具体地查看结构体的定义。

好像没了,那要怎么实现串口的通信呢?

在stm32f1xx_hal_uart.c中有一段IO 操作函数

注释里面已经大概告诉了我们不同的模式要使用什么样的api

阻塞模式

以阻塞模式为例,我们使用 HAL_UART_Transmit()发送消息

找到发送函数的定义

其输入参量需要*huart(这个已经定义好了,就是我们初始化时做的事情),然后是一个指向发送数据的uint8指针,以及数据的大小,最后是超时

我们先定义一个变量作为发送的消息

那么调用函数就应该把这几个参数传进去,注意需要取地址的地方

接受函数与之类似

我们可以稍微调整一下,把message改成数组,并且添加一个status标志位

在while循环中,我们查询status的状态,如果搞定了,就把消息transmit出去。

下载程序

然后把它丢到串口调试助手上,可以看到单片机能把我们发过去的内容发回来

但缺点有两个,一是我接收到的字符内容得把缓冲区填满了才会执行下一步操作

另一个就是由于是阻塞通信,在没有接受完所有消息时,它就会一直卡在串口接受的位置。

使用环形队列解决串口打印阻塞问题

队列(FIFO)是一种常见的线性存储结构,在嵌入式开发中经常用到,主要的应用场景有:

1. 高级一点的单片机内部串行通信模块,像UART、SPI、CAN等串行通信,内部带有FIFO缓存。有FIFO的模块可以一次写入或保存多个数据,而没有FIFO的模块只可以写入或保存一个数据。

2. 在RTOS中,可以通过消息队列实现任务(线程)间的通信

3. 解决CPU与外设由于速度差导致的阻塞

写数据索引write,读数据索引read,数据个数为write-read,普通队列写索引永远不小于读索引。但我们可利用的栈内存是有限的。

一种优化的队列是环形队列 ,也可以理解为首尾相连的队列。当写索引到达最大分配内存时,跳回到队列的头部继续写入,数据个数为(write+BUFFER_SIZE-read)%BUFFER_SIZE。

下面以使用环形队列来解决单片机串口打印阻塞问题为例来说明软件实现。

上面代码已经注释得够详细了,就不再描述了。

在需要打印数据时,直接调用printf函数格式化打印,在主函数大循环中执行debug_print_task就可以了。

相关问答

一个定时器中断,或者,外部中断,能打断主函数中的for或者,while这种循环吗?

来检测按键或者一些外部的电平信号定时器中断是计时进入中断,就是每隔一段时间进一次中断。也可用来检测按键。一个人按键假如最快的速度是0.5秒一次,你...也...

智慧交通专业怎么样?

还不错。因为智慧交通专业是一个新兴的领域,虽然随着社会经济的发展,相关行业逐渐兴起,但市场竞争激烈,就业岗位相对较少。同时,智慧交通专业要求综合素质...

cpu死机又叫程序死循环吗?

排他锁,等待事务A完成并释放其对行1持有的共享锁之前被阻塞。事务B完成之后事务A才能完成,但是事务B由事务A阻塞。该条件也称为循环依赖关系:事...

螺杆冰机的跳车问题-盖德问答-化工人互助问答社区

压力控制器松动;控制线错我们也一样发生过同样问题,原厂家配置不行(原装配置仪表联锁采用的是压力开关,环境腐蚀太大,故障率太高),无论如何维护都...

想问一下rtoto水龙头怎么自己维修?-设计本有问必答

方法1、换水龙头的轴心。知己知彼方能百战不殆,修水龙头也是一样的。要想将水龙头漏水给修好,就得了解水龙头漏水的原因,如果是因为水龙头内的轴心...

纯净水设备高压泵不启动该如何解决?

先要了解纯净水设备的高压泵是什么东西,这个高压泵是由电动机和联轴器、减速器和传动部分、泵头部分和公共底座等组成,在通电之后,它带动各个零部件运作。如果...

感应水龙头出故障怎么办- 一起装修网

[回答]随着人们生活水平的提高,感应水龙头已经渐渐走进人们的生活,不过有时候感应水龙头会产生一些故障,那么该怎么办呢?以下是一些故障解决办法。一方面...

海尔空调使用中出现f1如何解决? - 175****1292 的回答 - 懂得

海尔感因及解决方法:1、空调信号(控制)变压器损坏后会引起整机不工作;2、夏季空调电路上压敏电阻击穿损坏,多为雷击所致;3、冷凝器、蒸发器外部脏堵...

想请教下:小便器感应器大概多少钱?

[回答]红外感应部分是否采用环氧树脂封胶或防潮处理,连接插头用防水性插头,线路采用低功耗单片机控制,对光线具有抗干扰能力。如需了解更多,欢迎来电咨询!...

超再生式收音电路优缺点?

超再生:超再生和超外差电路性能各有优缺点,超再生接收机价格低廉,经济实惠,而且接收灵敏度高,但是缺点也很明显,那就是频率受温度漂移大,抗干扰能力差。超...

猜你喜欢