29. ADC 您所在的位置:网站首页 如何检测负电压 29. ADC

29. ADC

2024-07-15 23:13| 来源: 网络整理| 查看: 265

29.4.2.2. 代码分析¶

ADC宏定义

代码清单:ADC-1 ADC宏定义¶ 1 2 3 4 5 6 7 8 9 10 11 12 13// ADC GPIO 宏定义 #define RHEOSTAT_ADC_GPIO_PORT GPIOC #define RHEOSTAT_ADC_GPIO_PIN GPIO_PIN_1 #define RHEOSTAT_ADC_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() // ADC 序号宏定义 #define RHEOSTAT_ADC ADC1 #define RHEOSTAT_ADC_CLK_ENABLE() __HAL_RCC_ADC1_CLK_ENABLE() #define RHEOSTAT_ADC_CHANNEL ADC_CHANNEL_11 // ADC 中断相关宏定义 #define ADC_IRQ ADC1_2_IRQn #define ADC_IRQHandler ADC1_2_IRQHandler

当使用不同的IO时,只需要修改 代码清单:ADC-1 里面的宏定义即可,这极大的提高了程序的可移植性。

ADC GPIO初始化函数

代码清单:ADC-2 ADC GPIO初始化¶ 1 2 3 4 5 6 7 8 9 10 11 12 13static void Rheostat_ADC_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; // 使能 GPIO 时钟 RHEOSTAT_ADC_GPIO_CLK_ENABLE(); // 配置 IO GPIO_InitStructure.Pin = RHEOSTAT_ADC_GPIO_PIN; GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; GPIO_InitStructure.Pull = GPIO_NOPULL ; //不上拉不下拉 HAL_GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure); }

使用到GPIO时候都必须开启对应的GPIO时钟,GPIO用于AD转换功能必须配置为模拟输入模式。

配置ADC工作模式

代码清单:ADC-3 ADC工作模式配置¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45static void Rheostat_ADC_Mode_Config(void) { // 开启ADC时钟 RHEOSTAT_ADC_CLK_ENABLE(); // -------------------ADC Init 结构体 参数 初始化----------------------- // ADC1 ADC_Handle.Instance = RHEOSTAT_ADC; // 时钟为fpclk 4分频 ADC_Handle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4; // ADC 分辨率 ADC_Handle.Init.Resolution = ADC_RESOLUTION_12B; // 禁止扫描模式,多通道采集才需要 ADC_Handle.Init.ScanConvMode = DISABLE; // 连续转换 ADC_Handle.Init.ContinuousConvMode = ENABLE; // 非连续转换 ADC_Handle.Init.DiscontinuousConvMode = DISABLE; // 非连续转换个数 ADC_Handle.Init.NbrOfDiscConversion = 0; //禁止外部边沿触发 ADC_Handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; //使用软件触发,外部触发不用配置,注释掉即可 //ADC_Handle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; //数据右对齐 ADC_Handle.Init.DataAlign = ADC_DATAALIGN_RIGHT; //转换通道 1个 ADC_Handle.Init.NbrOfConversion = 1; //使能连续转换请求 ADC_Handle.Init.DMAContinuousRequests = ENABLE; //转换完成标志 ADC_Handle.Init.EOCSelection = DISABLE; // 初始化ADC HAL_ADC_Init(&ADC_Handle); //------------------------------------------------------------------- ADC_Config.Channel = RHEOSTAT_ADC_CHANNEL; ADC_Config.Rank = 1; // 采样时间间隔 ADC_Config.SamplingTime = ADC_SAMPLETIME_56CYCLES; ADC_Config.Offset = 0; // 配置 ADC 通道转换顺序为1,第一个转换,采样时间为3个时钟周期 HAL_ADC_ConfigChannel(&ADC_Handle, &ADC_Config); HAL_ADC_Start_IT(&ADC_Handle); }

首先,使用ADC_HandleTypeDef和ADC_ChannelConfTypeDef结构体分别定义一个ADC初始化和ADC通道配置变量,这两个结构体我们之前已经有详细讲解。

我们调用RHEOSTAT_ADC_CLK_ENABLE()开启ADC时钟。

接下来我们使用ADC_HandleTypeDef结构体变量ADC_Handle来配置ADC的寄存器基地址指针、分频系数为4、 ADC1为12位分辨率、单通道采集不需要扫描、启动连续转换、使用内部软件触发无需外部触发事件、 使用右对齐数据格式、转换通道为1,并调用HAL_ADC_Init函数完成ADC1工作环境配置。

使用ADC_ChannelConfTypeDef结构体变量ADC_Config来配置ADC的通道、转换顺序,可选为1到16; 采样周期选择,采样周期越短,ADC转换数据输出周期就越短但数据精度也越低,采样周期越长, ADC转换数据输出周期就越长同时数据精度越高。PC3对应ADC通道ADC_Channel_13, 这里我们选择ADC_SampleTime_56Cycles即56周期的采样时间,调用HAL_ADC_ConfigChannel函数完成ADC1的配置。

利用ADC转换完成中断可以非常方便的保证我们读取到的数据是转换完成后的数据而不用担心该数据可能是ADC正在转换时“不稳定”的数据。 我们使用HAL_ADC_Start_IT函数使能ADC转换完成中断,并在中断服务函数中读取转换结果数据。

ADC中断配置

代码清单:ADC-4 ADC中断配置¶ 1 2 3 4 5 6// 配置中断优先级 static void Rheostat_ADC_NVIC_Config(void) { HAL_NVIC_SetPriority(Rheostat_ADC_IRQ, 0, 0); HAL_NVIC_EnableIRQ(Rheostat_ADC_IRQ); }

我们使能了ADC转换完成中断,需要配置中断源和中断优先级。

ADC中断服务函数

代码清单:ADC-5 ADC中断服务函数¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14void ADC_IRQHandler(void) { HAL_ADC_IRQHandler(&ADC_Handle); } /** * @brief 转换完成中断回调函数(非阻塞模式) * @param AdcHandle : ADC句柄 * @retval 无 */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle) { /* 获取结果 */ ADC_ConvertedValue = HAL_ADC_GetValue(AdcHandle); } }

中断服务函数一般定义在stm32f1xx_it.c文件内,HAL_ADC_IRQHandler是HAL中自带的一个中断服务函数, 他处理过程中会指向一个回调函数给我们去添加用户代码,这里我们使用HAL_ADC_ConvCpltCallback转换完成中断, 在ADC转换完成后就会进入中断服务函数,在进入回调函数, 我们在回调函数内直接读取ADC转换结果保存在变量ADC_ConvertedValue(在main.c中定义)中。

ADC_GetConversionValue函数是获取ADC转换结果值的库函数,只有一个形参为ADC句柄,该函数还返回一个16位的ADC转换结果值

主函数

代码清单:ADC-6 主函数¶ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20/** * @brief 主函数 * @param 无 * @retval 无 */ int main(void) { /* 配置系统时钟为72 MHz */ SystemClock_Config(); /* 初始化USART1 配置模式为 115200 8-N-1 */ UARTx_Config(); Rheostat_Init(); while (1) { ADC_Vol =(float)ADC_ConvertedValue/4096*(float)3.3;//读取转换的AD值 printf("\r\n The current AD value = 0x%04X \r\n", ADC_ConvertedValue); printf("\r\n The current AD value = %f V \r\n",ADC_Vol); Delay(0x8fffff); } }

主函数先调用USARTx_Config函数配置调试串口相关参数,函数定义在bsp_debug_usart.c文件中。

接下来调用Rheostat _Init函数进行ADC初始化配置并启动ADC。Rheostat _Init函数是定义在bsp_adc.c文件中, 它只是简单的分别调用Rheostat_ADC_GPIO_Config ()、 Rheostat_ADC_Mode_Config ()和Rheostat_ADC_NVIC_Config()。

Delay函数只是一个简单的延时函数。

在ADC中断服务函数中我们把AD转换结果保存在变量ADC_ConvertedValue中,根据我们之前的分析可以非常清楚的计算出对应的电位器动触点的电压值。

最后就是把相关数据打印至串口调试助手。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有