栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

STM32 HAL库 串口DMA接收不定长数据

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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)
		{
			
			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;
}

 

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/744480.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号