ADC(三):注入组的使用

news2025/2/5 22:51:00

有关ADC的基础知识请参考标准库入门教程

ADC(三):注入组的使用

  • 1、规则组软件触发+注入组自动注入
  • 2、规则组外部触发+注入组自动注入
  • 3、规则组软件触发+注入组外部触发(TIM2_CC1)
  • 4、规则组软件触发+注入组外部触发(EXTI15)+间断模式
  • 5、模拟看门狗的使用

1、规则组软件触发+注入组自动注入

自动注入模式:就是跟随规则组转换,等待规则组转换完成后,在转换注入组,不会抢占规则组的转换。自动注入模式是由注入组的软件触发,不能由注入组的外部触发
在这里插入图片描述

①ADC.c文件的代码如下

#include "ADC.h"

uint16_t ADC1_Buffer[4] = {0};             //数据缓冲区
/**
 * @brief:ADC1初始化函数
 */
RCC_PeriphCLKInitTypeDef PeriphClkInit; //ADC时钟配置结构体
ADC_HandleTypeDef hadc1;                //ADC1配置结构体
ADC_ChannelConfTypeDef sConfig1;        //规则组通道配置结构体
ADC_InjectionConfTypeDef sConfigInjected;//注入组通道配置结构体
void ADC_Init(void)
{
    /* 1、ADC的时钟配置 < 14MHz  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; //需要配置的外设:ADC
    PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;    //设置ADC分频值:6分频 = 12MHz
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
        
    /* 2、ADC1的初始化 */
    __HAL_RCC_ADC1_CLK_ENABLE();                        //使能ADC1时钟
    hadc1.Instance = ADC1;                              //选择ADC1
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;         //数据对齐方式:右对齐
    hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;          //扫描模式:开启扫描(多个通道)
    hadc1.Init.ContinuousConvMode = ENABLE;             //转换模式:连续转换
    hadc1.Init.NbrOfConversion = 4;                     //扫描模式下规则组的数量
  //hadc1.Init.DiscontinuousConvMode = ENABLE;          //扫描模式规则组间断模式
  //hadc1.Init.NbrOfDiscConversion = 2;                 //规则组间断模式下每次间断的通道数:2队为1组
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;   //ADC触发:软件触发
    HAL_ADC_Init(&hadc1);
    
    /* 3、规则组通道配置 */
    sConfig1.Channel = ADC_CHANNEL_0;                    //通道选择:通道0
    sConfig1.Rank = ADC_REGULAR_RANK_1;                  //规则组盒子序号:1号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_1;                    //通道选择:通道1
    sConfig1.Rank = ADC_REGULAR_RANK_2;                  //规则组盒子序号:2号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_2;                    //通道选择:通道2
    sConfig1.Rank = ADC_REGULAR_RANK_3;                  //规则组盒子序号:3号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_3;                    //通道选择:通道3
    sConfig1.Rank = ADC_REGULAR_RANK_4;                  //规则组盒子序号:4号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    /* 4、组入组通道配置 */
    sConfigInjected.InjectedChannel = ADC_CHANNEL_4;                    //通道选择:通道4
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;                 //注入组盒子序号:1号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0,即:数据寄存器值=	测量值 - 偏移值
    sConfigInjected.InjectedNbrOfConversion = 4;                        //组入组通道数量:4个
    sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;            //关闭间断模式
    sConfigInjected.AutoInjectedConv = ENABLE;                          //自动注入:开启
    sConfigInjected.ExternalTrigInjecConv = ADC_INJECTED_SOFTWARE_START;//触发:软件触发
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_5;                    //通道选择:通道5
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;                 //注入组盒子序号:2号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_6;                    //通道选择:通道6
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;                 //注入组盒子序号:3号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_7;                    //通道选择:通道7
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_4;                 //注入组盒子序号:4号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    /* 5、ADC1校准 */
    HAL_ADCEx_Calibration_Start(&hadc1);                //ADC1自校准
    
    /* 6、开启ADC规则组转换 */
    HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC1_Buffer,4); //开启转换:DMA方式,转换完成DMA执行搬运,
                                                        //开启了DMA中断,搬运2后执行DMA中断
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,3,0);       //配置优先级
    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);             //使能中断源
    
    /* 7、开启ADC注入组转换 */
    HAL_ADCEx_InjectedStart_IT(&hadc1);                 //开启转换:注入组设置的通道全部转换完成中断
    HAL_NVIC_SetPriority(ADC1_2_IRQn,3,0);              //配置优先级
    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);                    //使能中断源
}

/**
 * @brief:HAL_ADC_Init()调用函数
 */
DMA_HandleTypeDef hdma1_ADC1;               //ADC1的DMA1的通道配置结构体
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    GPIO_InitTypeDef GPIO_Init;             //IO口配置的结构体
    if(hadc->Instance == ADC1)
    {
        /* 配置ADC1通道0:PA0,通道1:PA1,通道2:PA2,通道3:PA3 */
        __HAL_RCC_GPIOA_CLK_ENABLE();       //使能GPIOA时钟
        GPIO_Init.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3
                       |GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
        GPIO_Init.Mode = GPIO_MODE_ANALOG;  //选择模拟输入模式
        HAL_GPIO_Init(GPIOA, &GPIO_Init);
        
        /* 1、初始化DMA1的通道1配置 */
        __HAL_RCC_DMA1_CLK_ENABLE();                                    //使能DMA1的时钟
        hdma1_ADC1.Instance = DMA1_Channel1;                            //选择DMA1的通道1
        hdma1_ADC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  //外设站点数据宽度:16位
        hdma1_ADC1.Init.PeriphInc = DMA_PINC_DISABLE;                   //外设地址是否递增:选择不自增
        hdma1_ADC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     //内存站点数据宽度:16位
        hdma1_ADC1.Init.MemInc = DMA_MINC_ENABLE;                       //内存地址是否递增:选择自增
        hdma1_ADC1.Init.Direction = DMA_PERIPH_TO_MEMORY;               //传输方向:这里选择外设---->内存
        hdma1_ADC1.Init.Mode = DMA_CIRCULAR;                            //计数器传输模式:自动重装
        hdma1_ADC1.Init.Priority = DMA_PRIORITY_MEDIUM;                 //通道1传输优先级:选择中等
        __HAL_LINKDMA(&hadc1,DMA_Handle,hdma1_ADC1);                    //ADC1和DMA1构建链接
        HAL_DMA_Init(&hdma1_ADC1);
        
    }
    else if(hadc->Instance == ADC2)
    {
        
    }    
}

②ADC.h文件的代码如下

#ifndef __ADC_H
#define __ADC_H

#include "stm32f1xx_hal.h"
extern uint16_t ADC1_Buffer[4];
extern ADC_HandleTypeDef hadc1;                //ADC1配置结构体
extern DMA_HandleTypeDef hdma1_ADC1;           //ADC1的DMA1的通道配置结构体
void ADC_Init(void);

#endif

③main.c文件的代码如下

#include "stm32f1xx_hal.h"
#include "STM32_RCC_Init.h"
#include "ADC.h"
#include "UART.h"
 
int main(void){
    
	HAL_Init();
	HSE_RCC_Init(); 
	UART1_Init(115200);
    ADC_Init();
	printf("启动判断!\r\n");
    
	while(1){
       
	}	
}

④stm32f1xx_it.c文件的代码如下

#include "stm32f1xx_hal.h"   
#include "stm32f1xx_it.h" 
#include "ADC.h" 
#include "UART.h"
/**
 * @brief:DMA通道1中断服务函数
 */
void DMA1_Channel1_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma1_ADC1);//DMA中断服务总函数
}

/**
 * @brief:ADC中断服务函数
 */
void ADC1_2_IRQHandler(void)
{
     HAL_ADC_IRQHandler(&hadc1);//ADC中断服务总函数
}
/******************* 下面的中断的回调函数 ***************************/
/**
 * @brief:规则组的DMA通道1传输完成的中断服务函数
 */
float ADC_Value = 0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if(hadc->Instance == ADC1)
    {
        ADC_Value = ADC1_Buffer[0] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道0电压值 = %f\r\n",ADC_Value);            //输出电压值
        
        ADC_Value = ADC1_Buffer[1] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道1电压值 = %f\r\n",ADC_Value);           //输出电压值
        
        ADC_Value = ADC1_Buffer[2] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道2电压值 = %f\r\n",ADC_Value);            //输出电压值
        
        ADC_Value = ADC1_Buffer[3] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道3电压值 = %f\r\n",ADC_Value);           //输出电压值
    }else if(hadc->Instance == ADC2)
    {
    
    }
}

/**
 * @brief:ADC注入组中断服务函数
 */
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    uint32_t Data = 0;
    if(hadc->Instance == ADC1)
    {
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_1);   //获取注入组盒子序列1的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道4电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_2);   //获取注入组盒子序列2的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道5电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_3);   //获取注入组盒子序列3的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道6电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_4);   //获取注入组盒子序列4的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道7电压值 = %f\r\n",ADC_Value);                        //输出电压值
        __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC);                         //重新开启注入组中断,由于在自动注入时HAL_ADC_IRQHandler()
        																//会关闭注入组ADC中断,所以需要重新打开
    }
}

2、规则组外部触发+注入组自动注入

修改的代码如下:
将规则组修改为单次转换,且外部触发即可,注入组的代码不用修改
①ADC.c文件需要修改的代码如下

#include "ADC.h"

uint16_t ADC1_Buffer[4] = {0};             //数据缓冲区
/**
 * @brief:ADC1初始化函数
 */
RCC_PeriphCLKInitTypeDef PeriphClkInit; //ADC时钟配置结构体
ADC_HandleTypeDef hadc1;                //ADC1配置结构体
ADC_ChannelConfTypeDef sConfig1;        //规则组通道配置结构体
ADC_InjectionConfTypeDef sConfigInjected;//注入组通道配置结构体
void ADC_Init(void)
{
    /* 1、ADC的时钟配置 < 14MHz  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; //需要配置的外设:ADC
    PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;    //设置ADC分频值:6分频 = 12MHz
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
        
    /* 2、ADC1的初始化 */
    __HAL_RCC_ADC1_CLK_ENABLE();                        //使能ADC1时钟
    hadc1.Instance = ADC1;                              //选择ADC1
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;         //数据对齐方式:右对齐
    hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;          //扫描模式:开启扫描(多个通道)
    hadc1.Init.ContinuousConvMode = DISABLE;            //转换模式:单次转换
    hadc1.Init.NbrOfConversion = 4;                     //扫描模式下规则组的数量
  //hadc1.Init.DiscontinuousConvMode = ENABLE;          //扫描模式规则组间断模式
  //hadc1.Init.NbrOfDiscConversion = 2;                 //规则组间断模式下每次间断的通道数:2队为1组
    hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_EXT_IT11;   //ADC触发:外部中断EXTI11触发
    HAL_ADC_Init(&hadc1);
    
    /* 3、规则组通道配置 */
    sConfig1.Channel = ADC_CHANNEL_0;                    //通道选择:通道0
    sConfig1.Rank = ADC_REGULAR_RANK_1;                  //规则组盒子序号:1号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_1;                    //通道选择:通道1
    sConfig1.Rank = ADC_REGULAR_RANK_2;                  //规则组盒子序号:2号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_2;                    //通道选择:通道2
    sConfig1.Rank = ADC_REGULAR_RANK_3;                  //规则组盒子序号:3号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_3;                    //通道选择:通道3
    sConfig1.Rank = ADC_REGULAR_RANK_4;                  //规则组盒子序号:4号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    /* 4、组入组通道配置 */
    sConfigInjected.InjectedChannel = ADC_CHANNEL_4;                    //通道选择:通道4
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;                 //注入组盒子序号:1号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    sConfigInjected.InjectedNbrOfConversion = 4;                        //组入组通道数量:4个
    sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;            //关闭间断模式
    sConfigInjected.AutoInjectedConv = ENABLE;                          //自动注入:开启
    sConfigInjected.ExternalTrigInjecConv = ADC_INJECTED_SOFTWARE_START;//触发:软件触发
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_5;                    //通道选择:通道5
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;                 //注入组盒子序号:2号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_6;                    //通道选择:通道6
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;                 //注入组盒子序号:3号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_7;                    //通道选择:通道7
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_4;                 //注入组盒子序号:4号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    /* 5、ADC1校准 */
    HAL_ADCEx_Calibration_Start(&hadc1);                //ADC1自校准
    
    /* 6、开启ADC规则组转换 */
    HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC1_Buffer,4); //开启转换:DMA方式,转换完成DMA执行搬运,
                                                        //开启了DMA中断,搬运4后执行DMA中断
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,3,0);       //配置优先级
    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);             //使能中断源
    
    /* 7、开启ADC注入组转换 */
    HAL_ADCEx_InjectedStart_IT(&hadc1);                 //开启转换:注入组设置的通道全部转换完成中断
    HAL_NVIC_SetPriority(ADC1_2_IRQn,3,0);              //配置优先级
    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);                    //使能中断源
}

/**
 * @brief:HAL_ADC_Init()调用函数
 */
DMA_HandleTypeDef hdma1_ADC1;               //ADC1的DMA1的通道配置结构体
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    GPIO_InitTypeDef GPIO_Init;             //IO口配置的结构体
    if(hadc->Instance == ADC1)
    {
        /* 配置ADC1通道0:PA0,通道1:PA1,通道2:PA2,通道3:PA3 */
        __HAL_RCC_GPIOA_CLK_ENABLE();       //使能GPIOA时钟
        GPIO_Init.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3
                       |GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
        GPIO_Init.Mode = GPIO_MODE_ANALOG;  //选择模拟输入模式
        HAL_GPIO_Init(GPIOA, &GPIO_Init);
        
        /* 1、初始化DMA1的通道1配置 */
        __HAL_RCC_DMA1_CLK_ENABLE();                                    //使能DMA1的时钟
        hdma1_ADC1.Instance = DMA1_Channel1;                            //选择DMA1的通道1
        hdma1_ADC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  //外设站点数据宽度:16位
        hdma1_ADC1.Init.PeriphInc = DMA_PINC_DISABLE;                   //外设地址是否递增:选择不自增
        hdma1_ADC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     //内存站点数据宽度:16位
        hdma1_ADC1.Init.MemInc = DMA_MINC_ENABLE;                       //内存地址是否递增:选择自增
        hdma1_ADC1.Init.Direction = DMA_PERIPH_TO_MEMORY;               //传输方向:这里选择外设---->内存
        hdma1_ADC1.Init.Mode = DMA_CIRCULAR;                            //计数器传输模式:自动重装
        hdma1_ADC1.Init.Priority = DMA_PRIORITY_MEDIUM;                 //通道1传输优先级:选择中等
        __HAL_LINKDMA(&hadc1,DMA_Handle,hdma1_ADC1);                    //ADC1和DMA1构建链接
        HAL_DMA_Init(&hdma1_ADC1);
        
        /* 2、配置EXTI11 */
        __HAL_RCC_AFIO_CLK_ENABLE();            //使能AFIO时钟
        GPIO_Init.Pin = GPIO_PIN_11;            //选择PA11
        GPIO_Init.Mode = GPIO_MODE_IT_RISING;   //选择上升沿触发中断
        GPIO_Init.Pull = GPIO_PULLDOWN;         //选择下拉输入
        HAL_GPIO_Init(GPIOA, &GPIO_Init);
        
        /* 3、配置外部中断EXTI11的NVIC*/
        HAL_NVIC_SetPriority(EXTI15_10_IRQn,3,0);
        HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
        
    }
    else if(hadc->Instance == ADC2)
    {
        
    }    
}

3、规则组软件触发+注入组外部触发(TIM2_CC1)

在这里插入图片描述①注入组的外部触发与自动注入不同,他会抢占规则组的转换,等待注入组通道转换完成后,才能转换规则组通道。
②外部信号触发,ADC的注入组只转换1个通道。
③只有当注入组设置的通道全部转换完成后才会触发ADC中断。即需要4次外部触发才会进入中断服务函数,将测量的结果输出。
①ADC.c文件的代码如下

#include "ADC.h"

uint16_t ADC1_Buffer[4] = {0};             //数据缓冲区
/**
 * @brief:ADC1初始化函数
 */
RCC_PeriphCLKInitTypeDef PeriphClkInit; //ADC时钟配置结构体
ADC_HandleTypeDef hadc1;                //ADC1配置结构体
ADC_ChannelConfTypeDef sConfig1;        //规则组通道配置结构体
ADC_InjectionConfTypeDef sConfigInjected;//注入组通道配置结构体
void ADC_Init(void)
{
    /* 1、ADC的时钟配置 < 14MHz  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; //需要配置的外设:ADC
    PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;    //设置ADC分频值:6分频 = 12MHz
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
        
    /* 2、ADC1的初始化 */
    __HAL_RCC_ADC1_CLK_ENABLE();                        //使能ADC1时钟
    hadc1.Instance = ADC1;                              //选择ADC1
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;         //数据对齐方式:右对齐
    hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;          //扫描模式:开启扫描(多个通道)
    hadc1.Init.ContinuousConvMode = ENABLE;             //转换模式:连续转换
    hadc1.Init.NbrOfConversion = 4;                     //扫描模式下规则组的数量
  //hadc1.Init.DiscontinuousConvMode = ENABLE;          //扫描模式规则组间断模式
  //hadc1.Init.NbrOfDiscConversion = 2;                 //规则组间断模式下每次间断的通道数:2队为1组
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;   //ADC触发:软件触发
    HAL_ADC_Init(&hadc1);
    
    /* 3、规则组通道配置 */
    sConfig1.Channel = ADC_CHANNEL_0;                    //通道选择:通道0
    sConfig1.Rank = ADC_REGULAR_RANK_1;                  //规则组盒子序号:1号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_1;                    //通道选择:通道1
    sConfig1.Rank = ADC_REGULAR_RANK_2;                  //规则组盒子序号:2号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_2;                    //通道选择:通道2
    sConfig1.Rank = ADC_REGULAR_RANK_3;                  //规则组盒子序号:3号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_3;                    //通道选择:通道3
    sConfig1.Rank = ADC_REGULAR_RANK_4;                  //规则组盒子序号:4号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    /* 4、组入组通道配置 */
    sConfigInjected.InjectedChannel = ADC_CHANNEL_4;                    //通道选择:通道4
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;                 //注入组盒子序号:1号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    sConfigInjected.InjectedNbrOfConversion = 4;                        //组入组通道数量:4个
    sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;            //关闭间断模式
    sConfigInjected.AutoInjectedConv = DISABLE;                         //自动注入:关闭
    sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_T2_CC1;//触发:TIM2的CC1触发
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_5;                    //通道选择:通道5
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;                 //注入组盒子序号:2号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_6;                    //通道选择:通道6
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;                 //注入组盒子序号:3号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_7;                    //通道选择:通道7
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_4;                 //注入组盒子序号:4号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    /* 5、ADC1校准 */
    HAL_ADCEx_Calibration_Start(&hadc1);                //ADC1自校准
    
    /* 6、开启ADC规则组转换 */
    HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC1_Buffer,4); //开启转换:DMA方式,转换完成DMA执行搬运,
                                                        //开启了DMA中断,搬运4后执行DMA中断
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,3,0);       //配置优先级
    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);             //使能中断源
    
    /* 7、开启ADC注入组转换 */
    HAL_ADCEx_InjectedStart_IT(&hadc1);                 //开启转换:注入组设置的通道全部转换完成中断
    HAL_NVIC_SetPriority(ADC1_2_IRQn,3,0);              //配置优先级
    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);                    //使能中断源
}

/**
 * @brief:HAL_ADC_Init()调用函数
 */
DMA_HandleTypeDef hdma1_ADC1;               //ADC1的DMA1的通道配置结构体
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    GPIO_InitTypeDef GPIO_Init;             //IO口配置的结构体
    if(hadc->Instance == ADC1)
    {
        /* 配置ADC1通道0:PA0,通道1:PA1,通道2:PA2,通道3:PA3 */
        __HAL_RCC_GPIOA_CLK_ENABLE();       //使能GPIOA时钟
        GPIO_Init.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3
                       |GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
        GPIO_Init.Mode = GPIO_MODE_ANALOG;  //选择模拟输入模式
        HAL_GPIO_Init(GPIOA, &GPIO_Init);
        
        /* 1、初始化DMA1的通道1配置 */
        __HAL_RCC_DMA1_CLK_ENABLE();                                    //使能DMA1的时钟
        hdma1_ADC1.Instance = DMA1_Channel1;                            //选择DMA1的通道1
        hdma1_ADC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  //外设站点数据宽度:16位
        hdma1_ADC1.Init.PeriphInc = DMA_PINC_DISABLE;                   //外设地址是否递增:选择不自增
        hdma1_ADC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     //内存站点数据宽度:16位
        hdma1_ADC1.Init.MemInc = DMA_MINC_ENABLE;                       //内存地址是否递增:选择自增
        hdma1_ADC1.Init.Direction = DMA_PERIPH_TO_MEMORY;               //传输方向:这里选择外设---->内存
        hdma1_ADC1.Init.Mode = DMA_CIRCULAR;                            //计数器传输模式:自动重装
        hdma1_ADC1.Init.Priority = DMA_PRIORITY_MEDIUM;                 //通道1传输优先级:选择中等
        __HAL_LINKDMA(&hadc1,DMA_Handle,hdma1_ADC1);                    //ADC1和DMA1构建链接
        HAL_DMA_Init(&hdma1_ADC1);        
    }
    else if(hadc->Instance == ADC2)
    {
        
    }    
}

②ADC.h文件的代码如下

#ifndef __ADC_H
#define __ADC_H

#include "stm32f1xx_hal.h"
extern uint16_t ADC1_Buffer[4];
extern ADC_HandleTypeDef hadc1;                //ADC1配置结构体
extern DMA_HandleTypeDef hdma1_ADC1;           //ADC1的DMA1的通道配置结构体
void ADC_Init(void);

#endif

③Time.c文件的代码如下

#include "Time.h"

/**
 * 定时器TIM2的配置
 * psc: 时钟预分频数(1~65536)
 * arr: 自动重装值(1~65536)
 */
TIM_HandleTypeDef htim2_OC;                             //TIM2输出比较时基单元配置结构体
TIM_OC_InitTypeDef sConfig_OC;                          //比较通道配置结构体
void TIM2_Init(uint16_t psc, uint16_t arr)
{
    /* 2、配置TIM2的时基单元 */
    __HAL_RCC_TIM2_CLK_ENABLE();                            //使能TIM2时钟
    htim2_OC.Instance = TIM2;                               //选择定时器TIM2
    htim2_OC.Init.Prescaler = psc - 1;                      //预分频器
    htim2_OC.Init.CounterMode = TIM_COUNTERMODE_UP;         //向上计数
    htim2_OC.Init.Period = arr - 1;                         //自动重装载值
    htim2_OC.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;   //时钟分频因子,用于防干扰,与定时无关
    htim2_OC.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; //禁止预加载
    HAL_TIM_OC_Init(&htim2_OC);
    __HAL_TIM_CLEAR_FLAG(&htim2_OC,TIM_FLAG_UPDATE);        //清除更新标志位
    
    /* 3、TIM2输出比较通道1的配置 */
    sConfig_OC.OCMode = TIM_OCMODE_PWM1;                    //输出比较模式:PWM1模式(小于比较值输出低电平)
    sConfig_OC.Pulse = 1000;                                //比较值:1000
    sConfig_OC.OCPolarity = TIM_OCPOLARITY_LOW;             //有效电平:低电平
    HAL_TIM_OC_ConfigChannel(&htim2_OC,&sConfig_OC,TIM_CHANNEL_1);
    
    /* 4、启动TIM2 */
    HAL_TIM_OC_Start(&htim2_OC,TIM_CHANNEL_1);              //启动TIM2的通道1
}

/**
 * @brief:HAL_TIM_OC_Init()调用函数
 */
void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Init;             //IO口配置结构体
    if (htim->Instance == TIM1)                   
    {     

    }else if(htim->Instance == TIM2)
    {
        /* TIM2的CC1的引脚为PA0 */
        __HAL_RCC_GPIOA_CLK_ENABLE();       //开启GPIOA时钟
        
        /* 配置PA0 */
        GPIO_Init.Mode = GPIO_MODE_AF_PP;   //模式:输出模式
        GPIO_Init.Pin = GPIO_PIN_0;         //选择PA0
        GPIO_Init.Speed = GPIO_SPEED_FREQ_MEDIUM;//最大输出速度:中等
        HAL_GPIO_Init(GPIOA, &GPIO_Init);
    }
    else if(htim->Instance == TIM3)
    {
        
    }
}

④Time.h文件的代码如下

#ifndef __Time_H
#define __Time_H

#include "stm32f1xx_hal.h"
extern TIM_HandleTypeDef htim2_OC;                         //TIM2输出比较的时基单元配置结构体
void TIM2_Init(uint16_t psc, uint16_t arr);

#endif

⑤main.c文件的代码如下

#include "stm32f1xx_hal.h"
#include "STM32_RCC_Init.h"
#include "ADC.h"
#include "Time.h"
#include "UART.h"
 
int main(void){
    
	HAL_Init();
	HSE_RCC_Init(); 
	UART1_Init(115200);
    TIM2_Init(7200,10000);//0.1ms计数一次,PWM周期为1s,即1s触发一次注入组
    ADC_Init();
	printf("启动判断!\r\n");
    
	while(1){
       
	}	
}

⑥stm32f1xx_it.c文件的代码如下

#include "stm32f1xx_hal.h"   
#include "stm32f1xx_it.h" 
#include "ADC.h" 
#include "UART.h"

/**
 * @brief:DMA通道1中断服务函数
 */
void DMA1_Channel1_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma1_ADC1);//DMA中断服务总函数
}

/**
 * @brief:ADC中断服务函数
 */
void ADC1_2_IRQHandler(void)
{
     HAL_ADC_IRQHandler(&hadc1);//ADC中断服务总函数
}
/******************* 下面的中断的回调函数 ***************************/
/**
 * @brief:规则组的DMA通道1传输完成的中断服务函数
 */
float ADC_Value = 0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if(hadc->Instance == ADC1)
    {
        ADC_Value = ADC1_Buffer[0] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道0电压值 = %f\r\n",ADC_Value);            //输出电压值
        
        ADC_Value = ADC1_Buffer[1] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道1电压值 = %f\r\n",ADC_Value);           //输出电压值
        
        ADC_Value = ADC1_Buffer[2] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道2电压值 = %f\r\n",ADC_Value);            //输出电压值
        
        ADC_Value = ADC1_Buffer[3] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道3电压值 = %f\r\n",ADC_Value);           //输出电压值
    }else if(hadc->Instance == ADC2)
    {
    
    }
}

/**
 * @brief:ADC注入组中断服务函数
 */
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    uint32_t Data = 0;
    if(hadc->Instance == ADC1)
    {
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_1);   //获取注入组盒子序列1的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道4电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_2);   //获取注入组盒子序列2的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道5电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_3);   //获取注入组盒子序列3的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道6电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_4);   //获取注入组盒子序列4的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道7电压值 = %f\r\n",ADC_Value);                        //输出电压值
    }
}

4、规则组软件触发+注入组外部触发(EXTI15)+间断模式

【注意】
①注入组的间断队伍只有1个通道,已经规定好了。而规则组的间断队伍通道数由用户自己定义。
②不能同时使用自动注入+间断模式
③尽可能避免同时使用规则组的间断模式+注入组的间断模式
①ADC.c文件的代码如下

#include "ADC.h"

uint16_t ADC1_Buffer[4] = {0};             //数据缓冲区
/**
 * @brief:ADC1初始化函数
 */
RCC_PeriphCLKInitTypeDef PeriphClkInit; //ADC时钟配置结构体
ADC_HandleTypeDef hadc1;                //ADC1配置结构体
ADC_ChannelConfTypeDef sConfig1;        //规则组通道配置结构体
ADC_InjectionConfTypeDef sConfigInjected;//注入组通道配置结构体
void ADC_Init(void)
{
    /* 1、ADC的时钟配置 < 14MHz  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; //需要配置的外设:ADC
    PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;    //设置ADC分频值:6分频 = 12MHz
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
        
    /* 2、ADC1的初始化 */
    __HAL_RCC_ADC1_CLK_ENABLE();                        //使能ADC1时钟
    hadc1.Instance = ADC1;                              //选择ADC1
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;         //数据对齐方式:右对齐
    hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;          //扫描模式:开启扫描(多个通道)
    hadc1.Init.ContinuousConvMode = ENABLE;             //转换模式:连续转换
    hadc1.Init.NbrOfConversion = 4;                     //扫描模式下规则组的数量
  //hadc1.Init.DiscontinuousConvMode = ENABLE;          //扫描模式规则组间断模式
  //hadc1.Init.NbrOfDiscConversion = 2;                 //规则组间断模式下每次间断的通道数:2队为1组
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;   //ADC触发:软件触发
    HAL_ADC_Init(&hadc1);
    
    /* 3、规则组通道配置 */
    sConfig1.Channel = ADC_CHANNEL_0;                    //通道选择:通道0
    sConfig1.Rank = ADC_REGULAR_RANK_1;                  //规则组盒子序号:1号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_1;                    //通道选择:通道1
    sConfig1.Rank = ADC_REGULAR_RANK_2;                  //规则组盒子序号:2号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_2;                    //通道选择:通道2
    sConfig1.Rank = ADC_REGULAR_RANK_3;                  //规则组盒子序号:3号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_3;                    //通道选择:通道3
    sConfig1.Rank = ADC_REGULAR_RANK_4;                  //规则组盒子序号:4号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    /* 4、组入组通道配置 */
    sConfigInjected.InjectedChannel = ADC_CHANNEL_4;                    //通道选择:通道4
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;                 //注入组盒子序号:1号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    sConfigInjected.InjectedNbrOfConversion = 4;                        //组入组通道数量:4个
    sConfigInjected.InjectedDiscontinuousConvMode = ENABLE;             //开启间断模式
    sConfigInjected.AutoInjectedConv = DISABLE;                         //自动注入:关闭
    sConfigInjected.ExternalTrigInjecConv = ADC_EXTERNALTRIGINJECCONV_EXT_IT15;//触发:EXTI15触发
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_5;                    //通道选择:通道5
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;                 //注入组盒子序号:2号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_6;                    //通道选择:通道6
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;                 //注入组盒子序号:3号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_7;                    //通道选择:通道7
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_4;                 //注入组盒子序号:4号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    /* 5、ADC1校准 */
    HAL_ADCEx_Calibration_Start(&hadc1);                //ADC1自校准
    
    /* 6、开启ADC规则组转换 */
    HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC1_Buffer,4); //开启转换:DMA方式,转换完成DMA执行搬运,
                                                        //开启了DMA中断,搬运4后执行DMA中断
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,3,0);       //配置优先级
    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);             //使能中断源
    
    /* 7、开启ADC注入组转换 */
    HAL_ADCEx_InjectedStart_IT(&hadc1);                 //开启转换:设置通道全部转换完成中断
    HAL_NVIC_SetPriority(ADC1_2_IRQn,3,0);              //配置优先级
    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);                    //使能中断源
}

/**
 * @brief:HAL_ADC_Init()调用函数
 */
DMA_HandleTypeDef hdma1_ADC1;               //ADC1的DMA1的通道配置结构体
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    GPIO_InitTypeDef GPIO_Init;             //IO口配置的结构体
    if(hadc->Instance == ADC1)
    {
        /* 配置ADC1通道0:PA0,通道1:PA1,通道2:PA2,通道3:PA3 */
        __HAL_RCC_GPIOA_CLK_ENABLE();       //使能GPIOA时钟
        GPIO_Init.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3
                       |GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
        GPIO_Init.Mode = GPIO_MODE_ANALOG;  //选择模拟输入模式
        HAL_GPIO_Init(GPIOA, &GPIO_Init);
        
        /* 1、初始化DMA1的通道1配置 */
        __HAL_RCC_DMA1_CLK_ENABLE();                                    //使能DMA1的时钟
        hdma1_ADC1.Instance = DMA1_Channel1;                            //选择DMA1的通道1
        hdma1_ADC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  //外设站点数据宽度:16位
        hdma1_ADC1.Init.PeriphInc = DMA_PINC_DISABLE;                   //外设地址是否递增:选择不自增
        hdma1_ADC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     //内存站点数据宽度:16位
        hdma1_ADC1.Init.MemInc = DMA_MINC_ENABLE;                       //内存地址是否递增:选择自增
        hdma1_ADC1.Init.Direction = DMA_PERIPH_TO_MEMORY;               //传输方向:这里选择外设---->内存
        hdma1_ADC1.Init.Mode = DMA_CIRCULAR;                            //计数器传输模式:自动重装
        hdma1_ADC1.Init.Priority = DMA_PRIORITY_MEDIUM;                 //通道1传输优先级:选择中等
        __HAL_LINKDMA(&hadc1,DMA_Handle,hdma1_ADC1);                    //ADC1和DMA1构建链接
        HAL_DMA_Init(&hdma1_ADC1);
        
        /* 2、配置EXTI15:注入组外部触发 */
        __HAL_RCC_GPIOB_CLK_ENABLE();           //使能GPIOB时钟
        __HAL_RCC_AFIO_CLK_ENABLE();            //使能AFIO时钟
        GPIO_Init.Pin = GPIO_PIN_15;            //选择PB15
        GPIO_Init.Mode = GPIO_MODE_IT_RISING;   //选择上升沿触发中断
        GPIO_Init.Pull = GPIO_PULLDOWN;         //选择下拉输入
        HAL_GPIO_Init(GPIOB, &GPIO_Init);
        
        /* 3、配置外部中断EXTI15的NVIC*/
        HAL_NVIC_SetPriority(EXTI15_10_IRQn,3,0);
        HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
        
    }
    else if(hadc->Instance == ADC2)
    {
        
    }    
}

②ADC.h文件的代码如下

#ifndef __ADC_H
#define __ADC_H

#include "stm32f1xx_hal.h"
extern uint16_t ADC1_Buffer[4];
extern ADC_HandleTypeDef hadc1;                //ADC1配置结构体
extern DMA_HandleTypeDef hdma1_ADC1;           //ADC1的DMA1的通道配置结构体
void ADC_Init(void);

#endif

③main.c文件的代码如下

#include "stm32f1xx_hal.h"
#include "STM32_RCC_Init.h"
#include "ADC.h"
#include "UART.h"
 
int main(void){
    
	HAL_Init();
	HSE_RCC_Init(); 
	UART1_Init(115200);
    ADC_Init();
	printf("启动判断!\r\n");
    
	while(1){
       
	}	
}

④stm32f1xx_it.c文件的代码如下

#include "stm32f1xx_hal.h"   
#include "stm32f1xx_it.h" 
#include "ADC.h" 
#include "UART.h"

/**
 * @brief:DMA通道1中断服务函数
 */
void DMA1_Channel1_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma1_ADC1);//DMA中断服务总函数
}

/**
 * @brief:ADC中断服务函数
 */
void ADC1_2_IRQHandler(void)
{
     HAL_ADC_IRQHandler(&hadc1);//ADC中断服务总函数
}
/******************* 下面的中断的回调函数 ***************************/
/**
 * @brief:规则组的DMA通道1传输完成的中断服务函数
 */
float ADC_Value = 0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if(hadc->Instance == ADC1)
    {
        ADC_Value = ADC1_Buffer[0] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道0电压值 = %f\r\n",ADC_Value);            //输出电压值
        
        ADC_Value = ADC1_Buffer[1] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道1电压值 = %f\r\n",ADC_Value);           //输出电压值
        
        ADC_Value = ADC1_Buffer[2] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道2电压值 = %f\r\n",ADC_Value);            //输出电压值
        
        ADC_Value = ADC1_Buffer[3] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道3电压值 = %f\r\n",ADC_Value);           //输出电压值
    }else if(hadc->Instance == ADC2)
    {
    
    }
}

/**
 * @brief:ADC注入组中断服务函数
 */
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    uint32_t Data = 0;
    if(hadc->Instance == ADC1)
    {
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_1);   //获取注入组盒子序列1的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道4电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_2);   //获取注入组盒子序列2的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道5电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_3);   //获取注入组盒子序列3的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道6电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_4);   //获取注入组盒子序列4的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道7电压值 = %f\r\n",ADC_Value);                        //输出电压值
    }
}

5、模拟看门狗的使用

在这里插入图片描述
①ADC.c文件的代码如下

#include "ADC.h"

uint16_t ADC1_Buffer[4] = {0};             //数据缓冲区
/**
 * @brief:ADC1初始化函数
 */
RCC_PeriphCLKInitTypeDef PeriphClkInit;     //ADC时钟配置结构体
ADC_HandleTypeDef hadc1;                    //ADC1配置结构体
ADC_ChannelConfTypeDef sConfig1;            //规则组通道配置结构体
ADC_InjectionConfTypeDef sConfigInjected;   //注入组通道配置结构体
ADC_AnalogWDGConfTypeDef AnalogWDGConfig;   //模拟看门狗配置结构体
void ADC_Init(void)
{
    /* 1、ADC的时钟配置 < 14MHz  */
    PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; //需要配置的外设:ADC
    PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;    //设置ADC分频值:6分频 = 12MHz
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
        
    /* 2、ADC1的初始化 */
    __HAL_RCC_ADC1_CLK_ENABLE();                        //使能ADC1时钟
    hadc1.Instance = ADC1;                              //选择ADC1
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;         //数据对齐方式:右对齐
    hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;          //扫描模式:开启扫描(多个通道)
    hadc1.Init.ContinuousConvMode = ENABLE;             //转换模式:连续转换
    hadc1.Init.NbrOfConversion = 4;                     //扫描模式下规则组的数量
  //hadc1.Init.DiscontinuousConvMode = ENABLE;          //扫描模式规则组间断模式
  //hadc1.Init.NbrOfDiscConversion = 2;                 //规则组间断模式下每次间断的通道数:2队为1组
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;   //ADC触发:软件触发
    HAL_ADC_Init(&hadc1);
    
    /* 3、规则组通道配置 */
    sConfig1.Channel = ADC_CHANNEL_0;                    //通道选择:通道0
    sConfig1.Rank = ADC_REGULAR_RANK_1;                  //规则组盒子序号:1号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_1;                    //通道选择:通道1
    sConfig1.Rank = ADC_REGULAR_RANK_2;                  //规则组盒子序号:2号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_2;                    //通道选择:通道2
    sConfig1.Rank = ADC_REGULAR_RANK_3;                  //规则组盒子序号:3号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    sConfig1.Channel = ADC_CHANNEL_3;                    //通道选择:通道3
    sConfig1.Rank = ADC_REGULAR_RANK_4;                  //规则组盒子序号:4号
    sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    HAL_ADC_ConfigChannel(&hadc1, &sConfig1);
    
    /* 4、组入组通道配置 */
    sConfigInjected.InjectedChannel = ADC_CHANNEL_4;                    //通道选择:通道4
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;                 //注入组盒子序号:1号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    sConfigInjected.InjectedNbrOfConversion = 4;                        //组入组通道数量:4个
    sConfigInjected.InjectedDiscontinuousConvMode = DISABLE;            //关闭间断模式
    sConfigInjected.AutoInjectedConv = ENABLE;                          //自动注入:开启
    sConfigInjected.ExternalTrigInjecConv = ADC_INJECTED_SOFTWARE_START;//触发:软件触发
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_5;                    //通道选择:通道5
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;                 //注入组盒子序号:2号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_6;                    //通道选择:通道6
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;                 //注入组盒子序号:3号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    sConfigInjected.InjectedChannel = ADC_CHANNEL_7;                    //通道选择:通道7
    sConfigInjected.InjectedRank = ADC_INJECTED_RANK_4;                 //注入组盒子序号:4号
    sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5T
    sConfigInjected.InjectedOffset = 0;                                 //偏移值:0
    HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);
    
    /* 5、模拟看门狗的配置 */
    AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;       //模拟看门狗模式:选择规则组的某个通道
    AnalogWDGConfig.Channel = ADC_CHANNEL_0;                            //单通道:选择通道0。
    AnalogWDGConfig.ITMode = ENABLE;                                    //开启模拟看门狗中断
    AnalogWDGConfig.HighThreshold = 0xAFF;                              //寄存器的上限值 
    AnalogWDGConfig.LowThreshold = 0X3FF;                               //寄存器的下限值
    HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig);
    
    /* 5、ADC1校准 */
    HAL_ADCEx_Calibration_Start(&hadc1);                //ADC1自校准
    
    /* 6、开启ADC规则组转换 */
    HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC1_Buffer,4); //开启转换:DMA方式,转换完成DMA执行搬运,
                                                        //开启了DMA中断,搬运4后执行DMA中断
    HAL_NVIC_SetPriority(DMA1_Channel1_IRQn,3,0);       //配置优先级
    HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);             //使能中断源
    
    /* 7、开启ADC注入组转换 */
    HAL_ADCEx_InjectedStart_IT(&hadc1);                 //开启转换:设置通道全部转换完成中断
    HAL_NVIC_SetPriority(ADC1_2_IRQn,3,0);              //配置优先级
    HAL_NVIC_EnableIRQ(ADC1_2_IRQn);                    //使能中断源
}

/**
 * @brief:HAL_ADC_Init()调用函数
 */
DMA_HandleTypeDef hdma1_ADC1;               //ADC1的DMA1的通道配置结构体
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    GPIO_InitTypeDef GPIO_Init;             //IO口配置的结构体
    if(hadc->Instance == ADC1)
    {
        /* 配置ADC1通道0:PA0,通道1:PA1,通道2:PA2,通道3:PA3 */
        __HAL_RCC_GPIOA_CLK_ENABLE();       //使能GPIOA时钟
        GPIO_Init.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3
                       |GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7;
        GPIO_Init.Mode = GPIO_MODE_ANALOG;  //选择模拟输入模式
        HAL_GPIO_Init(GPIOA, &GPIO_Init);
        
        /* 1、初始化DMA1的通道1配置 */
        __HAL_RCC_DMA1_CLK_ENABLE();                                    //使能DMA1的时钟
        hdma1_ADC1.Instance = DMA1_Channel1;                            //选择DMA1的通道1
        hdma1_ADC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  //外设站点数据宽度:16位
        hdma1_ADC1.Init.PeriphInc = DMA_PINC_DISABLE;                   //外设地址是否递增:选择不自增
        hdma1_ADC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     //内存站点数据宽度:16位
        hdma1_ADC1.Init.MemInc = DMA_MINC_ENABLE;                       //内存地址是否递增:选择自增
        hdma1_ADC1.Init.Direction = DMA_PERIPH_TO_MEMORY;               //传输方向:这里选择外设---->内存
        hdma1_ADC1.Init.Mode = DMA_CIRCULAR;                            //计数器传输模式:自动重装
        hdma1_ADC1.Init.Priority = DMA_PRIORITY_MEDIUM;                 //通道1传输优先级:选择中等
        __HAL_LINKDMA(&hadc1,DMA_Handle,hdma1_ADC1);                    //ADC1和DMA1构建链接
        HAL_DMA_Init(&hdma1_ADC1);
        
    }
    else if(hadc->Instance == ADC2)
    {
        
    }    
}

②ADC.h文件的代码如下

#ifndef __ADC_H
#define __ADC_H

#include "stm32f1xx_hal.h"
extern uint16_t ADC1_Buffer[4];
extern ADC_HandleTypeDef hadc1;                //ADC1配置结构体
extern DMA_HandleTypeDef hdma1_ADC1;           //ADC1的DMA1的通道配置结构体
void ADC_Init(void);

#endif

③main.c文件的代码如下

#include "stm32f1xx_hal.h"
#include "STM32_RCC_Init.h"
#include "ADC.h"
#include "UART.h"
 
int main(void){
    
	HAL_Init();
	HSE_RCC_Init(); 
	UART1_Init(115200);
    ADC_Init();
	printf("启动判断!\r\n");
    
	while(1){
       
	}	
}

④stm32f1xx_it.c文件的代码如下

#include "stm32f1xx_hal.h"   
#include "stm32f1xx_it.h" 
#include "ADC.h" 
#include "UART.h"
/**
 * @brief:DMA通道1中断服务函数
 */
void DMA1_Channel1_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&hdma1_ADC1);//DMA中断服务总函数
}

/**
 * @brief:ADC中断服务函数
 */
void ADC1_2_IRQHandler(void)
{
     HAL_ADC_IRQHandler(&hadc1);//ADC中断服务总函数
}
/******************* 下面的中断的回调函数 ***************************/
/**
 * @brief:规则组的DMA通道1传输完成的中断服务函数
 */
float ADC_Value = 0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if(hadc->Instance == ADC1)
    {
        ADC_Value = ADC1_Buffer[0] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道0电压值 = %f\r\n",ADC_Value);            //输出电压值
        
        ADC_Value = ADC1_Buffer[1] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道1电压值 = %f\r\n",ADC_Value);           //输出电压值
        
        ADC_Value = ADC1_Buffer[2] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道2电压值 = %f\r\n",ADC_Value);            //输出电压值
        
        ADC_Value = ADC1_Buffer[3] * 3.3 / 4095;            //将二进制计数为电压电压值
        printf("通道3电压值 = %f\r\n",ADC_Value);           //输出电压值
    }else if(hadc->Instance == ADC2)
    {
    
    }
}

/**
 * @brief:ADC注入组中断服务函数
 */
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    uint32_t Data = 0;
    if(hadc->Instance == ADC1)
    {
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_1);   //获取注入组盒子序列1的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道4电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_2);   //获取注入组盒子序列2的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道5电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_3);   //获取注入组盒子序列3的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道6电压值 = %f\r\n",ADC_Value);                        //输出电压值
        
        Data = HAL_ADCEx_InjectedGetValue(hadc, ADC_INJECTED_RANK_4);   //获取注入组盒子序列4的数据寄存器的值
        ADC_Value = Data * 3.3 / 4095;                                  //将二进制计数为电压电压值
        printf("通道7电压值 = %f\r\n",ADC_Value);                        //输出电压值
        __HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC);
    }
}

/**
 * @brief:模拟看门狗的中断服务函数
 */
void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
{
    if(hadc->Instance == ADC1)
    {
       if(ADC1_Buffer[0] > 0xAFF)
       {
           printf("高于上限值了\r\n");
       }else if(ADC1_Buffer[0] < 0x3FF)
       {
           printf("低于下限值了\r\n");
       }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2267783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Debian 12 安装配置 fail2ban 保护 SSH 访问

背景介绍 双十一的时候薅羊毛租了台腾讯云的虚机, 是真便宜, 只是没想到才跑了一个月, 系统里面就收集到了巨多的 SSH 恶意登录失败记录. 只能说, 互联网真的是太不安全了. 之前有用过 fail2ban 在 CentOS 7 上面做过防护, 不过那已经是好久好久之前的故事了, 好多方法已经不…

基于Spring Boot + Vue3实现的在线商品竞拍管理系统源码+文档

前言 基于Spring Boot Vue3实现的在线商品竞拍管理系统是一种现代化的前后端分离架构的应用程序&#xff0c;它结合了Java后端框架Spring Boot和JavaScript前端框架Vue.js的最新版本&#xff08;Vue 3&#xff09;。该系统允许用户在线参与商品竞拍&#xff0c;并提供管理后台…

编译openssl遇到错误Parse errors: No plan found in TAP output的解决方法

在编译openssl时 tar -zxvf openssl-1.1.1p.tar.gz cd openssl-1.1.1p ./config --prefix/usr --openssldir/etc/ssl --shared zlib make make test 遇到错误 Parse errors: No plan found in TAP output 解决方法&#xff1a; yum install perl-Test-Simple

20241130 RocketMQ本机安装与SpringBoot整合

目录 一、RocketMQ简介 ???1.1、核心概念 ???1.2、应用场景 ???1.3、架构设计 2、RocketMQ Server安装 3、RocketMQ可视化控制台安装与使用 4、SpringBoot整合RocketMQ实现消息发送和接收? ? ? ? ? 4.1、添加maven依赖 ???4.2、yaml配置 ???4.3、…

【疑难杂症】 HarmonyOS NEXT中Axios库的响应拦截器无法拦截424状态码怎么办?

今天在开发一个HarmonyOS NEXT的应用的时候&#xff0c;发现http接口如果返回的状态码是424时&#xff0c;我在axios中定义的拦截器失效了。直接走到了业务调用的catch中。 问题表现&#xff1a; 我的拦截器代码如下&#xff1a; 解决办法&#xff1a; 先说解决办法&#xff…

Unity功能模块一对话系统(4)实现个性文本标签

本期我们将了解如何在TMPro中自定义我们的标签样式&#xff0c;并实现两种有趣的效果。 一.需求描述 1.定义<float>格式的标签&#xff0c;实现标签处延迟打印功能 2.定义<r" "></r>格式的标签&#xff0c;实现标签区间内文本片段的注释显示功能…

Llama 3 预训练(二)

目录 3. 预训练 3.1 预训练数据 3.1.1 网络数据筛选 PII 和安全过滤 文本提取与清理 去重&#xff08;De-duplication&#xff09; 启发式过滤&#xff08;Heuristic Filtering&#xff09; 基于模型的质量过滤 代码和数学推理数据处理 多语言数据处理 3.1.2 确定数…

电路元件与电路基本定理

电流、电压和电功率 电流 1 定义&#xff1a; 带电质点的有序运动形成电流 。 单位时间内通过导体横截面的电量定义为电流强度&#xff0c; 简称电流&#xff0c;用符号 i 表示&#xff0c;其数学表达式为&#xff1a;&#xff08;i单位&#xff1a;安培&#xff08;A&#x…

低代码开源项目Joget的研究——基本概念和Joget7社区版应用

大纲 1. 基本概念1.1 Form1.1.1 Form1.1.1.1 概述1.1.1.2 主要特点和用途1.1.1.3 创建和使用 Form1.1.1.4 示例 1.1.2 Section1.1.2.1 概述1.1.2.2 主要特点和用途1.1.2.3 示例 1.1.3 Column1.1.4 Field1.1.5 示例 1.2 Datalist1.2.1 Datalist1.2.1.1 主要特点和用途1.2.1.2 创…

【二叉树遍历 Java版】二叉树的前中后序遍历and层次遍历

二叉树的前中后序遍历and层次遍历 深度优先遍历题目链接递归前序遍历中序遍历后序遍历 迭代前序遍历后序遍历中序遍历 统一迭代前序遍历后序遍历中序遍历 广度优先遍历102. 二叉树的层序遍历107. 二叉树的层序遍历 II637. 二叉树的层平均值199. 二叉树的右视图 深度优先遍历 深…

【Sentinel】初识Sentinel

目录 1.1.雪崩问题及解决方案 1.1.1.雪崩问题 1.1.2.超时处理 1.1.3.仓壁模式 1.1.4.断路器 1.1.5.限流 1.1.6.总结 1.2.服务保护技术对比 1.3.Sentinel介绍和安装 1.3.1.初识Sentinel 1.3.2.安装Sentinel 1.4.微服务整合Sentinel 1.1.雪崩问题及解决方案 1.1.1.…

Apriori关联规则算法 HNUST【数据分析技术】(2025)

1.理论知识 Apriori是一种常用的数据关联规则挖掘方法&#xff0c;它可以用来找出数据集中频繁出现的数据集合。该算法第一次实现在大数据集上的可行的关联规则提取&#xff0c;其核心思想是通过连接产生候选项及其支持度&#xff0c;然后通过剪枝生成频繁项集。 Apriori算法的…

如何让Tplink路由器自身的IP网段 与交换机和电脑的IP网段 保持一致?

问题分析&#xff1a; 正常情况下&#xff0c;我的需求是&#xff1a;电脑又能上网&#xff0c;又需要与路由器处于同一局域网下&#xff08;串流Pico4 VR眼镜&#xff09;&#xff0c;所以&#xff0c;我是这么连接 交换机、路由器、电脑 的&#xff1a; 此时&#xff0c;登录…

系统思考—冰山模型

“卓越不是因机遇而生&#xff0c;而是智慧的选择与用心的承诺。”—— 亚里士多德 卓越&#xff0c;从来不是一次性行为&#xff0c;而是一种习惯。正如我们在日常辅导中常提醒自己&#xff1a;行为的背后&#xff0c;隐藏着选择的逻辑&#xff0c;而选择的根源&#xff0c;源…

TP5 动态渲染多个Layui表格并批量打印所有表格

记录&#xff1a; TP5 动态渲染多个Layui表格每个表格设置有2行表头&#xff0c;并且第一行表头在页面完成后动态渲染显示内容每个表格下面显示统计信息可点击字段排序一次打印页面上的所有表格打印页面上多个table时,让每个table单独一页 后端代码示例&#xff1a; /*** Nod…

【笔记】linux虚拟机与windows的文件共享之Samba服务基本配置

做完之后的总结写在最前面便于复习&#xff1a; 虚拟机上要共享的资源通过samba的操作 允许window通过网络去访问其共享资源 防止以后看不懂放在最前面 &#xff08;一&#xff09;虚拟机操作部分 下载 samba smbclient samba-common 在根目录/新建一个samba专用文件夹&…

PyTorch Instance Normalization介绍

Instance Normalization(实例归一化) 是一种标准化技术,与 Batch Normalization 类似,但它对每个样本独立地对每个通道进行归一化,而不依赖于小批量数据的统计信息。这使得它非常适合小批量训练任务以及图像生成任务(如风格迁移)。 Instance Normalization 的原理 对每…

攻防世界web新手第五题supersqli

这是题目&#xff0c;题目看起来像是sql注入的题&#xff0c;先试一下最常规的&#xff0c;输入1&#xff0c;回显正常 输入1‘&#xff0c;显示错误 尝试加上注释符号#或者–或者%23&#xff08;注释掉后面语句&#xff0c;使1后面的单引号与前面的单引号成功匹配就不会报错…

机器视觉中的单线程、多线程与跨线程:原理与应用解析

在机器视觉应用中&#xff0c;程序的运行效率直接影响到系统的实时性和稳定性。随着任务复杂度的提高&#xff0c;单线程处理往往无法满足高性能需求&#xff0c;多线程技术因此被广泛应用。此外&#xff0c;跨线程操作&#xff08;如在多线程中更新界面或共享资源&#xff09;…

JAVA学习笔记第二阶段开始 Day11 五种机制---机制1:泛型机制

JAVA基础进阶版链接 https://pdai.tech/md/java/basic/java-basic-x-generic.html 五种机制 泛型机制 用处&#xff0c;提高类型安全性和代码重用 泛型在编写代码中使用【类型占位符】&#xff0c;而不是具体的类型&#xff0c;泛型是通过“类型擦除”来实现的类型安全性&…