一. 了解串口协议和RS-232标准,以及RS232电平与TTL电平的区别;了解"USB/TTL转232"模块(以CH340芯片模块为例)的工作原理。
串口通信协议和RS-232标准,以及RS232电平和TTL电平的区别的分点解释:
-
串口通信协议:
- 是一种数据传输协议,常用于计算机和其他设备之间的通信。
- 它定义了数据传输的规则,如数据格式、传输速率等。
-
RS-232标准:
- 是一种标准的串口通信协议。
- 定义了数据传输的电压范围、信号线功能、连接方式和传输速率等。
-
RS-232电平和TTL电平的区别:
- 电压范围:
- RS-232:逻辑0表示-5V至-15V,逻辑1表示+5V至+15V。
- TTL:逻辑0表示0V至0.8V,逻辑1表示2V至5V。
- 逻辑定义:RS-232使用负逻辑,而TTL使用正逻辑。
- 电压范围:
-
USB/TTL转232模块(以CH340芯片模块为例)的工作原理:
- 功能:实现TTL或RS-232与USB之间的转换。
- 转换方式:内部电路将USB数据转换为串口数据或反之。
- 控制器:内部包含芯片控制器,负责数据转换的协调工作。
二. 安装 stm32CubeMX,配合Keil,使用HAL库(或标准库)方式,设置USART1 波特率为115200,1位停止位,无校验位,完成下列任务:
1)STM32系统给上位机(win10)连续发送“hello windows!”。win10采用“串口助手”工具接收。
2)在完成以上任务基础,继续扩展功能:当上位机给stm32发送一个字符“#”后,stm32暂停发送“hello windows!”;发送一个字符“*”后,stm32继续发送;
首先打开STM32Cube MX选择STM32F103C8T6后,
设置RCC的HSE为Crystal晶振;
配置SYS为:Serial Wire;
其次,配置NVIC:
设置USART1:
注意:在生产工程时,勾选生成".c/.h"文件,并且Toolchain/IDE需要选择MDK-ARM:
首先:打开并在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函数中设置接收中断:
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);//UATR的别名;接收到的数据存放地址;接收的字节数
然后在main函数中的while循环里面添加传输代码:
if(flag==1){
//发送信息
HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF);
//延时
HAL_Delay(1000);
}
并且重写中断处理函数:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//当输入的指令为“#”时,发送提示并改变flag
if(c=='#'){
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF);
}
//当输入的指令为“*”时,发送提示并改变flag
else if(c=='*'){
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);
}
最终main.c总代码:
#include "main.h"
#include "usart.h"
#include "gpio.h"
#include <string.h>
void SystemClock_Config(void);
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.开始发送
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
//设置接受中断
HAL_UART_Receive_IT(&huart1, (uint8_t *)&c, 1);
//当flag为1时,每秒发送一次信息
//当flag为0时,停止
while (1)
{
if(flag==1){
//发送信息
HAL_UART_Transmit(&huart1, (uint8_t *)&message, strlen(message),0xFFFF);
//延时
HAL_Delay(1000);
}
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
//当输入的指令为“#”时,发送提示并改变flag
if(c=='#'){
flag=0;
HAL_UART_Transmit(&huart1, (uint8_t *)&tips2, strlen(tips2),0xFFFF);
}
//当输入的指令为“*”时,发送提示并改变flag
else if(c=='*'){
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);
}
/* USER CODE END 4 */
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
烧录并展示:
结论:
当发送*后可以看到不断输出“hello Windows”
当输入#后端口停止输出
三. 在没有示波器条件下,可以使用Keil的软件仿真逻辑分析仪功能观察串口输出波形,并分析时序状态正确与否,计算波特率实际为多少。
1、Keil仿真设置:
点击“魔法棒”后在Debug下,勾选Use Simulator、Load Application at Startup、Run to main(),并将Dialog.DLL下改为DARMSTM.DLL,Parameter下改为-pSTM32F103RC:
通过USART1接口观察逻辑分析仪中的波形。波形将显示在时间轴上,对比预期的波特率大于实际观察到的波特率,
可能存在一些问题或限制因素导致传输速率下降。
实验总结:
本次实验主要涉及串口通信协议、RS-232标准以及电平差异的理解,同时利用STM32系统实现与上位机的串口通信。实验过程主要分为两个阶段:基础串口通信设置和基于特定字符的通信控制。
首先,我们深入了解了串口通信协议和RS-232标准,以及RS-232电平和TTL电平之间的主要区别。RS-232标准定义了数据传输的电压范围和信号线功能,而TTL电平通常具有更低的电压范围。在实验中,我们使用了CH340芯片模块作为USB/TTL转232模块,它能够实现TTL电平与RS-232电平之间的转换。
在第二阶段,我们利用STM32CubeMX和Keil软件设置了USART1的通信参数,包括波特率、停止位和校验位。通过HAL库(或标准库)编程,STM32系统成功地向上位机连续发送了“hello windows!”的消息。
最后,我们利用Keil的软件仿真逻辑分析仪功能观察并分析了串口输出波形。通过对比预期时序和实际时序,确认了波特率设置的准确性。
综上所述,本次实验成功地实现了STM32系统与上位机的串口通信,并验证了基于字符的发送控制功能。