上一期配置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;
}
?
?
?
|