STM32串口通信
一、理论知识
1.串口通信的基本原理
(1)串口协议
串口通讯是一种设备间非常常用的串行通讯方式,因为它简单、便捷,因此大部分电子设备都支持该通讯方式,电子工程师在调试设备时也经常使用该通 讯方式输出调试信息。
在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和片上外设;STM32标准库则是在寄存器与用户代码之间的软件层。对于通讯协议,我们也以分层的方式来理解,最基本的是把它分为物理层和协议层。
(2)RS-232标准
RS-232标准的主要特点
a.传输方式:
串行传输:RS-232通过串行方式进行数据传输,这意味着数据一位一位地通过单根传输线进行传输,与并行传输不同。
电压级别:RS-232定义了两种电压级别:
逻辑“1”(标称为“空闲”状态):通常是负电压,范围在-12V到-3V之间。
逻辑“0”:通常是正电压,范围在+3V到+15V之间。
设备之间的通信基于这些电压信号进行识别,传输信号的电压必须符合这些标准,以确保正确的信号解析。
b.数据传输速率:
RS-232支持不同的波特率(Baud Rate),通常的速率有9600、19200、38400、115200等。传输速率与距离之间存在一定的限制,通常RS-232适合在较短距离(通常在50英尺以内)内进行低至中速的数据传输。
2.DMA原理
a.定义
DMA(Direct Memory Access,直接存储器访问)是一种数据传输技术,它允许外设或存储器之间在不经过CPU的参与下直接进行数据传输。通过DMA,数据可以从一个地址空间直接传输到另一个地址空间,实现外设与存储器之间,或者存储器与存储器之间的高速数据传输。
我们知道,CPU是系统的核心,负责数据转移、计算处理以及程序控制等任务。在系统中,CPU需要处理大量事务,但其中一些任务(比如数据复制和存储)对处理速度要求不高。如果我们将这些任务从CPU中分担出去,让CPU专注于更加复杂和关键的计算任务,是否能够更有效地利用其处理能力呢?
因此,对于一些大量数据的传输任务,完全可以避免CPU的参与。例如,在希望将外设A的数据复制到外设B时,可以通过为这两个外设提供一条直接的数据通路,让数据在两者之间直接传输,而无需经过CPU的干预。
b.DMA传输方式
DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:
外设到内存 内存到外设 内存到内存 外设到外设
c.传输参数
数据传输,首先需要的是1 数据的源地址 2 数据传输位置的目标地址 ,3 传递数据多少的数据传输量 ,4 进行多少次传输的传输模式 DMA所需要的核心参数,便是这四个
当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,当剩余传输数据量为0时 达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式 当到达传输终点时会重新启动DMA传输。
也就是说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。
二、串口传输文件的实验
1.下载sscom
参考博客:
https://blog.youkuaiyun.com/gitblog_09776/article/details/143076343
2.硬件连接
将两个“USB/TTL”用杜邦线正确连接,这里我将TXD连接RXD,RXD连接TXD,5V连接5V,GND连接GND ,两USB接口插电脑
3.sscom调试
连接到两台计算机后,在两台电脑上都打开串口助手,这我这里进行发送文件,我这里选择了一张图片
发送端:根据步骤选择
接收端:
4.文件发送与接收
传输时间约为6.3秒
接收
点击保存数据可以看到存储的位置
在这里我发送的是一个图片jpg格式,接收方收到的是dat格式,将后缀改为jpg即可打开
图片属性:
由于:72.9KB=72.9×1024×8=597196.8位,波特率=115200位/s。
带入公式可得:
理论时间= 597196.8位/115200位/秒,约等于:5.184秒
对比实际传输时间“ 6.3s”,可知理论传输时间要小于实际传输时间。分析原因是在传输过程其中插入了一些延时,或者是传输过程中出错导致。
如果只连接TX和RX,而不连接电源和地线,文件传输将无法正常工作,大多数电子设备,包括用于文件传输的设备,都需要电源来供电。电源线(VCC)提供设备运行所需的电压,而地线(GND)则提供参考电压点,确保电子元件能够正确工作。没有电源,设备内部的电子元件无法正常工作,因此无法进行数据传输,虽然信号线(TX和RX)可以传输数据,但它们需要稳定的电源来维持信号强度和稳定性。如果电源不稳定或完全缺失,可能会导致信号衰减、噪声增加,从而影响数据传输的可靠性和速度。
三、STM32系统发送给上位机
1)STM32系统给上位机(win10)连续发送“hello windows!”,win10采用“串口助手”工具接收。
1.SM32CubeMx配置
新建工程
配置GPIO:PA0
区分串口通信的开启与关闭,要使用一个LED灯来显示。当串口通信开启(STM32向电脑发送信息)的时候,LED灯亮,当串口通信关闭(STM32停止向电脑发送消息)的时候,LED灯灭。
配置USART1,我们使用USART1进行数据传输。在这个界面按下图进行配置。我们对USART1的配置要做的只有两件事:一是选择串口工作模式为异步,二是开启USART1全局中断
进入Project Manager(工程管理),进行工程设置点击生成工程与代码
注意:路径不能包含中文和空格,不然生成的工程文件无法在Keil中打开
2.完善keil5工程
main.c文件中,在main函数里把while(1)那一块替换成如下代码:
char data[]="hello windows! ";
HAL_UART_Transmit(&huart1, (uint8_t *)data, 15, 0xffff);
//高电平点亮A0
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET);
HAL_Delay(500);
//低电平熄灭A0
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET);
HAL_Delay(500);
如下
随后编译生成hex文件
勾选框住的内容然后进行编译
编译
3.电路连接与烧录运行
先将stm32板子Boot0置1,Boot1置0
电路连接 将ttl的RX与TX分别于PA10与PA9相连,电源接电源,地接地
PA0接灯
实物图如下
下载烧录软件FlyMcu
参考博客:https://blog.youkuaiyun.com/qq_52102933/article/details/126882848
随后进行烧录,烧录时将stm32板子Boot0置1,Boot1置0,刚刚已经做过
烧录完成
下面进行串口调试
下载正点原子串口调试助手
下载地址:https://blog.youkuaiyun.com/gitblog_09721/article/details/143008251
将stm32板子Boot0置1
用正点原子串口调试助手进行调试,打开串口
4.效果展示
小灯持续闪烁
收到“hello windows!”
不加延时,收到“hello windows!”
可以看到有数据丢失的现象
5.keil仿真波形
设置Debug
添加观察引脚
选择window1 uart1
可以看到波形以及发送的效果
2)当上位机给stm32发送一个数字“0”后,stm32暂停发送“hello windows!”;发送一个数字“1”后,stm32继续发送;
1.cubemx配置
新建工程
时钟配置
设置sys
设置USART1
设置NVIC
设置Clock Coniguration 按照步骤选择
项目路径设置
2.keil文件完善
在main函数前添加全局变量
char c;//指令 0:停止 1:开始
char message[]="hello Windows\n";//输出信息
char tips[]="CommandError\n";//提示1
char tips1[]="Start.....\n";//提示2
char tips2[]="Stop......\n";//提示3
int flag=0;//标志 0:停止发送 1.开始发送
在while循环里添加发送代码
if(flag==1)
{
//发送信息
HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF);
//延时
HAL_Delay(1000);
}
改变中断函数为
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//当输入的指令为0时,发送提示并改变flag
if(c=='0'){
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF);
}
//当输入的指令为1时,发送提示并改变flag
else if(c=='1'){
flag=1;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF);
}
//当输入不存在指令时,发送提示并改变flag
else {
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips, strlen(tips),0xFFFF);
}
//重新设置中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);
}
3.编译烧录
编译生成hex文件
将Boot0置1,Boot1置0
FlyMcu进行烧录:
先读器件信息,再开始编程
要是失败了就多试几次
接下来,串口接发
Boot0置0,Boot1置1
4.效果展示
QQ2024129-163651
四. 学习STM32中断、DMA通信原理和编程方法
1)串口中断
1.配置CubeMx
创建新项目
RCC时钟配置
SYS配置
USART1设置
NVIC设置
时钟树设置
项目路径设置
2.keil文件完善
在main函数前定义全局变量
char c;//指令 0:停止 1:开始
char message[]="hello Windows\n";//输出信息
char tips[]="CommandError\n";//提示1
char tips1[]="Start.....\n";//提示2
char tips2[]="Stop......\n";//提示3
int flag=0;//标志 0:停止发送 1.开始发送
在while循环里添加传输代码
if(flag==1)
{
//发送信息
HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF);
//延时
HAL_Delay(1000);
}
在main函数外部添加中断处理函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//当输入的指令为0时,发送提示并改变flag
if(c=='0'){
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF);
}
//当输入的指令为1时,发送提示并改变flag
else if(c=='1'){
flag=1;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips1, strlen(tips1),0xFFFF);
}
//当输入不存在指令时,发送提示并改变flag
else {
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips, strlen(tips),0xFFFF);
}
//重新设置中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);
}
3.编译烧录
编译生成hex文件
用FlyMcu烧录(Boot0置1,Boot1置0)
用串口接发(Boot0置0,Boot1置1)
4.成果展示
2)DMA通信
1.配置CubeMx
创建新项目
时钟配置
sys配置
时钟树配置
选择异步通信模式
配置串口
使能中断
添加两个通道
项目路径设置
2.keil文件完善
在main函数while循环中加入以下内容
uint8_t data[] = "Congratulation,you did it!\r\n";
HAL_UART_Transmit_DMA(&huart1,(uint8_t *)data,30);
HAL_Delay(1000); //
3.烧录运行
编译生成HEX文件
FlyMcu进行烧录(将Boot0置1,Boot1置0):
先读器件信息,再开始编程
用串口进行接收(Boot0置0,Boot1置1)
4.成果展示
QQ2024128-12715
五、心得体会
本次串口通信实验涵盖了四个核心任务:文件互传、STM32系统向上位机连续发送“hello windows!”信息、串口中断的应用以及串口DMA(直接内存访问)的使用。在完成这些任务的过程中,我不仅掌握了串口通信的基础编程技巧,还深入了解了串口通信的参数配置,如数据位、停止位、校验位等,这些细节直接影响到程序的可读性、稳定性和可维护性,提升了我的编程能力和思维方式。
在文件互传任务中,我学习了如何通过串口实现计算机与STM32单片机之间的数据传输。这不仅加深了我对串口协议的理解,还让我更加熟悉了如何通过配置波特率、数据位、停止位和校验位等通信参数来确保稳定的通信。在实际编程时,我深刻认识到,良好的参数配置对程序的运行稳定性至关重要,任何一项配置的疏忽都可能导致通信失败,甚至系统崩溃。因此,我学会了如何通过细心调试,确保各项参数的匹配,提升了代码的可读性和可靠性。
在串口中断应用的任务中,我成功实现了基于中断机制的实时数据接收。这一过程中,我体会到中断在嵌入式系统中的重要性,尤其在需要快速响应外部事件的场合。通过配置串口接收中断,我能够在接收到数据的瞬间及时响应并处理,从而极大地提高了系统的响应速度。通过中断处理机制,我避免了轮询的低效方式,节省了CPU资源,优化了系统性能。这个经验使我更加深入理解了中断的工作原理和在嵌入式开发中的应用,尤其是在实时性要求较高的系统中,中断机制的重要性不言而喻。
在串口DMA的使用任务中,我进一步探讨了如何通过DMA方式提高数据传输的效率。DMA使得数据可以直接从外设传输到内存,或者从内存传输到外设,免去了CPU的干预。这种方式不仅有效提升了数据传输速率,还减少了系统的负担。通过实践,我加深了对DMA的理解,学习了如何配置DMA控制器,以及如何合理调度DMA通道以确保数据传输的顺利进行。DMA的使用大大提升了系统的性能,使得系统能够处理更多的数据而不必依赖CPU进行频繁的中断或轮询操作。
除了软件部分,硬件连接也是本次实验中的一个重要环节。在硬件连接中,最重要的细节之一是接口的匹配性。尤其是串口通信的接线问题,一旦接错或不匹配,就可能导致无法正常通信。此外,boot0和boot1引脚的配置也十分关键,正确设置这两个引脚的状态对于STM32的启动模式和程序烧录至关重要。若这两个引脚的状态设置不当,可能会导致烧录失败或者串口调试功能无法正常使用。因此,在实际操作中,我特别注意了这些硬件细节,确保每一项连接都符合标准,以保证实验的顺利进行。
通过本次串口通信实验,我不仅加深了对串口通信原理的理解,还进一步提升了在嵌入式系统中的编程能力和调试技巧。尤其是在硬件与软件配合的过程中,我意识到细节决定成败。每一个硬件接口的配置,每一项通信协议的选择,甚至每一行代码的编写,都会影响系统的稳定性和性能。
六、代码地址
https://gitee.com/shxingyu/serial-port-lighting
七、参考博客
https://blog.youkuaiyun.com/qq_47775761/article/details/139482350
https://blog.youkuaiyun.com/weixin_56102526/article/details/121169712
https://blog.youkuaiyun.com/qq_47281915/article/details/120870801
https://blog.youkuaiyun.com/2301_77559737/article/details/144264990?spm=1001.2014.3001.5502