1. 引言
本文设计了基于CH32V307和TencentOS Tiny的环境监测系统,通过DHT11传感器读取相关的数据,将温湿度数据显示在LCD上,并通过ESP8266实现下位机与腾讯云的连接,将该数据上传到腾讯云上,实现云端数据的监视。
2. 硬件介绍
整体架构
2.1 单片机
单片机采用CH32V307VCT6的芯片,CH32V307系列是基于32位RISC-V设计的互联型微控制器,配备了硬件堆栈区、快速中断入口,在标准RISC-V基础上大大提高了中断响应速度。加入单精度浮点指令集,扩充堆栈区,具有更高的运算性能。CH32V307是基于32位RISC-V设计的互联型微控制器,配备了硬件堆栈区、快速中断入口,在标准RISC-V基础上大大提高了中断响应速度。加入单精度浮点指令集,扩充堆栈区,具有更高的运算性能。扩展串口UART数量到8组,电机定时器到4组。提供USB2.0高速接口(480Mbps)并内置了PHY收发器,以太网MAC升级到千兆并集成了10M-PHY模块。
硬件使用的是 TencentOS Tiny CH32V_EVB RISC-V开发套件,板载Type-C接口WCH-LINK仿真器,板载esp8266 WiFi模组,支持腾讯云固件。
2.2 温湿度传感器
DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度±5%RH, 温度±2℃,量程湿度5~95%RH, 温度-20~+60℃。
2.3 显示模块
LCD模块使用的是ST7789,一般是用于262K彩色TFT-LCD的单片控制器/驱动程序。它由960条源线和480条栅线驱动电路组成。ST7796S能够连接直接 Y为外部微处理器,接受8位/9位/16位/18位并行接口,spi和ST7796S也提供mipi接口。
这是官网提供的原理图。
2.4 通信模块
通信模块使用是ESP8266,可以直接烧录腾讯云的AT固件,连接腾讯云的物联网平台非常简单。ESP-12F是安信可用ESP8266EX芯片做的一款WiFi模组,这个模块已经把内部的电路设计好了。实际测试,ESP01和01s不如12f系列的稳定,经常出问题,要是长期使用还是建议使用12f系列。
2.5 效果图
3 程序设计
程序分为三个任务,分别为温湿度采集、数据显示、数据上传三个任务。
(1)创建任务
其中任务1为数据显示,任务2为温湿度采集,任务3为上传上传。
tos_mail_q_create(&mail_q, mail_pool, MAIL_MAX, sizeof(mail_t));
tos_task_create(&task1, "task1", task1_entry, NULL, 3, task1_stk, TASK1_STK_SIZE, 0); // Create task1
tos_task_create(&task2, "task2", task2_entry, NULL, 3, task2_stk, TASK2_STK_SIZE, 0);// Create task2
tos_task_create(&task3, "task3", task3_entry, NULL, 2, task3_stk, TASK3_STK_SIZE, 0);// Create task3
(2)温湿度采集数据
温湿度采用的是DHT11采集环境信息,由于DHT11对延时要求比较高,所以该设计采用的是定时器实现延时。采用的是定时器3.
初始化定时器3,实现定时器分频。
void TIM3_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); ///使能TIM3时钟
TIM_TimeBaseInitStructure.TIM_Period = 0xffff; //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler = 144-1; //定时器分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
}
延时函数
//微秒级延时
void TIM3_Delayus(u16 xus)
{
TIM_Cmd(TIM3,ENABLE); //启动定时器
while(TIM3->CNT < xus);
TIM3->CNT = 0;
TIM_Cmd(TIM3,DISABLE); //关闭定时器
}
任务函数
void task2_entry(void *arg)
{
u8 temperature=0;
u8 humidity=0;
mail_t mail;
while (1) {
DHT11_Read_Data(&temperature,&humidity); //读取温湿度值
mail.temp = temperature;
mail.humi = humidity;
tos_mail_q_post_all(&mail_q, &mail, sizeof(mail_t));
tos_task_delay(5000);
}
}
(2)该系统移植的是系统中自带的LCD模块驱动代码,这里我添加的是实现汉字和英文混合显示的功能。其代码如下所示
void LCD_ShowStringCn(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey,u8 mode)
{
while(*s!='\0')
{
if(*s<128){
LCD_ShowChar(x,y,*s,fc,bc,sizey,mode);
x+=sizey/2;
s++;
}
else{
if(sizey==12) LCD_ShowChinese12x12(x,y,s,fc,bc,sizey,mode);
else if(sizey==16) LCD_ShowChinese16x16(x,y,s,fc,bc,sizey,mode);
else if(sizey==24) LCD_ShowChinese24x24(x,y,s,fc,bc,sizey,mode);
else if(sizey==32) LCD_ShowChinese32x32(x,y,s,fc,bc,sizey,mode);
else return;
s+=2;
x+=sizey;
}
}
}
这里需要自己取字模,字模的格式如下
创建的显示任务代码
void task1_entry(void *arg)
{
k_err_t err;
mail_t mail;
size_t mail_size;
u8 s_temp[128];
LCD_ShowString(0,0,"Welcome TencentOS",WHITE,BLACK,16,0);
while (1) {
err = tos_mail_q_pend(&mail_q, &mail, &mail_size, TOS_TIME_FOREVER);
if (err == K_ERR_NONE) {
TOS_ASSERT(mail_size == sizeof(mail_t));
printf("温度: %d, 湿度:%d \n", mail.temp, mail.humi);
sprintf(s_temp,"温度: %d, 湿度:%d ",mail.temp, mail.humi);
LCD_ShowStringCn(0,32,s_temp,GREEN,BLACK,16,0);
}
}
}
(3)创建上传任务代码
#define QOS0 0
void task3_entry(void *arg)
{
k_err_t err;
mail_t mail;
size_t mail_size;
char payload[256] = {0};
u8 temperature=0;
u8 humidity=0;
mqtt_state_t state;
char *product_id = "0G95XV3IEP";
char *device_name = "isnt0";
char *key = "C8CJeD69bCFvwsD13gnyBA==";
device_info_t dev_info;
memset(&dev_info, 0, sizeof(device_info_t));
esp8266_tencent_firmware_sal_init(HAL_UART_PORT_2);
esp8266_tencent_firmware_join_ap("TP-LINK_XXXX", "11112222");
strncpy(dev_info.product_id, product_id, PRODUCT_ID_MAX_SIZE);
strncpy(dev_info.device_name, device_name, DEVICE_NAME_MAX_SIZE);
strncpy(dev_info.device_serc, key, DEVICE_SERC_MAX_SIZE);
tos_tf_module_info_set(&dev_info, TLS_MODE_PSK);
mqtt_param_t init_params = DEFAULT_MQTT_PARAMS;
if (tos_tf_module_mqtt_conn(init_params) != 0) {
printf("module mqtt conn fail\n");
} else {
printf("module mqtt conn success\n");
}
if (tos_tf_module_mqtt_state_get(&state) != -1) {
printf("MQTT: %s\n", state == MQTT_STATE_CONNECTED ? "CONNECTED" : "DISCONNECTED");
}
static char topic_name[TOPIC_NAME_MAX_SIZE] = {0};
static char topic_name_sub[TOPIC_NAME_MAX_SIZE] = {0};
int size = snprintf(topic_name, TOPIC_NAME_MAX_SIZE, "$thing/up/property/%s/%s", product_id, device_name);
if (size < 0 || size > sizeof(topic_name) - 1) {
printf("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name));
}
size = snprintf(topic_name_sub, TOPIC_NAME_MAX_SIZE, "$thing/down/property/%s/%s", product_id, device_name);
if (size < 0 || size > sizeof(topic_name) - 1) {
printf("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name));
}
if (tos_tf_module_mqtt_sub(topic_name_sub, QOS0, default_message_handler) != 0) {
printf("module mqtt sub fail\n");
} else {
printf("module mqtt sub success\n");
}
while (1) {
/* use AT+PUB AT command */
memset(payload, 0, sizeof(payload));
sprintf(payload, "{\\\"method\\\":\\\"report\\\"\\,\\\"clientToken\\\":\\\"123\\\"\\,\\\"params\\\":{\\\"temp\\\":%d\\,\\\"humi\\\":%d}}",temperature,humidity);
printf("message publish: %s\n", payload);
if (tos_tf_module_mqtt_pub(topic_name, QOS0, payload) != 0) {
printf("module mqtt pub fail\n");
break;
} else {
printf("module mqtt pub success\n");
}
err = tos_mail_q_pend(&mail_q, &mail, &mail_size, TOS_TIME_FOREVER);
if (err == K_ERR_NONE) {
TOS_ASSERT(mail_size == sizeof(mail_t));
temperature = mail.temp ;
humidity= mail.humi ;
}
}
}
4 云平台设计
(1)物模型的搭建
(2)数据显示
这是完整的代码,在TencentOS-tiny-master\board\替换TencentOS_Tiny_CH32V307_EVB文件夹即可。 TencentOS_Tiny_CH32V307_EVB.rar
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。