ADC(三):注入组的使用

有关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");
       }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot整合log4j2日志框架1

一 log4j基本知识 1.1 log4j的日志级别 Log4j定义了8个级别的log&#xff08;除去OFF和ALL&#xff0c;可以说分为6个级别&#xff09;&#xff0c;优先级从低到高依次为&#xff1a;All&#xff0c;trace&#xff0c;debug&#xff0c;info&#xff0c;warn&#xff0c;err…

Java - 日志体系_Simple Logging Facade for Java (SLF4J)日志门面_SLF4J集成JUL 及 原理分析

文章目录 官网集成Jdk_logging步骤POM依赖使用 原理分析SLF4J 与 JUL 的集成获取 ILoggerFactory 的过程根据 ILoggerFactory 获取 Logger 实例的过程 小结 官网 https://slf4j.org/ Simple Logging Facade for Java &#xff08;SLF4J&#xff09; 用作各种日志记录框架&…

爆肝1个月:DDR4 的信号完整性(万字长文SI)

前言&#xff1a; 大学里面&#xff0c;总有很多课程&#xff0c;很浪费时间&#xff0c;学了没点用处&#xff0c;问过老师&#xff0c;为什么信号完整性&#xff0c;示波器使用等课程不开呢&#xff0c;这种是对工作真实有帮助的&#xff1f; 老师&#xff1a;因为老师…

一文详解MacOS+CLion——构建libtorch机器学习开发环境

对于希望在本地环境中进行深度学习开发的开发者来说&#xff0c;配置合适的工具链是至关重要的一步。本文旨在帮助您在 macOS 操作系统上&#xff0c;利用 CLion IDE 和 PyTorch 的 C依赖库——libtorch&#xff0c;快速搭建起一个高效的开发环境。这里我们将一步步地讲解如何下…

pg数据库postgis扩展相关技术简介

postgis-note pg数据库postgis扩展相关技术简介 简介 PostGIS是在对象关系型数据库PostgreSQL上增加了存储管理空间数据的能力的开源GIS数据库。依托于PostgreSQL的两个重要特性&#xff1a;Geometry对象、Gist索引。 webgis技术路线 Geometry对象 Geometry&#xff08;几…

Html——10 关键字和描述

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>淘宝网</title><meta name"keywords" content"我要自学网,自学HTML,自学CSS"/><meta name"description" content"要设置…

【原创学习笔记】近期项目中使用的西门子V20变频器总结(上篇)

现场V20 22kW变频器如图所示 进线分别为L1,L2,L3,PE线&#xff0c;出现分别为U,V,W接电机 在西门子官网查询手册后&#xff0c;查询可知可以通过多种方式控制变频器&#xff0c;比如&#xff1a;面板&#xff08;BOP&#xff09;控制&#xff0c;端子&#xff08;NPN/PNP&…

Exchange ProxyShell 攻击链利用详解

目录 ProxyShell CVE-2021-34473 SSRF ProxyShell 详细复现 ProxyShell 一键利用脚本 攻击者利用 ProxyShell 漏洞可绕过相关权限验证,进而配合其他漏洞可执行任意代码,控制Microsoft Exchange Server。 ProxyShell攻击链利用使用了以下漏洞: CVE-2021-34473 一个 SSR…

算法练习——模拟题

前言&#xff1a;模拟题的特点在于没有什么固定的技巧&#xff0c;完全考验自己的代码能力&#xff0c;因此有助于提升自己的代码水平。如果说一定有什么技巧的话&#xff0c;那就是有的模拟题能够通过找规律来简化算法。 一&#xff1a;替换所有问号 题目要求&#xff1a; 解…

ES 磁盘使用率检查及处理方法

文章目录 1. 检查原因2. 检查方法3. 处理方法3.1 清理数据3.2 再次检查磁盘使用率 1. 检查原因 磁盘使用率在 85%以下&#xff0c;ES 可正常运行&#xff0c;达到 85%及以上会影响 PEIM 数据存储。 在 ES 磁盘分配分片控制策略中&#xff0c;为了保护数据节点的安全&#xff0…

leetcode 面试经典 150 题:螺旋矩阵

链接螺旋矩阵题序号54题型二维数组&#xff08;矩阵&#xff09;解题方法模拟路径法难度中等熟练度✅✅✅ 题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3…

汽车CAN通信逻辑与LabVIEW开发

CAN通信的核心概念 CAN&#xff08;Controller Area Network&#xff09;是一种多主通信协议&#xff0c;广泛应用于汽车电子系统中&#xff0c;用于控制单元之间的高效通信。 ​ 消息优先级&#xff1a;每个CAN帧包含唯一的标识符&#xff08;ID&#xff09;&#xff0c;ID的…

CI/CD是什么?

CI/CD 定义 CI/CD 代表持续集成和持续部署&#xff08;或持续交付&#xff09;。它是一套实践和工具&#xff0c;旨在通过自动化构建、测试和部署来改进软件开发流程&#xff0c;使您能够更快、更可靠地交付代码更改。 持续集成 (CI)&#xff1a;在共享存储库中自动构建、测试…

Kubernetes之NodeSelector与NodeName实战

目录 目标 版本 官网 概述 实战 NodeName实战 NodeSelector实战 目标 通过配置NodeSelector与NodeName实现Pod运行&#xff08;或优先运行&#xff09;在我们期望的节点之上。了解这两种实现方法的区别。 版本 Kubernets v1.25.0 官网 将Pod分配给节点https://kubernet…

如何构建有效的AI Agents:从复杂到简约——深度解读Claude实践总结《Building effective agents》(上)

在人工智能技术日新月异的今天&#xff0c;大语言模型(LLM)已经成为技术创新的热点。 然而&#xff0c;在追逐技术前沿的热潮中&#xff0c;我们是否忽视了工程设计的本质&#xff1f; 作为全球人工智能领域的领军企业之一&#xff0c;Anthropic以其在AI安全和伦理方面的深入…

高中数学刷题版:函数奇偶性[干货]

文章目录 一、奇偶性定义例题 二、运算性质1、两个函数的和差积商2、复合函数3、画草图4、对称中心与对称轴 三、奇偶性判断例题 四、根据奇偶性求解析式例题 五、单调性与奇偶性的综合应用例题 一、奇偶性定义 1、定义域都是关于原点对称。 2、解析式关系 奇函数&#xff1a;…

【Sentinel】流控效果与热点参数限流

目录 1.流控效果 1.1.warm up 2.2.排队等待 1.3.总结 2.热点参数限流 2.1.全局参数限流 2.2.热点参数限流 2.3.案例 1.流控效果 在流控的高级选项中&#xff0c;还有一个流控效果选项&#xff1a; 流控效果是指请求达到流控阈值时应该采取的措施&#xff0c;包括三种&…

【Rust自学】7.4. use关键字 Pt.2 :重导入与换国内镜像源教程

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 7.4.1. 使用pub use重新导入名称 使用use将路径导入作用域内后。该名称在词作用域内是私有的。 以上一篇文章的代码为例&#xff1a; m…

集装箱的纸箱和塑料箱识别数据集,使用YOLO,COCO JSON,PASICAL VOC XML格式标注,识别准确率高达97.5%

集装箱的纸箱和塑料箱识别数据集&#xff0c;使用YOLO&#xff0c;COCO JSON&#xff0c;PASICAL VOC XML格式标注&#xff0c;识别准确率高达97.5% 数据集分割 训练组88&#xff05; 4605图片 有效集8% 438图片 测试集4% 219图片 预处理 自动定向&#x…

TOP K问题:利用堆排序找出数组中最小的k个数

设计一个算法&#xff0c;找出数组中最小的k个数。以任意顺序返回这k个数均可。 找小的数需要建大堆来解决&#xff0c;首先将数组中前K个数建成一个大堆&#xff0c;将从k1个数直到数组结束的所有数与堆顶的数进行比较&#xff0c;如果比堆顶的数小&#xff0c;则替换堆顶的数…