目录
一、介绍
D01粉尘传感器利用光学照射的原理,通过光路与电路的转换,测量出检测范围内的灰尘浓度,可灵敏检测直径为1μm以上灰尘颗粒物,直接应用单片机进行UART 通信。产品体积小、精度高、功耗低、测量范围宽、响应时间短、应用方便快捷。

以下是D01粉尘传感器的参数:
|------|--------------|
| 型号 | D01 |
| 工作电压 | 5V±5% |
| 工作电流 | 15mA |
| 检测种类 | PM0.3~PM10 |
| 工作温度 | -25~75℃ |
| 输出方式 | UART |
| 物理接口 | ZH1.5mm-4P插座 |
哔哩哔哩视频链接:
D01粉尘传感器(STM32)
(资料分享见文末)
二、传感器原理
1.原理图



2.引脚描述

三、程序设计
1.使用STM32F103C8T6读取DC01粉尘传感器采集的PM2.5数据,通过串口发送至电脑
2.将读取得到信息数据同时在OLED上显示
|----------|------|
| D01_TX | PB11 |
| D01_RX | PB10 |
| OLED_SCL | PB6 |
| OLED_SDA | PB7 |
| 串口 | 串口1 |
main.c文件
cpp
#include "stm32f10x.h"
#include "led.h"
#include "usart.h"
#include "delay.h"
#include "oled.h"
#include "usart3.h"
/*****************辰哥单片机设计******************
STM32
* 项目 : D01粉尘传感器实验
* 版本 : V1.0
* 日期 : 2025.7.28
* MCU : STM32F103C8T6
* 接口 : 参看usart3.h
* BILIBILI : 辰哥单片机设计
* CSDN : 辰哥单片机设计
* 作者 : 辰哥
**********************BEGIN***********************/
int value;
u8 buff[30];
int PM25_Value = 0;
int main(void)
{
SystemInit();//配置系统时钟为72M
delay_init(72);
LED_Init();
LED_On();
USART1_Config();
USART3_Config();
OLED_Init();
printf("Start \n");
delay_ms(1000);
//显示"粉尘浓度:"
OLED_ShowChinese(0,0,0,16,1);
OLED_ShowChinese(16,0,1,16,1);
OLED_ShowChinese(32,0,2,16,1);
OLED_ShowChinese(48,0,3,16,1);
OLED_ShowChar(64,0,':',16,1);
while (1)
{
LED_Toggle();
Get_PM2_5(); //读取PM2.5
if(PM25_Value>999)PM25_Value=999;
sprintf((char*)buff,"%dug/m3 ",PM25_Value);
//
printf("粉尘浓度: %dug/m3\r\n",PM25_Value);
OLED_ShowString(40,30,buff,16,1);
delay_ms(500);
}
}
usart3.c文件
cpp
#include "usart3.h"
#include <stdbool.h>
/*****************辰哥单片机设计******************
STM32
* 项目 : D01粉尘传感器实验
* 版本 : V1.0
* 日期 : 2025.7.28
* MCU : STM32F103C8T6
* 接口 : 串口3
* BILIBILI : 辰哥单片机设计
* CSDN : 辰哥单片机设计
* 作者 : 辰哥
**********************BEGIN***********************/
unsigned char Usart3RecBuf[USART3_RXBUFF_SIZE];//串口2接收数据缓存
unsigned int Rx3Counter = 0; //串口2收到数据标志位
bool rev_start = 0; //接收开始标志
bool rev_stop = 0; //接收停止标志
u8 pmBuf[5]; //pm2.5数据缓存数组
#define RATIO 1.0 //校准系数,选择范围0.1~1.0 (传感器一般不需要校准,选择1.0即可)
void USART3_Config(void){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //使能USART3,GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能GPIOB时钟
//USART3_TX GPIOB.10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.10
//USART3_RX GPIOB.11初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOB.11
//Usart3 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 4; //子优先级4
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//USART 初始化设置
USART_InitStructure.USART_BaudRate = 9600;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART3, &USART_InitStructure); //初始化串口3
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启串口接受中断
USART_Cmd(USART3, ENABLE); //使能串口3
}
void USART3_IRQHandler(void) //串口3中断服务程序
{
uint8_t Res;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
{
Res = USART_ReceiveData(USART3);//接收模块的数据
if ((Res == 0XA5)&&(rev_stop==0)) //如果收到0xA5,便开始接收
{
rev_start = 1;
}
if (rev_start == 1) //标志位为1,开始接收
{
Usart3RecBuf[Rx3Counter] = Res; //字符存到数组中
Rx3Counter ++;
if (Rx3Counter >= 4) //一帧数据接收完成
{
rev_start = 0;
rev_stop = 1;
Rx3Counter = 0;
}
}
}
if(USART_GetFlagStatus(USART3,USART_FLAG_ORE) == SET)
{
USART_ClearFlag(USART3,USART_FLAG_ORE);
}
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
}
void Get_PM2_5(void) //获取PM2.5值
{
char i = 0;
Rx3Counter = 0;
if(rev_stop == 1) //串口数据接收完成
{
for(i = 0; i < 4; i++)
{
pmBuf[i] = Usart3RecBuf[i];
}
/* 校验数据是否接收正确,校验方法:判断前面3个字节累加和取低7位是否和最后第4个字节相等 */
if(((pmBuf[0]+pmBuf[1]+pmBuf[2])&0x7F) == pmBuf[3])
{
PM25_Value = (unsigned int)((pmBuf[1]*128) + pmBuf[2]) * RATIO; //计算PM2.5(ug/m3) = (pmBuf[1]*128) + pmBuf[2] ;
}
rev_stop = 0;
}
}
usart3.h文件
cpp
#ifndef __USART3_H
#define __USART3_H
#include "stm32f10x.h" // Device header
#include "oled.h"
#include "usart.h"
/*****************辰哥单片机设计******************
STM32
* 项目 : D01粉尘传感器实验
* 版本 : V1.0
* 日期 : 2025.7.28
* MCU : STM32F103C8T6
* 接口 : 参串口3
* BILIBILI : 辰哥单片机设计
* CSDN : 辰哥单片机设计
* 作者 : 辰哥
**********************BEGIN***********************/
#define USART3_RXBUFF_SIZE 54
void USART3_Config(void);
uint8_t Usart3_GetRxFlag(void);
void Get_PM2_5(void);
extern int PM25_Value;
#endif
四、实验效果
