HAL库源码移植与使用之ADC

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




  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

广药门徒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值