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; //需要配置的外设:ADCPeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;    //设置ADC分频值:6分频 = 12MHzHAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);/* 2、ADC1的初始化 */__HAL_RCC_ADC1_CLK_ENABLE();                        //使能ADC1时钟hadc1.Instance = ADC1;                              //选择ADC1hadc1.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;                    //通道选择:通道0sConfig1.Rank = ADC_REGULAR_RANK_1;                  //规则组盒子序号:1号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_1;                    //通道选择:通道1sConfig1.Rank = ADC_REGULAR_RANK_2;                  //规则组盒子序号:2号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_2;                    //通道选择:通道2sConfig1.Rank = ADC_REGULAR_RANK_3;                  //规则组盒子序号:3号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_3;                    //通道选择:通道3sConfig1.Rank = ADC_REGULAR_RANK_4;                  //规则组盒子序号:4号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);/* 4、组入组通道配置 */sConfigInjected.InjectedChannel = ADC_CHANNEL_4;                    //通道选择:通道4sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;                 //注入组盒子序号:1号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.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;                    //通道选择:通道5sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;                 //注入组盒子序号:2号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);sConfigInjected.InjectedChannel = ADC_CHANNEL_6;                    //通道选择:通道6sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;                 //注入组盒子序号:3号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);sConfigInjected.InjectedChannel = ADC_CHANNEL_7;                    //通道选择:通道7sConfigInjected.InjectedRank = ADC_INJECTED_RANK_4;                 //注入组盒子序号:4号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_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的通道1hdma1_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; //需要配置的外设:ADCPeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;    //设置ADC分频值:6分频 = 12MHzHAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);/* 2、ADC1的初始化 */__HAL_RCC_ADC1_CLK_ENABLE();                        //使能ADC1时钟hadc1.Instance = ADC1;                              //选择ADC1hadc1.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;                    //通道选择:通道0sConfig1.Rank = ADC_REGULAR_RANK_1;                  //规则组盒子序号:1号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_1;                    //通道选择:通道1sConfig1.Rank = ADC_REGULAR_RANK_2;                  //规则组盒子序号:2号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_2;                    //通道选择:通道2sConfig1.Rank = ADC_REGULAR_RANK_3;                  //规则组盒子序号:3号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_3;                    //通道选择:通道3sConfig1.Rank = ADC_REGULAR_RANK_4;                  //规则组盒子序号:4号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);/* 4、组入组通道配置 */sConfigInjected.InjectedChannel = ADC_CHANNEL_4;                    //通道选择:通道4sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;                 //注入组盒子序号:1号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0sConfigInjected.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;                    //通道选择:通道5sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;                 //注入组盒子序号:2号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);sConfigInjected.InjectedChannel = ADC_CHANNEL_6;                    //通道选择:通道6sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;                 //注入组盒子序号:3号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);sConfigInjected.InjectedChannel = ADC_CHANNEL_7;                    //通道选择:通道7sConfigInjected.InjectedRank = ADC_INJECTED_RANK_4;                 //注入组盒子序号:4号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_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的通道1hdma1_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;            //选择PA11GPIO_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; //需要配置的外设:ADCPeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;    //设置ADC分频值:6分频 = 12MHzHAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);/* 2、ADC1的初始化 */__HAL_RCC_ADC1_CLK_ENABLE();                        //使能ADC1时钟hadc1.Instance = ADC1;                              //选择ADC1hadc1.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;                    //通道选择:通道0sConfig1.Rank = ADC_REGULAR_RANK_1;                  //规则组盒子序号:1号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_1;                    //通道选择:通道1sConfig1.Rank = ADC_REGULAR_RANK_2;                  //规则组盒子序号:2号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_2;                    //通道选择:通道2sConfig1.Rank = ADC_REGULAR_RANK_3;                  //规则组盒子序号:3号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_3;                    //通道选择:通道3sConfig1.Rank = ADC_REGULAR_RANK_4;                  //规则组盒子序号:4号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);/* 4、组入组通道配置 */sConfigInjected.InjectedChannel = ADC_CHANNEL_4;                    //通道选择:通道4sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;                 //注入组盒子序号:1号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0sConfigInjected.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;                    //通道选择:通道5sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;                 //注入组盒子序号:2号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);sConfigInjected.InjectedChannel = ADC_CHANNEL_6;                    //通道选择:通道6sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;                 //注入组盒子序号:3号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);sConfigInjected.InjectedChannel = ADC_CHANNEL_7;                    //通道选择:通道7sConfigInjected.InjectedRank = ADC_INJECTED_RANK_4;                 //注入组盒子序号:4号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_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的通道1hdma1_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;                               //选择定时器TIM2htim2_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;                                //比较值:1000sConfig_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;         //选择PA0GPIO_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; //需要配置的外设:ADCPeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;    //设置ADC分频值:6分频 = 12MHzHAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);/* 2、ADC1的初始化 */__HAL_RCC_ADC1_CLK_ENABLE();                        //使能ADC1时钟hadc1.Instance = ADC1;                              //选择ADC1hadc1.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;                    //通道选择:通道0sConfig1.Rank = ADC_REGULAR_RANK_1;                  //规则组盒子序号:1号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_1;                    //通道选择:通道1sConfig1.Rank = ADC_REGULAR_RANK_2;                  //规则组盒子序号:2号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_2;                    //通道选择:通道2sConfig1.Rank = ADC_REGULAR_RANK_3;                  //规则组盒子序号:3号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_3;                    //通道选择:通道3sConfig1.Rank = ADC_REGULAR_RANK_4;                  //规则组盒子序号:4号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);/* 4、组入组通道配置 */sConfigInjected.InjectedChannel = ADC_CHANNEL_4;                    //通道选择:通道4sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;                 //注入组盒子序号:1号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0sConfigInjected.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;                    //通道选择:通道5sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;                 //注入组盒子序号:2号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);sConfigInjected.InjectedChannel = ADC_CHANNEL_6;                    //通道选择:通道6sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;                 //注入组盒子序号:3号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);sConfigInjected.InjectedChannel = ADC_CHANNEL_7;                    //通道选择:通道7sConfigInjected.InjectedRank = ADC_INJECTED_RANK_4;                 //注入组盒子序号:4号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_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的通道1hdma1_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;            //选择PB15GPIO_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; //需要配置的外设:ADCPeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;    //设置ADC分频值:6分频 = 12MHzHAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);/* 2、ADC1的初始化 */__HAL_RCC_ADC1_CLK_ENABLE();                        //使能ADC1时钟hadc1.Instance = ADC1;                              //选择ADC1hadc1.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;                    //通道选择:通道0sConfig1.Rank = ADC_REGULAR_RANK_1;                  //规则组盒子序号:1号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_1;                    //通道选择:通道1sConfig1.Rank = ADC_REGULAR_RANK_2;                  //规则组盒子序号:2号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_2;                    //通道选择:通道2sConfig1.Rank = ADC_REGULAR_RANK_3;                  //规则组盒子序号:3号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);sConfig1.Channel = ADC_CHANNEL_3;                    //通道选择:通道3sConfig1.Rank = ADC_REGULAR_RANK_4;                  //规则组盒子序号:4号sConfig1.SamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5THAL_ADC_ConfigChannel(&hadc1, &sConfig1);/* 4、组入组通道配置 */sConfigInjected.InjectedChannel = ADC_CHANNEL_4;                    //通道选择:通道4sConfigInjected.InjectedRank = ADC_INJECTED_RANK_1;                 //注入组盒子序号:1号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0sConfigInjected.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;                    //通道选择:通道5sConfigInjected.InjectedRank = ADC_INJECTED_RANK_2;                 //注入组盒子序号:2号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);sConfigInjected.InjectedChannel = ADC_CHANNEL_6;                    //通道选择:通道6sConfigInjected.InjectedRank = ADC_INJECTED_RANK_3;                 //注入组盒子序号:3号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_ADCEx_InjectedConfigChannel(&hadc1, &sConfigInjected);sConfigInjected.InjectedChannel = ADC_CHANNEL_7;                    //通道选择:通道7sConfigInjected.InjectedRank = ADC_INJECTED_RANK_4;                 //注入组盒子序号:4号sConfigInjected.InjectedSamplingTime = ADC_SAMPLETIME_41CYCLES_5;   //采样时间:41.5TsConfigInjected.InjectedOffset = 0;                                 //偏移值:0HAL_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的通道1hdma1_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.rhkb.cn/news/497198.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录算法【Day4】

Day4 1.链表的题目&#xff0c;要在草稿纸上模拟清晰后就简单了 2.双指针更加灵活的应用。 3.环形链表多练习。 24. 两两交换链表中的节点 class Solution { public:ListNode* swapPairs(ListNode* head) {ListNode* _dummyHead new ListNode(0); //虚拟头结点_dummyHead…

(南京观海微电子)——GH7009开机黑屏案例分析

一、 现象描述&#xff1a; 不良现象: LVDS模组&#xff0c;开机大概2秒后就黑屏。 二、问题分析 等主机进入Kernel 后做以下测试&#xff1a; 1、手动reset LCM 后 可以显示正常&#xff1b; 总结&#xff1a; 1&#xff09;uboot 部分HS 太窄&#xff0c;仅有4个clk宽度&am…

PaddleOCR文字识别模型的FineTune

一、paddleOCR paddle框架为百度开发的深度学习框架&#xff0c;其中对于文字检测、识别具有较为便利的开发条件。同时PaddleOCR文字识别工具较为轻量化&#xff0c;并可按照任务需求进行model的finetune&#xff0c;满足实际的业务需求。 源码来源&#xff1a;githubOCR 在gi…

Spark生态圈

Spark 主要用于替代Hadoop中的 MapReduce 计算模型。存储依然可以使用 HDFS&#xff0c;但是中间结果可以存放在内存中&#xff1b;调度可以使用 Spark 内置的&#xff0c;也可以使用更成熟的调度系统 YARN 等。 Spark有完善的生态圈&#xff1a; Spark Core&#xff1a;实现了…

影刀进阶指令 | Kimi (对标ChatGPT)

文章目录 影刀进阶指令 | Kimi &#xff08;对标ChatGPT&#xff09;一. 需求二. 流程三. 实现3.1 流程概览3.2 流程步骤讲解1\. 确定问题2\. 填写问题并发送3\. 检测答案是否出完 四. 运维 影刀进阶指令 | Kimi &#xff08;对标ChatGPT&#xff09; 简单讲讲RPA调用kimi实现…

Spring Security3.0.2版本

前言&#xff1a; 通过实践而发现真理&#xff0c;又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识&#xff0c;又从理性认识而能动地指导革命实践&#xff0c;改造主观世界和客观世界。实践、认识、再实践、再认识&#xff0c;这种形式&#xff0c;循环往…

--spring.profiles.active=prod

rootproduct-qualification:~# ps -ef | grep java root 5110 1 3 16:57 ? 00:00:54 java -jar productQualification.jar --spring.profiles.activeprod root 6476 5797 0 17:26 pts/0 00:00:00 grep --colorauto java好的&#xff0c;你使用 ps …

力扣矩阵-算法模版总结

lc-73.矩阵置零-(时隔14天)-12.27 思路&#xff1a;(23min22s) 1.直接遍历遇0将行列设0肯定不行&#xff0c;会影响后续判断&#xff0c;题目又要求原地算法&#xff0c;那么进一步考虑是否可以将元素为0&#xff0c;其行列需要设为0的位置给存储下来&#xff0c;最后再遍历根据…

Markov test笔记

补充知识 来源于数学之美第五章&#xff1a; 到了 19 世纪&#xff0c;概率论的发展从相对静止的随机变量的研究发展到随机变量的时间序列 ( s 1 , s 2 , s 3 , … ) (s_1, s_2, s_3, \dots) (s1​,s2​,s3​,…)&#xff0c;即随机过程&#xff08;动态的&#xff09;。这在…

DeepSpeed 使用 LoRA 训练后文件结构详解

DeepSpeed 使用 LoRA 训练后文件结构详解 在大语言模型&#xff08;LLM&#xff09;的训练过程中&#xff0c;DeepSpeed 提供了强大的分布式训练能力&#xff0c;而 LoRA&#xff08;Low-Rank Adaptation&#xff09;通过参数高效微调技术显著减少了资源占用。完成训练后&…

GitHub 桌面版配置 |可视化界面进行上传到远程仓库 | gitLab 配置【把密码存在本地服务器】

&#x1f947; 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 &#x1f389; 声明: 作为全网 AI 领域 干货最多的博主之一&#xff0c;❤️ 不负光阴不负卿 ❤️ 文章目录 桌面版安装包下载clone 仓库操作如下GitLab 配置不再重复输入账户和密码的两个方…

docker-开源nocodb,使用已有数据库

使用已有数据库 创建本地数据库 数据库&#xff1a;nocodb 用户&#xff1a;nocodb 密码&#xff1a;xxxxxx修改docker-compose.yml 默认网关的 IP 地址是 172.17.0.1&#xff08;适用于 bridge 网络模式&#xff09;version: "2.1" services:nocodb:environment:…

uniapp 前端解决精度丢失的问题 (后端返回分布式id)

原因&#xff1a; 后端使用分布式id, id为19位数&#xff0c;导致精度丢失 &#xff0c;前端解决方法 这个是通过浏览器请求回来的数据&#xff0c;这个时候id 数据已经丢失了&#xff0c;在数据库查询不到&#xff0c;在调获详情接口的时候会有问题 实际的&#xff1a; 解决…

SQL-leetcode-180. 连续出现的数字

180. 连续出现的数字 表&#xff1a;Logs -------------------- | Column Name | Type | -------------------- | id | int | | num | varchar | -------------------- 在 SQL 中&#xff0c;id 是该表的主键。 id 是一个自增列。 找出所有至少连续出现三次的数字。 返回的…

【教程】通过Docker运行AnythingLLM

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 官方教程&#xff1a;Local Docker Installation ~ AnythingLLM 1、先创建一个目录用于保存anythingllm的持久化文件&#xff1a; sudo mkdir /app su…

soular使用教程

用 soular 配置你的组织&#xff0c;工作更高效&#xff01;以下是快速上手的简单步骤&#xff1a; &#xfeff; 1. 账号管理 可以对账号信息进行多方面管理&#xff0c;包括分配不同的部门、用户组等&#xff0c;从而确保账号权限和职责的清晰分配。 &#xfeff; 1.1 用…

Github - 如何提交一个带有“verified”标识的commit

Github - 如何提交一个带有“verified”标识的commit 前言(Why) 今天在Github上浏览某项目的commit记录的时候发现&#xff0c;有的commit记录带有verified绿色标识&#xff0c;有的带有橘色的Unverified标识&#xff0c;还有的什么都不显示。 既然我是根正苗红的作者(bushi)…

基于Bregman的交替方向乘子法

目录标题 ADMM方法简介Bregman散度Bregman ADMM的原理主要优势代码示例&#xff1a;各个符号的解释&#xff1a;**梯度的几何含义**&#xff1a;具体数学公式&#xff1a;**应用示例**&#xff1a;**ADMM的标准形式&#xff1a;****ADMM中的变量角色&#xff1a;****ADMM中的更…

【操作系统】课程 3进程同步与通信 同步测练 章节测验

3.1知识点导图 无 3.2进程同步与互斥 【本章学习目标】 &#xff08;1&#xff09;了解进程通信的机制和通信方式。 &#xff08;2&#xff09;理解多道程序环境下进程间通信的机制&#xff1b;消息传递系统的实现。 &#xff08;3&#xff09;掌握临界资源和临界区的概念…

React中最优雅的异步请求

给大家分享在React19中使用useSuspense处理异步请求为什么是被认为最优雅的解决方案 一. 传统方案 解决异步请求的方案中&#xff0c;我们要处理至少两个最基本的逻辑 正常的数据显示数据加载的UI状态 例如&#xff1a; export default function Index(){const [content, …