IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32 HAL库 串口DMA接收不定长数据 -> 正文阅读

[嵌入式]STM32 HAL库 串口DMA接收不定长数据

上一期配置https://blog.csdn.net/zy19981110/article/details/123005092?spm=1001.2014.3001.5501

参考他人的代码https://blog.csdn.net/euxnijuoh/article/details/81638676?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-0.pc_relevant_default&spm=1001.2101.3001.4242.1&utm_relevant_index=3?DMA为默认设置,普通模式。

单独创建.c和.h文件,以便查看整理

#ifndef __USARTDMA_H
#define __USARTDMA_H

#include "usart.h"
#include "dma.h"
#include "stm32g0xx_hal.h"
#include "string.h"

/*实际需要接收的长度*/
#define UART1_RX_MH440D_SIZE 9

/*缓存长度*/
#define USART_BUFFER_SIZE  128

struct _UsartDMA_Rx
{
	 struct 
	 {
			volatile uint8_t Len;        //DMA中接收一帧数据的长度
			volatile uint8_t Flag;       //数据接收完成标志  
			uint8_t Buffer[128];  			 //接收数据缓存
	 }U1;   //串口1                                                            

	 struct 
	 {
	 		volatile uint8_t Len;        //DMA中接收一帧数据的长度
			volatile uint8_t Flag;       //数据接收完成标志  
			uint8_t Buffer[128];  			 //接收数据缓存
	 }U2;	  //串口2
};

extern struct _UsartDMA_Rx UsartDMA_Rx;


void UsartIDLE_Init(void);
void USART1_IDLE(void);

#endif

可以自行增加多个串口 ,在主函数前调用

#include "UsartDMA.h"

struct _UsartDMA_Rx UsartDMA_Rx;

void UsartIDLE_Init()
{
 __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE); 
  HAL_UART_Receive_IT(&huart1,UsartDMA_Rx.U1.Buffer,USART_BUFFER_SIZE);
	__HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE); 
  HAL_UART_Receive_IT(&huart2,UsartDMA_Rx.U2.Buffer,USART_BUFFER_SIZE);
}

?这个代码放到it.c中对应的串口中断服务函数中,注意放到用户代码区域,防止代码被cubemx生成后清空。

?

void USART1_IDLE(void)    //串口中断
{
    uint32_t tmp_flag = 0;
    uint32_t temp;
    
    if(USART1 == huart1.Instance){
        tmp_flag =__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE); //获取IDLE标志位
            
        if((tmp_flag != RESET))				//idle标志被置位
        { 
            UsartDMA_Rx.U1.Flag = 1;  // 接受完成标志位置1 
            __HAL_UART_CLEAR_IDLEFLAG(&huart1);//清除标志位               

             HAL_UART_DMAStop(&huart1); //     
            temp  =  __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);	// 获取DMA中未传输的数据个数                     
            UsartDMA_Rx.U1.Len =  USART_BUFFER_SIZE - temp; 	//总计数减去未传输的数据个数,得到已经接收的数据个数
               
            HAL_UART_Receive_DMA(&huart1,UsartDMA_Rx.U1.Buffer,USART_BUFFER_SIZE);//重新打开DMA接收
        }
    }
 }

忘了说要在usart.h文件中进行外部声明,不然会找不到定义。?

实际应用,直接发完就读,测试传感器时没写太多功能函数

/*和校验*/
uint8_t GetCheckSum(uint8_t *packet,uint8_t start,uint8_t end)
{
	uint8_t i, checksum;
	for( i = start; i < (end-1); i++)
	{
	checksum += packet[i];
	}
	checksum = 0xff-checksum +1;
	return checksum;
}

void MH440D_SendCom(_MH440D* MH440D)
{
	uint8_t i;
	uint8_t Sendbuff[9]={0xff,MH440D->CH4_N,MH440D->CH4_Com,0,0,0,0,0,0};

	MH440D->CheckSum=GetCheckSum(Sendbuff,1,8);
	Sendbuff[8]=MH440D->CheckSum;
	memcpy(MH440D->SendBuff,Sendbuff,9);    //复制数组
	
	HAL_UART_Transmit_DMA(&huart1,MH440D->SendBuff ,9);    //发送一次
}

FlagStatus MH440D_Read(_MH440D* MH440D)
{
	 if(UsartDMA_Rx.U1.Flag==1)
	 {
			UsartDMA_Rx.U1.Len  = 0;//清除计数
			UsartDMA_Rx.U1.Flag = 0;//清除接收结束标志位
		 
		 /*取出缓存数组*/
			memcpy(MH440D->RecBuff,UsartDMA_Rx.U1.Buffer,UART1_RX_MH440D_SIZE);
	
			if( MH440D->RecBuff[0]==0XFF  && MH440D->RecBuff[1] ==0x86)    //判断设备首地址和命令
			{
				
				 MH440D->CheckSum =GetCheckSum(MH440D->RecBuff,1,8);   
				 if(MH440D->RecBuff[8]==MH440D->CheckSum)
				 {
					 
					  MH440D->CH4_H=MH440D->RecBuff[2];       //读出传感器数据
					  MH440D->CH4_L=MH440D->RecBuff[3];
					  memset(UsartDMA_Rx.U1.Buffer,0,sizeof(UsartDMA_Rx.U1.Buffer)); //清空数组
						return 1;	
				 }
				 
				 else
						return  0;
				
			}
			else
				return 0;
		}
	 else
		 return 0;
}
FlagStatus SF6_ReadData(uint8_t ID)
{
		 if(UsartDMA_Rx.U2.Flag==1)
	 {
			UsartDMA_Rx.U2.Len  = 0;//清除计数
			UsartDMA_Rx.U2.Flag = 0;//清除接收结束标志位
		 
		 /*取出缓存数组*/
			memcpy(SF6.RecBuff,UsartDMA_Rx.U2.Buffer,7);
	 }
	 else 
		 return 0;
	
		if(SF6.RecBuff[0]==ID)
		{
			/*确认传感器地址后进行CRC校验*/
			SF6.CRC_Val=CRC16(SF6.RecBuff,5,&SF6.Recv_CRC_L,&SF6.Recv_CRC_H); 
			
			if(SF6.RecBuff[5]==SF6.Recv_CRC_L && SF6.RecBuff[6]==SF6.Recv_CRC_H)
			{
				/*读气体值*/
				if(SF6.RecBuff[1]==SF6_ReadGas && SF6.RecBuff[2]==0x02)
				{
					SF6.PPM_L=SF6.RecBuff[4];
					SF6.PPM_H=SF6.RecBuff[3];
					return 1;
				}
				else 
						;
				
			}
			else
				return 0;
			
		}
		else 
			return 0;
}

?

?

?

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-02-26 11:46:32  更:2022-02-26 11:48:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:45:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码