STM32串口通信(STM32F103C86)
实验任务:
一. 了解串口协议和RS-232标准,以及RS232电平与TTL电平的区别;了解"USB/TTL转232"模块(以CH340芯片模块为例)的工作原理。二. 串口传输文件的实验。将两台笔记本电脑,借助 USB/TTL转RS232模块和杜邦线,建立起串口连接。然后用串口助手等工具软件(如sscom,带文件传输功能)将一台笔记本上的一个大文件(图片、视频和压缩包软件)传输到另外一台电脑。
(1)预估文件大小、波特率和传输时间三者之间的关系,并对比实际传输时间。
(2)如果只接TX–RX, RX–TX 这样两根线,不接电源线或者不接GND地线,文件传输是否还能正常工作?请解释原因。三. 安装 stm32CubeMX,配合Keil,使用HAL库(或标准库)方式,设置USART1
波特率为115200,1位停止位,无校验位,完成下列任务:(1)STM32系统给上位机(win11)连续发送“hello windows!”,win11采用“串口助手”工具接收。如果STM32的连续发送之间不加延时语句,观察win11端是否出现接收数据丢失的现象。
(2)在完成以上任务基础,继续扩展功能:当上位机给stm32发送一个字符“#”后,stm32暂停发送“hello windows!”;发送一个字符“*”后,stm32继续发送;
四. 学习STM32中断、DMA通信原理和编程方法。使用stm32tubemx和HAL库分别完成以下编程练习:
(1) 采用串口中断方式重做上面任务二(2)的串口通信实验。
(2)STM32采用串口DMA方式,用115200bps或更高速率向上位机连续发送数据。
五. 在没有示波器条件下,可以使用Keil的软件仿真逻辑分析仪功能观察任务三(1)串口输出波形,并分析时序状态正确与否,计算波特率实际为多少。
(一)串口通信的基本原理
1.串口协议和RS-232标准
串口协议是一种数据传输协议,常用于计算机和其他设备之间的通信。它定义了数据传输的规则,如数据格式、传输速率等。RS-232是电子工业协会(EIA)制定的一种异步传输标准接口,它同时对应着电平标准和通信协议(时序)。RS-232标准定义了数据传输的电压范围、信号线功能、连接方式和传输速率等。
RS-232标准在1970年发布,命名为EIA-232-E,作为工业标准,以保证不同厂家产品之间的兼容。RS-232总线规定了25条线,包含了两个信号通道,即第一通道(称为主通道)和第二通道(称为副通道)。利用RS-232总线可以实现全双工通信,通常使用的是主通道,而副通道使用较少。在一般应用中,使用3条~9条信号线就可以实现全双工通信,采用三条信号线(接收线、发送线和信号线)能实现简单的全双工通信过程。
2.RS232电平与TTL电平的区别
- 电压范围:RS-232电平逻辑中,逻辑0表示-5V至-15V,逻辑1表示+5V至+15V;而TTL电平逻辑中,逻辑0表示0V至0.8V,逻辑1表示2V至5V。
- 逻辑定义:RS-232使用负逻辑,即更高的电压代表逻辑“0”,而TTL使用正逻辑,即更高的电压代表逻辑“1”。
3."USB/TTL转232"模块的工作原理(以CH340芯片模块为例)
CH340是一个USB总线的转接芯片,实现USB转串口、USB转IrDA红外或者USB转打印口的功能。在串口方式下,CH340提供常用的MODEM联络信号,用于为计算机扩展异步串口,或者将普通的串口设备直接升级到USB总线。
CH340芯片模块的工作原理如下:
- 功能:实现TTL或RS-232与USB之间的转换。
- 转换方式:内部电路将USB数据转换为串口数据或反之。
- 控制器:内部包含芯片控制器,负责数据转换的协调工作。
CH340芯片模块通过内部的电路设计,将USB接口的数据信号转换为TTL电平的串口信号,或者将TTL电平的串口信号转换为USB接口的数据信号。这种转换使得计算机可以通过USB接口与使用TTL电平的串口设备进行通信。在实际应用中,CH340模块可以方便地将USB接口的设备连接到使用RS-232标准的串口设备上,实现数据的传输和通信。
(二)串口传输文件
1.电路连接
- 首先我们需要两台电脑,两台电脑都需要安装好串口助手用于发送和接收文件。
将两个线用杜邦线正确连接,这里我将TXD连接RXD,RXD连接TXD,5V连接5V,GND连接GND。如图所示:
2.发送图片
- 连接到两台计算机后,在两台电脑上都打开串口助手,这我这里进行发送文件,我这里选择了一张图片:
- 发送完毕后串口发送方显示:
- 在接收端的界面如图所示:
- 将文件转化为gpj格式在接收端选择文件打开方式,用画图打开如图所示:
(1)预估文件大小、波特率和传输时间三者之间的关系,并对比实际传输时间。
根据文件大小,理论时间=(文件大小*8)/波特率
2909288×8/115200=202.0339(s)
得到理论时间应为202.0393s,但实际传输时间为263s左右,可以看到实际时间比理论时间要长,分析原因是在传输过程其中插入了一些延时,或者是传输过程中出错导致。
(2)如果只接TX–RX, RX–TX 这样两根线,不接电源线或者不接GND地线,文件传输是否还能正常工作?请解释原因。
不能。如果只连接 TX(发送)和 RX(接收)两根线,而不连接电源线和地线(GND),文件传输通常不能正常工作。
设备需要电源来为内部的通信芯片、电路等提供能量,使其能够正常运行。没有电源,通信芯片无法工作,也就无法对要发送的数据进行编码、调制等操作,也无法对接收的数据进行解码、校验等处理。
通信信号是以 GND 为参考电平的,它定义了信号的高低电平的基准。没有 GND,接收端无法正确判断接收到的信号是高电平还是低电平,会导致信号识别错误,从而无法正确接收和解析数据,文件传输自然无法正常进行。
(三)stm32串口通信
硬件原理图:
1.HAL库配置
(1)打开STM32CubeMX,在主界面点击:ACCESS TO MCU SELECTOR:
配置前需要先安装STM32CubeMX软件
(2)选择单片机型号以及点击开始工程项目:
(3)点击system core,进入SYS,在debug下选择serial wire:
(4)配置时钟,进入上面的RCC,有两个时钟,一个是HSEe和LSE,将HSE那里设为Crystal/Ceramic Resonator:
(5)设置串口USART1,打开
Connectivity
,设置MODE为 异步通信(Asynchronous)
参数设置波特率为115200 Bits/s,传输数据长度为8 Bit,奇偶检验无,停止位1
(6)进入CLK Configuration (时钟配置)中,进行时钟配置:
开发板的外部晶振为8MHz,我们填入8;通道选择LSE;PLLM选择为/1;倍频系数N选择为x9;系统时钟选择PLLCLK;系统时钟设定为72Mz;APB1分频系数选择为/2即PCLK1位36MHz;APB2分频系数选择为/1即PCLK2位72MHz。
(7)进入Project Manager(工程管理),进行工程设置点击生成工程与代码:
配置好后如下:
2.完善keil5工程
2.1 发送“hello windows!”
打开生成的.hex
工程后,在main.c的while循环里面输入以下代码
HAL_UART_Transmit(&huart1, (uint8_t *)"Hello Windows!\r\n", 16 , 0xffff);
HAL_Delay(1000);
注意一定要写在/* USER CODE BEGIN WHILE */
和/* USER CODE END WHLIE */
中间,防止再次配置CubeMX
时代码被清除。
2.2 上位机控制发送“hello windows!”
当上位机给stm32发送一个字符“#”后,stm32暂停发送“hello windows!”;发送一个字符“*”后,stm32继续发送。
main.c代码为:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
char rcData='*';
uint8_t flag = 1; // 用于控制是否继续发送 "hello windows"
char tips[]="CommandError\n";//提示1
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// 接收数据
HAL_UART_Receive(&huart1, (uint8_t *)&rcData, 1,1000);
// 检查是否需要发送 "hello windows"
if (flag)
{
HAL_UART_Transmit(&huart1, (uint8_t *)"Hello Windows!\r\n", 16 , 0xffff);
HAL_Delay(1000); // 延迟1000ms
}
// 检查接收到的数据
if (rcData == '#')
{
// 如果接收#
flag = 0; // 停止发送 "hello windows"
}
else if (rcData == '*')
{
// 如果接收*
flag = 1; // 继续发送 "hello windows"
}
else
{
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips, strlen(tips),0xFFFF);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
注意一定要写在/* USER CODE BEGIN */
和/* USER CODE END */
中间,防止再次配置CubeMX
时代码被清除。
3.电路连接
-
使用stlink连接STM32与电脑,将程序下载STM32中,连接图如下:
-
在进行MCU(微控制单元)与串口转换模块的连接时,需要确保正确的引脚对应,以实现数据的正确传输,连接方式如下:
-
MCU的TX(发送)引脚 应连接到串口转换模块的RX(接收)引脚。
-
MCU的RX(接收)引脚应连接到串口转换模块的TX(发送)引脚。
-
MCU的地(GND) 应连接到串口转换模块的地(GND),以确保两者的电平参考一致。
-
配置好的串口RX为PA10,TX为PA9:
- 连接
PA10 RX——串口 TX
PA9 TX——串口 RX
4.硬件实现
4.1 发送“hello windows!”实现
- 代码烧录好后,用串口将STM32连接电脑,波特率与单片机一致,设置为115200,停止位为1,数据位为8,打开时间戳,可以发现大约1s,电脑接收一次
“hello windows!”
。
- 将
HAL_Delay(1000);
注释掉,去掉延时,接收情况如下:
出现了数据丢失(由于传输速度很快,有时候会看不到)
4.2 上位机控制发送“hello windows!”实现
当上位机给stm32发送一个字符“#”后,stm32暂停发送“hello windows!”;发送一个字符“*”后,stm32继续发送。代码如下:
串口
可以从时间看出,发送一个字符“#”后,stm32暂停发送“hello windows!”;发送一个字符“*”后,stm32继续发送。
(四)STM32中断与DMA原理
1.STM32串口中断
- 在前面配置STM32cubx的基础配置串口中断,打开中断就可以:
用串口中断的方式写代码,当上位机给stm32发送一个字符“#”后,stm32暂停发送“hello windows!”;发送一个字符“*”后,stm32继续发送。 - 代码设计如下:
- 在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.开始发送
- main函数
int main(void)
{
/* USER CODE BEGIN 1 */
// 初始化后开启一次串口接收中断
HAL_UART_Receive_IT(&huart1, NULL, 1);
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//设置接受中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);
// HAL_UART_Transmit(&huart1, (uint8_t *)"Hello Windows!\r\n", 16 , 0xffff);
// HAL_Delay(1000);
if(flag==1)
{
//发送信息
HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF);
//延时
HAL_Delay(1000);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
- 中断处理函数
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);
}
- 实现结果如下:
打开串口,串口向上位机发送 “hello windows!”
,上位机发送#
,串口发送stop
表示暂停,上位机发送*
,串口可恢复发送,Start.....hello Windows
表示开始发送。
串口中断
2.STM32采用串口DMA方式
2.1STM32CubeMX配置
选择芯片、配置SYS、RCC与前面一致,这里我就忽略了
- USART使能中断
后面j就是时钟配置和文件生成,与前文一致
2.2完善keil5工程
- 在主函数和while之间写上:
uint8_t Senbuff[] = "Hello world!"; //定义数据发送数组
- 在while里写上:
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff));
HAL_Delay(1000);
2.3硬件实现
可以收到串口向上位机连续发送的数据。
(六)仿真串口输出波形
1.keil仿真
1.1仿真过程
- 按照图示勾选,以及参数设置:
- 点击菜单栏
Debug
按钮
点开逻辑分析仪的窗口。(两个途径)
- 熟悉逻辑分析仪窗口。
- 开启实时显示波形功能。(不然的话只能让程序全速运行一会再让它停止才会有波形的出现)
- 监听GPIO口
1.2仿真结果
-
观察USART1_SR引脚的时序波形
-
得到的波形如下:
-串口发送实际持续时间:
11.04639-10.04639=1(s)
- 串口每隔1s发送一次,与理论值一模一样。
(七)github上传代码
注册自己的github或gitee账号,下载git客户端,并熟悉其基本使用命令。将自己的项目代码(项目主目录下所有文件)通过git命令提交到github/gitee对应的项目仓库中
(1)注册github账号
github官方网站:https://github.com/
注册过程:略
(2)安装git客户端与tortoisegit
git客户端下载地址:https://www.git-scm.com/
tortoisegit下载地址:https://tortoisegit.org/
双击下载的安装包,默认安装直到完成。
(3)配置git客户端
打开git bash,输入以下内容,邮箱为github注册邮箱
ssh-keygen -t rsa -C "L2053897864@outlook.com"
- 回车,输入“yes”,再回车,将在“C:\Users\john.ssh\id_rsa.pub”文件生成ssh密钥,复制所有内容
- 登录github,打开“Settings”
- 点击左侧“SSH and GPG keys”菜单,然后点击右侧上方“New SSH key”按钮,“Title”随意输入名称,“Key”处粘贴刚才复制的密钥,注意最后不要留空格或换行,保存配置
- 打开git bash,输入以下内容验证ssh连接
ssh -T git@github.com
第一次需要输入“yes”然后回车才能看到连接成功的信息,以后就不需要了
(4)配置全局信息
配置全局的用户名、邮箱信息,作为提交人信息
git config --global user.name "ice_queen"
git config --global user.email "L2053897864@outlook.com"
(5)创建github仓库
- 登录github,创建一个工程,点击
Create repository
- 名为“usrat”(这里为LED我忘记截图了),并选择一个license,以“Apache License 2.0”为例
- 创建完
usart
仓库之后,查看该仓库,只包含两个文件:README.md
和LICENSE
(6)初始化目录文件夹
-
找到目标文件夹(想上传代码所在的地方)空白处右键,选择
Open Git Bash Here
,打开git 命令窗口
-
将文件添加到暂存区并且告知Git,把文件提交到仓库,使用ls可以查看当前文件夹下的所有内容。
git init
//初始化目录
ls
//查看当前文件夹下的所有文件
- 把需要推送的文件添加到暂存区,暂存区是一个临时存储区域,用于记录即将提交到本地仓库的文件更改。
git add XXX
- 告知Git,把文件添加到仓库
git commit -m "xxxx"
//写入一句话,用于告诉Git干什么
(7)远程连接GitHub账户
-
点击Clone or dowload会出现一个地址,copy这个地址备用
-
根据创建好的Git仓库页面的提示,可以在本地
sy3 STM32_usart
仓库的命令行输入:
git remote add origin https://github.com/ice-queen1/usart.git
注意origin后面加的是你Github上创建好的仓库的地址
- 关联好之后我们就可以把本地库的所有内容推送到远程仓库(也就是Github)上了,通过:
git push -u origin master
- 出现登录页面后根据指引操作,但是我已经登陆过一次了,就没有弹出来,完成之后是这样的:
- 这时候你再重新刷新Github页面进入刚才新建的那个仓库里面就会发现项目已经成功上传了:
总结
本次实验用串口传输文件,通过串口,可以将一台笔记本上的一个大文件(图片、视频和压缩包软件)传输到另外一台电脑。传输的时间会比理想的时间长,可能是因为插入了时长或传输时出现了错误。用串口传输文件一定要连接好电源线和GND地线,不然不能够正常传输文件。
本次实验主要用了三种方法来进行上位机控制串口的发送,分别是串口、中断串口和DMA,这三种方法均能实现上位机控制串口发送信息,在配置STM32cubmx时有一些区别,但是代码的逻辑思维差不多
借助 Keil 软件的仿真逻辑分析仪功能对串口输出波形进行观察,通过这一手段可以直观地看到串口在数据发送过程中的波形表现,
再次使用github上传代码,这次相比于上次速度更快了,但github经常因为网络问题登不上,这也阻碍了我上传。
通过本次实验,我对串口有了更深入的了解,通过动手操作解决遇到的问题,我更加清晰地知道了自己对于串口的运用还不是很熟练,这次实验很好地巩固了我对串口知识了解的基础,希望在我能够更加灵活地利用串口去制作一些小项目以及生活中,将学会的知识用在生活需要的地方去。
参考:
STM32串口通信USART学习笔记
两台电脑之间实现串口通信
STM32简单串口通信
HAL库中断方式进行串口通信