[平头哥RVB2601创意应用开发]体验分享四:ADC 多通道测试+LVGL显示
# 欢迎使用Markdown编辑器## 合集
###1. [平头哥RVB2601创意应用开发]体验分享一:开箱、环境搭建、输出helloworld](https://bbs.eeworld.com.cn/thread-1197148-1-1.html)
###2. [平头哥RVB2601创意应用开发]体验分享二:多种方式点灯,组件学习](https://bbs.eeworld.com.cn/thread-1197151-1-1.html)
###3. [[平头哥RVB2601创意应用开发]体验分享三:基于RTOS实现按键控制LED](https://bbs.eeworld.com.cn/thread-1197189-1-1.html)
## 一、 ADC的使用
### 1.1 硬件分析
主要使用2601的ADC采集joystick的x和y方向AD值。
通过芯片和电路分析,这里使用PA5(PA5_ADC_A3)和PA6(PA6_ADC_A4),分别是2601的ADC_CH2和ADC_CH3.
如下图所示,断开原来J1(11-12)和J2(5-6)的短接帽,然后将J1-11和J2_6分别连接joystick的x、y信号输出。
### 1.2 ADC初始化
这里使用CSI2接口。(https://yoc.docs.t-head.cn/yocbook/Chapter3-AliOS/CSI%E8%AE%BE%E5%A4%87%E9%A9%B1%E5%8A%A8%E6%8E%A5%E5%8F%A3/CSI2/ADC.html)
这里主要使用以下函数:
函数 说明
csi_adc_init ADC设备初始化
csi_adc_start 启动ADC数据转换(同步)
csi_adc_channel_enable 开启或者关闭一个ADC通道
csi_adc_channel_sampling_time 设置通道采样时间
csi_adc_sampling_time 设置ADC采样时间
csi_adc_freq_div 设置ADC分频系数
主要代码如下:
```
void myAdc_init(void)
{
int ret;
/* GPIO init */
csi_pin_set_mux(EXAMPLE_ADC_CHANNEL3_PIN, EXAMPLE_ADC_CHANNEL3_PIN_FUNC); //通道3引脚复用
csi_pin_set_mux(EXAMPLE_ADC_CHANNEL2_PIN, EXAMPLE_ADC_CHANNEL2_PIN_FUNC); //通道2引脚复用
/* Initialize ADC peripheral */
ret = csi_adc_init(&adc, 0); // 0为idx默认值。
if (ret != CSI_OK)
LOGD(TAG, "adc init error .\n");
/* Configure frequency divsion, this value can be one of(4 8 16 32 64 128) */
ret = csi_adc_freq_div(&adc, 128);
if (ret != CSI_OK)
LOGD(TAG, "adc_freq_div = %d .\n", ret);
/* Configure sampling time */
ret = csi_adc_sampling_time(&adc, 5);
if (ret != CSI_OK)
LOGD(TAG, "adc_sampling_time error .\n");
ret = csi_adc_channel_enable(&adc, EXAMPLE_ADC_CHANNEL3, true); //使能通道3
if (ret != CSI_OK)
LOGD(TAG, "channel3_enable error .\n");
ret = csi_adc_channel_enable(&adc, EXAMPLE_ADC_CHANNEL2, true); //使能通道2
if (ret != CSI_OK)
LOGD(TAG, "channel2_enable error .\n");
}
```
### 1.3 读取转换结果
csi_adc_read 读取ADC转换结果
主要代码如下:
```
// 一次转换一个通道,按顺序依次从使能的通道,按照通道号由小到大逐个通道转换。
// 这里调用myAdc_get()函数两次,即可以转换通道2和通道3.
uint32_t myAdc_get(void)
{
int32_t ret;
/* Trigger new conversion */
ret = csi_adc_start(&adc);
if (ret != CSI_OK)
LOGD(TAG, "adc_start error .\n");
/* Read result */
ret = csi_adc_read(&adc);
return ret;
}
```
### 1.4 主函数中任务设计
```
static void application_adcTask_entry(void *arg)
{
uint32_t res_x = 0,res_y =0; //保存转换结果
myAdc_init();//adc初始化
while (1)
{
res_x = myAdc_get(); //获取通道2 结果
res_y = myAdc_get(); //获取通道3结果;这里顺序是按照使能的通道,按照通道号由小到大逐次转换,因为使能了2个通道,所以调用两次
LOGD(TAG, "adc = %d,%d\n", res_x,res_y);//串口打印转换结果
//互斥量上锁,将结果传送到adcRes[]供lvgl任务调用
if (1 == aos_mutex_is_valid(&adc_mutex))
{
aos_mutex_lock(&adc_mutex, AOS_WAIT_FOREVER);
adcRes = res_x;
adcRes = res_y;
aos_mutex_unlock(&adc_mutex);
}
aos_msleep(1000);
}
aos_task_exit(0);
}
```
## 二、 使用lvgl label显示AD转换值
### 2.1 oled驱动和lvgl gui库的移植
这里使用ch2601_gui_demo中的文件,oeld.c和oled.h。
###2.2 lvgl任务设计
界面如下:
全局变量定义:
---
```
lv_obj_t *lbl_adc_x = NULL;
lv_obj_t *lbl_adc_y = NULL;
```
创建label子函数:
---
```
static void gui_label_create(void)
{
lv_obj_t *lbl_title = lv_label_create(lv_scr_act(), NULL);
lv_label_set_long_mode(lbl_title, LV_LABEL_LONG_BREAK);
lv_label_set_align(lbl_title, LV_LABEL_ALIGN_CENTER);
lv_obj_set_pos(lbl_title, 0, 2);
lv_obj_set_size(lbl_title, 128, 20);
lv_label_set_text(lbl_title, "LVGL ADC DEMO");
lbl_adc_x = lv_label_create(lv_scr_act(), lbl_title);
lv_obj_set_pos(lbl_adc_x, 0, 30);
lv_obj_set_size(lbl_adc_x, 64, 20);
lv_label_set_text(lbl_adc_x, "X:0000");
lbl_adc_y = lv_label_create(lv_scr_act(), lbl_adc_x);
lv_obj_set_pos(lbl_adc_y, 64, 30);
lv_label_set_text(lbl_adc_y, "Y:0000");
}
```
lvgl任务:
---
```
static void application_lvglTask_entry(void *arg)
{
lv_init();
/*Initialize for LittlevGL*/
oled_init();
/*Select display 1*/
gui_label_create();
while (1)
{
if (1 == aos_mutex_is_valid(&adc_mutex))
{
aos_mutex_lock(&adc_mutex, AOS_WAIT_FOREVER);
lv_label_set_text_fmt(lbl_adc_x, "X:%d", adcRes);
lv_label_set_text_fmt(lbl_adc_y, "Y:%d", adcRes);
aos_mutex_unlock(&adc_mutex);
}
/* Periodically call the lv_task handler.
* It could be done in a timer interrupt or an OS task too.*/
lv_task_handler();
aos_msleep(10);
lv_tick_inc(1);
}
}
```
## 三、 运行结果
## 四、 总结
4.1 反而是最基础的功能,遇到了很多的坑。
4.1.1 一开始使用了ADC的HAL库,运行结果不正确。折腾了好久,最后换成了csi方案,虽然hal里也是使用了csi接口来完成的。随后抽时间再试试。
4.1.2 无论是CSI接口还是HAL接口,一直掉坑的原因是官方文档对关键参数的解释和说明上,几乎就没有,另外就是接口库过多,没有统一的对这些接口的使用说明,然后在使用和选择上花费大量的时间。
4.2 AD的连续转换模式和dma模式的使用
连续转换是否能够一次完成两个通道的转换,这个需要随后再考证。
使用DMA的话,可以多次采集完成一些滤波算法。这里对数据不敏感,有时间再测试。 <p>我还想能显示波形呢,那样更厉害~</p>
wangerxian 发表于 2022-4-6 15:56
我还想能显示波形呢,那样更厉害~
<p>使用chart组件?</p> wo4fisher 发表于 2022-4-7 00:08
使用chart组件?
<p>可以啊~试试呗。</p>
页:
[1]