STM32串口通信USART练习

本文详细介绍STM32的USART串口通信实践,包括设置115200波特率、无校验位和1位停止位的配置,通过中断实现数据接收与发送控制,以及如何与上位机交互。通过实例演示,学习了中断处理和串口调试技巧。

一、STM32的USART介绍

通用同步异步收发器(Universal Synchronous Asynchronous Receiver and Transmitter)是一个串行通信设备,可以灵活地与外部设备进行全双工数据交换。有别于 USART 还有一个UART(Universal Asynchronous Receiver and Transmitter),它是在 USART 基础上裁剪掉了同步通信功能,只有异步通信。简单区分同步和异步就是看通信时需不需要对外提供时钟输出,我们平时用的串口通信基本都是 UART。
USART 满足外部设备对工业标准 NRZ 异步串行数据格式的要求,并且使用了小数波特率发生器,可以提供多种波特率,使得它的应用更加广泛。USART 支持同步单向通信和半双工单线通信;还支持局域互连网络 LIN、智能卡(SmartCard)协议与 lrDA(红外线数据协会) SIR ENDEC 规范。
USART 在 STM32 应用最多莫过于“打印”程序信息,一般在硬件设计时都会预留一个USART通信接口连接电脑,用于在调试程序是可以把一些调试信息“打印”在电脑端的串口调试助手工具上,从而了解程序运行是否正确、如果出错哪具体哪里出错等等。

二、USART串口通信实践

1、任务要求

(1)设置波特率为115200,1位停止位,无校验位。

(2)STM32系统给上位机(win10)连续发送“hello windows!”,上位机接收程序可以使用“串口调试助手“,也可自己编程。

(3)当上位机给stm32发送“Stop,stm32”后,stm32停止发送。

2、所用器材

① STM32最小核心板(STM32F103C8T6)

②USB转TTL(ch340芯片)

③ IDE:KEIL5 MDK

④ 实验所用串口:USART1

3、主要代码

  • 主函数main.c
#include "delay.h"
#include "usart.h"
#include "string.h"

u8 Res[50];

int main(void)
 {
	u8 flag=1;
	u8 len;
	u8 i;
	u16 times=0; 
	delay_init();	    	 //延时函数初始化	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
	uart_init(115200);	 //串口初始化为115200
	 
	 while(1)
	{
        if(USART_RX_STA&0x8000)
		{
			// 获取接收到的数据长度
			len = USART_RX_STA&0x3FFF;
			printf("你发送的消息为: \r\n");
			for(i=0; i<len;i++)
			{
				USART1->DR=Res[i];
				while((USART1->SR&0X40)==0);
			}
			printf("\r\n\r\n");					
			//判断是否接收到Stop,stm32
				if(Res[i-1] == '2')
		{
			if(Res[i-2] == '3'&&Res[i-3] == 'm'&&Res[i-4] == 't'&&Res[i-5] == 's'&&Res[i-6] == ',')
			if(Res[i-7] == 'p'&&Res[i-8] == 'o'&&Res[i-9] == 't'&&Res[i-10] == 'S')
			{
				flag=0;
				printf("\r\n\r\n停止发送\r\n\r\n");
			}
		}
		//判断是否接收到Start
				if (Res[i-1] == 't')
		{
			if(Res[i-2] == 'r'&&Res[i-3] == 'a'&&Res[i-4] == 't'&&Res[i-5] == 'S')
			{
				flag=1;
				printf("\r\n\r\n开始发送\r\n\r\n");
			}
		}	
			USART_RX_STA=0;
		}
			times++;
			if(times%100==0&&flag==1)
				printf("hello windows!\r\n");   
			delay_ms(10);
	}
}
  • 中断函数USART1_IRQHandler
void USART1_IRQHandler(void)               	//串口1中断服务程序
{
	u8 temp;
	if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
	{	 
		temp=USART_ReceiveData(USART1);	//读取接收到的数据
		
			if((USART_RX_STA & 0x8000)==0)
		{
			//接收到了0x0d
			if(USART_RX_STA & 0x4000)
			{
				// 接收错误,重新开始
				if(temp != 0x0a) 
					USART_RX_STA=0;
				// 接收完成
				else USART_RX_STA |= 0x8000;
			}
			// 还未接收到0x0d
			else
			{
				if(temp == 0x0d) USART_RX_STA |= 0x4000;
				else
				{
					Res[USART_RX_STA & 0x3FFF]=temp;
					USART_RX_STA++;
					//接收数据错误,重新开始接收
					if(USART_RX_STA > 49) 
						USART_RX_STA=0;
				}
			}
		}
	
  • 串口初始化函数
u16 USART_RX_STA=0;  
void uart_init(u32 bound)
{
  //GPIO端口设置
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
	USART_DeInit(USART1);        //复位串口 1
  
	//USART1_TX   GPIOA.9
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
   
  //USART1_RX	  GPIOA.10初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  

  //Usart1 NVIC 配置
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
  
   //USART 初始化设置

	USART_InitStructure.USART_BaudRate = bound;//串口波特率
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式

  USART_Init(USART1, &USART_InitStructure); //初始化串口1
  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
  USART_Cmd(USART1, ENABLE);                    //使能串口1 

}

4、代码解析

  • 总体流程
    在这里插入图片描述

  • 中断函数
    当接收中断发生时,我定义了一个用来存储接收数据的缓存数组,用来在主函数中判断是否接收到Stop,stm32或者Start,还定义了一个变量用来标记接收状态,判断接收是否完成,其中0~13位用来记录接收到的有效数据的个数,14位用来判断是否接收到回车,有则置为1,15位用来判断是否接收到换行,有则置为1,标志着接收完成。
    在这里插入图片描述

  • 主函数

先对串口、GPIO口、延时函数以及中断设置进行初始化,我还设置了一个标记变量,用来决定是否发送hello windows。函数开始时发送hello windows,然后等待中断。当上位机有数据发送到单片机时,执行中断函数,开始缓存数据,当接收完毕,接收完成标志位置为1,输出发送的数据,然后对发送的数据进行判断,若为“Stop,stm32",则将标记变量设为0,停止发送,若为”Start“,则将标记变量设为1,继续发送,其他字符将保持原来状态不变。

三、效果展示

  • 连接如图所示,分别连接PA9,PA10以及3.3V和GND引脚,且BOOT0置为1,BOOT1置为0。
    在这里插入图片描述
  • USB转TTL连接图,其中RX连接到PA9引脚,TX连接到PA10引脚 ,这是因为PA9引脚的复用模式是发送数据TX,而PA10是接收数据RX。一发一收才能建立起通信。
    在这里插入图片描述
  • 将程序烧录进STM32
    在这里插入图片描述
  • 打开串口调试助手设置好相关参数

注意安装好ch340的驱动,并且确保连线正确,不然识别不出端口号

在这里插入图片描述

  • 代码效果
    在这里插入图片描述

四、总结

这次实验让我了解了串口通信的相关内容,同时也搞清楚了中断函数的使用,这次实验大部分时间还是在调试代码上,主要是因为对相关的库函数不够了解。

五、参考资料

<think>好的,用户想要寻找与STM32相关的练习项目、示例代码和教程。首先,我需要回忆一下之前用户提供的引用内容,看看有没有相关的信息可以整合。引用1提到了使用STM32连接摄像头和OpenCV进行视觉导航和物体识别,这可能是一个中级项目。引用2和3分别涉及旋转编码器的使用和中断处理,这些都是比较基础的硬件接口应用。 接下来,我应该分类整理这些项目,从基础到高级,这样用户可以根据自己的水平选择合适的练习。基础部分可能包括GPIO控制、中断、定时器等,比如LED流水灯、按键中断、PWM调光。这些都是入门级的项目,适合新手熟悉STM32的基本操作。 然后是中阶项目,涉及外设模块的应用,比如引用2中的旋转编码器计次,以及串口通信、ADC读取传感器数据等。这些项目需要一定的硬件连接知识,并且能够结合具体的模块进行编程,帮助用户加深对STM32外设的理解。 高阶项目可能像引用1提到的视觉处理,或者物联网应用,需要集成更多的模块和复杂的算法。这些项目适合有一定经验的开发者,能够综合运用多种技术解决问题。 另外,用户可能需要示例代码和教程的指引。引用2和3中提到的中断配置和编码器处理,可以作为代码示例的参考。同时,应该推荐一些学习资源,比如官方文档、社区论坛和视频教程,帮助用户系统地学习。 还要考虑用户可能的后续问题,比如如何调试STM32程序,或者如何优化性能,但根据当前问题,先集中在项目推荐和资源提供上。需要确保回答结构清晰,分点列出,便于用户浏览。同时,按照系统指令,数学公式用$...$,但在这个问题中可能用不上,所以主要注意代码块和引用标注的正确使用。 最后,生成的相关问题需要围绕STM32的学习路径、常见模块、代码调试和实战应用展开,这样用户如果有进一步的需求,可以继续提问。确保每个引用都正确对应到项目或知识点,比如引用1对应视觉项目,引用2对应编码器项目,引用3对应中断配置。</think>### STM32练习项目与示例代码指南 #### 一、基础项目(硬件接口与基础外设) 1. **GPIO控制LED流水灯** 使用STM32的GPIO模块实现LED流水灯效果,结合定时器中断控制闪烁频率。 ```c // 示例:配置GPIO为推挽输出模式(以STM32F4为例) GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); ``` 2. **按键中断控制** 通过外部中断实现按键触发事件,例如按下按键切换LED状态[^3]。 ```c // 配置按键引脚为外部中断模式 GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; // 上升沿触发 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI0_IRQn); ``` 3. **旋转编码器计次** 使用外部中断和定时器捕获编码器信号,测量旋转方向和速度(参考引用[^2]的代码逻辑)。 --- #### 二、中阶项目(外设模块应用) 1. **串口通信与传感器数据采集** 通过UART连接温湿度传感器(如DHT11),实现数据采集与上位机显示。 ```c // 示例:串口接收中断处理 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart->Instance == USART1) { // 处理接收到的传感器数据 } } ``` 2. **PWM控制电机调速** 利用定时器输出PWM信号控制直流电机转速,结合PID算法实现闭环控制。 ```c // 配置TIM3通道1为PWM输出 TIM_OC_InitTypeDef sConfigOC; sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 500; // 占空比50%(假设ARR=1000) HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); ``` 3. **多摄像头视觉处理(参考引用[^1])** 使用STM32与OpenMV模块实现简单物体识别,通过串口发送坐标数据。 --- #### 三、高阶项目(综合系统设计) 1. **智能家居控制中心** 集成Wi-Fi模块(如ESP8266)、温湿度传感器和继电器,实现远程控制家电。 2. **机器人视觉导航** 结合STM32与OpenCV边缘计算模块,实现SLAM(同步定位与地图构建)[^1]。 3. **CAN总线通信系统** 搭建多节点CAN网络,实现工业设备间的实时数据交互。 --- #### 四、学习资源推荐 1. **官方文档与工具** - [STM32CubeMX](https://www.st.com/):自动生成初始化代码 - [HAL库手册](https://www.st.com/resource/en/user_manual/dm00105879.pdf) 2. **社区与教程** - 开源平台:GitHub搜索“STM32 Project” - 视频教程:B站“江科大自动化”STM32系列[^2] 3. **书籍推荐** - 《STM32库开发实战指南》 - 《嵌入式实时操作系统μC/OS-II原理与应用》 ---
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值