嵌入式技术论坛
直播中

王浩

7年用户 1324经验值
私信 关注
[经验]

基于RT-Thread和CPK-RA2L1板制作一个空气质量监测系统

  一、背景
  有幸参加RT-Thread的活动,体验RT-Thread Studio 和瑞萨 CPK-RA2L1评估板。本篇结合前面的文章,暂时制作一个空气质量监测系统,主要使用:DHT11、PMS1003, OLED模块, 后续继续扩展甲醛,CO2, IAQ模块
  二、模块信息
  目前使用的三个模块的相关信息
  三、新建工程
  这里使用的模块,我们需要提前分配好引脚:UART0 采集PMS1003, DHT11 使用P0208 引脚, OLED I2C1通信 使用P0205 P0206,
  配置RT-Thread Settings ,添加u8g2 库,配置i2c,具体信息如下图
2.jpg
3.jpg
  在 RA Smart Configurator 种添加UART0,配置好引脚和波特率
2.jpg
  在 RA Smart Configurator 种添加I2C1
2.jpg
  四、编写代码
  hal_entery.c
  /*
  * Copyright (c) 2006-2021, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date Author Notes
  * 2021-10-10 Sherman first version
  */
  #include 《rtthread.h》
  #include “hal_data.h”
  #include 《rtdevice.h》
  #include “dht11.h”
  #include 《rtdbg.h》
  #include “pms1003.h”
  #include 《string.h》
  #include 《rthw.h》
  #include 《u8g2_port.h》
  //#define DBG_ENABLE
  //#define DBG_SECTION_NAME “pms_series”
  //#define DBG_LEVEL DBG_LOG
  //#define DBG_COLOR
  //#define DBG_ENABLE
  #define LED1_PIN “P502” /* Onboard LED pins */
  #define USER_INPUT “P004”
  /******** DHT11 *********/
  #define DATA_PIN 0x0208 //P208 dht11
  #define THREAD_PRIORITY 5
  #define THREAD_STACK_SIZE 1024
  #define THREAD_TIMESLICE 10
  static rt_thread_t tid_dht11 = RT_NULL;
  /******** PMS1003 *********/
  //tx P101 rx P100
  #define PMS_SERIES_UART “uart0”
  #ifdef PMS_SERIES_SAMPLE_USING_DMA
  struct rt_messagequeue pms_mq;
  #else
  struct rt_semaphore pms_sem;
  #endif
  pms_device_t PMS1003;
  struct rx_msg
  {
  rt_device_t dev;
  rt_size_t size;
  };
  /******** OLED *********/
  static rt_thread_t tid_oled = RT_NULL;
  int temp = 0;
  int humi = 0;
  int PM2_5 = 0;
  int PM10 = 0;
  static void Dht11ThreadEntry(void *parameter)
  {
  dht_device_t sensor = dht_create(DATA_PIN);
  rt_int32_t temp_;
  rt_int32_t humi_;
  while (1)
  {
  if(dht_read(sensor))
  {
  temp_ = dht_get_temperature(sensor) / 10;
  humi_ = dht_get_humidity(sensor) / 10;
  temp = temp_;
  humi = humi_;
  // rt_kprintf(“Temp: %d, Humi: %dn”, temp, humi);
  }
  else
  {
  // rt_kprintf(“Read dht sensor failed.n”);
  }
  rt_thread_mdelay(500);
  }
  dht_delete(sensor);
  }
  int dht11_init()
  {
  rt_err_t ret = RT_EOK;
  tid_dht11 = rt_thread_create(“dht11”,
  Dht11ThreadEntry,
  RT_NULL,
  THREAD_STACK_SIZE,
  THREAD_PRIORITY,
  THREAD_TIMESLICE);
  if (tid_dht11 != RT_NULL)
  {
  rt_thread_startup(tid_dht11);
  }
  else
  {
  ret = RT_ERROR;
  }
  return ret;
  }
  //INIT_APP_EXPORT(dht11_init);
  void pms_series_debug(pms_device_t dev)
  {
  rt_kprintf(“*********************************begin***********************************n”);
  rt_kprintf(“PM1_0_CF1 = %5dtPM2_5_CF1 = %5dtPM10_0_CF1 = %5dn”,dev-》PM1_0_CF1,dev-》PM2_5_CF1,dev-》PM10_0_CF1);
  rt_kprintf(“PM1_0_amb = %5dtPM2_5_amb = %5dtPM10_0_amb = %5dn”,dev-》PM1_0_amb,dev-》PM2_5_amb,dev-》PM10_0_amb);
  rt_kprintf(“air_0_3um = %5dtair_0_5um = %5dtair_1_0um = %5dn”,dev-》air_0_3um,dev-》air_0_5um,dev-》air_1_0um);
  rt_kprintf(“air_2_5um = %5dt”,dev-》air_2_5um);
  rt_kprintf(“version = %5d errorCode = %5dn”,dev-》version,dev-》errorCode);
  rt_kprintf(“********************************over*************************************n”);
  }
  static void serial_thread_entry(void *parameter)
  {
  #ifndef PMS_SERIES_SAMPLE_USING_DMA
  rt_err_t result;
  char ch;
  pms_device_t dev = parameter;
  while (1)
  {
  while (rt_device_read(dev-》serial, 0, &ch, 1) == 0)
  {
  rt_sem_control(&pms_sem, RT_IPC_CMD_RESET, RT_NULL);
  rt_sem_take(&pms_sem, RT_WAITING_FOREVER);
  }
  result = pms_get_byte(dev,ch);
  if (result == RT_EOK)
  {
  // pms_series_debug(dev); // for debug
  PM2_5 = dev-》PM2_5_CF1;
  PM10 = dev-》PM10_0_CF1;
  // rt_kprintf(“air_2_5um = %dn”,PM2_5);
  }
  }
  #endif
  #ifdef PMS_SERIES_SAMPLE_USING_DMA
  struct rx_msg msg;
  rt_err_t result;
  rt_uint32_t rx_length;
  static rt_uint8_t rx_buffer[RT_SERIAL_RB_BUFSZ + 1];
  pms_device_t dev = parameter;
  while (1)
  {
  rt_memset(&msg, 0, sizeof(msg));
  result = rt_mq_recv(&pms_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
  if (result == RT_EOK)
  {
  rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
  rx_buffer[rx_length] = ‘’;
  result = frame_check(dev,rx_buffer,rx_length);
  if (result == RT_EOK)
  {
  pms_series_debug(dev);
  rt_kprintf(“rx buff success”);
  }
  else
  {
  rt_kprintf(“rx buff error”);
  }
  }
  }
  #endif
  }
  static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
  {
  RT_ASSERT(dev);
  #ifndef PMS_SERIES_SAMPLE_USING_DMA
  if (size 》 0)
  {
  rt_sem_release(&pms_sem);
  }
  return RT_EOK;
  #endif
  #ifdef PMS_SERIES_SAMPLE_USING_DMA
  rt_err_t result;
  struct rx_msg msg;
  msg.dev = dev;
  msg.size = size;
  result = rt_mq_send(&pms_mq, &msg, sizeof(msg));
  if ( result == -RT_EFULL)
  {
  rt_kprintf(“message queue full!n”);
  }
  return result;
  #endif
  }
  int PMS1003Init()
  {
  static pms_device_t dev = NULL;
  rt_err_t ret = RT_EOK;
  dev = pms_init(PMS_SERIES_UART);
  #ifndef PMS_SERIES_SAMPLE_USING_DMA
  rt_sem_init(&pms_sem, “pms_sem”, 0, RT_IPC_FLAG_FIFO);
  rt_device_open(dev-》serial, RT_DEVICE_FLAG_INT_RX);
  rt_device_set_rx_indicate(dev-》serial, uart_input);
  #endif
  #ifdef PMS_SERIES_SAMPLE_USING_DMA
  static char msg_pool[256];
  rt_err_t result;
  result = rt_mq_init(&pms_mq, “pms_mq”,
  msg_pool,
  sizeof(struct rx_msg),
  sizeof(msg_pool),
  RT_IPC_FLAG_FIFO);
  if (result != RT_EOK)
  {
  rt_kprintf(“init message queue failed.n”);
  }
  result = rt_device_open(dev-》serial, RT_DEVICE_FLAG_DMA_RX);
  if (result != RT_EOK)
  {
  rt_kprintf(“open device failed.n”);
  }
  result = rt_device_set_rx_indicate(dev-》serial, uart_input);
  if (result != RT_EOK)
  {
  rt_kprintf(“set rx indicate failed.n”);
  }
  #endif
  rt_thread_t thread = rt_thread_create(“pms1003”, serial_thread_entry, dev, 1024, 3, 10);
  if (thread != RT_NULL)
  {
  rt_thread_startup(thread);
  }
  else
  {
  ret = RT_ERROR;
  }
  return ret;
  }
  //INIT_APP_EXPORT(PMS1003Init);
  char tmp_buff[18]={‘’};
  char pm_buff[16]={‘’};
  char pm10_buff[16]={‘’};
  static int F_clean = 0;
  static void OledThreadEntry(void *parameter)
  {
  u8g2_t u8g2;
  u8g2_Setup_ssd1306_i2c_128x64_noname_f( &u8g2, U8G2_R0, u8x8_byte_rtthread_hw_i2c, u8x8_gpio_and_delay_rtthread);
  u8g2_InitDisplay(&u8g2);
  u8g2_SetPowerSave(&u8g2, 0);//是否开启省电模式 , 1 表示启用显示器的省电模式,屏幕上看不到任何东西, 0 表示禁用省电模式
  u8g2_ClearBuffer(&u8g2);
  u8g2_SetFont(&u8g2, u8g2_font_unifont_t_arabic); //u8g2_font_ncenB08_tr u8g2_font_unifont_t_symbols
  while (1)
  {
  sprintf(tmp_buff, “Temp:%dt Humi:%dt”, temp, humi);
  sprintf(pm_buff, “PM2.5:%d”, PM2_5);
  sprintf(pm10_buff, “PM10:%d”, PM10);
  rt_thread_mdelay(300);
  if (1 == F_clean)
  {
  u8g2_ClearBuffer(&u8g2);
  }
  else if (50 == F_clean)
  {
  u8g2_ClearBuffer(&u8g2);
  F_clean = 0;
  }
  u8g2_DrawStr(&u8g2, 1, 10, &tmp_buff);
  u8g2_SendBuffer(&u8g2);
  u8g2_DrawStr(&u8g2, 1, 30, &pm_buff);
  u8g2_SendBuffer(&u8g2);
  u8g2_DrawStr(&u8g2, 1, 50, &pm10_buff);
  u8g2_SendBuffer(&u8g2);
  rt_kprintf(“F_clean:%d n”,F_clean++);
  }
  }
  int OLED_Init()
  {
  rt_err_t ret = RT_EOK;
  tid_oled = rt_thread_create(“oled”,
  OledThreadEntry,
  RT_NULL,
  1024,
  2,
  THREAD_TIMESLICE);
  if (tid_oled != RT_NULL)
  {
  rt_thread_startup(tid_oled);
  }
  else
  {
  ret = RT_ERROR;
  }
  return ret;
  }
  //INIT_APP_EXPORT(OLED_Init);
  void hal_entry(void)
  {
  rt_kprintf(“nHello RT-Thread!n”);
  rt_uint32_t led1_pin = rt_pin_get(LED1_PIN);
  dht11_init();
  PMS1003Init();
  OLED_Init();
  while (1)
  {
  rt_pin_write(led1_pin, PIN_HIGH);
  rt_thread_mdelay(500);
  rt_pin_write(led1_pin, PIN_LOW);
  rt_thread_mdelay(500);
  }
  }
  void irq_callback_test(void *args)
  {
  rt_kprintf(“n IRQ03 triggered n”);
  }
  void icu_sample(void)
  {
  /* init */
  rt_uint32_t pin = rt_pin_get(USER_INPUT);
  rt_kprintf(“n pin number : 0x%04X n”, pin);
  rt_err_t err = rt_pin_attach_irq(pin, PIN_IRQ_MODE_RISING, irq_callback_test, RT_NULL);
  if (RT_EOK != err)
  {
  rt_kprintf(“n attach irq failed. n”);
  }
  err = rt_pin_irq_enable(pin, PIN_IRQ_ENABLE);
  if (RT_EOK != err)
  {
  rt_kprintf(“n enable irq failed. n”);
  }
  }
  MSH_CMD_EXPORT(icu_sample, icu sample);
  dht11.c
  /*
  * Copyright (c) 2006-2021, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date Author Notes
  * 2023-03-08 DYC the first version
  */
  #include “dht11.h”
  #include 《stdio.h》
  #include “hal_data.h”
  #include 《board.h》
  #define DBG_TAG “sensor.asair.dhtxx”
  #ifdef PKG_USING_DHTXX_DEBUG
  #define DBG_LVL DBG_LOG
  #else
  #define DBG_LVL DBG_ERROR
  #endif
  #include 《rtdbg.h》
  /* timing */
  #define DHT1x_BEGIN_TIME 20 /* ms */
  #define DHT2x_BEGIN_TIME 1 /* ms */
  #define DHTxx_PULL_TIME 30 /* us */
  #define DHTxx_REPLY_TIME 100 /* us */
  #define MEASURE_TIME 40 /* us */
  RT_WEAK void rt_hw_us_delay(rt_uint32_t us)
  {
  rt_uint32_t delta;
  us = us * (SysTick-》LOAD / (1000000 / RT_TICK_PER_SECOND));
  delta = SysTick-》VAL;
  while (delta - SysTick-》VAL 《 us) continue;
  }
  /**
  * This function will split a number into two part according to times.
  *
  * @param num the number will be split
  * @param integer the integer part
  * @param decimal the decimal part
  * @param times how many times of the real number (you should use 10 in this case)
  *
  * @Return 0 if num is positive, 1 if num is negative
  */
  int split_int(const int num, int *integer, int *decimal, const rt_uint32_t times)
  {
  int flag = 0;
  if (num 《 0) flag = 1;
  int anum = num《0 ? -num : num;
  *integer = anum / times;
  *decimal = anum % times;
  return flag;
  }
  /**
  * This function will convert temperature in degree Celsius to Kelvin.
  *
  * @param c the temperature indicated by degree Celsius
  *
  * @return the result
  */
  float convert_c2k(float c)
  {
  return c + 273.15;
  }
  /**
  * This function will convert temperature in degree Celsius to Fahrenheit.
  *
  * @param c the temperature indicated by degree Celsius
  *
  * @return the result
  */
  float convert_c2f(float c)
  {
  return c * 1.8 + 32;
  }
  /**
  * This function will convert temperature in degree Fahrenheit to Celsius.
  *
  * @param f the temperature indicated by degree Fahrenheit
  *
  * @return the result
  */
  float convert_f2c(float f)
  {
  return (f - 32) * 0.55555;
  }
  /**
  * This function will read a bit from sensor.
  *
  * @param pin the pin of Dout
  *
  * @return the bit value
  */
  static uint8_t dht_read_bit(const rt_base_t pin)
  {
  uint8_t retry = 0;
  while(rt_pin_read(pin) && retry 《 DHTxx_REPLY_TIME)
  {
  retry++;
  rt_hw_us_delay(1);
  }
  retry = 0;
  while(!rt_pin_read(pin) && retry 《 DHTxx_REPLY_TIME)
  {
  retry++;
  rt_hw_us_delay(1);
  }
  rt_hw_us_delay(MEASURE_TIME);
  return rt_pin_read(pin);
  }
  /**
  * This function will read a byte from sensor.
  *
  * @param pin the pin of Dout
  *
  * @return the byte
  */
  static uint8_t dht_read_byte(const rt_base_t pin)
  {
  uint8_t i, byte = 0;
  for(i=0; i《8; i++)
  {
  byte 《《= 1;
  byte |= dht_read_bit(pin);
  }
  return byte;
  }
  /**
  * This function will read and update data array.
  *
  * @param dev the device to be operated
  *
  * @return RT_TRUE if read successfully, otherwise return RT_FALSE.
  */
  rt_bool_t dht_read(dht_device_t dev)
  {
  RT_ASSERT(dev);
  uint8_t i, retry = 0, sum = 0;
  #ifdef PKG_USING_DHTXX_INTERRUPT_DISABLE
  rt_base_t level;
  #endif
  /* Reset data buffer */
  rt_memset(dev-》data, 0, DHT_DATA_SIZE);
  /* MCU request sampling */
  rt_pin_mode(dev-》pin, PIN_MODE_OUTPUT);
  rt_pin_write(dev-》pin, PIN_LOW);
  if (dev-》type == DHT11) {
  rt_thread_mdelay(DHT1x_BEGIN_TIME); /* Tbe */
  } else {
  rt_thread_mdelay(DHT2x_BEGIN_TIME);
  }
  #ifdef PKG_USING_DHTXX_INTERRUPT_DISABLE
  level = rt_hw_interrupt_disable();
  #endif
  rt_pin_mode(dev-》pin, PIN_MODE_INPUT_PULLUP);
  rt_hw_us_delay(DHTxx_PULL_TIME); /* Tgo */
  /* Waiting for sensor reply */
  while (rt_pin_read(dev-》pin) && retry 《 DHTxx_REPLY_TIME)
  {
  retry++;
  rt_hw_us_delay(1); /* Trel */
  }
  if(retry 》= DHTxx_REPLY_TIME) return RT_FALSE;
  retry = 0;
  while (!rt_pin_read(dev-》pin) && retry 《 DHTxx_REPLY_TIME)
  {
  retry++;
  rt_hw_us_delay(1); /* Treh */
  };
  if(retry 》= DHTxx_REPLY_TIME) return RT_FALSE;
  /* Read data */
  for(i=0; i《DHT_DATA_SIZE; i++)
  {
  dev-》data[i] = dht_read_byte(dev-》pin);
  }
  #ifdef PKG_USING_DHTXX_INTERRUPT_DISABLE
  rt_hw_interrupt_enable(level);
  #endif
  /* Checksum */
  for(i=0; i《DHT_DATA_SIZE-1; i++)
  {
  sum += dev-》data[i];
  }
  if(sum != dev-》data[4]) return RT_FALSE;
  return RT_TRUE;
  }
  /**
  * This function will get the humidity from dhtxx sensor.
  *
  * @param dev the device to be operated
  *
  * @return the humidity value
  */
  rt_int32_t dht_get_humidity(dht_device_t const dev)
  {
  RT_ASSERT(dev);
  rt_int32_t humi = 0;
  switch(dev-》type)
  {
  case DHT11:
  humi = dev-》data[0] * 10 + dev-》data[1];
  break;
  default:
  break;
  }
  return humi;
  }
  /**
  * This function will get the temperature from dhtxx sensor.
  *
  * @param dev the device to be operated
  *
  * @return the temperature value
  */
  rt_int32_t dht_get_temperature(dht_device_t const dev)
  {
  RT_ASSERT(dev);
  rt_int32_t temp = 0;
  switch(dev-》type)
  {
  case DHT11:
  temp = dev-》data[2] * 10 + (dev-》data[3] & 0x7f);
  if(dev-》data[3] & 0x80) {
  temp = -temp;
  }
  break;
  default:
  break;
  }
  return temp;
  }
  /**
  * This function will init dhtxx sensor device.
  *
  * @param dev the device to init
  * @param pin the pin of Dout
  *
  * @return the device handler
  */
  rt_err_t dht_init(struct dht_device *dev, const rt_base_t pin)
  {
  if(dev == NULL)
  return -RT_ERROR;
  dev-》type = DHT_TYPE;
  dev-》pin = pin;
  rt_memset(dev-》data, 0, DHT_DATA_SIZE);
  rt_pin_mode(dev-》pin, PIN_MODE_INPUT_PULLUP);
  return RT_EOK;
  }
  // 1、初始化类型
  dht_device_t dht_create(const rt_base_t pin)
  {
  dht_device_t dev;
  dev = rt_calloc(1, sizeof(struct dht_device));
  if (dev == RT_NULL)
  {
  LOG_E(“Can‘t allocate memory for dhtxx device”);
  return RT_NULL;
  }
  dev-》type = DHT_TYPE;
  dev-》pin = pin;
  rt_memset(dev-》data, 0, DHT_DATA_SIZE);
  rt_pin_mode(dev-》pin, PIN_MODE_INPUT_PULLUP);
  return dev;
  }
  void dht_delete(dht_device_t dev)
  {
  if (dev)
  rt_free(dev);
  }
  dht11.h
  /*
  * Copyright (c) 2006-2021, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date Author Notes
  * 2023-03-08 DYC the first version
  */
  #ifndef SRC_DHT11_H_
  #define SRC_DHT11_H_
  #include 《stdio.h》
  #include 《rthw.h》
  #include 《rtdevice.h》
  #include 《board.h》
  #include 《rtthread.h》
  #define DHTLIB_VERSION “0.9.0”
  #define DHT_DATA_SIZE 5
  /* sensor model type */
  #define DHT11 0
  #define DHT_TYPE DHT11
  struct dht_device
  {
  rt_base_t pin;
  rt_uint8_t type;
  rt_uint8_t data[DHT_DATA_SIZE];
  rt_mutex_t lock;
  };
  typedef struct dht_device *dht_device_t;
  dht_device_t dht_create(const rt_base_t pin);
  void dht_delete(dht_device_t dev);
  rt_err_t dht_init(struct dht_device *dev, const rt_base_t pin);
  rt_bool_t dht_read(dht_device_t dev);
  rt_int32_t dht_get_humidity(dht_device_t dev);
  rt_int32_t dht_get_temperature(dht_device_t dev);
  float convert_c2k(float c);//将摄氏温度转为开氏温度
  float convert_c2f(float c);//将摄氏温度转为华氏温度
  float convert_f2c(float f);//将华氏温度转为摄氏温度
  rt_int32_t split_int(const rt_int32_t num, rt_int32_t *integer,
  rt_int32_t *decimal, const rt_uint32_t times);
  rt_err_t rt_hw_dht_init(const char *name, struct rt_sensor_config *cfg);
  #endif /* SRC_DHT11_H_ */
  pms1003.c
  /*
  * Copyright (c) 2006-2021, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date Author Notes
  * 2023-03-08 DYC the first version
  */
  //#define DBG_SECTION_NAME “pms_series”
  //#define DBG_LEVEL DBG_LOG
  //#define DBG_COLOR
  #include 《rtdbg.h》
  #include 《stdio.h》
  #include “pms1003.h”
  #define RT_SERIAL_RB_BUFSZ 64
  #define COMM_START1 0x42
  #define COMM_START2 0x4D
  #define FRAME_HEAD1 0x00
  #define FRAME_HEAD2 0x01
  #define FRAME_LENH 0x02
  #define FRAME_LENL 0x03
  #define FRAME_RECEIVE 0x04
  #define FRAME_CHECK 0x05
  rt_err_t frame_check(pms_device_t dev,rt_uint8_t *buf,rt_uint16_t len)
  {
  rt_uint16_t sum=0;
  RT_ASSERT(dev);
  for(uint8_t i=0;i《(len-2);i++)
  {
  sum += buf[i];
  }
  if((buf[len-1] == (sum&0xFF)) && (buf[len-2] == (sum 》》 8)))
  {
  dev-》PM1_0_CF1 = ((rt_uint16_t)(buf[4])《《8) | buf[5];
  dev-》PM2_5_CF1 = ((rt_uint16_t)(buf[6])《《8) | buf[7];
  dev-》PM10_0_CF1 = ((rt_uint16_t)(buf[8])《《8) | buf[9];
  dev-》PM1_0_amb = ((rt_uint16_t)(buf[10])《《8) | buf[11];
  dev-》PM2_5_amb = ((rt_uint16_t)(buf[12])《《8) | buf[13];
  dev-》PM10_0_amb = ((rt_uint16_t)(buf[14])《《8) | buf[15];
  dev-》air_0_3um = ((rt_uint16_t)(buf[16])《《8) | buf[17];
  dev-》air_0_5um = ((rt_uint16_t)(buf[18])《《8) | buf[19];
  dev-》air_1_0um = ((rt_uint16_t)(buf[20])《《8) | buf[21];
  dev-》air_2_5um = ((rt_uint16_t)(buf[22])《《8) | buf[23];
  dev-》version = buf[len - 4];
  dev-》errorCode = buf[len - 3];
  return RT_EOK;
  }
  return RT_ERROR;
  }
  rt_err_t pms_get_byte(pms_device_t dev, char data)
  {
  rt_err_t result;
  static uint8_t state = FRAME_HEAD1;
  static uint8_t cnt = 0;
  static rt_uint8_t buf[40] = {0};
  RT_ASSERT(dev);
  if(state == FRAME_HEAD1 && data == COMM_START1)
  {
  buf[cnt++] = data;
  state = FRAME_HEAD2;
  }
  else if (state == FRAME_HEAD2 && data == COMM_START2)
  {
  buf[cnt++] = data;
  state = FRAME_LENH;
  }
  else if (state == FRAME_LENH)
  {
  buf[cnt++] = data;
  state = FRAME_LENL;
  }
  else if (state == FRAME_LENL)
  {
  buf[cnt++] = data;
  state = FRAME_RECEIVE;
  }
  else if (state == FRAME_RECEIVE)
  {
  buf[cnt++] = data;
  if(cnt 》= COMM_LEN - 1)
  state = FRAME_CHECK;
  }
  else if (state == FRAME_CHECK)
  {
  buf[cnt++] = data;
  state = FRAME_HEAD1;
  cnt = 0;
  result = frame_check(dev, buf, COMM_LEN);
  if (result == RT_EOK)
  {
  LOG_D(“check success”);
  return result;
  }
  else
  {
  LOG_E(“check error”);
  }
  }
  else {}
  return result;
  }
  pms_device_t pms_init(const char *uart_name)
  {
  pms_device_t dev;
  RT_ASSERT(uart_name);
  dev = rt_calloc(1, sizeof(struct pms_device));
  if (dev == RT_NULL)
  {
  LOG_E(“Can’t allocate memory for pms device %s”,uart_name);
  return RT_NULL;
  }
  dev-》serial = rt_device_find(uart_name);
  if (!dev-》serial)
  {
  rt_free(dev);
  rt_kprintf(“find %s failed!n”, uart_name);
  }
  else
  {
  dev-》config.baud_rate = BAUD_RATE_9600;
  dev-》config.data_bits = DATA_BITS_8;
  dev-》config.stop_bits = STOP_BITS_1;
  dev-》config.parity = PARITY_NONE;
  dev-》config.bit_order = BIT_ORDER_LSB;
  dev-》config.invert = NRZ_NORMAL;
  dev-》config.rx_bufsz = RT_SERIAL_RB_BUFSZ;
  dev-》config.reserved = 0;
  rt_device_control(dev-》serial, RT_DEVICE_CTRL_CONFIG, &dev-》config);
  }
  return dev;
  }
  void pms_deinit(pms_device_t dev)
  {
  RT_ASSERT(dev);
  rt_free(dev);
  }
  pms1003.h
  /*
  * Copyright (c) 2006-2021, RT-Thread Development Team
  *
  * SPDX-License-Identifier: Apache-2.0
  *
  * Change Logs:
  * Date Author Notes
  * 2023-03-08 DYC the first version
  */
  #ifndef SRC_PMS1003_H_
  #define SRC_PMS1003_H_
  #define DBG_TAG “pms_series”
  #define DBG_LVL DBG_INFO
  #include 《rtdbg.h》
  #include 《rthw.h》
  #include 《rtdevice.h》
  #define COMM_LEN 32
  struct pms_device
  {
  rt_device_t serial;
  struct serial_configure config;
  rt_uint16_t len;
  rt_uint16_t PM1_0_CF1;
  rt_uint16_t PM2_5_CF1;
  rt_uint16_t PM10_0_CF1;
  rt_uint16_t PM1_0_amb;
  rt_uint16_t PM2_5_amb;
  rt_uint16_t PM10_0_amb;
  rt_uint16_t air_0_3um;
  rt_uint16_t air_0_5um;
  rt_uint16_t air_1_0um;
  rt_uint16_t air_2_5um;
  rt_uint16_t air_5_0um;
  rt_uint16_t air_10_0um;
  rt_uint8_t version;
  rt_uint8_t errorCode;
  rt_uint16_t checksum;
  };
  typedef struct pms_device *pms_device_t;
  pms_device_t pms_init(const char *uart_name);
  rt_err_t frame_check(pms_device_t dev,rt_uint8_t *buf,rt_uint16_t len);
  rt_err_t pms_get_byte(pms_device_t dev, char data);
  void pms_deinit(pms_device_t dev);
  #endif /* SRC_PMS1003_H_ */
  五、烧录验证与扩展
  基本功能做完了,由于后续买的co2, 甲醛, IAQ模块还在路上,后续到了会继续往该系统中添加,还要与ESP8266 模块通信,完成本地系统数据远程访问,通过blinker实现数据的可视化,随时随地查看室内空气质量。




原作者:快乐小鸟

更多回帖

发帖
×
20
完善资料,
赚取积分