小工具知识网

当前位置: 首页 > 行业知识 > stm32——hal库学习笔记(ADC)

行业知识

stm32——hal库学习笔记(ADC)

2026-10-19 17:20:34 来源:互联网转载

这里写目录标题

  • 一、ADC简介(了解)
    • 1.1,什么是ADC?
    • 1.2,常见的ADC类型
    • 1.3,并联比较型工作示意图
    • 1.4,逐次逼近型工作示意图
    • 1.5,ADC的特性参数
    • 1.6,STM32各系列ADC的主要特性
    • 二、ADC工作原理(掌握)
      • 2.1,ADC框图简介(F1)
      • 2.2,参考电压/模拟部分电压(战舰为例)
      • 2.3,输入通道 ( F1为例)
      • 2.4,转换序列(F1为例)
      • 2.5,触发源(F1)
      • 2.6,转换时间(F1)
      • 2.7,数据寄存器(F1)
      • 2.8,中断
      • 2.9,单次转换模式和连续转换模式
      • 2.10,扫描模式
      • 三、单通道ADC采集实验(熟悉)
        • 3.1,实验简要(了解)
        • 3.2,ADC寄存器介绍(了解)
        • 3.3,单通道ADC采集实验配置步骤(掌握)
        • 3.4,编程实战:单通道ADC采集实验(掌握)
        • 四、单通道ADC采集(DMA读取)实验(熟悉)
          • 4.1,实验简要(了解)
          • 4.2,单通道ADC采集(DMA读取)实验配置步骤(掌握)
          • 4.3,编程实战:单通道ADC采集(DMA读取)实验(掌握)
          • 五、多通道ADC采集(DMA读取)实验(熟悉)
          • 六、单通道ADC过采样实验(熟悉)
            • 6.1,如何用过采样和求均值的方式提高ADC的分辨率?(熟悉)
            • 6.2,实验简要(了解)
            • 6.3,编程实战:单通道ADC过采样(16位分辨率)实验(掌握)
            • 七、内部温度传感器实验(熟悉)
              • 7.1,STM32内部温度传感器简介(了解)
              • 7.2,温度计算方法(熟悉)
              • 7.3,实验简要(了解)
              • 7.4,编程实战:内部温度传感器实验(掌握)
              • 八、光敏传感器实验(熟悉)
                • 8.1,光敏二极管简介(了解)
                • 8.2,实验原理(熟悉)
                • 8.3,实验简要(了解)
                • 8.4,���程实战:光敏传感器实验(掌握)

                  一、ADC简介(了解)

                  1.1,什么是ADC?

                  ADC,全称:Analog-to-Digital Converter,指模拟/数字转换器

                  1.2,常见的ADC类型

                  1.3,并联比较型工作示意图

                  优点:转换速度快

                  缺点:成本高、功耗高、分辨率低

                  1.4,逐次逼近型工作示意图

                  优点:结构简单、低功耗

                  缺点:转换速度较慢

                  特点:

                  分辨率和采样速度相互矛盾,

                  分辨率越高,采样速率越低

                  1.5,ADC的特性参数

                  1.6,STM32各系列ADC的主要特性

                  二、ADC工作原理(掌握)

                  2.1,ADC框图简介(F1)

                  ①参考电压/模拟部分电压

                  ②输入通道

                  ③转换序列

                  ④触发源

                  ⑤转换时间

                  ⑥数据寄存器

                  ⑦中断

                  2.2,参考电压/模拟部分电压(战舰为例)

                  2.3,输入通道 ( F1为例)

                  2.4,转换序列(F1为例)

                  规则组和注入组执行优先级对比

                  规则序列和注入序列(F1为例)

                  2.5,触发源(F1)

                  2.6,转换时间(F1)

                  2.7,数据寄存器(F1)

                  2.8,中断

                  2.9,单次转换模式和连续转换模式

                  2.10,扫描模式

                  三、单通道ADC采集实验(熟悉)

                  3.1,实验简要(了解)

                  3.2,ADC寄存器介绍(了解)

                  3.3,单通道ADC采集实验配置步骤(掌握)

                  HAL_ADC_Init()、HAL_ADCEx_Calibration_Start()
                  HAL_ADC_MspInit()     //配置NVIC、CLOCK、GPIO等
                  HAL_ADC_ConfigChannel()
                  HAL_ADC_Start()
                  HAL_ADC_PollForConversion()
                  HAL_ADC_GetValue()

                  相关HAL库函数介绍

                  关键结构体介绍(F1为例)

                  3.4,编程实战:单通道ADC采集实验(掌握)

                  (战舰为例)

                  adc.c

                  #include "./BSP/ADC/adc.h"#include "./SYSTEM/delay/delay.h"ADC_HandleTypeDef g_adc_handle;   /* ADC句柄 *//** * @brief       ADC初始化函数 *   @note      本函数支持ADC1/ADC2任意通道, 但是不支持ADC3 *              我们使用12位精度, ADC采样时钟=12M, 转换时间为: 采样周期 + 12.5个ADC周期 *              设置最大采样周期: 239.5, 则转换时间 = 252 个ADC周期 = 21us * @param       无 * @retval      无 */void adc_init(void){    g_adc_handle.Instance = ADC_ADCX;                        /* 选择哪个ADC */    g_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;       /* 数据对齐方式:右对齐 */    g_adc_handle.Init.ScanConvMode = ADC_SCAN_DISABLE;       /* 非扫描模式,仅用到一个通道 */    g_adc_handle.Init.ContinuousConvMode = DISABLE;          /* 关闭连续转换模式 */    g_adc_handle.Init.NbrOfConversion = 1;                   /* 赋值范围是1~16,本实验用到1个规则通道序列 */    g_adc_handle.Init.DiscontinuousConvMode = DISABLE;       /* 禁止规则通道组间断模式 */    g_adc_handle.Init.NbrOfDiscConversion = 0;               /* 配置间断模式的规则通道个数,禁止规则通道组间断模式后,此参数忽略 */    g_adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* 触发转换方式:软件触发 */    HAL_ADC_Init(&g_adc_handle);                             /* 初始化 */    HAL_ADCEx_Calibration_Start(&g_adc_handle);              /* 校准ADC */}/** * @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;        RCC_PeriphCLKInitTypeDef adc_clk_init = {0};                ADC_ADCX_CHY_CLK_ENABLE();                                /* 使能ADCx时钟 */        ADC_ADCX_CHY_GPIO_CLK_ENABLE();                           /* 开启GPIO时钟 */        /* 设置ADC时钟 */        adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;    /* ADC外设时钟 */        adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;       /* 分频因子6时钟为72M/6=12MHz */        HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);                 /* 设置ADC时钟 */        /* 设置AD采集通道对应IO引脚工作模式 */        gpio_init_struct.Pin = ADC_ADCX_CHY_GPIO_PIN;             /* ADC通道IO引脚 */        gpio_init_struct.Mode = GPIO_MODE_ANALOG;                 /* 模拟 */        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_1CYCLE_5, 1.5个ADC时钟周期        ADC_SAMPLETIME_7CYCLES_5, 7.5个ADC时钟周期 *   @arg       ADC_SAMPLETIME_13CYCLES_5, 13.5个ADC时钟周期     ADC_SAMPLETIME_28CYCLES_5, 28.5个ADC时钟周期 *   @arg       ADC_SAMPLETIME_41CYCLES_5, 41.5个ADC时钟周期     ADC_SAMPLETIME_55CYCLES_5, 55.5个ADC时钟周期 *   @arg       ADC_SAMPLETIME_71CYCLES_5, 71.5个ADC时钟周期     ADC_SAMPLETIME_239CYCLES_5, 239.5个ADC时钟周期 * @param       rank: 多通道采集时需要设置的采集编号,                假设你定义channle1的rank=1,channle2 的rank=2,                那么对应你在DMA缓存空间的变量数组AdcDMA[0] 就i是channle1的转换结果,AdcDMA[1]就是通道2的转换结果。                 单通道DMA设置为 ADC_REGULAR_RANK_1 *   @arg       编号1~16:ADC_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_ChannelConfTypeDef adc_ch_conf;        adc_ch_conf.Channel = ch;                            /* 通道 */    adc_ch_conf.Rank = rank;                             /* 序列 */    adc_ch_conf.SamplingTime = stime;                    /* 采样时间 */    HAL_ADC_ConfigChannel(adc_handle, &adc_ch_conf);     /* 通道配置 */}/** * @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, ADC_REGULAR_RANK_1, ADC_SAMPLETIME_239CYCLES_5);    /* 设置通道,序列和采样时间 */    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  

                  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_1 #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_1                                 /* 通道Y,  0  __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);   /* 得到某个通道给定次数采样的平均值 */#endif     uint16_t adcx;    float temp;    HAL_Init();                             /* 初始化HAL库 */    sys_stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */    delay_init(72);                         /* 延时初始化 */    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, "ATOM@ALIENTEK", RED);    lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH1_VAL:", BLUE);    lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH1_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);   /* 显示ADCC采样后的原始值 */         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-3=0.1111 */        temp *= 1000;                                    /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */        lcd_show_xnum(150, 130, temp, 3, 16, 0X80, BLUE);/* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */        LED0_TOGGLE();        delay_ms(100);    }}    g_adc_handle.Instance = ADC_ADCX;                        /* 选择哪个ADC */    g_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;       /* 数据对齐方式:右对齐 */    g_adc_handle.Init.ScanConvMode = ADC_SCAN_DISABLE;       /* 非扫描模式,仅用到一个通道 */    g_adc_handle.Init.ContinuousConvMode = DISABLE;          /* 关闭连续转换模式 */    g_adc_handle.Init.NbrOfConversion = 1;                   /* 赋值范围是1~16,本实验用到1个规则通道序列 */    g_adc_handle.Init.DiscontinuousConvMode = DISABLE;       /* 禁止规则通道组间断模式 */    g_adc_handle.Init.NbrOfDiscConversion = 0;               /* 配置间断模式的规则通道个数,禁止规则通道组间断模式后,此参数忽略 */    g_adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* 触发转换方式:软件触发 */    HAL_ADC_Init(&g_adc_handle);                             /* 初始化 */    HAL_ADCEx_Calibration_Start(&g_adc_handle);              /* 校准ADC */}/** * @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;        RCC_PeriphCLKInitTypeDef adc_clk_init = {0};                ADC_ADCX_CHY_CLK_ENABLE();                                /* 使能ADCx时钟 */        ADC_ADCX_CHY_GPIO_CLK_ENABLE();                           /* 开启GPIO时钟 */        /* 设置ADC时钟 */        adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;    /* ADC外设时钟 */        adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;       /* 分频因子6时钟为72M/6=12MHz */        HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);                 /* 设置ADC时钟 */        /* 设置AD采集通道对应IO引脚工作模式 */        gpio_init_struct.Pin = ADC_ADCX_CHY_GPIO_PIN;             /* ADC通道IO引脚 */        gpio_init_struct.Mode = GPIO_MODE_ANALOG;                 /* 模拟 */        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_1CYCLE_5, 1.5个ADC时钟周期        ADC_SAMPLETIME_7CYCLES_5, 7.5个ADC时钟周期 *   @arg       ADC_SAMPLETIME_13CYCLES_5, 13.5个ADC时钟周期     ADC_SAMPLETIME_28CYCLES_5, 28.5个ADC时钟周期 *   @arg       ADC_SAMPLETIME_41CYCLES_5, 41.5个ADC时钟周期     ADC_SAMPLETIME_55CYCLES_5, 55.5个ADC时钟周期 *   @arg       ADC_SAMPLETIME_71CYCLES_5, 71.5个ADC时钟周期     ADC_SAMPLETIME_239CYCLES_5, 239.5个ADC时钟周期 * @param       rank: 多通道采集时需要设置的采集编号,                假设你定义channle1的rank=1,channle2 的rank=2,                那么对应你在DMA缓存空间的变量数组AdcDMA[0] 就i是channle1的转换结果,AdcDMA[1]就是通道2的转换结果。                 单通道DMA设置为 ADC_REGULAR_RANK_1 *   @arg       编号1~16:ADC_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_ChannelConfTypeDef adc_ch_conf;        adc_ch_conf.Channel = ch;                            /* 通道 */    adc_ch_conf.Rank = rank;                             /* 序列 */    adc_ch_conf.SamplingTime = stime;                    /* 采样时间 */    HAL_ADC_ConfigChannel(adc_handle, &adc_ch_conf);     /* 通道配置 */}/** * @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, ADC_REGULAR_RANK_1, ADC_SAMPLETIME_239CYCLES_5);    /* 设置通道,序列和采样时间 */    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 DR, mar, 0);       /* 启动DMA,并开启中断 */    HAL_ADC_Start_DMA(&g_adc_dma_handle, &mar, 0);                          /* 开启ADC,通过DMA传输结果 */}/** * @brief       使能一次ADC DMA传输 *   @note      该函数用寄存器来操作,防止用HAL库操作对其他参数有修改,也为了兼容性 * @param       ndtr: DMA传输的次数 * @retval      无 */void adc_dma_enable(uint16_t cndtr){    ADC_ADCX->CR2 &= ~(1 CCR &= ~(1 CCR & (1 CNDTR = cndtr;              /* DMA传输数据量 */    ADC_ADCX_DMACx->CCR |= 1 CR2 |= 1 CR2 |= 1     if (ADC_ADCX_DMACx_IS_TC())    {        g_adc_dma_sta = 1;                      /* 标记DMA传输完成 */        ADC_ADCX_DMACx_CLR_TC();                /* 清除DMA1 数据流7 传输完成中断 */    }} __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)  /* PA口时钟使能 */#define ADC_ADCX                            ADC1 #define ADC_ADCX_CHY                        ADC_CHANNEL_1                                /* 通道Y,  0  __HAL_RCC_ADC1_CLK_ENABLE(); }while(0)   /* ADC1 时钟使能 *//* ADC单通道/多通道 DMA采集 DMA及通道 定义 * 注意: ADC1的DMA通道只能是: DMA1_Channel1, 因此只要是ADC1, 这里是不能改动的 *       ADC2不支持DMA采集 *       ADC3的DMA通道只能是: DMA2_Channel5, 因此如果使用 ADC3 则需要修改 */#define ADC_ADCX_DMACx                      DMA1_Channel1#define ADC_ADCX_DMACx_IRQn                 DMA1_Channel1_IRQn#define ADC_ADCX_DMACx_IRQHandler           DMA1_Channel1_IRQHandler#define ADC_ADCX_DMACx_IS_TC()              ( DMA1-ISR & (1  DMA1-IFCR |= 1     uint16_t i;    uint16_t adcx;    uint32_t sum;    float temp;    HAL_Init();                             /* 初始化HAL库 */    sys_stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */    delay_init(72);                         /* 延时初始化 */    usart_init(115200);                     /* 串口初始化为115200 */    led_init();                             /* 初始化LED */    lcd_init();                             /* 初始化LCD */    adc_dma_init((uint32_t)&g_adc_dma_buf); /* 初始化ADC DMA采集 */    lcd_show_string(30,  50, 200, 16, 16, "STM32", RED);    lcd_show_string(30,  70, 200, 16, 16, "ADC DMA TEST", RED);    lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);    lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH1_VAL:", BLUE);    lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH1_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */    adc_dma_enable(ADC_DMA_BUF_SIZE);   /* 启动ADC DMA采集 */    while (1)    {        if (g_adc_dma_sta == 1)        {            /* 计算DMA 采集到的ADC数据的平均值 */            sum = 0;            for (i = 0; i  (uint32_t)DMA1_Channel7)                   /* 大于DMA1_Channel7, 则为DMA2的通道了 */    {        __HAL_RCC_DMA2_CLK_ENABLE();                                          /* DMA2时钟使能 */    }    else    {        __HAL_RCC_DMA1_CLK_ENABLE();                                          /* DMA1时钟使能 */    }    /* 设置ADC时钟 */    adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;                    /* ADC外设时钟 */    adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;                       /* 分频因子6时钟为72M/6=12MHz */    HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);                                 /* 设置ADC时钟 */    /*         设置ADC1通道0~5对应的IO口模拟输入        AD采集引脚模式设置,模拟输入        PA0对应 ADC1_IN0        PA1对应 ADC1_IN1        PA2对应 ADC1_IN2        PA3对应 ADC1_IN3        PA4对应 ADC1_IN4        PA5对应 ADC1_IN5    */    gpio_init_struct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;  /* GPIOA0~5 */    gpio_init_struct.Mode = GPIO_MODE_ANALOG;                                 /* 模拟 */    HAL_GPIO_Init(GPIOA, &gpio_init_struct);    /* 初始化DMA */    g_dma_nch_adc_handle.Instance = ADC_ADCX_DMACx;                           /* 设置DMA通道 */    g_dma_nch_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;               /* 从外设到存储器模式 */    g_dma_nch_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;                   /* 外设非增量模式 */    g_dma_nch_adc_handle.Init.MemInc = DMA_MINC_ENABLE;                       /* 存储器增量模式 */    g_dma_nch_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  /* 外设数据长度:16位 */    g_dma_nch_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     /* 存储器数据长度:16位 */    g_dma_nch_adc_handle.Init.Mode = DMA_NORMAL;                              /* 外设流控模式 */    g_dma_nch_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;                 /* 中等优先级 */    HAL_DMA_Init(&g_dma_nch_adc_handle);    __HAL_LINKDMA(&g_adc_nch_dma_handle, DMA_Handle, g_dma_nch_adc_handle);   /* 将DMA与adc联系起来 */    /* 初始化ADC */    g_adc_nch_dma_handle.Instance = ADC_ADCX;                                 /* 选择哪个ADC */    g_adc_nch_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;                /* 数据对齐方式:右对齐 */    g_adc_nch_dma_handle.Init.ScanConvMode = ADC_SCAN_ENABLE;                 /* 使能扫描模式 */    g_adc_nch_dma_handle.Init.ContinuousConvMode = ENABLE;                    /* 使能连续转换 */    g_adc_nch_dma_handle.Init.NbrOfConversion = 6;                            /* 赋值范围是1~16,本实验用到6个规则通道序列 */    g_adc_nch_dma_handle.Init.DiscontinuousConvMode = DISABLE;                /* 禁止规则通道组间断模式 */    g_adc_nch_dma_handle.Init.NbrOfDiscConversion = 0;                        /* 配置间断模式的规则通道个数,禁止规则通道组间断模式后,此参数忽略 */    g_adc_nch_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;          /* 软件触发 */    HAL_ADC_Init(&g_adc_nch_dma_handle);                                      /* 初始化 */    HAL_ADCEx_Calibration_Start(&g_adc_nch_dma_handle);                       /* 校准ADC */    /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_0;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_1;                                    /* 采样序列里的第1个 */    adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;                    /* 采样时间,设置最大采样周期:239.5个ADC周期 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 通道配置 */        adc_ch_conf.Channel = ADC_CHANNEL_1;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_2;                                    /* 采样序列里的第2个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_2;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_3;                                    /* 采样序列里的第3个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_3;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_4;                                    /* 采样序列里的第4个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_4;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_5;                                    /* 采样序列里的第5个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_5;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_6;                                    /* 采样序列里的第6个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    /* 配置DMA数据流请求中断优先级 */    HAL_NVIC_SetPriority(ADC_ADCX_DMACx_IRQn, 3, 3);    HAL_NVIC_EnableIRQ(ADC_ADCX_DMACx_IRQn);    HAL_DMA_Start_IT(&g_dma_nch_adc_handle, (uint32_t)&ADC1->DR, mar, 0);     /* 启动DMA,并开启中断 */    HAL_ADC_Start_DMA(&g_adc_nch_dma_handle, &mar, 0);                        /* 开启ADC,通过DMA传输结果 */}/*************************单通道ADC采集(DMA读取)实验和多通道ADC采集(DMA读取)实验公用代码*******************************//** * @brief       使能一次ADC DMA传输 *   @note      该函数用寄存器来操作,防止用HAL库操作对其他参数有修改,也为了兼容性 * @param       ndtr: DMA传输的次数 * @retval      无 */void adc_dma_enable(uint16_t cndtr){    ADC_ADCX->CR2 &= ~(1 CCR &= ~(1 CCR & (1 CNDTR = cndtr;              /* DMA传输数据量 */    ADC_ADCX_DMACx->CCR |= 1 CR2 |= 1 CR2 |= 1     if (ADC_ADCX_DMACx_IS_TC())    {        g_adc_dma_sta = 1;                      /* 标记DMA传输完成 */        ADC_ADCX_DMACx_CLR_TC();                /* 清除DMA1 数据流7 传输完成中断 */    }} __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)  /* PA口时钟使能 */#define ADC_ADCX                            ADC1 #define ADC_ADCX_CHY                        ADC_CHANNEL_1                                /* 通道Y,  0  __HAL_RCC_ADC1_CLK_ENABLE(); }while(0)   /* ADC1 时钟使能 *//* ADC单通道/多通道 DMA采集 DMA及通道 定义 * 注意: ADC1的DMA通道只能是: DMA1_Channel1, 因此只要是ADC1, 这里是不能改动的 *       ADC2不支持DMA采集 *       ADC3的DMA通道只能是: DMA2_Channel5, 因此如果使用 ADC3 则需要修改 */#define ADC_ADCX_DMACx                      DMA1_Channel1#define ADC_ADCX_DMACx_IRQn                 DMA1_Channel1_IRQn#define ADC_ADCX_DMACx_IRQHandler           DMA1_Channel1_IRQHandler#define ADC_ADCX_DMACx_IS_TC()              ( DMA1-ISR & (1  DMA1-IFCR |= 1     uint16_t i,j;    uint16_t adcx;    uint32_t sum;    float temp;    HAL_Init();                                 /* 初始化HAL库 */    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */    delay_init(72);                             /* 延时初始化 */    usart_init(115200);                         /* 串口初始化为115200 */    led_init();                                 /* 初始化LED */    lcd_init();                                 /* 初始化LCD */    adc_nch_dma_init((uint32_t)&g_adc_dma_buf); /* 初始化ADC DMA采集 */    lcd_show_string(30,  50, 200, 16, 16, "STM32", RED);    lcd_show_string(30,  70, 200, 16, 16, "ADC 6CH DMA TEST", RED);    lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);    lcd_show_string(30, 110, 200, 12, 12, "ADC1_CH0_VAL:", BLUE);    lcd_show_string(30, 122, 200, 12, 12, "ADC1_CH0_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */        lcd_show_string(30, 140, 200, 12, 12, "ADC1_CH1_VAL:", BLUE);    lcd_show_string(30, 152, 200, 12, 12, "ADC1_CH1_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */    lcd_show_string(30, 170, 200, 12, 12, "ADC1_CH2_VAL:", BLUE);    lcd_show_string(30, 182, 200, 12, 12, "ADC1_CH2_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */    lcd_show_string(30, 200, 200, 12, 12, "ADC1_CH3_VAL:", BLUE);    lcd_show_string(30, 212, 200, 12, 12, "ADC1_CH3_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */    lcd_show_string(30, 230, 200, 12, 12, "ADC1_CH4_VAL:", BLUE);    lcd_show_string(30, 242, 200, 12, 12, "ADC1_CH4_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */    lcd_show_string(30, 260, 200, 12, 12, "ADC1_CH5_VAL:", BLUE);    lcd_show_string(30, 272, 200, 12, 12, "ADC1_CH5_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */    adc_dma_enable(ADC_DMA_BUF_SIZE);   /* 启动ADC DMA采集 */    while (1)    {        if (g_adc_dma_sta == 1)        {            /* 循环显示通道0~通道5的结果 */            for(j = 0; j  (uint32_t)DMA1_Channel7)                   /* 大于DMA1_Channel7, 则为DMA2的通道了 */    {        __HAL_RCC_DMA2_CLK_ENABLE();                                          /* DMA2时钟使能 */    }    else    {        __HAL_RCC_DMA1_CLK_ENABLE();                                          /* DMA1时钟使能 */    }    /* 设置ADC时钟 */    adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;                    /* ADC外设时钟 */    adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;                       /* 分频因子6时钟为72M/6=12MHz */    HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);                                 /* 设置ADC时钟 */    /*         设置ADC1通道0~5对应的IO口模拟输入        AD采集引脚模式设置,模拟输入        PA0对应 ADC1_IN0        PA1对应 ADC1_IN1        PA2对应 ADC1_IN2        PA3对应 ADC1_IN3        PA4对应 ADC1_IN4        PA5对应 ADC1_IN5    */    gpio_init_struct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;  /* GPIOA0~5 */    gpio_init_struct.Mode = GPIO_MODE_ANALOG;                                 /* 模拟 */    HAL_GPIO_Init(GPIOA, &gpio_init_struct);    /* 初始化DMA */    g_dma_nch_adc_handle.Instance = ADC_ADCX_DMACx;                           /* 设置DMA通道 */    g_dma_nch_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;               /* 从外设到存储器模式 */    g_dma_nch_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;                   /* 外设非增量模式 */    g_dma_nch_adc_handle.Init.MemInc = DMA_MINC_ENABLE;                       /* 存储器增量模式 */    g_dma_nch_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  /* 外设数据长度:16位 */    g_dma_nch_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     /* 存储器数据长度:16位 */    g_dma_nch_adc_handle.Init.Mode = DMA_NORMAL;                              /* 外设流控模式 */    g_dma_nch_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;                 /* 中等优先级 */    HAL_DMA_Init(&g_dma_nch_adc_handle);    __HAL_LINKDMA(&g_adc_nch_dma_handle, DMA_Handle, g_dma_nch_adc_handle);   /* 将DMA与adc联系起来 */    /* 初始化ADC */    g_adc_nch_dma_handle.Instance = ADC_ADCX;                                 /* 选择哪个ADC */    g_adc_nch_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;                /* 数据对齐方式:右对齐 */    g_adc_nch_dma_handle.Init.ScanConvMode = ADC_SCAN_ENABLE;                 /* 使能扫描模式 */    g_adc_nch_dma_handle.Init.ContinuousConvMode = ENABLE;                    /* 使能连续转换 */    g_adc_nch_dma_handle.Init.NbrOfConversion = 6;                            /* 赋值范围是1~16,本实验用到6个规则通道序列 */    g_adc_nch_dma_handle.Init.DiscontinuousConvMode = DISABLE;                /* 禁止规则通道组间断模式 */    g_adc_nch_dma_handle.Init.NbrOfDiscConversion = 0;                        /* 配置间断模式的规则通道个数,禁止规则通道组间断模式后,此参数忽略 */    g_adc_nch_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;          /* 软件触发 */    HAL_ADC_Init(&g_adc_nch_dma_handle);                                      /* 初始化 */    HAL_ADCEx_Calibration_Start(&g_adc_nch_dma_handle);                       /* 校准ADC */    /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_0;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_1;                                    /* 采样序列里的第1个 */    adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;                    /* 采样时间,设置最大采样周期:239.5个ADC周期 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 通道配置 */        adc_ch_conf.Channel = ADC_CHANNEL_1;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_2;                                    /* 采样序列里的第2个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_2;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_3;                                    /* 采样序列里的第3个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_3;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_4;                                    /* 采样序列里的第4个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_4;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_5;                                    /* 采样序列里的第5个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_5;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_6;                                    /* 采样序列里的第6个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    /* 配置DMA数据流请求中断优先级 */    HAL_NVIC_SetPriority(ADC_ADCX_DMACx_IRQn, 3, 3);    HAL_NVIC_EnableIRQ(ADC_ADCX_DMACx_IRQn);    HAL_DMA_Start_IT(&g_dma_nch_adc_handle, (uint32_t)&ADC1->DR, mar, 0);     /* 启动DMA,并开启中断 */    HAL_ADC_Start_DMA(&g_adc_nch_dma_handle, &mar, 0);                        /* 开启ADC,通过DMA传输结果 */}/*************************单通道ADC采集(DMA读取)实验和多通道ADC采集(DMA读取)实验公用代码*******************************//** * @brief       使能一次ADC DMA传输 *   @note      该函数用寄存器来操作,防止用HAL库操作对其他参数有修改,也为了兼容性 * @param       ndtr: DMA传输的次数 * @retval      无 */void adc_dma_enable(uint16_t cndtr){    ADC_ADCX->CR2 &= ~(1 CCR &= ~(1 CCR & (1 CNDTR = cndtr;              /* DMA传输数据量 */    ADC_ADCX_DMACx->CCR |= 1 CR2 |= 1 CR2 |= 1     if (ADC_ADCX_DMACx_IS_TC())    {        g_adc_dma_sta = 1;                      /* 标记DMA传输完成 */        ADC_ADCX_DMACx_CLR_TC();                /* 清除DMA1 数据流7 传输完成中断 */    }} __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)  /* PA口时钟使能 */#define ADC_ADCX                            ADC1 #define ADC_ADCX_CHY                        ADC_CHANNEL_1                                /* 通道Y,  0  __HAL_RCC_ADC1_CLK_ENABLE(); }while(0)   /* ADC1 时钟使能 *//* ADC单通道/多通道 DMA采集 DMA及通道 定义 * 注意: ADC1的DMA通道只能是: DMA1_Channel1, 因此只要是ADC1, 这里是不能改动的 *       ADC2不支持DMA采集 *       ADC3的DMA通道只能是: DMA2_Channel5, 因此如果使用 ADC3 则需要修改 */#define ADC_ADCX_DMACx                      DMA1_Channel1#define ADC_ADCX_DMACx_IRQn                 DMA1_Channel1_IRQn#define ADC_ADCX_DMACx_IRQHandler           DMA1_Channel1_IRQHandler#define ADC_ADCX_DMACx_IS_TC()              ( DMA1-ISR & (1  DMA1-IFCR |= 1     uint16_t i;    uint32_t adcx;    uint32_t sum;    float temp;    HAL_Init();                                 /* 初始化HAL库 */    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */    delay_init(72);                             /* 延时初始化 */    usart_init(115200);                         /* 串口初始化为115200 */    led_init();                                 /* 初始化LED */    lcd_init();                                 /* 初始化LCD */    adc_dma_init((uint32_t)&g_adc_dma_buf);     /* 初始化ADC DMA采集 */    adc_channel_set(&g_adc_dma_handle, ADC_ADCX_CHY, ADC_REGULAR_RANK_1, ADC_SAMPLETIME_1CYCLE_5); /* 设置ADCX对应通道采样时间为1.5个时钟周期, 已达到最高的采集速度 */    lcd_show_string(30,  50, 200, 16, 16, "STM32", RED);    lcd_show_string(30,  70, 200, 16, 16, "ADC OverSample TEST", RED);    lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);    lcd_show_string(30, 110, 200, 16, 16, "ADC1_CH1_VAL:", BLUE);    lcd_show_string(30, 130, 200, 16, 16, "ADC1_CH1_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */    adc_dma_enable(ADC_DMA_BUF_SIZE);           /* 启动ADC DMA采集 */    while (1)    {        if (g_adc_dma_sta == 1)        {            /* 计算DMA 采集到的ADC数据的平均值 */            sum = 0;            for (i = 0; i  N */            /* 显示结果 */            lcd_show_xnum(134, 110, adcx, 5, 16, 0, BLUE);      /* 显示ADCC采样后的原始值 */            temp = (float)adcx * (3.3 / 65536);                 /* 获取计算后的带小数的实际电压值,比如3.1111 */            adcx = temp;                                        /* 赋值整数部分给adcx变量,因为adcx为u16整形 */            lcd_show_xnum(134, 130, adcx, 1, 16, 0, BLUE);      /* 显示电压值的整数部分,3.1111的话,这里就是显示3 */            temp -= adcx;                                       /* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */            temp *= 1000;                                       /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */            lcd_show_xnum(150, 130, temp, 3, 16, 0X80, BLUE);   /* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */            g_adc_dma_sta = 0;                                  /* 清除DMA采集完成状态标志 */            adc_dma_enable(ADC_DMA_BUF_SIZE);                   /* 启动下一次ADC DMA采集 */        }        LED0_TOGGLE();        delay_ms(100);    }}

                  七、内部温度传感器实验(熟悉)

                  7.1,STM32内部温度传感器简介(了解)

                  7.2,温度计算方法(熟悉)

                  7.3,实验简要(了解)

                  7.4,编程实战:内部温度传感器实验(掌握)

                  adc.c

                  #include "./BSP/ADC/adc.h"#include "./SYSTEM/delay/delay.h"ADC_HandleTypeDef g_adc_handle;   /* ADC句柄 *//** * @brief       ADC初始化函数 *   @note      本函数支持ADC1/ADC2任意通道, 但是不支持ADC3 *              我们使用12位精度, ADC采样时钟=12M, 转换时间为: 采样周期 + 12.5个ADC周期 *              设置最大采样周期: 239.5, 则转换时间 = 252 个ADC周期 = 21us * @param       无 * @retval      无 */void adc_init(void){    g_adc_handle.Instance = ADC_ADCX;                        /* 选择哪个ADC */    g_adc_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;       /* 数据对齐方式:右对齐 */    g_adc_handle.Init.ScanConvMode = ADC_SCAN_DISABLE;       /* 非扫描模式,仅用到一个通道 */    g_adc_handle.Init.ContinuousConvMode = DISABLE;          /* 关闭连续转换模式 */    g_adc_handle.Init.NbrOfConversion = 1;                   /* 赋值范围是1~16,本实验用到1个规则通道序列 */    g_adc_handle.Init.DiscontinuousConvMode = DISABLE;       /* 禁止规则通道组间断模式 */    g_adc_handle.Init.NbrOfDiscConversion = 0;               /* 配置间断模式的规则通道个数,禁止规则通道组间断模式后,此参数忽略 */    g_adc_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* 触发转换方式:软件触发 */    HAL_ADC_Init(&g_adc_handle);                             /* 初始化 */    HAL_ADCEx_Calibration_Start(&g_adc_handle);              /* 校准ADC */}/** * @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;        RCC_PeriphCLKInitTypeDef adc_clk_init = {0};                ADC_ADCX_CHY_CLK_ENABLE();                                /* 使能ADCx时钟 */        ADC_ADCX_CHY_GPIO_CLK_ENABLE();                           /* 开启GPIO时钟 */        /* 设置ADC时钟 */        adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;    /* ADC外设时钟 */        adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;       /* 分频因子6时钟为72M/6=12MHz */        HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);                 /* 设置ADC时钟 */        /* 设置AD采集通道对应IO引脚工作模式 */        gpio_init_struct.Pin = ADC_ADCX_CHY_GPIO_PIN;             /* ADC通道IO引脚 */        gpio_init_struct.Mode = GPIO_MODE_ANALOG;                 /* 模拟 */        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_1CYCLE_5, 1.5个ADC时钟周期        ADC_SAMPLETIME_7CYCLES_5, 7.5个ADC时钟周期 *   @arg       ADC_SAMPLETIME_13CYCLES_5, 13.5个ADC时钟周期     ADC_SAMPLETIME_28CYCLES_5, 28.5个ADC时钟周期 *   @arg       ADC_SAMPLETIME_41CYCLES_5, 41.5个ADC时钟周期     ADC_SAMPLETIME_55CYCLES_5, 55.5个ADC时钟周期 *   @arg       ADC_SAMPLETIME_71CYCLES_5, 71.5个ADC时钟周期     ADC_SAMPLETIME_239CYCLES_5, 239.5个ADC时钟周期 * @param       rank: 多通道采集时需要设置的采集编号,                假设你定义channle1的rank=1,channle2 的rank=2,                那么对应你在DMA缓存空间的变量数组AdcDMA[0] 就i是channle1的转换结果,AdcDMA[1]就是通道2的转换结果。                 单通道DMA设置为 ADC_REGULAR_RANK_1 *   @arg       编号1~16:ADC_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_ChannelConfTypeDef adc_ch_conf;        adc_ch_conf.Channel = ch;                            /* 通道 */    adc_ch_conf.Rank = rank;                             /* 序列 */    adc_ch_conf.SamplingTime = stime;                    /* 采样时间 */    HAL_ADC_ConfigChannel(adc_handle, &adc_ch_conf);     /* 通道配置 */}/** * @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, ADC_REGULAR_RANK_1, ADC_SAMPLETIME_239CYCLES_5);    /* 设置通道,序列和采样时间 */    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  (uint32_t)DMA1_Channel7)                 /* 大于DMA1_Channel7, 则为DMA2的通道了 */    {        __HAL_RCC_DMA2_CLK_ENABLE();                                        /* DMA2时钟使能 */    }    else    {        __HAL_RCC_DMA1_CLK_ENABLE();                                        /* DMA1时钟使能 */    }    /* 设置ADC时钟 */    adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;                  /* ADC外设时钟 */    adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;                     /* 分频因子6时钟为72M/6=12MHz */    HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);                               /* 设置ADC时钟 */    /* 设置AD采集通道对应IO引脚工作模式 */    gpio_init_struct.Pin = ADC_ADCX_CHY_GPIO_PIN;                           /* ADC通道对应的IO引脚 */    gpio_init_struct.Mode = GPIO_MODE_ANALOG;                               /* 模拟 */    HAL_GPIO_Init(ADC_ADCX_CHY_GPIO_PORT, &gpio_init_struct);    /* 初始化DMA */    g_dma_adc_handle.Instance = ADC_ADCX_DMACx;                             /* 设置DMA通道 */    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;    /* 外设数据长度:16位 */    g_dma_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;       /* 存储器数据长度:16位 */    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);         /* 将DMA与adc联系起来 */    g_adc_dma_handle.Instance = ADC_ADCX;                                   /* 选择哪个ADC */    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;                              /* 赋值范围是1~16,本实验用到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 */    /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_ADCX_CHY;                                     /* 通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_1;                                  /* 序列 */    adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;                  /* 采样时间,设置最大采样周期:239.5个ADC周期 */    HAL_ADC_ConfigChannel(&g_adc_dma_handle, &adc_ch_conf);                 /* 通道配置 */    /* 配置DMA数据流请求中断优先级 */    HAL_NVIC_SetPriority(ADC_ADCX_DMACx_IRQn, 3, 3);    HAL_NVIC_EnableIRQ(ADC_ADCX_DMACx_IRQn);    HAL_DMA_Start_IT(&g_dma_adc_handle, (uint32_t)&ADC1->DR, mar, 0);       /* 启动DMA,并开启中断 */    HAL_ADC_Start_DMA(&g_adc_dma_handle, &mar, 0);                          /* 开启ADC,通过DMA传输结果 */}/*************************单通道ADC采集(DMA读取)实验和多通道ADC采集(DMA读取)实验公用代码*******************************/DMA_HandleTypeDef g_dma_nch_adc_handle = {0};                               /* 定义要搬运ADC多通道数据的DMA句柄 */ADC_HandleTypeDef g_adc_nch_dma_handle = {0};                               /* 定义ADC(多通道DMA读取)句柄 *//** * @brief       ADC N通道(6通道) DMA读取 初始化函数 *   @note      本函数还是使用adc_init对ADC进行大部分配置,有差异的地方再单独配置 *              另外,由于本函数用到了6个通道, 宏定义会比较多内容, 因此,本函数就不采用宏定义的方式来修改通道了, *              直接在本函数里面修改, 这里我们默认使用PA0~PA5这6个通道. * *              注意: 本函数还是使用 ADC_ADCX(默认=ADC1) 和 ADC_ADCX_DMACx( DMA1_Channel1 ) 及其相关定义 *              不要乱修改adc.h里面的这两部分内容, 必须在理解原理的基础上进行修改, 否则可能导致无法正常使用. * * @param       mar         : 存储器地址  * @retval      无 */void adc_nch_dma_init(uint32_t mar){    GPIO_InitTypeDef gpio_init_struct;    RCC_PeriphCLKInitTypeDef adc_clk_init = {0};    ADC_ChannelConfTypeDef adc_ch_conf = {0};    ADC_ADCX_CHY_CLK_ENABLE(); /* 使能ADCx时钟 */    __HAL_RCC_GPIOA_CLK_ENABLE();                                             /* 开启GPIOA时钟 */    if ((uint32_t)ADC_ADCX_DMACx > (uint32_t)DMA1_Channel7)                   /* 大于DMA1_Channel7, 则为DMA2的通道了 */    {        __HAL_RCC_DMA2_CLK_ENABLE();                                          /* DMA2时钟使能 */    }    else    {        __HAL_RCC_DMA1_CLK_ENABLE();                                          /* DMA1时钟使能 */    }    /* 设置ADC时钟 */    adc_clk_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;                    /* ADC外设时钟 */    adc_clk_init.AdcClockSelection = RCC_ADCPCLK2_DIV6;                       /* 分频因子6时钟为72M/6=12MHz */    HAL_RCCEx_PeriphCLKConfig(&adc_clk_init);                                 /* 设置ADC时钟 */    /*         设置ADC1通道0~5对应的IO口模拟输入        AD采集引脚模式设置,模拟输入        PA0对应 ADC1_IN0        PA1对应 ADC1_IN1        PA2对应 ADC1_IN2        PA3对应 ADC1_IN3        PA4对应 ADC1_IN4        PA5对应 ADC1_IN5    */    gpio_init_struct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;  /* GPIOA0~5 */    gpio_init_struct.Mode = GPIO_MODE_ANALOG;                                 /* 模拟 */    HAL_GPIO_Init(GPIOA, &gpio_init_struct);    /* 初始化DMA */    g_dma_nch_adc_handle.Instance = ADC_ADCX_DMACx;                           /* 设置DMA通道 */    g_dma_nch_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;               /* 从外设到存储器模式 */    g_dma_nch_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;                   /* 外设非增量模式 */    g_dma_nch_adc_handle.Init.MemInc = DMA_MINC_ENABLE;                       /* 存储器增量模式 */    g_dma_nch_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  /* 外设数据长度:16位 */    g_dma_nch_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     /* 存储器数据长度:16位 */    g_dma_nch_adc_handle.Init.Mode = DMA_NORMAL;                              /* 外设流控模式 */    g_dma_nch_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;                 /* 中等优先级 */    HAL_DMA_Init(&g_dma_nch_adc_handle);    __HAL_LINKDMA(&g_adc_nch_dma_handle, DMA_Handle, g_dma_nch_adc_handle);   /* 将DMA与adc联系起来 */    /* 初始化ADC */    g_adc_nch_dma_handle.Instance = ADC_ADCX;                                 /* 选择哪个ADC */    g_adc_nch_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;                /* 数据对齐方式:右对齐 */    g_adc_nch_dma_handle.Init.ScanConvMode = ADC_SCAN_ENABLE;                 /* 使能扫描模式 */    g_adc_nch_dma_handle.Init.ContinuousConvMode = ENABLE;                    /* 使能连续转换 */    g_adc_nch_dma_handle.Init.NbrOfConversion = 6;                            /* 赋值范围是1~16,本实验用到6个规则通道序列 */    g_adc_nch_dma_handle.Init.DiscontinuousConvMode = DISABLE;                /* 禁止规则通道组间断模式 */    g_adc_nch_dma_handle.Init.NbrOfDiscConversion = 0;                        /* 配置间断模式的规则通道个数,禁止规则通道组间断模式后,此参数忽略 */    g_adc_nch_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;          /* 软件触发 */    HAL_ADC_Init(&g_adc_nch_dma_handle);                                      /* 初始化 */    HAL_ADCEx_Calibration_Start(&g_adc_nch_dma_handle);                       /* 校准ADC */    /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_0;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_1;                                    /* 采样序列里的第1个 */    adc_ch_conf.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;                    /* 采样时间,设置最大采样周期:239.5个ADC周期 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 通道配置 */        adc_ch_conf.Channel = ADC_CHANNEL_1;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_2;                                    /* 采样序列里的第2个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_2;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_3;                                    /* 采样序列里的第3个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_3;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_4;                                    /* 采样序列里的第4个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_4;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_5;                                    /* 采样序列里的第5个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    adc_ch_conf.Channel = ADC_CHANNEL_5;                                      /* 配置使用的ADC通道 */    adc_ch_conf.Rank = ADC_REGULAR_RANK_6;                                    /* 采样序列里的第6个 */    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &adc_ch_conf);               /* 配置ADC通道 */    /* 配置DMA数据流请求中断优先级 */    HAL_NVIC_SetPriority(ADC_ADCX_DMACx_IRQn, 3, 3);    HAL_NVIC_EnableIRQ(ADC_ADCX_DMACx_IRQn);    HAL_DMA_Start_IT(&g_dma_nch_adc_handle, (uint32_t)&ADC1->DR, mar, 0);     /* 启动DMA,并开启中断 */    HAL_ADC_Start_DMA(&g_adc_nch_dma_handle, &mar, 0);                        /* 开启ADC,通过DMA传输结果 */}/*************************单通道ADC采集(DMA读取)实验和多通道ADC采集(DMA读取)实验公用代码*******************************//** * @brief       使能一次ADC DMA传输 *   @note      该函数用寄存器来操作,防止用HAL库操作对其他参数有修改,也为了兼容性 * @param       ndtr: DMA传输的次数 * @retval      无 */void adc_dma_enable(uint16_t cndtr){    ADC_ADCX->CR2 &= ~(1 CCR &= ~(1 CCR & (1 CNDTR = cndtr;              /* DMA传输数据量 */    ADC_ADCX_DMACx->CCR |= 1 CR2 |= 1 CR2 |= 1     if (ADC_ADCX_DMACx_IS_TC())    {        g_adc_dma_sta = 1;                      /* 标记DMA传输完成 */        ADC_ADCX_DMACx_CLR_TC();                /* 清除DMA1 数据流7 传输完成中断 */    }}/*********************************************内部温度传感器实验代码***************************************************//** * @brief       ADC 内部温度传感器 初始化函数 *   @note      本函数还是使用adc_init对ADC进行大部分配置,有差异的地方再单独配置 *              注意: STM32F103内部温度传感器只连接在ADC1的通道16上, 其他ADC无法进行转换. * * @param       无 * @retval      无 */void adc_temperature_init(void){    adc_init();                                            /* 先初始化ADC */    SET_BIT(g_adc_handle.Instance-CR2, ADC_CR2_TSVREFE);  /* TSVREFE = 1, 启用内部温度传感器和Vrefint */}/** * @brief       获取内部温度传感器温度值 * @param       无 * @retval      温度值(扩大了100倍,单位:℃.) */short adc_get_temperature(void){    uint32_t adcx;    short result;    double temperature;    adcx = adc_get_result_average(ADC_TEMPSENSOR_CHX, 20);  /* 读取内部温度传感器通道,10次取平均 */    temperature = (float)adcx * (3.3 / 4096);               /* 转化为电压值 */    temperature = (1.43 - temperature) / 0.0043 + 25;       /* 计算温度 */    result = temperature *= 100;                            /* 扩大100倍. */    return result;}

                  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_1 #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_1                                /* 通道Y,  0  __HAL_RCC_ADC1_CLK_ENABLE(); }while(0)   /* ADC1 时钟使能 *//* ADC单通道/多通道 DMA采集 DMA及通道 定义 * 注意: ADC1的DMA通道只能是: DMA1_Channel1, 因此只要是ADC1, 这里是不能改动的 *       ADC2不支持DMA采集 *       ADC3的DMA通道只能是: DMA2_Channel5, 因此如果使用 ADC3 则需要修改 */#define ADC_ADCX_DMACx                      DMA1_Channel1#define ADC_ADCX_DMACx_IRQn                 DMA1_Channel1_IRQn#define ADC_ADCX_DMACx_IRQHandler           DMA1_Channel1_IRQHandler#define ADC_ADCX_DMACx_IS_TC()              ( DMA1-ISR & (1  DMA1-IFCR |= 1     short temp;    HAL_Init();                                 /* 初始化HAL库 */    sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟, 72Mhz */    delay_init(72);                             /* 延时初始化 */    usart_init(115200);                         /* 串口初始化为115200 */    led_init();                                 /* 初始化LED */    lcd_init();                                 /* 初始化LCD */    adc_temperature_init();                     /* 初始化ADC内部温度传感器采集 */    lcd_show_string(30,  50, 200, 16, 16, "STM32", RED);    lcd_show_string(30,  70, 200, 16, 16, "Temperature TEST", RED);    lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);    lcd_show_string(30, 120, 200, 16, 16, "TEMPERATE: 00.00C", BLUE);    while (1)    {        temp = adc_get_temperature();   /* 得到温度值 */        if (temp 

上一篇:哪里有机房防雷施工?

下一篇:监测服务器温度怎么设置?