玩转RT-Thread系列教程(8)--ADC—光敏数据的采集


玩转RT-Thread系列教程(8)–ADC—光敏数据的采集

一、查看电路原理图

光敏电阻

二、添加ADC—DMA配置

1.配置Cubemx

为ADC设置频率,72/6=12分频

DMA配置

关闭终端

生成代码

2.添加Kconfig中ADC配置

3.打开env,配置ADC3

menuconfig

4.保存配置,生成mdk工程

三、ADC外设的使用

1.添加adc外设初始化

打开stm32f1xx_hal_msp.c我们可以看见,cubemx生成的代码自动添加到了该文件中。

接下来我们打开main.c复制一下初始化部分。

/**
  * @brief ADC3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC3_Init(void)
{

  /* USER CODE BEGIN ADC3_Init 0 */

  /* USER CODE END ADC3_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC3_Init 1 */

  /* USER CODE END ADC3_Init 1 */
  /** Common config
  */
  hadc3.Instance = ADC3;
  hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc3.Init.ContinuousConvMode = ENABLE;
  hadc3.Init.DiscontinuousConvMode = DISABLE;
  hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc3.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc3) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_5;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC3_Init 2 */

  /* USER CODE END ADC3_Init 2 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();

}

2.编写业务逻辑,获取光敏传感器数值

因为开发板IO引脚的电压最高为3.3v,同时ADC采用16字节对齐,所以最大数值为4096,经过换算得出换算电压公式:

V(adc) = ADC * 3.3 / 4096

完整代码:

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#include "button_app.h"

ADC_HandleTypeDef hadc3;
DMA_HandleTypeDef hdma_adc3;

//定义key 控制块
struct key_state_type key0 = { 0 };
struct key_state_type key1 = { 0 };

static void MX_ADC3_Init(void);
static void MX_DMA_Init(void);
static void Get_Light_Value(void);

static uint16_t adc_data;
static uint32_t light_value;

int main(void)
{
        MX_DMA_Init();
        MX_ADC3_Init();
        HAL_ADC_Start(&hadc3);
        HAL_ADC_Start_DMA(&hadc3,(uint32_t*)&adc_data,(uint32_t)1);

    while (1)
    {
                Get_Light_Value();
        rt_pin_write(LED0_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(LED0_PIN, PIN_LOW);
        rt_thread_mdelay(500);
    }
}

void Get_Light_Value(void)
{
        light_value = adc_data * 330/4096;
        rt_kprintf("light value is:%d.%02d\r\n",light_value/100,light_value%100);
}

/**
  * @brief ADC3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC3_Init(void)
{

  /* USER CODE BEGIN ADC3_Init 0 */

  /* USER CODE END ADC3_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC3_Init 1 */

  /* USER CODE END ADC3_Init 1 */
  /** Common config
  */
  hadc3.Instance = ADC3;
  hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc3.Init.ContinuousConvMode = ENABLE;
  hadc3.Init.DiscontinuousConvMode = DISABLE;
  hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc3.Init.NbrOfConversion = 1;
  if (HAL_ADC_Init(&hadc3) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_6;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC3_Init 2 */

  /* USER CODE END ADC3_Init 2 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();

}

3.编译、下载、验证

adc

可以看见当用手去靠近光敏传感器时,电压明显增加。

四、结合LVGL使用

上次我们学习了LVGL的移植,那么我们今天就将其应用起来做一个综合案例吧

4.1.案例分析

使用LVGL创建仪表盘,通过仪表盘来动态显示我们采集到的ADC数据。

4.2.编码实现

4.2.1创建LVGL线程
static int _lv_init = 0;
static void lvgl_tick_run(void *p)
{
    if (_lv_init)
    {
          //LVGL心跳
        lv_tick_inc(1);
    }
}

static int lvgl_tick_handler_init(void)
{
    rt_timer_t timer = RT_NULL;
    int ret;

    timer = rt_timer_create("lv_tick", lvgl_tick_run, RT_NULL, 1, RT_TIMER_FLAG_PERIODIC);

    if (timer == RT_NULL)
    {
        return RT_ERROR;
    }

    ret = rt_timer_start(timer);
    return ret;
}

static void lvgl_th_run(void *p)
{
        tp_dev.init();                         //触摸屏初始化
        //
    lv_init();                                 //lvgl系统初始化
    lv_port_disp_init();                //lvgl显示接口初始化
    lv_port_indev_init();                //lvgl输入接口初始化    
        _lv_init = 1;                             //开启心跳
    lvgl_tick_handler_init();        //心跳定时器
        //
        lv_test_theme_1(lv_theme_night_init(210,NULL));
        while(1)
    {
              tp_dev.scan(0);
        lv_task_handler();
        rt_thread_mdelay(5);
    }
}

int rt_lvgl_init(void)
{
    rt_err_t ret = RT_EOK;
    rt_thread_t thread = RT_NULL;

    thread = rt_thread_create("lvgl", lvgl_th_run, RT_NULL, 2048, 15, 10);

    if(thread == RT_NULL)
    {
        return RT_ERROR;
    }

    rt_thread_startup(thread);

    return RT_EOK;
}
INIT_APP_EXPORT(rt_lvgl_init);
4.2.2编写UI显示
/*********************
 *      INCLUDES
 *********************/
#include "lv_test_theme_1.h"
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#include <stdio.h>

#if LV_USE_TESTS
/*********************
 *      DEFINES
 *********************/
/* defined the LED0 pin: PB5 */
#define LED0_PIN    GET_PIN(B, 5)
/* defined the LED1 pin: PE5 */
#define LED1_PIN    GET_PIN(E, 5)
/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void create_tab1(lv_obj_t * parent);
static void create_tab2(lv_obj_t * parent);
static void create_tab3(lv_obj_t * parent);

/**********************
 *  STATIC VARIABLES
 **********************/
lv_style_t gauge_style;
lv_obj_t * gauge1;

lv_obj_t * label1;

//结构体赋值
lv_color_t needle_colors1[1];//指针的颜色

extern float light_value;
/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 **********************/

/**
 * Create a test screen with a lot objects and apply the given theme on them
 * @param th pointer to a theme
 */
void lv_test_theme_1(lv_theme_t * th)
{
    lv_theme_set_current(th);
    th = lv_theme_get_current();
    lv_obj_t * scr = lv_cont_create(NULL, NULL);
    lv_disp_load_scr(scr);

    lv_obj_t * tv = lv_tabview_create(scr, NULL);
    lv_obj_set_size(tv, lv_disp_get_hor_res(NULL), lv_disp_get_ver_res(NULL));
    lv_obj_t * tab1 = lv_tabview_add_tab(tv, "RB_Team");

    lv_gauge_test_start(tab1);
}

//任务回调函数
void task_cb(lv_task_t * task)
{
    //设置指针的数值
    lv_gauge_set_value(gauge1, 0, (rt_int16_t)light_value * 10);
}

void lv_gauge_test_start(lv_obj_t * parent)
{
    //1.创建自定义样式
    lv_style_copy(&gauge_style, &lv_style_pretty_color);
    gauge_style.body.main_color = LV_COLOR_MAKE(0x5F, 0xB8, 0x78);  //关键数值点之前的刻度线的起始颜色,为浅绿色
    gauge_style.body.grad_color =  LV_COLOR_MAKE(0xFF, 0xB8, 0x00); //关键数值点之前的刻度线的终止颜色,为浅黄色
    gauge_style.body.padding.left = 13;//每一条刻度线的长度
    gauge_style.body.padding.inner = 8;//数值标签与刻度线之间的距离
    gauge_style.body.border.color = LV_COLOR_MAKE(0x33, 0x33, 0x33); //中心圆点的颜色
    gauge_style.line.width = 4;//刻度线的宽度
    gauge_style.text.color = LV_COLOR_WHITE;//数值标签的文本颜色
    gauge_style.line.color = LV_COLOR_OLIVE;//关键数值点之后的刻度线的颜色

    //仪表盘
    gauge1 = lv_gauge_create(parent, NULL);//创建仪表盘
    lv_obj_set_size(gauge1, 300, 300); //设置仪表盘的大小
    lv_gauge_set_style(gauge1, LV_GAUGE_STYLE_MAIN, &gauge_style); //设置样式
    lv_gauge_set_range(gauge1, 0, 50); //设置仪表盘的范围
    needle_colors1[0] = LV_COLOR_TEAL;
    lv_gauge_set_needle_count(gauge1, 1, needle_colors1); //设置指针的数量和其颜色
    lv_gauge_set_value(gauge1, 0, (rt_int16_t)light_value * 10); //设置指针1指向的数值
    lv_gauge_set_critical_value(gauge1, 40); //设置关键数值点
    lv_gauge_set_scale(gauge1, 240, 41, 10); //设置角度,刻度线的数量,数值标签的数量
    lv_obj_align(gauge1, NULL, LV_ALIGN_IN_LEFT_MID, 50, 0); //设置与屏幕居中对齐

    //3.创建一个标签来显示指针1的数值
    label1 = lv_label_create(parent, NULL);
    lv_label_set_long_mode(label1, LV_LABEL_LONG_BREAK); //设置长文本模式
    lv_obj_set_width(label1, 80); //设置固定的宽度
    lv_label_set_align(label1, LV_LABEL_ALIGN_CENTER); //设置文本居中对齐
    lv_label_set_style(label1, LV_LABEL_STYLE_MAIN, &lv_style_pretty); //设置样式
    lv_label_set_body_draw(label1, true); //使能背景重绘制
    lv_obj_align(label1, gauge1, LV_ALIGN_CENTER, 0, 60); //设置与gauge1的对齐方式
    lv_label_set_text(label1, "0.0 V/h"); //设置文本
    lv_label_set_recolor(label1, true); //使能文本重绘色

    //4.创建一个任务来模拟速度指针的变化
    lv_task_create(task_cb, 300, LV_TASK_PRIO_MID, NULL);
}

#endif /*LV_USE_TESTS*/

4.3.编译、下载、验证


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