RTThread的IO设备-ADC(模数转换器) 开发

问题描述

RT-Thread 提供的 ADC 设备管理接口来访问 ADC 硬件,

【1】可以直接通过 rt-thread/src/device.c提供的以下相关接口实现。

rt_device_find() 根据 ADC 设备名称查找设备获取设备句柄
rt_adc_enable() 使能 ADC 设备
rt_adc_read() 读取 ADC 设备数据
rt_adc_disable() 关闭 ADC 设备

【2】 可以通过 stm32cubemx生成的源码board/src/main.c以及libraries/../Inc/stm32l4xx_hal_adc.h、libraries/../Src/stm32l4xx_hal_adc.c提供的HAL_ADC_Start、HAL_ADC_Stop等相关接口实现。

案例实现:

一、前期配置

【1】stm32cubemx配置板卡

完成配置,生成代码 。

【2】开启ADC驱动支持,工程目录启动RT-Thread的EVN工具命令窗口,启动menuconfig命令完成配置。

或者,采用RT-Thread Studio的rt-thread settings的开启ADC驱动支持。

【3】在board/../Inc/stm32l4xx_hal_conf.h文件中取消ADC宏定义的注销,启用ADC模块

#define HAL_ADC_MODULE_ENABLED

 二、代码实现

【1】方法一

1)将stm32cubemx生成的源码文件board\CubeMX_Config\Src\main.c文件中的static void MX_ADC1_Init(void)函数定义拷贝到自行编译源码中,实现ADC初始化。代码案例如下:

#include <rtthread.h>
#include "board.h"
#include "stm32l4xx_hal_adc.h"

ADC_HandleTypeDef hadc1;

/* ADC1 初始化函数 */
void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_MultiModeTypeDef multimode = {0};
  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */
  /** Common config
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_3;//第3通道
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

rt_uint32_t get_adc_value(void)
{
    HAL_ADC_Start(&hadc1);
    HAL_ADC_PollForConversion(&hadc1, 100);

    return (rt_uint32_t)HAL_ADC_GetValue(&hadc1);
}
/*线程函数*/
void adc_entry(void *parameter)
{
    int count = 1;
    rt_uint32_t read_value = 0;

    MX_ADC1_Init();
    while ((count++)<10)
    {
        read_value = get_adc_value();
        rt_thread_mdelay(1000);
        rt_kprintf("adc value = %d\r\n", read_value);
    }
}

/* 创建线程 */
int adc_sample(void)
{
    rt_thread_t tid;    //线程句柄

    tid = rt_thread_create("adc_sample",
                            adc_entry,
                            RT_NULL,
                            512,
                            9,
                            10);
   if(tid != RT_NULL)
   {
        //线程创建成功,启动线程
        rt_thread_startup(tid);
   }

   return 0;

}

/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adc_sample, adc test example);

【2】方法二,采用device.c的IO设备访问接口实现,先开启ADC1宏定义

可以在rtconfig.h或board.h头文件中添加宏定义:#define BSP_USING_ADC1

示例代码如下:

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

rt_adc_device_t dev;

void adc1_entry(void *parameter)
{
    int count = 0;
    rt_uint32_t read_value = 0;
    while((count++)<10)
    {
        read_value = rt_adc_read(dev, 5);
        rt_kprintf("adc value = %d\r\n", read_value);
        rt_thread_mdelay(1000);
    }
}

/* 创建线程 */
int adc_sample1(void)
{
    dev = (rt_adc_device_t)rt_device_find("adc1");
    if(RT_NULL==dev)
    {
        rt_kprintf("rt_device_find adc1 failed!\n");
        return RT_ERROR;
    }
    rt_err_t ret = rt_adc_enable(dev, 5);//第5通道
    if(ret<0)
    {
        rt_kprintf("rt_adc_enable adc1 failed!\n");
    }
    rt_thread_t tid;    //线程句柄

    tid = rt_thread_create("adc_sample1",
                            adc1_entry,
                            RT_NULL,
                            512,
                            9,
                            10);
   if(tid != RT_NULL)
   {
        //线程创建成功,启动线程
        rt_thread_startup(tid);
   }

   return 0;

}

/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adc_sample1, adc test example);

三、编译及测试

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)