RT-Thread Studio学习(十四)ADC
- 一、简介
- 二、新建RT-Thread项目并使用外部时钟
- 三、启用ADC
- 四、测试
一、简介
本文将基于STM32F407VET芯片介绍如何在RT-Thread Studio开发环境下使用ADC设备。硬件及开发环境如下:
- OS WIN10
- STM32F407VET6
- STM32CubeMX v6.10.0
- STM32Cube MCU Package for STM32F4 Series v1.28.0
- RT-Thread Studio v2.2.7
- RT-Thread Source Code v5.0.2
- STM32F4 chip support packages v0.2.3
二、新建RT-Thread项目并使用外部时钟
打开RT-Thread Studio软件新建基于芯片的项目,并使用外部时钟系统,具体参见《RT-Thread Studio学习(一)使用外部时钟系统》。
三、启用ADC
- 打开ADC驱动框架
在RT-Thread Setting
中借助图形化配置工具打开软件ADC的驱动框架,如下图所示:
- 定义ADC相关的宏
在board.h
文件中使能宏定义:
#define BSP_USING_ADC1
#define BSP_USING_ADC2
#define BSP_USING_ADC3
- 复制ADC初始化函数
双击RT-Thread Studio工程中的cubemx.ioc文件,使能ADC1、ADC2和ADC3,具体如下图:
3个ADC分别对应引脚PC0、PC1和PC2。
使能ADC后再重新生成STM32CubeMX代码,将.\cubemx\Src\adc.c中的函数HAL_DAC_MspInit(DAC_HandleTypeDef* dacHandle)
复制到board.c的末尾。
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{GPIO_InitTypeDef GPIO_InitStruct = {0};if(adcHandle->Instance==ADC1){/* USER CODE BEGIN ADC1_MspInit 0 *//* USER CODE END ADC1_MspInit 0 *//* ADC1 clock enable */__HAL_RCC_ADC1_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**ADC1 GPIO ConfigurationPC0 ------> ADC1_IN10*/GPIO_InitStruct.Pin = GPIO_PIN_0;GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/* USER CODE BEGIN ADC1_MspInit 1 *//* USER CODE END ADC1_MspInit 1 */}else if(adcHandle->Instance==ADC2){/* USER CODE BEGIN ADC2_MspInit 0 *//* USER CODE END ADC2_MspInit 0 *//* ADC2 clock enable */__HAL_RCC_ADC2_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**ADC2 GPIO ConfigurationPC1 ------> ADC2_IN11*/GPIO_InitStruct.Pin = GPIO_PIN_1;GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/* USER CODE BEGIN ADC2_MspInit 1 *//* USER CODE END ADC2_MspInit 1 */}else if(adcHandle->Instance==ADC3){/* USER CODE BEGIN ADC3_MspInit 0 *//* USER CODE END ADC3_MspInit 0 *//* ADC3 clock enable */__HAL_RCC_ADC3_CLK_ENABLE();__HAL_RCC_GPIOC_CLK_ENABLE();/**ADC3 GPIO ConfigurationPC2 ------> ADC3_IN12*/GPIO_InitStruct.Pin = GPIO_PIN_2;GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);/* USER CODE BEGIN ADC3_MspInit 1 *//* USER CODE END ADC3_MspInit 1 */}
}
- 定义
.\cubemx\Inc\stm32f4xx_hal_conf.h
中的相关宏
#define HAL_ADC_MODULE_ENABLED
四、测试
修改main.c
的代码为:
/** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-01-15 RT-Thread first version*/#include <rtthread.h>
#include "stm32f4xx.h"
#include <rtdevice.h>#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>// PC0 ------> ADC1_IN10
// PC1 ------> ADC2_IN11
// PC2 ------> ADC3_IN12
// PA4 ------> DAC_OUT1
// PA5 ------> DAC_OUT2#define ADC_DEV_NAME "adc1" /* ADC 设备名称 */
#define REFER_VOLTAGE 330 /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS (1 << 12) /* 转换位数为12位 */#define DAC_DEV_NAME "dac1" /* DAC 设备名称 */
#define DAC_DEV_CHANNEL 1 /* DAC 通道 */
#define REFER_VOLTAGE 330 /* 参考电压 3.3V,数据精度乘以100保留2位小数*/
#define CONVERT_BITS (1 << 12) /* 转换位数为12位 */// 读取adc的使用命令get_adc adc1 1
// 第一个参数为命令,第二个参数为 adc 设备名称,第 3 个参数为 adc 通道,
// 返回值为 adc 电压值
static int adc_get(int argc, char *argv[])
{if(argc!=3){rt_kprintf("Usage: adc_get <device name> <channel>\n");rt_kprintf("Example: adc_get adc1 1\n");return RT_ERROR;}rt_adc_device_t adc_dev;rt_uint32_t value, vol, channel;rt_err_t ret = RT_EOK;char adcdevname[RT_NAME_MAX];rt_strncpy(adcdevname, argv[1], RT_NAME_MAX);channel = atoi(argv[2]); // ADC channel/* 查找设备 */adc_dev = (rt_adc_device_t)rt_device_find(adcdevname);if (adc_dev == RT_NULL){rt_kprintf("adc sample run failed! can't find %s device!\n", adcdevname);return RT_ERROR;}/* 使能设备 */ret = rt_adc_enable(adc_dev, channel);/* 读取采样值 */value = rt_adc_read(adc_dev, channel);rt_kprintf("the value is :%d \n", value);/* 转换为对应电压值 */vol = value * REFER_VOLTAGE / CONVERT_BITS;rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);/* 关闭通道 */ret = rt_adc_disable(adc_dev, channel);rt_kprintf("adc_get %s channel:%d\n", adcdevname, channel);return ret;
}// 设置dac的使用命令 dac_set dac1 1 200
// 第一个参数为命令,第二个参数为 dac 设备名称,第 3 个参数为 dac 通道,
// 第 4 个参数为 dac 输出数值
static int dac_set(int argc, char *argv[])
{if(argc!=4){rt_kprintf("Usage: dac_set <device name> <channel> <value>\n");rt_kprintf("Example: dac_set dac1 1 1000\n");return RT_ERROR;}rt_dac_device_t dac_dev;rt_uint32_t value, vol, channel;rt_err_t ret = RT_EOK;char dacdevname[RT_NAME_MAX];rt_strncpy(dacdevname, argv[1], RT_NAME_MAX);channel = atoi(argv[2]); // DAC channelvalue = atoi(argv[3]);/* 查找设备 */dac_dev = (rt_dac_device_t)rt_device_find(dacdevname);if (dac_dev == RT_NULL){rt_kprintf("dac sample run failed! can't find %s device!\n", dacdevname);return RT_ERROR;}/* 打开通道 */ret = rt_dac_enable(dac_dev, channel);/* 设置输出值 */rt_dac_write(dac_dev, channel, value);rt_kprintf("the value is :%d \n", value);/* 转换为对应电压值 */vol = value * REFER_VOLTAGE / CONVERT_BITS;rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);/* 延时查看效果,关闭通道后无输出 */
// rt_thread_mdelay(500);/* 关闭通道 */
// ret = rt_dac_disable(dac_dev, channel);return ret;
}static int dac1_vol_sample()
{rt_dac_device_t dac_dev;rt_uint32_t value, vol;rt_err_t ret = RT_EOK;/* 查找设备 */dac_dev = (rt_dac_device_t)rt_device_find(DAC_DEV_NAME);if (dac_dev == RT_NULL){rt_kprintf("dac sample run failed! can't find %s device!\n", DAC_DEV_NAME);return RT_ERROR;}/* 打开通道 */ret = rt_dac_enable(dac_dev, DAC_DEV_CHANNEL);/* 设置输出值 */value=1000;rt_dac_write(dac_dev, DAC_DEV_CHANNEL, value);rt_kprintf("the value is :%d \n", value);/* 转换为对应电压值 */vol = value * REFER_VOLTAGE / CONVERT_BITS;rt_kprintf("the voltage is :%d.%02d \n", vol / 100, vol % 100);/* 延时查看效果,关闭通道后无输出 */// rt_thread_mdelay(500);/* 关闭通道 */// ret = rt_dac_disable(dac_dev, DAC_DEV_CHANNEL);return ret;
}int main(void)
{int count = 1;LOG_D("Hello RT-Thread! 2024.1.17");LOG_D("System CLock information");LOG_D("SYSCLK_Frequency = %d", HAL_RCC_GetSysClockFreq());LOG_D("HCLK_Frequency = %d", HAL_RCC_GetHCLKFreq());LOG_D("PCLK1_Frequency = %d", HAL_RCC_GetPCLK1Freq());LOG_D("PCLK2_Frequency = %d", HAL_RCC_GetPCLK2Freq());LOG_D("SysTick->LOAD = %d", SysTick->LOAD);LOG_D("Current tick = %d", rt_tick_get());dac1_vol_sample();while (count++){LOG_D("Hello RT-Thread! %d", rt_tick_get());rt_thread_mdelay(60000);}return RT_EOK;
}/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(adc_get, get adc voltage);
MSH_CMD_EXPORT(dac_set, set dac voltage. Useage: dac_set adc2 11 200);
将引脚PA4和PC1短接,运行结果如下:
在PA4脚用万用表测得输出电压为0.8080V