玩转RT-Thread系列教程(9)--485总线读取温湿度


玩转RT-Thread系列教程(9)–485总线读取温湿度

一、485总线介绍

485(一般称作 RS485/EIA-485)是隶属于 OSI 模型物理层的电气特性规定为 2 线,半双工,多点通信的标准。它的电气特性和 RS-232 大不一样。用缆线两端的电压差值来表示传递信号。RS485 仅仅规定了接受端和发送端的电气特性。它没有规定或推荐任何数据协议。

RS485 的特点包括:

1) 接口电平低,不易损坏芯片。RS485 的电气特性:逻辑“1”以两线间的电压差为+(26)V表示;逻辑“0”以两线间的电压差为-(26)V 表示。接口信号电平比 RS232 降低了,不易损坏接口电路的芯片,且该电平与 TTL 电平兼容,可方便与 TTL 电路连接。

2) 传输速率高。10 米时,RS485 的数据最高传输速率可达 35Mbps,在 1200m 时,传输速度可达 100Kbps。

3) 抗干扰能力强。RS485 接口是采用平衡驱动器和差分接收器的组合,抗共模干扰能力增强,即抗噪声干扰性好。

4) 传输距离远,支持节点多。RS485 总线最长可以传输 1200m 以上(速率≤100Kbps)一般最大支持 32 个节点,如果使用特制的 485 芯片,可以达到 128 个或者 256 个节点,最大的可以支持到 400 个节点。

在这里插入图片描述

二、485温湿度传感器使用

2.1、使用PC测试485通信

首先,先按照规定接线方式,进行安装连接,连接好后,打开CommMontor串口监控精灵,如下图:

链接:https://pan.baidu.com/s/1Q6jRuoZfVMEH-rt7gZ5BNw 提取码:y89c

其中 01 03 00 00 00 02 C4 0B为问询帧,所以只要串口发送这一串十六进制即可得到485总线回复

2.2、使用RT-Thread进行485通信

根据我们之前串口实验,我们只需稍作修改即可完成485的通信。

2.2.1、编写485通信代码
uint16_t temp = 0;  //定义温度变量
uint16_t humi = 0;  //定义湿度变量

char tem[10] = {0}; //存放温度数据的数组
char hum[10] = {0}; //存放湿度数据的数组

unsigned char sensor_T_H[8] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B}; //温湿度传感器

static void serial_thread_entry(void *parameter)
{
    struct rx_msg msg;
    rt_err_t result;
    rt_uint32_t rx_length;
    static char rx_buffer[RT_SERIAL_RB_BUFSZ + 1];

    while (1)
    {
        rt_memset(&msg, 0, sizeof(msg));

        rt_device_write(serial, 0, sensor_T_H, sizeof(sensor_T_H));  //发送采集数据指令

        /* 从消息队列中读取消息*/
        result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);

        if (result == RT_EOK)
        {
            /* 从串口读取数据*/
            rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);

            for(uint8_t a = 0; a < 8; a++)
            {
                rt_kprintf("sensor[%d] = %.2x \r\n", a, rx_buffer[a]);
            }

            temp = 1.0 * ((rx_buffer[3] << 8) + rx_buffer[4]);
            humi = 1.0 * ((rx_buffer[5] << 8) + rx_buffer[6]);

            sprintf((char*)tem, "%.2f", (float)temp / 100); //拼接到温度数组里
            sprintf((char*)hum, "%.2f", (float)humi / 100); //拼接到湿度数组里

            /* 打印数据 */
            rt_kprintf("tem:[%s]    hum:[%s]\r\n", tem, hum);

                        rt_thread_mdelay(1000);
        }
    }
}

当然了,不要忘记,485问询串口的比特率是9600!!所以我们需要在串口初始化添加修改波特率的配置。

    config.baud_rate = BAUD_RATE_9600;        //修改波特率为 9600
    config.data_bits = DATA_BITS_8;           //数据位 8
    config.stop_bits = STOP_BITS_1;           //停止位 1
    config.bufsz     = 64;                       //修改缓冲区 buff size 为 128
    config.parity    = PARITY_NONE;           //无奇偶校验位
    rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);

2.3、编译、下载、查看结果

通过串口可以清晰的看到485设备返回的帧,通过拼接即可得到正确的温度湿度数据。

三、使用LVGL显示温湿度数据

这次我们要结合LVGL来动态显示温湿度数据。为了达到直观的效果,这里的显示我用折线图来显示,用到的控件为lv_chart。

3.1、编码设计

extern int16_t temp;  //定义温度变量
extern int16_t humi;  //定义湿度变量

const lv_coord_t series1_y[POINT_COUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
const lv_coord_t series2_y[POINT_COUNT] = {5, 5, 5, 5, 5, 5, 5, 5, 5, 5};

lv_style_t chart_style;
lv_chart_series_t * series1;
lv_chart_series_t * series2;

//任务回调函数
void task_cb(lv_task_t * task)
{
        //往series1数据线上添加新的数据点
        lv_chart_set_next(chart1,series1,temp);
        //往series2数据线上添加新的数据点
        lv_chart_set_next(chart1,series2,humi);
}

void lv_gauge_test_start(lv_obj_t * parent)
{
        //1.创建样式
        lv_style_copy(&chart_style,&lv_style_pretty);
        chart_style.body.main_color = LV_COLOR_WHITE;
        chart_style.body.grad_color = chart_style.body.main_color;
        chart_style.body.border.color = LV_COLOR_BLACK;
        chart_style.body.border.width = 3;
        chart_style.body.border.opa = LV_OPA_COVER;
        chart_style.body.radius = 1;
        chart_style.line.color = LV_COLOR_GRAY;
        chart_style.text.color = LV_COLOR_WHITE;

        //2.创建图表对象
        chart1 = lv_chart_create(parent,NULL);
        lv_obj_set_size(chart1,250,200);
        lv_obj_align(chart1,NULL,LV_ALIGN_IN_RIGHT_MID,-70,0);
        lv_chart_set_type(chart1,LV_CHART_TYPE_LINE);
        lv_chart_set_series_opa(chart1,LV_OPA_80);
        lv_chart_set_series_width(chart1,4);
        lv_chart_set_series_darking(chart1,LV_OPA_80);
        lv_chart_set_style(chart1,LV_CHART_STYLE_MAIN,&chart_style);
        lv_chart_set_point_count(chart1,POINT_COUNT);
        lv_chart_set_div_line_count(chart1,4,4);
        lv_chart_set_range(chart1,0,100);
        lv_chart_set_y_tick_length(chart1,10,3);
        lv_chart_set_y_tick_texts(chart1,"100\n90\n80\n70\n60\n50\n40\n30\n20\n10\n0",5,LV_CHART_AXIS_DRAW_LAST_TICK);
        lv_chart_set_x_tick_length(chart1,10,3);
        lv_chart_set_x_tick_texts(chart1,"0\n2\n4\n6\n8\n10",5,LV_CHART_AXIS_DRAW_LAST_TICK);
        lv_chart_set_margin(chart1,40);
        //2.2 往图表中添加第1条数据线
        series1 = lv_chart_add_series(chart1,LV_COLOR_RED);
        lv_chart_set_points(chart1,series1,(lv_coord_t*)series1_y);

        //2.3 往图表中添加第2条数据线
        series2 = lv_chart_add_series(chart1,LV_COLOR_BLUE);
        lv_chart_set_points(chart1,series2,(lv_coord_t*)series2_y);

        lv_chart_refresh(chart1);

    //4.创建一个任务来显示变化
    lv_task_create(task_cb, 300, LV_TASK_PRIO_MID, NULL);
}

3.2、实现效果

当握住温湿度传感器我们可以直观的看到,温度和湿度发生了明显变化,是不是很有成就感呢。


文章作者: Rb菌
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Rb菌 !
  目录