一款产品里用到粉尘检测,最后在淘宝上找一到了一款,攀藤型号是:PMS9003 还有一款外形类似型号是DSL-08。看了资料是可以通用的。
传感器的产品资料放在百度网盘里
链接:https://pan.baidu.com/s/1oNCwO7n9oEdzju91cF99xg?pwd=1234
提取码:1234
芯片:STM32F103C8T6
粉尘传感器:DSL-08
通电后,粉尘传感器是一直发送32个字节的数据过来,所以我们只要解析出这个数据,对应PDF文档资料换算就可以了。在使用过程中发现单片机对DSL-08传感器发送各种命令都无效。
过程如下:
一、设置串口3为接收端,利用USART3的DMA空闲不定长收发。
新建两个文档:PMS.C PMS.H
PMS.C文档
/*
PM2.5驱动文件
型号:DSL-08
日期:2023.9.18
*/
#include "string.h"
#include "stdio.h"
#include "usart.h"
#include "PMS/PMS.H"
用户自定义变量//
struct PM_Data PM; //定义一个PM的结构体变量
uint8_t TX3CMD[9]={0XAA,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XBB}; //发送命令包
uint8_t RX3Buffer[BufferSize]={0}; //串口接收缓存
uint8_t RX3Len = 0; //串口接收数据长度
/*****************************************************************
* 名 称: SendCMD()
* 功 能: 串口3发送1个字节
* 入口参数: t 发送的字节
* 出口参数: 无
*****************************************************************/
void SendCMD(uint8_t t)
{
HAL_UART_Transmit(&huart3, &t, 1, 0xffff);
}
/*****************************************************************
* 名 称: WriteCMD
* 功 能: 发送控制命令
* 入口参数: 根据资料,发送相应命令
* 出口参数: 无
* 说明:将命令写入后,生成校验和,DMA发送
* PM2.5模块默认是一直发送数据的,可以不必操作命令也能使用。
根据资料测试命令无效,不受控制。
*****************************************************************/
void WriteCMD(uint8_t Command)
{
uint16_t CRCTemp = 0;
CRCTemp=TX3CMD[0]+Command+(uint8_t)TX3CMD[8]; //生成校验和
TX3CMD[6]= CRCTemp>>8;
TX3CMD[7]= CRCTemp; //第6 7位为校验和位,将数据拆分
HAL_UART_Transmit_DMA(&huart3, TX3CMD,sizeof(TX3CMD)); //DMA发送
//验证
// for(uint8_t i=0;i<9;i++)
// {
// printf("%d :%0X ",i,TX3CMD[i]);
// }
// printf("\r\n");
}
/*****************************************************************
* 名 称:
* 功 能: 将数据显示出来
* 入口参数:
* 出口参数: 无
*****************************************************************/
void PrintfData(void)
{
if(RX3Len==32)
{
printf("长度:%d\r\n",RX3Len);
for(uint8_t i=0;i<RX3Len;i++)
{
// printf("RX3Buffer[%d]=%0X\r\n",i,RX3Buffer[i]);
printf("%d: %0X ",i+1,RX3Buffer[i]);
}
//清0,进行下一轮读取
// for(uint8_t i=0;i<RX3Len;i++)
// {
// RX3Buffer[i]=0; //缓存数据清0
// }
// RX3Len=0; //退出前清0
}
}
/*****************************************************************
* 名 称: GetPMData
* 功 能: 将接收到的数据转换
* 入口参数: 无
* 出口参数: 无
* 说明:
*
*****************************************************************/
void GetPMData(void)
{
if(RX3Buffer[0]!=0X42&&RX3Buffer[1]!=0X4D)
{
RX3Len=0;
}
else if(RX3Len>31)
{
uint16_t H_valueTemp;
H_valueTemp=0;
PM.PM1 = ((H_valueTemp|RX3Buffer[4]) << 8) | RX3Buffer[5]; //PM1.0浓度
H_valueTemp=0;
PM.PM2 = ((H_valueTemp|RX3Buffer[6]) << 8) | RX3Buffer[7]; //PM2.5浓度
H_valueTemp=0;
PM.PM10 = ((H_valueTemp|RX3Buffer[8]) << 8) | RX3Buffer[9]; //PM10浓度
//0.1升空气中的颗粒物数量
H_valueTemp=0;
PM.Dust_03um = ((H_valueTemp|RX3Buffer[16]) << 8) | RX3Buffer[17]; //0.3um
H_valueTemp=0;
PM.Dust_05um = ((H_valueTemp|RX3Buffer[18]) << 8) | RX3Buffer[19]; //0.5um
H_valueTemp=0;
PM.Dust_1um = ((H_valueTemp|RX3Buffer[20]) << 8) | RX3Buffer[21]; //1um
H_valueTemp=0;
PM.Dust_2um = ((H_valueTemp|RX3Buffer[22]) << 8) | RX3Buffer[23]; //2.5um
H_valueTemp=0;
PM.Dust_5um = ((H_valueTemp|RX3Buffer[24]) << 8) | RX3Buffer[25]; //5um
H_valueTemp=0;
PM.Dust_10um = ((H_valueTemp|RX3Buffer[26]) << 8) | RX3Buffer[27]; //10um
// printf("\r\nPM浓度:\r\n");
// printf("PM1.0=%dug/m3 ",PM.PM1);
// printf("PM2.5=%dug/m3 ",PM.PM2);
// printf("PM10=%dug/m3 ",PM.PM10);
// printf("\r\n0.1升空气中的颗粒物:\r\n");
// printf("0.3um=%d个 0.5um=%d个 1.0um=%d个 2.5um=%d个 5um=%d个 10um=%d个\r\n",PM.Dust_03um,PM.Dust_05um,PM.Dust_1um,PM.Dust_2um,PM.Dust_5um,PM.Dust_10um);
}
}
PMS.H
/*!
* \file hmi_driver.h
* \brief DS-08 PM2.5激光传感器
* \version 1.0
* \date 2023.9.18
* \copyright 攀藤科技,小米专用
*/
#ifndef _PMS_
#define _PMS_
#include "main.h"
#define BufferSize 64 //缓存宽度最小64
//#define CMD_HEAD 0XAA //帧头
//#define CMD_TAIL 0XBB //帧尾
//#define SEND_DATA(P) SendCMD(P) //发送一个字节
//#define BEGIN_CMD() TX_8(0XAA) //帧头
//#define END_CMD() TX_8(0XBB) //帧尾
//PM2.5相关函数
//数据结构体
struct PM_Data{
uint16_t PM1; //标准下PM1.0浓度
uint16_t PM2; //标准下PM2.5浓度
uint16_t PM10; //标准下PM10浓度
uint16_t Dust_03um; //0.1升空气中0.3um颗粒个数
uint16_t Dust_05um; //0.1升空气中0.5um颗粒个数
uint16_t Dust_1um; //0.1升空气中1um颗粒个数
uint16_t Dust_2um; //0.1升空气中2.5um颗粒个数
uint16_t Dust_5um; //0.1升空气中5um颗粒个数
uint16_t Dust_10um; //0.1升空气中10um颗粒个数
uint16_t CheckCRC;
};
extern struct PM_Data PM; //定义一个PM的结构体变量
extern uint8_t RX3Buffer[BufferSize]; //串口接收缓存
extern uint8_t RX3Len; //串口接收数据长度
/函数/
void SendCMD(uint8_t t);
void InitDustSensor(void);
//void ReadDustSensor(void);
void AutoRun(void);
void WriteCMD(uint8_t Command);
void PrintfData(void);
void GetPMData(void);
#endif
在main.c中加入头文件
//激光粉尘传感器
#include "PMS/PMS.H"
初始化中加入,开启不定长接收
///PM2.5传感器/
//外设:USART3//
HAL_UARTEx_ReceiveToIdle_DMA(&huart3,RX3Buffer,BufferSize); //开启空闲中断并调用DMA,数据存入RXBuffer
// HAL_UART_Receive_DMA(&huart2,RXBuffer,BUFFER_SIZE);//开启一次接收
__HAL_UART_ENABLE_IT(&huart3, UART_IT_ERR);//使能串口错误中断
加入中断回调函数
/**
* 函数功能: 串口空闲中断DMA回调函数
* 输入参数: huart为串口号,Size为空闲接收数据位数
* 返 回 值: 无
* 说 明:STM32CubeMX中 RX的DMA Mode设置成
*/
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart->Instance == USART3)
{
// printf("进入空闲中断,串口3\r\n");
HAL_UART_AbortReceive(&huart3); //该函数有两个功能,先关闭DMA接收,但DMA能发送,置位RX Ready状态,忽略了错误标志和IT标志处理,比HAL_UART_DMAStop好
RX3Len=Size;
HAL_UARTEx_ReceiveToIdle_DMA(&huart3, RX3Buffer, BufferSize);//开启DMA空闲接收,将接收的数据存入RX3Buffer,数据长度 BufferSize
}
}
while循环中只要调用GetPMData()函数就可以了,记得加个延时,不然可能会卡死