STM32—串口

news/2024/6/3 19:30:10 标签: stm32, 单片机, 嵌入式硬件

串口介绍

串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串行接口(Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢是设备间接线通信的一种方式数据一位一位地顺序传送双向通信,全双工传送速度相对较慢
UART是异步串行接口,通信双方使用时钟不同,因为双方硬件配置不同,但是需要约定通信 速度,叫做波特率。对于单片机和pc之间通信,pc端用软件配置,则单片机需要用代码完成配置,也可以用波特率配置软件直接生成
在这里插入图片描述

常用函数的介绍

串口发送/接收函数:

 - HAL_UART_Transmit();//串口发送数据,使用超时管理机制
 - HAL_UART_Receiver();//串口接收数据,使用超时管理机制
 - 
 - HAL_UART_Transmit_IT();//串口中断模式发送
 - HAL_UART_Receive_IT();//串口中断模式接收
 作用:以中断的方式接收指定字节的数据
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数1:UART_HandleTypeDef 结构体类型指针变量
参数2:指向要发送的数据地址
参数3:要发送的数据大小,以字节为单位
参数4:设置的超时时间,ms为单位
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
参数1:UART_HandleTypeDef 结构体类型指针变量
参数2:指向接收数据缓存区
参数3:要接收的数据大小,以字节为单位
参数4:设置的超时时间,ms为单位

串口中断回调函数

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)//串口中断处理函数
__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)//发送中断回调函数
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)//接受中断回调函数

状态标志变量
USART_RX_STA
从0开始,串口中断接收到一个数据(一个字节)就自增1。当数据读取全部OK的时候(回车和换行符来的时候),那么USART_RX_STA的最高位置置1,表示串口数据接收全部完毕了。然后main函数里面可以处理数据了。
在这里插入图片描述

串口接收中断流程
在这里插入图片描述

串口实验(非中断)

需求:接收串口工具发送的字符串,并且将其发送回串口工具
TX——PA10 RX——PA9(交叉接线)
使用CubeMX配置工程,串口配置
1.选定串口
2.选择模式
异步通信
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
效果:在这里插入图片描述

如何使用printf打印数据到串口调试助手
1.重写fputc函数

int fputc(int ch,FILE *f)
{
	unsigned char temp[1] = {ch};
	HAL_UART_Transmit(&huart1,temp,1,0xffff);
	return ch;

2.添加#include stdio.h头文件,使用MicroLIB库
在这里插入图片描述

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		//HAL_UART_Transmit(&huart1,"hello\n",strlen("hello\n"),100);
		HAL_UART_Receive(&huart1,buff,19,100);
	//	HAL_UART_Transmit(&huart1,buff,strlen(buff),100);
	//	printf("hello wrold\n");
		printf(buff);//打印到串口调试助手
		memset(buff,0,20);//清空buff
  }
  /* USER CODE END 3 */

串口实验(中断)

需求:通过中断的方法接收串口工具发送的字符串,并将其发送回串口工具
串口配置
1.选定串口
2.选择模式
异步通信
前面步骤与上面一样
打开串口中断
在这里插入图片描述
根据中断接收流程可知,最后会在UART_Receive_IT函数中调用HAL_UART_RxCpltCallback函数,该函数为一个虚函数,我们可以在main.c中重写,接收到一个数据,就在函数中处理
在这里插入图片描述

在这里插入图片描述

//定义最大接收字节数200
#define USART_REC_LEN 200
 

//接收缓冲,串口接收到的数据放到这个数组里面,最大USART_REC_LEN字节
uint8_t UART1_RX_Buffer[USART_REC_LEN];
uint8_t buf = 0;
uint16_t USART_RX_STA = 0;

//接收完成回调函数,收到一个数据后,在这里处理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	//1.判断中断是由哪个串口触发
	if(huart->Instance == USART1){
		//判断接收是否完成(USART_RX_STA的bit15位置为1)
		if((USART_RX_STA & 0x8000) == 0){//等于0则表示没有接收完成
			//如果收到了0x0d(回车),看bit14是否为1
			if(USART_RX_STA & 0x4000){
					//则继续判断是否收到0x0a(换行)
					if(buf == 0x0a){
						//如果0x0a和0x0d都收到,则将bit15位置置1
						USART_RX_STA |= 0x8000;
					}else {
						//否则认为接收错误,USART_RX_STA置0
						USART_RX_STA = 0;
						
					}
			}else {  //如果没有收到0x0d回车
				//先判断这个字符是否是0x0d回车
				if(buf == 0x0d){
					//是的话就将bit14置1
					USART_RX_STA |= 0x4000;
				}else {
					//不是的话,就将接收到的数据保存到缓存数组里面去
					UART1_RX_Buffer[USART_RX_STA & 0x3FFF] = buf;
					USART_RX_STA++;
					
					//如果接收数据大于USART_REC_LEN(200字节),则重新开始接收
					if(USART_RX_STA > USART_REC_LEN - 1 ){
						USART_RX_STA = 0;
						
					}
				}
				
			}
			
		}
		//重新开启中断
		HAL_UART_Receive_IT(&huart1,&buf,1);
	}
	

}

参考博文:http://t.csdn.cn/q4IPk
解释:从串口接收到的数据只有一个字节的,也就是串口是一个字节一个字节进行判断的,每次buf里面都是最新的字节,所以我们要读到一条完整的或者指定的数据长度,我们就要用UART1_RX_Buffer来存储,而USART_RX_STA就是辅助判断数据状态的。
在这里插入图片描述
两个表对应看,想要知道触发串口中断后,串口是否接收完成所有数据(0代表没有接收完成,1代表完成。)

UART1_RX_Buffer是专门存放数据的,串口接收到一个字节的数据,USART_RX_STA就会累加,UART1_RX_Buffer[USART_RX_STA]=buf就可以按顺序保存数据,但是bit15和bit14位指定进行两个判断功能,就不能拿来使用保存数据,所以我们这里&0X3FFF来截断数据。

//不是的话,就将接收到的数据保存到缓存数组里面去
UART1_RX_Buffer[USART_RX_STA & 0x3FFF] = buf;
USART_RX_STA++;				
//如果接收数据大于USART_REC_LEN(200字节),则重新开始接收
if(USART_RX_STA > USART_REC_LEN - 1 ){
		USART_RX_STA = 0;						
	}

main函数

int main(void)
{
  /* USER CODE BEGIN 1 */
	// unsigned char buff[20] = {0};
	
  /* 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 */

	HAL_UART_Receive_IT(&huart1,&buf,1);


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {	
		//判断串口是否接收完成
		if(USART_RX_STA & 0x8000){
				printf("收到数据:");
			//将收到的数据发送到串口
			HAL_UART_Transmit(&huart1,UART1_RX_Buffer,USART_RX_STA & 0x3FFF,0xffff);
			//等待发送完成
			while(huart1.gState != HAL_UART_STATE_READY);
			
			printf("\r\n");
			//重新开始下一次接收
			USART_RX_STA = 0;
		}
		printf("hello world\n");
		HAL_Delay(1000);
  }
  /* USER CODE END 3 */
}


http://www.niftyadmin.cn/n/31236.html

相关文章

esp32 烧录协议

esp32的rom固化了出场固件。进入烧录模式后,esp32串口输出:给esp32烧录固件的时候,需要和rom的bootloder进行通讯。通讯时,使用 SLIP 数据包帧进行双向数据传输。每个 SLIP 数据包都以 0xC0 开始和结束。 在数据包中,所…

Java 以数据流的形式发送数据request Java 数据封装到request中

Java 以数据流的形式发送数据request Java 数据封装到request中 一、描述 1、在做微信支付结果通知的时候,看到一个描述:微信会把相关支付结果及用户信息通过数据流的形式发送给商户 ,那么java如何通过数据流的形式发送数据呢? 二…

28.设计模式(工厂、装饰)详解

目录 一.工厂设计模式 1.1 工厂设计模式的作用 1.2 案例 二.装饰设计模式 2.1 装饰设计模式的作用 2.2 步骤 2.3 案例 一.工厂设计模式 1.1 工厂设计模式的作用 1.对象通过工厂的方法创建返回,工厂的方法可以为该对象进行加工和数据注入。2.可以实现类与类之…

「随笔」什么是AI技术

文章目录前言一、什么是AI技术二、AI技术是如何实现的2.1 知识图谱2.2 问答系统2.3 AI芯片三、AI在不同领域的发展趋势3.1 硅光芯片3.2 个性化推荐前言 本文主要介绍什么是AI技术。 一、什么是AI技术 人工智能(Artificial Intelligence),英…

[VCS]Coverage Options Introduction

Coverage Options Introduction摘要:VCS仿真中,可以产生以下两类coverage:code coverage和function coverage,对于code coverage,在编译和仿真需要加额外参数。对于function coverage,编译和仿真不需要加额…

解决Vue启动失败报错:Module not found: Error: Can‘t resolve ‘less-loader‘

问题描述 今天想在网上找一个好看的登录页面,把别人的代码引入进来之后,发现项目编译不了,并且报错了: Module not found: Error: Can’t resolve ‘less-loader’ 分析问题 从错误的日志就可以看出来,是缺少了less-…

uniapp项目

目录 一、HBuilder创建项目 二、引入uView 2.1 npm方式安装 2.2 下载方式安装 三、小程序的分包 三、App.vue中的生命周期 四、工具封装 五、api接口请求封装 六、store 七、加载顺序 八、flex的使用 一、HBuilder创建项目 文件--新建--项目--默认模板--Vue2--创建 …

九龙证券|石墨烯电池和锂离子电池哪个好

电池技术是电动汽车大力推广和开展的最大门槛,而电池工业正处于铅酸电池和传统锂电池开展均遇瓶颈的阶段,石墨烯储能设备的研制成功后,若能批量生产,则将为电池工业乃至电动车工业带来新的改造。那么石墨烯电池和锂离子电池哪个更…