聪聪哥哥 发表于 2024-6-16 16:09

基于CW32F030开发板设计的环境检测系统(带无线监测功能)

本帖最后由 聪聪哥哥 于 2024-6-17 10:36 编辑

基于CW32F030开发板设计的环境检测系统前言:一:开发板介绍:CW32F030CxTx StartKit 评估板为用户提供一种经济且灵活的方式使用 CW32F030CxTx 芯片构建系统原型。可进行性能、功耗、功能等各方面快速验证。
CW32F030CxTx StartKit 评估板需要搭配 CW-DAPLINK 调试器一起使用。
CW32F030CxTx StartKit 评估板带有 CW32F030 StartKit 软件包及 CW32F030-StdPeriph-Lib 固件库和例程。
CW32F030CxTx StartKit 评估板板载资源介绍:• CW32F030CxTx 微控制器(ARM® Cortex®-M0+ 最高主频 64MHz),LQFP48 封装,64K 字节 FLASH,8K 字节 RAM
• 3 颗 LED:
- 电源指示灯(LED3),用户指示灯(LED1,LED2)
• 三个轻触开关:
- 复位轻触开关(S3),用户轻触开关(S1,S2)
• USB 转串口芯片(CH340N)
• FLASH 芯片(W25Q64JVSSIQ)
• EEPROM 芯片(CW24C02AD)
• 板载接口:
- Mini USB 接口(串口通信,USB 供电)
- 下载器调试接口
- 所有 GPIO 口通过排针引出
• 多种方式供电:USB VBUS 供电,3.3V 供电(LD1117AS33TR),外接 1.65V ~ 5.5V 供电
• CW32F030-StdPeriph-Lib 软件包提供全面免费的固件库和例程
• 支持多种集成开发环境,IAR™,Keil®
使用开发环境:KEIL5.28A,调试器使用:自制的DAP调试器(实测很好用)
二:PM5003T颗粒物传感器模块资料:2.1:PM5003T颗粒物传感器产品介绍:PMS5003T 是一款可以同时监测空气中颗粒物浓度及温湿度的二合一传感器。其中颗粒物浓度的监测基于激光散射原理,可连续采集并计算单位体积内空气中不 同粒径的悬浮颗粒物个数,即颗粒物浓度分布,进而换算成为质量浓度。传感器同时内嵌瑞士生产的温湿度一体检测芯片。颗粒物浓度数值及温度、湿度合并以通用数字接口形式输出。本传感器可嵌入各种与空气质量监测和改善相关的仪器设备,为其提供及时准确的环境参数。工作原理:本传感器采用激光散射原理。即令激光照射在空气中的悬浮颗粒物上产生散射, 同时在某一特定角度收集散射光,得到散射光强随时间变化的曲线。进而微处理 器利用基于米氏(MIE)理论的算法,得出颗粒物的等效粒径及单位体积内不同 粒径的颗粒物数量。2.2:硬件接口定义:输出结果:1. 主要输出为单位体积内各浓度颗粒物质量以及个数,其中颗粒物个数的单位 体积为 0.1 升,质量浓度单位为:微克/立方米。 2. 输出分为主动输出和被动输出两种状态。传感器上电后默认状态为主动输出, 即传感器主动向主机发送串行数据,时间间隔为 200~800ms,空气中颗粒物 浓度越高,时间间隔越短。主动输出又分为两种模式:平稳模式和快速模式。 在空气中颗粒物浓度变化较小时,传感器输出为平稳模式,即每三次输出同样的一组数值,实际数据更新周期约为 2s。当空气中颗粒物浓度变化较大时, 传感器输出自动切换为快速模式,每次输出都是新的数值,实际数据更新周 期为 200~800ms。3. 温湿度输出:输出吸入传感器内部的采样空气温度及湿度。典型电路连接方式:2.3电路设计应注意:1. PMS5003T 需要 5V 供电,这是因为风机需要 5V 驱动。但其他数据通讯和控 制管脚均需要 3.3V 作为高电平。因此与之连接通讯的主板 MCU 应为 3.3V 供 电。如果主板 MCU 为 5V 供电,则在通讯线(RXD、TXD)和控制线(SET、 RESET)上应当加入电平转换芯片或电路。 2. SET 和 RESET 内部有上拉电阻,如果不使用,则应悬空。 3. PIN7 和 PIN8 为程序内部调试用,应用电路中应使其悬空。 4. 应用休眠功能时应注意:休眠时风扇停止工作,而风扇重新启动需要至少 30秒的稳定时间,因此为获得准确的数据,休眠唤醒后传感器工作时间不应低于 30秒。附:主要代码如下:分为串口初始化和串口接收函数
void PMS5003_GPIO_Configuration(void){    GPIO_InitTypeDef GPIO_InitStructure;    //UART TX RX 复用    PMS5003_USART_AFTX;    PMS5003_USART_AFRX;    GPIO_InitStructure.Pins = PMS5003_USART_TX_GPIO_PIN;    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;    GPIO_Init(PMS5003_USART_TX_GPIO_PORT, &GPIO_InitStructure);    GPIO_InitStructure.Pins = PMS5003_USART_RX_GPIO_PIN;    GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;    GPIO_Init(PMS5003_USART_TX_GPIO_PORT, &GPIO_InitStructure);}/** * @brief 配置UART * */void PMS5003_UART_Configuration(void){    USART_InitTypeDef USART_InitStructure;    USART_InitStructure.USART_BaudRate = PMS5003_USART_BaudRate;    USART_InitStructure.USART_Over = USART_Over_16;    USART_InitStructure.USART_Source = USART_Source_PCLK;    USART_InitStructure.USART_UclkFreq = PMS5003_USART_UclkFreq;    USART_InitStructure.USART_StartBit = USART_StartBit_FE;    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(PMS5003_USARTx, &USART_InitStructure);       //使能UARTx RX中断    USART_ITConfig(PMS5003_USARTx, USART_IT_RC, ENABLE);}/** * @brief 配置NVIC * */void PMS5003_NVIC_Configuration(void){    //优先级,无优先级分组//    NVIC_SetPriority(PMS5003_USART_IRQ, 0);    //UARTx中断使能    NVIC_EnableIRQ(PMS5003_USART_IRQ);}在串口接收中断中做数据处理,主要代码如下:///**// * @brief 处理串口3 接收到的数据// *// */void DealData(void)               {          EnvirDataMent.uPm25 = Deal_USART_RX_BUF;         EnvirDataMent.uPm25 = (EnvirDataMent.uPm25<<8)+Deal_USART_RX_BUF;          EnvirDataMent.uPm100 = Deal_USART_RX_BUF;         EnvirDataMent.uPm100 = (EnvirDataMent.uPm100<<8)+Deal_USART_RX_BUF;

         EnvirDataMent.uTemputer = Deal_USART_RX_BUF;         EnvirDataMent.uTemputer = (EnvirDataMent.uTemputer<<8)+Deal_USART_RX_BUF;          EnvirDataMent.uHumidity = Deal_USART_RX_BUF;         EnvirDataMent.uHumidity = (EnvirDataMent.uHumidity<<8)+Deal_USART_RX_BUF;
}
三:E32模块模块资料:
该电路只需将模块的TXD 与 RXD 连接到 MCU的RXD和TXD即可。E32模块是基于SX1278射频芯片的贴片型无线串口模块(TTL电平),透明传输方式,发射功率100MW,工作在410-441MHZ频段,采用LORA扩频技术。SX1278支持LORA扩频技术,通讯距离远,抗干扰能力强的优势,同时有极强的保密性。模块具有数据加密和压缩功能,模块在空中传输的数据,具有随机性,通过严密的加解密算法,使得数据截获失去意义。而数据压缩功能有概率减小传输时间,减少受干扰的概率,提高可考性和传输效率。模块的特点功能:模块的工作参数模块的指令格式:
主要代码如下:分为串口初始化和串口发送函数///**// * @brief 处理串口3 接收到的数据// *// */
void DealData(void)               {          EnvirDataMent.uPm25 = Deal_USART_RX_BUF;         EnvirDataMent.uPm25 = (EnvirDataMent.uPm25<<8)+Deal_USART_RX_BUF;          EnvirDataMent.uPm100 = Deal_USART_RX_BUF;         EnvirDataMent.uPm100 = (EnvirDataMent.uPm100<<8)+Deal_USART_RX_BUF;

         EnvirDataMent.uTemputer = Deal_USART_RX_BUF;         EnvirDataMent.uTemputer = (EnvirDataMent.uTemputer<<8)+Deal_USART_RX_BUF;          EnvirDataMent.uHumidity = Deal_USART_RX_BUF;         EnvirDataMent.uHumidity = (EnvirDataMent.uHumidity<<8)+Deal_USART_RX_BUF;}/*工作界面下显示,温度,湿度数据*/void USART2_E32_SENDDATA(char mode){            char buf = {0};      switch (mode)      {                case 0 :                                                  E32_USART_SendString(CW_UART2,"温度值:");                         sprintf(buf," %4.1f ℃",EnvirDataMent.uTemputer/10.0);
                                                 E32_USART_SendString(CW_UART2,buf);                              break ;
                case 1 : E32_USART_SendString(CW_UART2,"湿度值");                                     sprintf(buf," %4.1f%% ",EnvirDataMent.uHumidity/10.0);                                                 E32_USART_SendString(CW_UART2,buf);                              break ;                case 2 : E32_USART_SendString(CW_UART2,"PM值");
                                                 sprintf(buf," %4.1f   ",EnvirDataMent.uPm25/10.0);                                                 E32_USART_SendString(CW_UART2,buf);                              break ;                      default :                              break ;      }}四:OLED模块模块资料:4.1:OLED 简介: OLED,即有机发光二极管(Organic Light-Emitting Diode),又称为有机电激光显示(Organic Electroluminesence Display, OELD)。因为具备轻薄、省电等特性,因此从 2003 年开始,这种显示设备在 MP3 播放器上得到了广泛应用,而对于同属数码类产品的 DC 与手机,此前只是在一些展会上展示过采用 OLED 屏幕的工程样品。自 2007 年后,寿命得 到很大提高,具备了许多 LCD 不可比拟的优势。GND:电源地 VCC:2.2V~5.5V SCL(D0):CLK 时钟 (高电平 2.2V~5.5V) SDA(D1):MOSI 数据(高电平 2.2V~5.5V) RST:复位(高电平 2.2V~5.5V) D/C:数据/命令(高电平 2.2V~5.5V) 兼容 3.3V 和 5V 控制芯片的 I/O 电平(无需任何设置,直接兼容)。实物图片4.2:汉字显示方法:需要使用软件做自己的字库
IIC驱动部分/*引脚配置*/#define OLED_W_SCL(x)                GPIO_WritePin(CW_GPIOA, GPIO_PIN_1, (GPIO_PinState)(x))#define OLED_W_SDA(x)                GPIO_WritePin(CW_GPIOA, GPIO_PIN_0, (GPIO_PinState)(x))
/*引脚初始化*/void OLED_I2C_Init(void){   __RCC_GPIOA_CLK_ENABLE();
      GPIO_InitTypeDef GPIO_InitStruct;       GPIO_InitStruct.IT=GPIO_IT_NONE;      GPIO_InitStruct.Mode=GPIO_MODE_OUTPUT_OD;      GPIO_InitStruct.Pins=GPIO_PIN_1 | GPIO_PIN_0;      GPIO_InitStruct.Speed=GPIO_SPEED_LOW;      GPIO_Init(CW_GPIOA, &GPIO_InitStruct);      GPIO_WritePin(CW_GPIOA,GPIO_PIN_1 | GPIO_PIN_0,GPIO_Pin_SET);
      OLED_W_SCL(1);      OLED_W_SDA(1);}
/*** @briefI2C开始* @param无* @retval 无*/void OLED_I2C_Start(void){      OLED_W_SDA(1);      OLED_W_SCL(1);      OLED_W_SDA(0);      OLED_W_SCL(0);}/*** @briefI2C停止* @param无* @retval 无*/void OLED_I2C_Stop(void){      OLED_W_SDA(0);      OLED_W_SCL(1);      OLED_W_SDA(1);}/*** @briefI2C发送一个字节* @paramByte 要发送的一个字节* @retval 无*/void OLED_I2C_SendByte(uint8_t Byte){      uint8_t i;      for (i = 0; i < 8; i++)      {                if(Byte & (0x80 >> i)) OLED_W_SDA(1);                else OLED_W_SDA(0);                OLED_W_SCL(1);                OLED_W_SCL(0);      }      OLED_W_SCL(1);      //额外的一个时钟,不处理应答信号      OLED_W_SCL(0);}/*** @briefOLED写命令* @paramCommand 要写入的命令* @retval 无*/void OLED_WriteCommand(uint8_t Command){      OLED_I2C_Start();      OLED_I2C_SendByte(0x78);                //从机地址      OLED_I2C_SendByte(0x00);                //写命令      OLED_I2C_SendByte(Command);       OLED_I2C_Stop();}/*** @briefOLED写数据* @paramData 要写入的数据* @retval 无*/void OLED_WriteData(uint8_t Data){      OLED_I2C_Start();      OLED_I2C_SendByte(0x78);                //从机地址      OLED_I2C_SendByte(0x40);                //写数据      OLED_I2C_SendByte(Data);      OLED_I2C_Stop();}/*** @briefOLED设置光标位置* @paramY 以左上角为原点,向下方向的坐标,范围:0~7* @paramX 以左上角为原点,向右方向的坐标,范围:0~127* @retval 无*/void OLED_SetCursor(uint8_t Y, uint8_t X){      OLED_WriteCommand(0xB0 | Y);                                        //设置Y位置      OLED_WriteCommand(0x10 | ((X & 0xF0) >> 4));      //设置X位置低4位      OLED_WriteCommand(0x00 | (X & 0x0F));                        //设置X位置高4位}/*** @briefOLED清屏* @param无* @retval 无*/void OLED_Clear(void){      uint8_t i, j;      for (j = 0; j < 8; j++)      {                OLED_SetCursor(j, 0);                for(i = 0; i < 128; i++)                {                        OLED_WriteData(0x00);                }      }}/*** @briefOLED显示一个中文* @paramLine 行位置,范围:1~4* @paramColumn 列位置,范围:1~15,注意两个汉字的列位置间隔两个位置                        比如:                              OLED_ShowChinese(1,1,0);第一个汉字                        OLED_ShowChinese(1,3,1);第二个汉字* @paramSelect 从汉字库选择汉字索引* @retval 无*/void OLED_ShowChinese(uint8_t Line, uint8_t Column, uint8_t Select){      uint8_t i;      OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);                //设置光标位置在上半部分      for (i = 0; i < 16; i++)      {                OLED_WriteData(OLED_F16x16);                        //显示上半部分内容      }      OLED_SetCursor((Line - 1) * 2+1, (Column - 1) * 8);                //设置光标位置在上半部分      for (i = 0; i < 16; i++)      {                OLED_WriteData(OLED_F16x16);                        //显示上半部分内容      }}/*** @briefOLED显示一个字符* @paramLine 行位置,范围:1~4* @paramColumn 列位置,范围:1~16* @paramChar 要显示的一个字符,范围:ASCII可见字符* @retval 无*/void OLED_ShowChar(uint8_t Line, uint8_t Column, char Char){                  uint8_t i;      OLED_SetCursor((Line - 1) * 2, (Column - 1) * 8);                //设置光标位置在上半部分      for (i = 0; i < 8; i++)      {                OLED_WriteData(OLED_F8x16);                        //显示上半部分内容      }      OLED_SetCursor((Line - 1) * 2 + 1, (Column - 1) * 8);      //设置光标位置在下半部分      for (i = 0; i < 8; i++)      {                OLED_WriteData(OLED_F8x16);                //显示下半部分内容      }}/*** @briefOLED显示字符串* @paramLine 起始行位置,范围:1~4* @paramColumn 起始列位置,范围:1~16* @paramString 要显示的字符串,范围:ASCII可见字符* @retval 无*/void OLED_ShowString(uint8_t Line, uint8_t Column, char *String){      uint8_t i;      for (i = 0; String != '\0'; i++)      {                OLED_ShowChar(Line, Column + i, String);      }}/*** @briefOLED次方函数* @retval 返回值等于X的Y次方*/uint32_t OLED_Pow(uint32_t X, uint32_t Y){      uint32_t Result = 1;      while (Y--)      {                Result *= X;      }      return Result;}
/*** @briefOLED显示数字(十进制,正数)* @paramLine 起始行位置,范围:1~4* @paramColumn 起始列位置,范围:1~16* @paramNumber 要显示的数字,范围:0~4294967295* @paramLength 要显示数字的长度,范围:1~10* @retval 无*/void OLED_ShowNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length){      uint8_t i;      for (i = 0; i < Length; i++)                                                            {                OLED_ShowChar(Line, Column + i, Number / OLED_Pow(10, Length - i - 1) % 10 + '0');      }}
/*** @briefOLED显示数字(十进制,带符号数)* @paramLine 起始行位置,范围:1~4* @paramColumn 起始列位置,范围:1~16* @paramNumber 要显示的数字,范围:-2147483648~2147483647* @paramLength 要显示数字的长度,范围:1~10* @retval 无*/void OLED_ShowSignedNum(uint8_t Line, uint8_t Column, int32_t Number, uint8_t Length){      uint8_t i;      uint32_t Number1;      if (Number >= 0)      {                OLED_ShowChar(Line, Column, ' ');                Number1 = Number;      }      else      {                OLED_ShowChar(Line, Column, '-');                Number1 = -Number;      }      for (i = 0; i < Length; i++)                                                            {                OLED_ShowChar(Line, Column + i + 1, Number1 / OLED_Pow(10, Length - i - 1) % 10 + '0');      }}
/*** @briefOLED显示数字(十六进制,正数)* @paramLine 起始行位置,范围:1~4* @paramColumn 起始列位置,范围:1~16* @paramNumber 要显示的数字,范围:0~0xFFFFFFFF* @paramLength 要显示数字的长度,范围:1~8* @retval 无*/void OLED_ShowHexNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length){      uint8_t i, SingleNumber;      for (i = 0; i < Length; i++)                                                            {                SingleNumber = Number / OLED_Pow(16, Length - i - 1) % 16;                if (SingleNumber < 10)                {                        OLED_ShowChar(Line, Column + i, SingleNumber + '0');                }                else                {                        OLED_ShowChar(Line, Column + i, SingleNumber - 10 + 'A');                }      }}
/*** @briefOLED显示数字(二进制,正数)* @paramLine 起始行位置,范围:1~4* @paramColumn 起始列位置,范围:1~16* @paramNumber 要显示的数字,范围:0~1111 1111 1111 1111* @paramLength 要显示数字的长度,范围:1~16* @retval 无*/void OLED_ShowBinNum(uint8_t Line, uint8_t Column, uint32_t Number, uint8_t Length){      uint8_t i;      for (i = 0; i < Length; i++)                                                            {                OLED_ShowChar(Line, Column + i, Number / OLED_Pow(2, Length - i - 1) % 2 + '0');      }}/*** @briefOLED初始化* @param无* @retval 无*/void OLED_Init(void){      uint32_t i, j;
      for (i = 0; i < 1000; i++)                        //上电延时      {                for (j = 0; j < 1000; j++);      }
      OLED_I2C_Init();                        //端口初始化
      OLED_WriteCommand(0xAE);      //关闭显示
      OLED_WriteCommand(0xD5);      //设置显示时钟分频比/振荡器频率      OLED_WriteCommand(0x80);
      OLED_WriteCommand(0xA8);      //设置多路复用率      OLED_WriteCommand(0x3F);
      OLED_WriteCommand(0xD3);      //设置显示偏移      OLED_WriteCommand(0x00);
      OLED_WriteCommand(0x40);      //设置显示开始行
      OLED_WriteCommand(0xA1);      //设置左右方向,0xA1正常 0xA0左右反置
      OLED_WriteCommand(0xC8);      //设置上下方向,0xC8正常 0xC0上下反置
      OLED_WriteCommand(0xDA);      //设置COM引脚硬件配置      OLED_WriteCommand(0x12);
      OLED_WriteCommand(0x81);      //设置对比度控制      OLED_WriteCommand(0xCF);
      OLED_WriteCommand(0xD9);      //设置预充电周期      OLED_WriteCommand(0xF1);
      OLED_WriteCommand(0xDB);      //设置VCOMH取消选择级别      OLED_WriteCommand(0x30);
      OLED_WriteCommand(0xA4);      //设置整个显示打开/关闭
      OLED_WriteCommand(0xA6);      //设置正常/倒转显示
      OLED_WriteCommand(0x8D);      //设置充电泵      OLED_WriteCommand(0x14);
      OLED_WriteCommand(0xAF);      //开启显示
      OLED_Clear();                              //OLED清屏}
显示部分:
五:CW32F030C8拓展板实现的主要功能:



实物图片如下:
B站视频链接如下,感兴趣的可以移步去看下,感谢!!!!!https://www.bilibili.com/video/BV1B1VLevEuT/?spm_id_from=333.999.0.0&vd_source=fb5a6d1a3332aab1989e0f3e24f2afc1
   

huquanz711 发表于 2024-6-17 07:47

感觉空气净化器也就当时那啥主持人制作了个关于雾霾的视频,然后就火起来了,现在又淡出人们生活了

聪聪哥哥 发表于 2024-6-17 07:56

huquanz711 发表于 2024-6-17 07:47
感觉空气净化器也就当时那啥主持人制作了个关于雾霾的视频,然后就火起来了,现在又淡出人们生活了...

嗯,这个也就是可以监控空气的PM数据什么的

trucyw 发表于 2024-6-17 08:24

雾霾也看在什么地方测试

聪聪哥哥 发表于 2024-6-17 09:38

trucyw 发表于 2024-6-17 08:24
雾霾也看在什么地方测试

模块是可以读取的,那个PM2.5 数值就是 显示的颗粒数

qintian0303 发表于 2024-6-17 11:12

多挺好的,不过室内PM2.5检测一般都不太理想,CW这个板子太丑

money112345 发表于 2024-6-17 14:24

很好

小夏天的大西瓜 发表于 2024-6-17 22:40

模块请问链接能发一下嘛?

聪聪哥哥 发表于 2024-6-18 20:03

具体是哪一个i

OKAKAKO 发表于 2024-6-21 21:05

楼主这是设计的PCB板嘛?

聪聪哥哥 发表于 2024-6-26 07:30

OKAKAKO 发表于 2024-6-21 21:05
楼主这是设计的PCB板嘛?

是的,绘制了一个拓展板

中国龙芯CDX 发表于 2024-6-26 15:14

输出分为主动输出和被动输出两种状态
页: [1]
查看完整版本: 基于CW32F030开发板设计的环境检测系统(带无线监测功能)