本帖最后由 聪聪哥哥 于 2025-8-31 10:13 编辑
前言:
设计的智能环境监测系统适用场景有:家庭环境安全监测,实验室环境安全监测、大棚内的环境监测、医院,学校的环境监测;
空气质量的监测:如学校,医院等等,当空气内的PM2.5超过一定值后,PMS5003T颗粒物传感器精度高,可以及时的对空气中的颗粒物进行监测,提醒人们注意安全,做好自身的防护。
空气中温湿度的监测;例如大棚,植物的生长需要合适的环境,PMS5003T颗粒物传感器不仅仅可以监测PM数据,对温湿度也有极其精度高的监测,当棚内温湿度低于植物生长所需要的环境,可以及时的做出报警,及时提醒人们去控制大棚内的温湿度。
一:所使用的模块介绍:
1.1 模块的基本参数
PMS5003T是一款可以同时监测空气中颗粒物浓度及温湿度的二合一传感器。其中颗粒物浓度的监测基于激光散射原理,可连续采集并计算单位体积内空气中不同粒径的悬浮颗粒物个数,即颗粒物浓度分布,进而换算成为质量浓度。传感器同时内嵌瑞士生产的温湿度一体检测芯片。颗粒物浓度数值及温度、湿度合并以通用数字接口形式输出。本传感器可嵌入各种与空气质量监测和改善相关的仪器设备,为其提供及时准确的环境参数。
工作原理
1.2 模块的工作原理:
本传感器采用激光散射原理。即令激光照射在空气中的悬浮颗粒物上产生散射同时在某一特定角度收集散射光,得到散射光强随时间变化的曲线。进而微处理器利用基于米氏(MIE)理论的算法,得出颗粒物的等效粒径及单位体积内不同粒径的颗粒物数量。传感器各功能部分框图如图下所示
1.3 模块的通讯方式:
PMS5003T 主动式传输协议
默认波特率: 9600bps 校验位:无 停止位:1位 协议总长度:32字节
1.4 模块的安装:
1.金属外壳与内部电源地导通,注意不要和其他外部板组电路或机箱外壳短接。
2.进风口和出风口所在的平面紧贴用户机内壁与外界连通的气孔为最佳安装方式,如无法实现,则出风口周围 2cm 之内无遮挡。进风口和出风口之间应有结构使气流隔离,避免气流在用户机内部从出风口直接回流到进风口。
3.用户机内壁为进风口所开的通气孔不应小于进风口的尺寸。
二:软件配置如下:
2.1这里我们使用串口3进行数据的采集;
查看一下手册,确定一下所使用的GPIO口:
这里我们使用默认的引脚PB10,PB11即可。
2.2 为了更好的实现CH32的性能,我们使用DMA+空闲中断的方式,来进行接收模块发出的数据;
可以看到这里使用的DMA1的通道2 (USART3_TXD)和通道3(USART3_RXD)这里由于我们仅仅使用串口3的接收功能,所以这里不对TXD进行配置也是可以的。
三:串口底层驱动配置如下所示:
串口3串口的编写过程:
系统初始化,配置系统时钟;
配置串口3的引脚,波特率等信息,这里需要注意波特率,校验位等参数需要要模块相同;
使能DMA的发送,接收功能;
使能串口3空闲中断,开启接收
3.1 串口的初始化:
- /*******************************************************************************
- * Function Name : USART3_Initialize
- * Description : 初始化串口3
- * Input : baud 波特率
- * Output : None
- * Return : NOne
- *******************************************************************************/
- void USART3_Init(int baud)
- {
- GPIO_InitTypeDef GPIO_InitStructure = {0};
- USART_InitTypeDef USART_InitStructure = {0};
- NVIC_InitTypeDef NVIC_InitStructure = {0};
- RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3 , ENABLE );
- RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE );
- /* USART3 TX-->B.10 RX-->B.11 */
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
- GPIO_Init( GPIOB, &GPIO_InitStructure );
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- GPIO_Init( GPIOB, &GPIO_InitStructure );
- USART_InitStructure.USART_BaudRate = 9600;
- USART_InitStructure.USART_WordLength = USART_WordLength_8b;
- 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_Tx | USART_Mode_Rx;
- /* Enable USART3 Receive and Transmit interrupts */
- USART_DMACmd(USART3, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE); //使能USART2的收发DMA
- USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);
- USART_Init( USART3, &USART_InitStructure );
- DMA_USART3_TX_Configuration(2);//发送2个空字节
- DMA_USART3_RX_Configuration();
- DMA_Cmd( DMA1_Channel2, ENABLE ); /* USART3 Tx */
- DMA_Cmd( DMA1_Channel3, ENABLE ); /* USART3 Rx */
- NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- USART_Cmd( USART3, ENABLE );
- }
3.2 DMA通道3的配置如下所示:
- /*******************************************************************************
- * Function Name : DMA_USART3_RX_Configuration
- * Description : Configures the DMA To USART3 RX.
- * Input : None
- * Output : None
- * Return : None
- * USART3 RX -> DAM1-CH3
- *******************************************************************************/
- void DMA_USART3_RX_Configuration(void)
- {
- DMA_InitTypeDef DMA_USART3_RX_InitStructure; //定义USART2的接收DMA结构体
- NVIC_InitTypeDef NVIC_InitStructure = {0};
- RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
- DMA_DeInit(DMA1_Channel3);
- DMA_USART3_RX_InitStructure.DMA_PeripheralBaseAddr = ( u32 )( &USART3->DATAR );
- DMA_USART3_RX_InitStructure.DMA_MemoryBaseAddr = (u32)RecBuffer3;//定义接收数组
- DMA_USART3_RX_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
- DMA_USART3_RX_InitStructure.DMA_BufferSize = reclength2; //接收数组的最大的长度
- DMA_USART3_RX_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_USART3_RX_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_USART3_RX_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- DMA_USART3_RX_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_USART3_RX_InitStructure.DMA_Mode = DMA_Mode_Circular; //循环模式,接收数据循环存入
- DMA_USART3_RX_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //最高优先级
- DMA_USART3_RX_InitStructure.DMA_M2M = DMA_M2M_Disable;
- NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel3_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
- DMA_Init(DMA1_Channel3, &DMA_USART3_RX_InitStructure);
- }
3.3 串口3的中断处理函数
- /*******************************************************************************
- * Function Name : void USART3_IRQHandler(void)
- * Description : 串口3的中断服务函数
- * Input : 串口3的空闲中断服务函数
- * Output : None
- * Return : NOne
- *******************************************************************************/
- void USART3_IRQHandler(void)
- {
- if (USART_GetITStatus(USART3, USART_IT_IDLE) != RESET) //触发空闲中断
- {
- USART_ClearFlag(USART3,USART_IT_IDLE);
- uint16_t rxlen3 = (reclength3 - DMA1_Channel3->CNTR);
- memcpy(Usart3_DEAL_RX_Buf,RecBuffer3,rxlen3 );
- usart3_Flag = 1 ;
- memset(RecBuffer3,0,reclength3);//清空接收数组
- DMA_Cmd(DMA1_Channel3, DISABLE);
- DMA_SetCurrDataCounter(DMA1_Channel3, reclength3); //重设接收个数
- DMA_Cmd(DMA1_Channel3, ENABLE);
- }
- }
3.4 接收的数据处理函数:
- /***********************************************************************************************
- * @brief void DWIN_Rec_Deal(void)
- * @param 串口2从DWIN屏接收数据
- * @retval 无
- * @author 聪聪哥哥
- * @version V1.1.0
- * @date 15-8-2025
- 42 4D 00 1C 00 0F 00 16 00 1B 00 0F 00 16 00 1B 0E 76 03 98 00 76 00 10 00 C3 00 DC 91 00 05 00
- *************************************************************************************************/
- void UART3_Rec_Deal(void)
- {
- if(usart3_Flag == 1)
- {
- usart3_Flag = 0 ;
- if((Usart3_DEAL_RX_Buf[0] == 0x42)&&(Usart3_DEAL_RX_Buf[1] == 0x4D))
- {
- EnvirMentPara.uiPM10CF = ( Usart3_DEAL_RX_Buf[4] << 8 ) +Usart3_DEAL_RX_Buf[5] ;
- EnvirMentPara.uiPM25CF = ( Usart3_DEAL_RX_Buf[6] << 8 ) +Usart3_DEAL_RX_Buf[7] ;
- EnvirMentPara.uiPM100CF = ( Usart3_DEAL_RX_Buf[8] << 8 ) +Usart3_DEAL_RX_Buf[9] ;
- EnvirMentPara.uiPM10Concent = ( Usart3_DEAL_RX_Buf[10] << 8 ) +Usart3_DEAL_RX_Buf[11] ;
- EnvirMentPara.uiPM25Concent = ( Usart3_DEAL_RX_Buf[12] << 8 ) +Usart3_DEAL_RX_Buf[13] ;
- EnvirMentPara.uiPM100Concent = ( Usart3_DEAL_RX_Buf[14] << 8 ) +Usart3_DEAL_RX_Buf[15] ;
- EnvirMentPara.uiPartMmatter03 = ( Usart3_DEAL_RX_Buf[16] << 8 ) +Usart3_DEAL_RX_Buf[17] ;
- EnvirMentPara.uiPartMmatter05 = ( Usart3_DEAL_RX_Buf[18] << 8 ) +Usart3_DEAL_RX_Buf[19] ;
- EnvirMentPara.uiPartMmatter10 = ( Usart3_DEAL_RX_Buf[20] << 8 ) +Usart3_DEAL_RX_Buf[21] ;
- EnvirMentPara.iTemperature = ( Usart3_DEAL_RX_Buf[24] << 8 ) +Usart3_DEAL_RX_Buf[25] ;
- EnvirMentPara.iHumidness = ( Usart3_DEAL_RX_Buf[26] << 8 ) +Usart3_DEAL_RX_Buf[27] ;
- }
- memset(Usart3_DEAL_RX_Buf,0,reclength3);
- }
- }
3.5 串口屏幕显示部分如下所示:
- /***********************************************************************************************
- * @brief void WorkPageData(void)
- * @param 工作界面数据显示
- * @retval 无
- * @author 聪聪哥哥
- * @version V1.1.0
- * @date 15-08-2025
- *************************************************************************************************/
- void WorkPageData(void)
- {
- Display_Text(0x00,"21IC lun tan cong cong ");
- Add_Write_Data(0x100 ,EnvirMentPara.iTemperature);
- Add_Write_Data(0x102 ,EnvirMentPara.iHumidness);
- Add_Write_Data(0x104 ,EnvirMentPara.uiPM10CF);
- Add_Write_Data(0x106 ,EnvirMentPara.uiPM25CF);
- Add_Write_Data(0x107 ,EnvirMentPara.uiPM100CF);
- }
四:实物验证图片如下所示:
测试动态图如下所示:
|