| **银杏科技有限公司旗下技术文档发布平台** |||| |技术支持电话|**0379-69926675-801**||| |技术支持邮件|Gingko@vip.163.com||| ^ 版本 ^ 日期 ^ 作者 ^ 修改内容 ^ | V1.0 | 2021-01-05 | yang | 初次建立 | ===== 实验三十三:lv_chart图表 ===== ==== 一、图表 ==== 图表是可视化数据点的基本对象,它有折线图(线上带点或不带点)和柱状图两种类型,还支持网格线、2个y轴、轴刻度和刻度文本。 图表的主体部分叫做 **LV_CHART_PART_BG** ,它使用所有典型的背景属性。其中**text**样式属性决定轴文本的样式,**line**属性决定刻度的样式,填充值在侧面增加了一些空间,因此会使数据序列区域更小,填充也可用于为轴文本和刻度线留出空间。 数据序列区域的背景称为 **LV_CHART_PART_SERIES_BG** ,并放置在主体背景上。在此部分上绘制了网格线和数据,除典型的背景样式属性外,网格线还使用线型属性。数据序列的样式可以通过 **LV_CHART_PART_SERIES** 引用。 对于柱状图,使用以下属性: * **radius** 柱的半径。 * **padding_inner** 相同 x 坐标的柱间距。 如果是折线图,则使用以下属性: * **line properties** 线属性来描述线。 * **size** 点的大小半径。 * **bg_opa** 线条下方区域的整体不透明度。 * **bg_main_stop** 在顶部的渐变透明度的百分比(0:在顶部透明,255:bg_opa 在顶部不透明)。 * **bg_grad_stop** 在底部的渐变透明度的百分比(0:底部透明,255:bg_opa 在底部不透明)。 * **bg_drag_dir**设置为 **LV_GRAD_DIR_VER** 使能通过 **bg_main_stop** 和 **bg_grad_stop** 进行透明度渐变功能。 ==== 二、图表数据 ==== === 2.1、数据序列 === 通过 **lv_chart_add_series(chart, color)** 可以在图表中添加多条数据序列。如果不使用外部数组,结构体 **lv_chart_series_t**将包含所选颜色和数据点的数组,如果分配了外部数组,则与该序列关联的任何数据点缩占用的内存都将释放,而数据系列将指向外部数组。 === 2.2、数据类型 === 数据显示类型有以下几种: * **LV_CHART_TYPE_NONE** 不显示任何数据,可用于隐藏系列。 * **LV_CHART_TYPE_LINE** 在两点之间画线。 * **LV_CHART_TYPE_COLUMN** 绘制柱。 指定显示类型使用**lv_chart_set_type(chart, LV_CHART_TYPE_...)**。 === 2.3、修改数据 === 有几种方式可以设置序列数据值: * 使用**ser1->points[3] = 7**在数组中手动设置值,并使用**lv_chart_refresh(chart)**刷新图表。 * 使用**lv_chart_set_point_id(chart, ser, value, id)**,其中 **id** 是要更新的点的索引。 * 使用 **lv_chart_set_next(chart, ser, value)** 在数据末尾添加新值。 * 将所有点初始化为给定值**lv_chart_init_points(chart, ser, value)**。 * 使用**lv_chart_set_points(chart, ser, value_array)**设置数组中的所有点。 注意:使用** LV_CHART_POINT_DEF** 作为值时,图表将跳过此步骤,不绘制数据。 === 2.4、修改数列的默认起点 === 如果希望从默认点(序列的**point[0]**)以外的其他点开始绘图,则可以使用函数 **lv_chart_set_x_start_point(chart, ser, id)** 设置新的起始索引,其中** id** 是开始绘图的新索引位置。 === 2.5、设置外部数据源 === 使用**lv_chart_set_ext_array(chart, ser, array, point_cnt )** 可以将外部数据源分配给图表数据系列,其中** array** 是 **lv_coord_t** 的外部数组,具有** point_cnt** 个元素。注意:在外部数据源更新后应该调用**lv_chart_refresh(chart)** 以更新图表。 ==== 三、图表设置 ==== === 3.1、获取当前图表信息 === 有四种方式可获取有关图表的信息: * **lv_chart_get_type(chart)** 返回当前图表类型。 * **lv_chart_get_point_count(chart)** 返回当前图表点数。 * **lv_chart_get_x_start_point(ser)** 返回指定数据序列的当前绘图索引。 * **lv_chart_get_point_id(chart, ser, id)** 返回指定数据序列的指定索引处的数据值。 === 3.2、更新方式 === 在末尾添加新值的情况下** (lv_chart_set_next)**,有两种更新模式: * **LV_CHART_UPDATE_MODE_SHIFT** 将旧数据整体向左移动一位,丢掉第一个,然后在右侧末尾添加新数据。 * **LV_CHART_UPDATE_MODE_CIRCULAR** 循环添加新数据(类似心电图,总是从前往后逐个更新数据)。 使用 **lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_...)** 可以更改图表的更新模式。 === 3.3、点数 === 数据序列中的点数默认值为 **10**,可以通过 **lv_chart_set_point_count(chart, point_num)** 来修改。注意:将外部缓冲区分配给序列时,也会影响处理点的数量。 === 3.4、垂直范围 === 使用 **lv_chart_set_range(chart, y_min, y_max)** 可以指定 **y** 轴方向上的最小值和最大值。数据点的值将按比例缩放。默认范围是:**[0,100]**。 === 3.5、网格线 === 水平和垂直网格线的数量可以通过**lv_chart_set_div_line_count(chart, hdiv_num, vdiv_num)** 来修改。默认设置为 3 条水平分割线和 5 条垂直分割线。 === 3.6、刻度线和标签 === 坐标轴可以添加刻度线和标签。 若要想在 x 轴上设置刻度线和标签文本,可以使用**lv_chart_set_x_tick_text(chart, list_of_values, num_tick_marks, LV_CHART_AXIS_...)**,** list_of_values** 是一个带有 '**\n**' 终止文本(最后一个元素没有)且带有用于刻度的文本的字符串,例如:**const char * list_of_values = "first\nsec\nthird"**。如果设置了**list_of_values**,则**num_tick_marks**为两个标签之间的刻度数。**list_of_values**可以为**NULL**,如果为**NULL**,则它指定总的刻度数。 主刻度线绘制在放置文本的位置,次刻度线绘制在其他位置。要设置 x 轴上刻度线的长度,使用**lv_chart_set_x_tick_length(chart, major_tick_len, minor_tick_len)**。同样的,要设置y 轴也有相同功能的函数 **lv_chart_set_y_tick_text 和 lv_chart_set_y_tick_length** 。 下面的例子实现的功能为,从ADC读取iCore4T电源电压值并以折线图的形式绘制在图表中,上方的文本显示当前电压值,下方的滑块可以调节当前y轴的显示区间[0v,6v]。 {{ :icore4t:icore4t_rtt_lvgl_33_1.gif?direct |}} // main.c 文件内容 #include #include #include #include "gui.h" #include "power_adc.h" #define LED0_PIN GET_PIN(A, 10) /* 定义LED引脚 */ #define THREAD_PRIORITY 25 /* 线程优先级 */ #define THREAD_STACK_SIZE 1024 /* 线程堆栈大小 */ #define THREAD_TIMESLICE 5 /* 线程时间片 */ static rt_thread_t tid1 = RT_NULL; /* 定义线程 */ int main(void) { lv_gui_run(); /* 绘制图形界面 */ /* 创建线程,获取AD值更新到图表 */ tid1 = rt_thread_create("thread1", power_adc_run, RT_NULL, THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); if (tid1 != RT_NULL) rt_thread_startup(tid1); /* 启动线程 */ rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); /* 设置LED引脚为输出模式 */ while(1){ rt_pin_write(LED0_PIN, PIN_HIGH); /* LED闪烁 */ rt_thread_mdelay(100); rt_pin_write(LED0_PIN, PIN_LOW); rt_thread_mdelay(100); } return RT_EOK; } // power_adc.c 文件内容 #include #include #include #include "lvgl.h" #include "gui.h" #include "power_adc.h" void power_adc_run(void *parameter) { /* 电源AD读取线程入口函数 */ int value = 0; int voltage; static rt_adc_device_t adc_device = RT_NULL; adc_device = (rt_adc_device_t)rt_device_find("adc1"); /* 搜搜索ADC设备 */ if(adc_device != RT_NULL){ while(1){ value = rt_adc_read(adc_device, atoi("16"));/* 读取电源电压,通道16 */ voltage = (int) (value*1500/65535); /* 换算电压值*100 */ lv_chart_set_next(chart, ser1, voltage); /* 更新数据序列 */ lv_chart_refresh(chart); /* 刷新图标 */ /* 更新标签 */ lv_label_set_text_fmt(label, "The voltage of iCore4T is: %d.%d v", voltage/100, voltage%100); rt_thread_mdelay(100); /* 100ms采集一次 */ } } } // gui.c 图形界面绘制函数 void lv_gui_run(void) { lvgl2rtt_init("lcd"); /* 初始化lvgl2rtt */ chart = lv_chart_create(lv_scr_act(), NULL); /* 创建图表 */ lv_obj_set_size(chart, 200, 150); /* 设置尺寸 */ lv_obj_align(chart, NULL, LV_ALIGN_CENTER, 0, 0); /* 设置位置 */ lv_chart_set_type(chart, LV_CHART_TYPE_LINE); /* 选择折线图 */ lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT);/* 更新模式为左移 */ lv_chart_set_y_tick_texts(chart, list_of_values, NULL, LV_CHART_AXIS_PRIMARY_Y); /* 设置刻度 */ lv_chart_set_range(chart, 440, 470); /* 设置y轴显示范围 */ lv_chart_set_point_count(chart, 50); /* 设置图表点数 */ lv_obj_set_style_local_bg_opa(chart, LV_CHART_PART_SERIES, LV_STATE_DEFAULT, LV_OPA_50); lv_obj_set_style_local_bg_grad_dir(chart, LV_CHART_PART_SERIES, LV_STATE_DEFAULT , LV_GRAD_DIR_VER); lv_obj_set_style_local_bg_main_stop(chart, LV_CHART_PART_SERIES, LV_STATE_DEFAULT, 255); /* 顶部透明度 */ lv_obj_set_style_local_bg_grad_stop(chart, LV_CHART_PART_SERIES, LV_STATE_DEFAULT, 200); /* 底部透明度 */ ser1 = lv_chart_add_series(chart, LV_COLOR_RED); /* 图表添加红色线 */ lv_chart_init_points(chart, ser1, 0); /* 赋初值为0 */ lv_chart_refresh(chart); /* 刷新图表 */ label = lv_label_create(lv_scr_act(), NULL); /* 创建标签 */ lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, -105, 20); /* 设置位置 */ lv_obj_t * slider = lv_slider_create(lv_scr_act(), NULL); /* 创建滑块 */ lv_slider_set_value(slider, 30, LV_ANIM_OFF); /* 设置初始值 */ lv_obj_set_event_cb(slider, slider_event_cb); /* 绑定回调函数 */ lv_slider_set_range(slider, 0, 600); /* 设置值范围 */ lv_obj_set_size(slider, 200, 10); /* 设置滑块尺寸 */ lv_obj_align(slider, NULL, LV_ALIGN_CENTER, 0, 100); /* 设置滑块位置 */ lv_slider_set_type(slider, LV_SLIDER_TYPE_RANGE); /* 设置双点模式 */ lv_slider_set_left_value(slider, 440, LV_ANIM_OFF); /* 设置左值位置 */ lv_slider_set_value(slider, 470, LV_ANIM_OFF); /* 设置右值位置 */ } 更改样式,显示刻度坐标可以参考下例: {{ :icore4t:icore4t_rtt_lvgl_33_2.png?direct |}} // power_adc.c 文件内容 static lv_style_t style1; /* 新建样式 */ lv_style_set_bg_color(&style1, LV_CHART_PART_BG, LV_COLOR_BLUE); /* 背景色蓝色*/ lv_style_set_pad_left(&style1, LV_STATE_DEFAULT, LV_DPX(240)); /* 左填充 */ chart = lv_chart_create(lv_scr_act(), NULL); /* 创建图表 */ lv_obj_set_size(chart, 300, 150); /* 设置尺寸 */ lv_obj_add_style(chart,LV_OBJ_PART_MAIN, &style1); /* 设置样式 */ lv_chart_set_div_line_count(chart, 5, 7); /* 设置网格线 */ lv_obj_align(chart, NULL, LV_ALIGN_CENTER, 0, 0); /* 设置位置 */ lv_chart_set_type(chart, LV_CHART_TYPE_LINE); /* 选择折线图 */ lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT); /* 更新模式为左移 */ lv_chart_set_y_tick_texts(chart, list_of_values, NULL, LV_CHART_AXIS_PRIMARY_Y); /* 设置刻度 */ lv_chart_set_range(chart, 0, 600); /* 设置y轴显示范围 */ lv_chart_set_point_count(chart, 50); /* 设置图表点数 */