ADC类型:
F1 F4 H4 H7用的都是逐次递进式
ADC电气特性:
该ADC只能承受3.6v以下电压
F1时钟不能超过14Mhz
流程顺序:先配置好1参考电压和芯片电源,再配置2电压输入通道并通过模拟多路开关选择通路到注入通道或规则通道,adc芯片测完这些路的电压值会放到规则或注入通道内,规则组只有一个存电压值数据的寄存器却有16通道可输入,注入组则有四个数值保存器也只有四路输入通道,这使得注入组测量最快
而且注入组与规则组触发源不一样,规则组正在被测量时可以被注入组插队
eg:规则组先被触发8路测量,正当测量到第四组一半时,注入组被触发,那等到当前正执行的第四组规则组测量完成,注入组马上插队到第五组规则组前面,等到注入组全部测量完成才会继续测量第五组规则组
模拟看门狗可以在测得的电压值超出某一范围时,且adc看门狗中断被使能的情况下,他就会触发中断
-
接线:
以战舰v3为例,他把Vref接了VDDA总板子电源,使得参考电压为主板正电源,这样做其实有个坏处,这会使得你不能用该ADC测板上电压,也就是测不了板子主供电源的电池电量
你设置测量顺序然后发送触发信号的流程就相当于,往SQRX里面写入要转换的通道注入组不存在人为设定序列的功能, 它是由以下公式而定
eg:若你填入JL为3代表你添加了四个注入组测量,则它一旦被触发会从x=4-3=1,jsq1开始-》jsq2-》...
若你填1则代表加入了两个注入组测量目标,则它一旦被触发就会从x=4-1=3,jsq3开始->jsq4->jsq1...
触发源:
触发源只能选一个
外部触发又分为软件触发(人工触发)和外设触发
外部触发源在结构图下方有
ADC时钟不能超过14Mhz
检测周期:
采样时间由smp确定
ADC模式:
因为数据存储器有32位而f1的adc为12位精度,所以要选择对齐方式
结构体参数:
单通道adc加dma
adc.c
#include "./BSP/ADC/adc.h"
DMA_HandleTypeDef g_dma_adc_handle;
ADC_HandleTypeDef g_adc_dma_handle;
uint8_t g_adc_dma_sta;
/* ADC DMA读取 初始化函数 */
void adc_dma_init(uint32_t mar)
{
ADC_ChannelConfTypeDef adc_ch_conf;
__HAL_RCC_DMA1_CLK_ENABLE();
g_dma_adc_handle.Instance = DMA1_Channel1;
g_dma_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;
g_dma_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;
g_dma_adc_handle.Init.MemInc = DMA_MINC_ENABLE;
g_dma_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
g_dma_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
g_dma_adc_handle.Init.Mode = DMA_NORMAL;
g_dma_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;
HAL_DMA_Init(&g_dma_adc_handle);
__HAL_LINKDMA(&g_adc_dma_handle, DMA_Handle, g_dma_adc_handle);
g_adc_dma_handle.Instance = ADC1;
g_adc_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;
g_adc_dma_handle.Init.ScanConvMode = ADC_SCAN_DISABLE;
g_adc_dma_handle.Init.ContinuousConvMode = ENABLE;
g_adc_dma_handle.Init.NbrOfConversion = 1;
g_adc_dma_handle.Init.DiscontinuousConvMode = DISABLE;
g_adc_dma_handle.Init.NbrOfDiscConversion = 0;
g_adc_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;
HAL_ADC_Init(&g_adc_dma_handle);
HAL_ADCEx_Calibration_Start(&g_adc_dma_handle);
adc_ch_conf.Channel = ADC_CHANNEL_1;
adc_ch_conf.Rank = ADC_REGULAR_RANK_1;
adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;
HAL_ADC_ConfigChannel(&g_adc_dma_handle, &adc_ch_conf);
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 3, 3);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
HAL_DMA_Start_IT(&g_dma_adc_handle, (uint32_t)&ADC1->DR, mar, 0);
HAL_ADC_Start_DMA(&g_adc_dma_handle, &mar ,0);
}
/* ADC MSP初始化函数 */
void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
if(hadc->Instance == ADC1)
{
GPIO_InitTypeDef gpio_init_struct;
RCC_PeriphCLKInitTypeDef adc_clk_init = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_ADC1_CLK_ENABLE();
gpio_init_struct.Pin = GPIO_PIN_1;
gpio_init_struct.Mode = GPIO_MODE_ANALOG;
HAL_GPIO_Init(GPIOA, &gpio_init_struct);
adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;
adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;
HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);
}
}
/* 使能一次ADC DMA传输函数 */
void adc_dma_enable(uint16_t cndtr)
{
ADC1->CR2 &= ~(1 << 0);
DMA1_Channel1->CCR &= ~(1 << 0);
while (DMA1_Channel1->CCR & (1 << 0));
DMA1_Channel1->CNDTR = cndtr;
DMA1_Channel1->CCR |= 1 << 0;
ADC1->CR2 |= 1 << 0;
ADC1->CR2 |= 1 << 22;
// __HAL_ADC_DISABLE(&g_adc_dma_handle);
//
// __HAL_DMA_DISABLE(&g_dma_adc_handle);
// while (__HAL_DMA_GET_FLAG(&g_dma_adc_handle, __HAL_DMA_GET_TC_FLAG_INDEX(&g_dma_adc_handle)));
// DMA1_Channel1->CNDTR = cndtr;
// __HAL_DMA_ENABLE(&g_dma_adc_handle);
//
// __HAL_ADC_ENABLE(&g_adc_dma_handle);
// HAL_ADC_Start(&g_adc_dma_handle);
}
/* ADC DMA采集中断服务函数 */
void DMA1_Channel1_IRQHandler(void)
{
if (DMA1->ISR & (1<<1))
{
g_adc_dma_sta = 1;
DMA1->IFCR |= 1 << 1;
}
}
adc.h
#ifndef __ADC_H
#define __ADC_H
#include "./SYSTEM/sys/sys.h"
void adc_dma_init(uint32_t mar);
void adc_dma_enable(uint16_t cndtr);
#endif