网站建设哪家有实力,嘉兴类网站系统总部,小程序二次开发多少钱,嘉峪关建设厅官方网站ADC定义#xff1a; ADC即模拟数字转换器#xff0c;英文详称 Analog-to-digital converter#xff0c;可以将外部的模拟信号转换 ADC数模转换中一些常用函数#xff1a;
1. HAL_ADC_Init 函数 HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *hadc); 初始化ADC 形参 ADC即模拟数字转换器英文详称 Analog-to-digital converter可以将外部的模拟信号转换 ADC数模转换中一些常用函数
1. HAL_ADC_Init 函数 HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef *hadc); 初始化ADC 形参ADC_HandleTypeDef 结构体类型指针变量 返回值HAL_StatusTypeDef枚举类型 typedef struct { ADC_TypeDef *Instance; /* ADC 寄存器基地址 */ ADC_InitTypeDef Init; /* ADC 参数初始化结构体变量 */ __IO uint32_t NbrOfCurrentConversionRank;/* 当前转换等级的 ADC 数 */ DMA_HandleTypeDef *DMA_Handle; /* DMA 配置结构体 */ HAL_LockTypeDef Lock; /* ADC 锁定对象 */ __IO uint32_t State; /* ADC 工作状态 */ __IO uint32_t ErrorCode; /* ADC 错误代码 */ }ADC_HandleTypeDef; 其中第二个成员变量Init需要重点配置 typedef struct { uint32_t ClockPrescaler; /* 设置预分频系数即 PRESC[3:0]位可选(2,4,6,8) */ uint32_t Resolution; /* 配置 ADC 的分辨率,可选(12位10,8,6)分辨率高精度高时间长 */ uint32_t ScanConvMode; /* 扫描模式 可选(ADC_SCAN_DISABLE单通道ADC_SCAN_ENABLE多)*/ uint32_t EOCSelection; /* 转换完成标志位() */ FunctionalState ContinuousConvMode; /* 开启连续转换模式否则就是单次转换模式 */ uint32_t NbrOfConversion; /* 设置转换通道数目 */ FunctionalState DiscontinuousConvMode; /* 单次转换模式选择 */ uint32_t NbrOfDiscConversion; /* 单次转换通道的数目 */ uint32_t ExternalTrigConv; /* ADC 外部触发源选择 */ uint32_t ExternalTrigConvEdge; /* ADC 外部触发极性*/ FunctionalState DMAContinuousRequests; /* DMA 转换请求模式*/ } ADC_InitTypeDef; 1) ClockPrescalerADC 预分频系数选择可选的分频系数为 2、4、6、8。由于 ADC 最大时钟 不得超过 36Mhz我们这里配置 4 分频即 ADC 的时钟频率为84 / 4 21Mhz。 2) Resolution配置 ADC 的分辨率可选的分辨率有 12 位、10 位、8 位和 6 位。分辨率越高 转换数据精度越高转换时间也越长反之分辨率越低转换数据精度越低转换时间也越 短。 3) ScanConvMode配置是否使用扫描。如果是单通道转换使用 ADC_SCAN_DISABLE如果 是多通道转换使用 ADC_SCAN_ENABLE。 4) EOCSelection可选参数为 ADC_EOC_SINGLE_CONV 和 ADC_EOC_SEQ_CONV指定转 换结束时是否产生 EOS 中断或事件标志。 5) ContinuousConvMode可选参数为 ENABLE 和 DISABLE配置自动连续转换还是单次转换。 使用 ENABLE 配置为使能自动连续转换使用 DISABLE 配置为单次转换转换一次后停止 需要手动控制才重新启动转换。 6) NbrOfConversion设置常规转换通道数目范围是1~16。 7) DiscontinuousConvMode配置是否使用不连续的采样模式比如要转换的通道有 1、2、5、 7、8、9那么第一次触发会进行通道 1 与通道 2下次触发就是转换通道 5 与通道 7这 样不连续的转换依次类推。此参数只有将 ScanConvMode 使能还有 ContinuousConvMode 失能的情况下才有效不可同时使能。 8) NbrOfDiscConversion不连续采样通道数。 9) ExternalTrigConv外部触发方式的选择如果使用软件触发那么外部触发会关闭。 10) ExternalTrigConvEdge外部触发极性选择如果使用外部触发可以选择触发的极性可 选有禁止触发检测、上升沿触发检测、下降沿触发检测以及上升沿和下降沿均可触发检测。 11) DMAContinuousRequests指定 DMA 请求是否以一次性模式执行(当达到转换次数时DMA 传输停止)或在连续模式下(DMA 传输无限制无论转换的数量)。注:在连续模式下DMA 必 须配置为循环模式。否则当达到 DMA 缓冲区最大指针时将触发溢出。注意:当常规组和注 入组都没有转换时(禁用 ADC或启用 ADC没有连续模式或可以启动转换的外部触发器) 必须修改此参数。该参数可设置为“启用”或“禁用”。 2.HAL_ADCEx_Calibration_Start函数 HAL_StatusTypeDef HAL_ADCEx_Calibration_Start(ADC_HandleTypeDef *hadc);ADC自校准功能 形参:ADC_HandleTypeDef 结构体类型指针变量 返回值HAL_StatusTypeDef枚举类型的值 3. HAL_ADC_ConfigChannel函数 HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef *hadc, ADC_ChannelConfTypeDef *sConfig);ADC自校准功能 形参:参数1ADC_HandleTypeDef 结构体类型指针变量 参数2ADC_ChannelConfTypeDef 结构体类型指针变量 typedef struct { uint32_t Channel; /* ADC 转换通道(0~19)*/ uint32_t Rank; /* ADC 转换顺序(1~16) */ uint32_t SamplingTime; /* ADC 采样周期(480个ADC时钟周期) */ uint32_t Offset; /* ADC 偏移量 */ } ADC_ChannelConfTypeDef; 4.HAL_ADC_Start 函数 HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc);ADC启动函数 形参ADC_HandleTypeDef 结构体类型指针变量 返回值HAL_StatusTypeDef枚举类型的值 5. HAL_ADC_PollForConversion函数 等待规则组转换完成函数 HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef *hadc,uint32_t Timeout); 形参参数1ADC_HandleTypeDef 结构体类型指针变量 参数2等待转换的等待时间ms 返回值HAL_StatusTypeDef 枚举类型的值。 6. HAL_ADC_GetValue 函数 uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef *hadc); 获取ADC转换值 形参ADC_HandleTypeDef 结构体类型指针变量 返回值当前的转换值uint32_t 类型数据 7.HAL_DMA_Start 函数 启动DMA传输(在任何能使用DMA传输的场景) HAL_Status TypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) 参数(DMA_HandleTypeDef 结构体类型指针变量,DMA 传输的源地址,DMA 传输的目的地址,要传输的数据项数目) 8. HAL_ADC_Start_DMA 函数 只启动有ADC(DMA传输)方式 HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t *pData, uint32_t Length); 形参(ADC_HandleTypeDef 结构体类型指针变量, ADC 采样数据传输的目的地址,要传输的数据项数目) 9.HAL_DMA_Init 函数 初始化DMA HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma); 参数DMA_HandleTypeDef 结构体类型指针变量 typedef struct __DMA_HandleTypeDef { void *Instance; /* 寄存器基地址 */ DMA_InitTypeDef Init; /* DAM 通信参数 */ HAL_LockTypeDef Lock; /* DMA 锁对象 */ __IO HAL_DMA_StateTypeDef State; /* DMA 传输状态 */ void *Parent; /* 父对象状态HAL 库处理的中间变量 */ void (*XferCpltCallback)( struct __DMA_HandleTypeDef *hdma);/*DMA 传输完成回调*/ /* DMA 一半传输完成回调 */ void (* XferHalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); /* DMA 传输完整的 Memory1 回调 */ void (* XferM1CpltCallback)( struct __DMA_HandleTypeDef * hdma); /* DMA 传输半完全内存回调 */ void (* XferM1HalfCpltCallback)( struct __DMA_HandleTypeDef * hdma); /*DMA 传输错误回调*/ void (* XferErrorCallback)( struct __DMA_HandleTypeDef * hdma); /* DMA 传输中止回调 */ void (* XferAbortCallback)( struct __DMA_HandleTypeDef * hdma); __IO uint32_t ErrorCode; /* DMA 存取错误代码 */ uint32_t StreamBaseAddress; /* DMA 通道基地址 */ uint32_t StreamIndex; /* DMA 通道索引 */ }DMA_HandleTypeDef; 重点介绍第二个成员变量Init typedef struct { uint32_t Channel; /* 传输通道例如DMA_CHANEL_4 */ uint32_t Direction; /* 传输方向例如存储器到外设 DMA_MEMORY_TO_PERIPH */ uint32_t PeriphInc; /* 外设非增量模式非增量模式 DMA_PINC_DISABLE */ uint32_t MemInc; /* 存储器非增量模式增量模式 DMA_MINC_ENABLE */ uint32_t PeriphDataAlignment; /* 外设数据大小8/16/32 位 */ uint32_t MemDataAlignment; /* 存储器数据大小8/16/32 位 */ uint32_t Mode; /* 模式外设流控模式/循环模式/普通模式 */ uint32_t Priority; /* DMA 优先级低/中/高/非常高 */ uint32_t FIFOMode; /* FIFO 模式开启或者禁止 */ uint32_t FIFOThreshold; /* FIFO 阈值选择 */ uint32_t MemBurst; /* 存储器突发模式单次/4 个节拍/8 个节拍/16 个节拍 */ uint32_t PeriphBurst; /* 外设突发模式单次/4 个节拍/8 个节拍/16 个节拍 */ }DMA_InitTypeDef 单通道ADC采集配置步骤
a.开启ADCx和GPIO时钟
b.初始化ADCx,配置器工作参数和硬件Msp的IO
c.配置ADC通道并启动AD转换
d.读取ADC值 单/多通道ADC采集(DMA读取)配置
a.开启ADCx和GPIO时钟
b.初始化ADC配置其工作参数和硬件Msp
c.配置ADC通道并启动AD转换
d.初始化DMA
e.使能DMA对应数据流中断配置DMA中断优先级
f.编写中断服务函数 单通道ADC采集实验代码
//adc.c#include ./BSP/ADC/adc.h
#include ./SYSTEM/delay/delay.hADC_HandleTypeDef g_adc_handle; /* ADC句柄 *//*** brief ADC初始化函数* note 本函数支持ADC1/ADC2任意通道, 但是不支持ADC3* 我们使用12位精度, ADC采样时钟21M, 转换时间为: 采样周期 12个ADC周期* 设置最大采样周期: 480, 则转换时间 492 个ADC周期 23.42us* param 无* retval 无*/
void adc_init(void)
{g_adc_handle.Instance ADC_ADCX;g_adc_handle.Init.ClockPrescaler ADC_CLOCKPRESCALER_PCLK_DIV4; /* 4分频ADCCLK PCLK2/4 84/4 21Mhz */g_adc_handle.Init.Resolution ADC_RESOLUTION_12B; /* 12位模式 */g_adc_handle.Init.DataAlign ADC_DATAALIGN_RIGHT; /* 右对齐 */g_adc_handle.Init.ScanConvMode DISABLE; /* 非扫描模式 */g_adc_handle.Init.ContinuousConvMode DISABLE; /* 关闭连续转换 */g_adc_handle.Init.NbrOfConversion 1; /* 1个转换在规则序列中 也就是只转换规则序列1 */g_adc_handle.Init.DiscontinuousConvMode DISABLE; /* 禁止不连续采样模式 */g_adc_handle.Init.NbrOfDiscConversion 0; /* 不连续采样通道数为0 */g_adc_handle.Init.ExternalTrigConv ADC_SOFTWARE_START; /* 软件触发 */g_adc_handle.Init.ExternalTrigConvEdge ADC_EXTERNALTRIGCONVEDGE_NONE; /* 使用软件触发 */g_adc_handle.Init.DMAContinuousRequests DISABLE; /* 关闭DMA请求 */HAL_ADC_Init(g_adc_handle); /* 初始化 */
}/*** brief ADC底层驱动引脚配置时钟使能此函数会被HAL_ADC_Init()调用* param hadc:ADC句柄* retval 无*/
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{if(hadc-Instance ADC_ADCX){GPIO_InitTypeDef gpio_init_struct;ADC_ADCX_CHY_CLK_ENABLE(); /* 使能ADCx时钟 */ADC_ADCX_CHY_GPIO_CLK_ENABLE(); /* 开启GPIO时钟 *//* AD采集引脚模式设置,模拟输入 */gpio_init_struct.Pin ADC_ADCX_CHY_GPIO_PIN;gpio_init_struct.Mode GPIO_MODE_ANALOG; //模拟输入模式gpio_init_struct.Pull GPIO_NOPULL; //该模式用来配置gpio的外部上下拉电阻HAL_GPIO_Init(ADC_ADCX_CHY_GPIO_PORT, gpio_init_struct);}
}/*** brief 设置ADC通道采样时间* param adcx : adc句柄指针,ADC_HandleTypeDef* param ch : 通道号, ADC_CHANNEL_0~ADC_CHANNEL_17* param stime: 采样时间 0~7, 对应关系为:* arg ADC_SAMPLETIME_3CYCLES, 3个ADC时钟周期 ADC_SAMPLETIME_15CYCLES, 15个ADC时钟周期* arg ADC_SAMPLETIME_28CYCLES, 28个ADC时钟周期 ADC_SAMPLETIME_56CYCLES, 56个ADC时钟周期* arg ADC_SAMPLETIME_84CYCLES, 84个ADC时钟周期 ADC_SAMPLETIME_112CYCLES,112个ADC时钟周期* arg ADC_SAMPLETIME_144CYCLES,144个ADC时钟周期 ADC_SAMPLETIME_480CYCLES,480个ADC时钟周期* param rank: 多通道采集时需要设置的采集编号,假设你定义channel1的rank1channel2的rank2那么对应你在DMA缓存空间的变量数组AdcDMA[0] 就i是channel1的转换结果AdcDMA[1]就是通道2的转换结果。 单通道DMA设置为 ADC_REGULAR_RANK_1* arg 编号1~16ADC_REGULAR_RANK_1~ADC_REGULAR_RANK_16* retval 无*/
void adc_channel_set(ADC_HandleTypeDef *adc_handle, uint32_t ch, uint32_t rank, uint32_t stime)
{/* 配置对应ADC通道 */ADC_ChannelConfTypeDef adc_channel;adc_channel.Channel ch; /* 设置ADCX对通道ch */adc_channel.Rank rank; /* 设置采样序列 */adc_channel.SamplingTime stime; /* 设置采样时间 */HAL_ADC_ConfigChannel( adc_handle, adc_channel);
}/*** brief 获得ADC转换后的结果* param ch: 通道值 0~17取值范围为ADC_CHANNEL_0~ADC_CHANNEL_17* retval 无*/
uint32_t adc_get_result(uint32_t ch)
{adc_channel_set(g_adc_handle, ch, 1, ADC_SAMPLETIME_480CYCLES); /* 设置通道序列和采样时间 */HAL_ADC_Start(g_adc_handle); /* 开启ADC */HAL_ADC_PollForConversion(g_adc_handle, 10); /* 轮询转换 */return (uint16_t)HAL_ADC_GetValue(g_adc_handle); /* 返回最近一次ADC1规则组的转换结果 */
}/*** brief 获取通道ch的转换值取times次, 然后平均* param ch : 通道号, 0~17* param times : 获取次数* retval 通道ch的times次转换结果平均值*/
uint32_t adc_get_result_average(uint32_t ch, uint8_t times)
{uint32_t temp_val 0;uint8_t t;for (t 0; t times; t) /* 获取times次数据 */{temp_val adc_get_result(ch);delay_ms(5);}return temp_val / times; /* 返回平均值 */
}//adc.h#ifndef __ADC_H
#define __ADC_H#include ./SYSTEM/sys/sys.h/******************************************************************************************/
/* ADC及引脚 定义 */#define ADC_ADCX_CHY_GPIO_PORT GPIOA
#define ADC_ADCX_CHY_GPIO_PIN GPIO_PIN_5
#define ADC_ADCX_CHY_GPIO_CLK_ENABLE() do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0) /* PA口时钟使能 */#define ADC_ADCX ADC1
#define ADC_ADCX_CHY ADC_CHANNEL_5 /* 通道Y, 0 Y 17 */
#define ADC_ADCX_CHY_CLK_ENABLE() do{ __HAL_RCC_ADC1_CLK_ENABLE(); }while(0) /* ADC1 时钟使能 *//******************************************************************************************/void adc_init(void); /* ADC初始化 */
void adc_channel_set(ADC_HandleTypeDef *adc_handle, uint32_t ch, uint32_t rank, uint32_t stime); /* ADC通道设置 */
uint32_t adc_get_result(uint32_t ch); /* 获得某个通道值 */
uint32_t adc_get_result_average(uint32_t ch, uint8_t times); /* 得到某个通道给定次数采样的平均值 */#endifmain.c
#include ./SYSTEM/sys/sys.h
#include ./SYSTEM/usart/usart.h
#include ./SYSTEM/delay/delay.h
#include ./BSP/LED/led.h
#include ./BSP/LCD/lcd.h
#include ./BSP/ADC/adc.hint main(void)
{uint16_t adcx;float temp;HAL_Init(); /* 初始化HAL库 */sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */delay_init(168); /* 延时初始化 */usart_init(115200); /* 串口初始化为115200 */led_init(); /* 初始化LED */lcd_init(); /* 初始化LCD */adc_init(); /* 初始化ADC */lcd_show_string(30, 50, 200, 16, 16, STM32, RED);lcd_show_string(30, 70, 200, 16, 16, ADC TEST, RED);lcd_show_string(30, 90, 200, 16, 16, ATOMALIENTEK, RED);lcd_show_string(30, 110, 200, 16, 16, ADC1_CH5_VAL:, BLUE);lcd_show_string(30, 130, 200, 16, 16, ADC1_CH5_VOL:0.000V, BLUE); /* 先在固定位置显示小数点 */while (1){adcx adc_get_result_average(ADC_ADCX_CHY, 10); /* 获取通道5的转换值10次取平均 */lcd_show_xnum(134, 110, adcx, 5, 16, 0, BLUE); /* 显示ADC采样后的原始值 */temp (float)adcx * (3.3 / 4096); /* 获取计算后的带小数的实际电压值比如3.1111 */adcx temp; /* 赋值整数部分给adcx变量因为adcx为u16整形 */lcd_show_xnum(134, 130, adcx, 1, 16, 0, BLUE); /* 显示电压值的整数部分3.1111的话这里就是显示3 */temp - adcx; /* 把已经显示的整数部分去掉留下小数部分比如3.1111-30.1111 */temp * 1000; /* 小数部分乘以1000例如0.1111就转换为111.1相当于保留三位小数。 */lcd_show_xnum(150, 130, temp, 3, 16, 0X80, BLUE); /* 显示小数部分前面转换为了整形显示这里显示的就是111. */LED0_TOGGLE();delay_ms(100);}
}