四、代码实现
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 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);
}
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2023-02-25 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_ */
/*
* 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》
#define LED1_PIN “P502” /* Onboard LED pins */
#define DBG_ENABLE
#define DBG_SECTION_NAME “pms_series”
#define DBG_LEVEL DBG_LOG
#define DBG_COLOR
#include 《rtdbg.h》
#include 《pms1003.h》
#define PMS_SERIES_UART “uart0”
#define DBG_ENABLE
struct rx_msg
{
rt_device_t dev;
rt_size_t size;
};
#ifdef PMS_SERIES_SAMPLE_USING_DMA
struct rt_messagequeue pms_mq;
#else
struct rt_semaphore pms_sem;
#endif
void pms_series_debug(pms_device_t dev)
{
LOG_D(“*********************************begin***********************************”);
LOG_D(“PM1_0_CF1 = %5dtPM2_5_CF1 = %5dtPM10_0_CF1 = %5d”,dev-》PM1_0_CF1,dev-》PM2_5_CF1,dev-》PM10_0_CF1);
LOG_D(“PM1_0_amb = %5dtPM2_5_amb = %5dtPM10_0_amb = %5d”,dev-》PM1_0_amb,dev-》PM2_5_amb,dev-》PM10_0_amb);
LOG_D(“air_0_3um = %5dtair_0_5um = %5dtair_1_0um = %5d”,dev-》air_0_3um,dev-》air_0_5um,dev-》air_1_0um);
LOG_D(“air_2_5um = %5dt”,dev-》air_2_5um);
LOG_D(“version = %5d errorCode = %5d”,dev-》version,dev-》errorCode);
LOG_D(“********************************over*************************************”);
}
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);
}
}
#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);
LOG_D(“rx buff success”);
}
else
{
LOG_E(“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 pms_sample(int argc, char *argv[])
int pms_sample()
{
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)
{
LOG_E(“init message queue failed.n”);
}
result = rt_device_open(dev-》serial, RT_DEVICE_FLAG_DMA_RX);
if (result != RT_EOK)
{
LOG_E(“open device failed.n”);
}
result = rt_device_set_rx_indicate(dev-》serial, uart_input);
if (result != RT_EOK)
{
LOG_E(“set rx indicate failed.n”);
}
#endif
rt_thread_t thread = rt_thread_create(“serial”, serial_thread_entry, dev, 1024, 3, 10);
if (thread != RT_NULL)
{
rt_thread_startup(thread);
}
else
{
ret = RT_ERROR;
}
return ret;
}
INIT_APP_EXPORT(pms_sample);
//MSH_CMD_EXPORT(pms_sample, pms_series drive sample);
void hal_entry(void)
{
rt_kprintf(“nHello RT-Thread!n”);
rt_uint32_t led1_pin = rt_pin_get(LED1_PIN);
while (1)
{
rt_pin_write(led1_pin, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(led1_pin, PIN_LOW);
rt_thread_mdelay(500);
}
}
五、 烧录验证