STM32——ADC知识总结及多通道采样实验

1.ADC概念

ADC,全称:Analog-to-Digital Converter,指模拟/数字转换器
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2 STM32各系列ADC的主要特性

在这里插入图片描述

3.F4框图

在这里插入图片描述

4.转换序列与转换时间

A/D转换被组织为两组:规则组(常规转换组)和注入组(注入转换组)
规则组最多可以有16个转换,注入组最多有4个转换

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.2转换时间

在这里插入图片描述
在这里插入图片描述

5.触发源blog.csdnimg.cn/direct/f7ca0dd32f5443aab9798321c743be8e.png)

6.中断

在这里插入图片描述

7.单次转换模式和连续转换模式与扫描模式

单次转换模式和连续转换模式与
扫描模式
在这里插入图片描述
在这里插入图片描述

8 结构体

typedef struct
{
ADC_TypeDef Instance; / ADC 寄存器基地址 /
ADC_InitTypeDef Init; /
ADC 参数初始化结构体变量 */
DMA_HandleTypeDef DMA_Handle; / DMA 配置结构体 */
……
} ADC_HandleTypeDef;

typedef struct
{
uint32_t DataAlign; /* 设置数据的对齐方式 /
uint32_t ScanConvMode; /
扫描模式 /
FunctionalState ContinuousConvMode; /
开启单次转换模式或者连续转换模式 / uint32_t NbrOfConversion; / 设置转换通道数目 /
FunctionalState DiscontinuousConvMode; /
是否使用规则通道组间断模式 /
uint32_t NbrOfDiscConversion; /
配置间断模式的规则通道个数 /
uint32_t ExternalTrigConv; /
ADC 外部触发源选择 */
} ADC_InitTypeDef;

typedef struct
{
uint32_t Channel; /* ADC 转换通道*/
uint32_t Rank; /* ADC 转换顺序 /
uint32_t SamplingTime; /
ADC 采样周期 */
} ADC_ChannelConfTypeDef;

9. 多通道采集实验配置步骤在这里插入图片描述

在这里插入图片描述

10 实战

10.1 adc.h

#ifndef __ADC_H
#define __ADC_H

#include "./SYSTEM/sys/sys.h"

//1.开启 ADCx 和通道输出的 GPIO 时钟,配置该 IO 口的复用功能输出
//1.1 ADC及引脚定义  ADC复用PA5口
#define ADC_ADCX_CHY_GPIO_PORT          GPIOA
#define ADC_ADCX_CHY_GPIO_PIN           GPIO_PIN_5               
#define ADC_ADCX_CHY_GPIO_CLK_ENABLE()  do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)      //PA口时钟使能

#define ADC_ADCX                        ADC1
#define ADC_ADCX_CHY                    ADC_CHANNEL_5                                      //通道Y,  0 <= Y <= 17
#define ADC_ADCX_ADCX_GPIO_CLK_ENABLE()      do{ __HAL_RCC_ADC1_CLK_ENABLE(); }while(0)    // PA口时钟使能

#define ADC_CH_NUM              6                                                          //转换的通道数目 

///* ADC DMA采集 DMA数据流相关 定义
// * 注意: 这里我们的通道还是使用上面的定义.
#define ADC_ADCX_DMASx             DMA2_Stream4
#define ADC_ADCX_DMASx_Chanel      DMA_CHANNEL_0                                          //ADC1_DMA请求源
#define ADC_ADCX_DMASx_IRQn        DMA2_Stream4_IRQn                                      //DMA2_Stream4_IRQn
#define ADC_ADCX_DMASx_IRQHandler  DMA2_Stream4_IRQHandler                                

#define ADC_ADCX_DMASx_IS_TC()     ( DMA2->HISR & (1 << 5) )                             //判断 DMA2_Stream4 传输完成标志, 这是一个假函数形式, * 不能当函数使用, 只能用在if等语句里面
#define ADC_ADCX_DMASx_CLR_TC()     do{ DMA2->HIFCR |= 1 << 5; }while(0)                 //清除 DMA2_Stream4 传输完成标志

void adc_channel_set(ADC_HandleTypeDef *adc_handle, uint32_t ch, uint32_t rank, uint32_t stime);    /* ADC通道设置 */

void adc_dma_enable( uint16_t ndtr);        /* 使能一次ADC DMA采集传输 */

void adc_nch_dma_init(uint32_t tmr);        /* ADC多通道 DMA采集初始化 */
void adc_nch_dma_gpio_init(void);           /* ADC多通道 GPIO初始化 */
void adc_nch_dma_enable(uint16_t ndtr);     /* 使能一次ADC DMA多通道采集传输 */

#endif 

10.2 adc.c


#include "./SYSTEM/delay/delay.h"
#include "./BSP/ADC/adc.h"


//使用 ADC1 采集(DMA 读取)通道 0\1\2\3\4\5 的电压,在 LCD 模块上面显示对应的 ADC
//转换值以及换算成电压后的电压值。可以使用杜邦线连接 PA0\PA1\PA2\PA3\PA4\PA5 到你想测
//量的电压源(0~3.3V),然后通过 TFTLCD 显示的电压值。
//多通道 ADC 采集(DMA 读取)配置步骤:
//1.开启 ADCx 和通道输出的 GPIO 时钟,配置该 IO 口的复用功能输出

//2.初始化 ADCx,配置其工作参数
//2.1  HAL_ADC_Init 函数,设置 ADCx 时钟分频系数、分辨率、模式、扫描方式、对齐方式等信息。
//2.2  会调用:HAL_ADC_MspInit 回调函数来,对 ADC 底层以及其输入通道 IO
//的初始化,包括:ADC 及 GPIO 时钟使能、GPIO 模式设置等

//3.配置 ADC 通道并启动 AD 转换器
//3.1在 HAL 库中,通过 HAL_ADC_ConfigChannel 函数来设置配置 ADC 的通道,根据需求设
//置通道、序列、采样时间和校准配置单端输入模式或差分输入模式等。这里配置多通道输出,
//需要多次调用该函数
//3.2 配置好 ADC 通道之后,通过 HAL_ADC_Start 函数启动 AD 转换器

//4 初始化 DMA
//4.1HAL_DMA_Init 函数初始化 DMA,包括配置通道,外设地址,存储器地址,传输数
//据量等。
//4.2HAL 库为了处理各类外设的 DMA 请求,在调用相关函数之前,需要调用一个宏定义标识
//符,来连接 DMA 和外设句柄。这个宏定义为__HAL_LINKDMA。

//5 使能 DMA 对应数据流中断,配置 DMA 中断优先级,使能 ADC,使能并启动 DMA
//5.1 HAL_ADC_Start 函数开启 ADC 转换
//5.2 HAL_DMA_Start_IT 函数启动 DMA 读取,使能 DMA 中断。
//5.3 HAL_NVIC_EnableIRQ 函数使能 DMA 数据流中断。
//5.4 HAL_NVIC_SetPriority 函数设置中断优先级

//6 编写中断服务函数
//通用DMA中断处理函数HAL_DMA_IRQHandler,
//在该函数内部

ADC_HandleTypeDef g_adc_nch_dma_handle;     /* 与DMA关联的ADC句柄 */
DMA_HandleTypeDef g_dma_nch_adc_handle;     /* 与ADC关联的DMA句柄 */
uint8_t g_adc_dma_sta = 0;              /* DMA传输状态标志, 0,未完成; 1, 已完成 */

// * @brief       ADC初始化函数
// *   @note      本函数支持ADC1/ADC2任意通道, 但是不支持ADC3
// *              我们使用12位精度, ADC采样时钟=21M, 转换时间为: 采样周期 + 12个ADC周期
// *              设置最大采样周期: 480, 则转换时间 = 492 个ADC周期 = 23.42us
// * @param       无
// * @retval      无
// */

//2.初始化 ADCx,配置其工作参数
//2.1  HAL_ADC_Init 函数,设置 ADCx 时钟分频系数、分辨率、模式、扫描方式、对齐方式等信息。
//2.2  会调用:HAL_ADC_MspInit 回调函数来,对 ADC 底层以及其输入通道 IO
//的初始化,包括:ADC 及 GPIO 时钟使能、GPIO 模式设置等

//4 初始化 DMA
//4.1HAL_DMA_Init 函数初始化 DMA,包括配置通道,外设地址,存储器地址,传输数
//据量等。
//4.2HAL 库为了处理各类外设的 DMA 请求,在调用相关函数之前,需要调用一个宏定义标识
//符,来连接 DMA 和外设句柄。这个宏定义为__HAL_LINKDMA。
void adc_nch_dma_init(uint32_t mar)
{
    ADC_ADCX_CHY_CLK_ENABLE();                     //使能ADCx时钟
    //疑问1
    if ((uint32_t)ADC_ADCX_DMASx > (uint32_t)DMA2)      /* 大于DMA1_Stream7, 则为DMA2 */
    {
        __HAL_RCC_DMA2_CLK_ENABLE();                    /* DMA2时钟使能 */
    }
    else
    {
        __HAL_RCC_DMA1_CLK_ENABLE();                    /* DMA1时钟使能 */
    }
    
    // HAL_DMA_Init 函数初始化 DMA,包括配置通道,外设地址,存储器地址,传输数据量等。

    g_dma_nch_adc_handle.Instance = ADC_ADCX_DMASx;                             /* 设置DMA数据流 寄存器基地址 */
    g_dma_nch_adc_handle.Init.Channel = DMA_CHANNEL_0;                          /* 设置DMA通道 */
    g_dma_nch_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;                 /* DIR = 1 , 外设到存储器模式 */
    g_dma_nch_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;                     /* 外设非增量模式 */
    g_dma_nch_adc_handle.Init.MemInc =  DMA_MINC_ENABLE;                         /* 存储器增量模式 */
    g_dma_nch_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;    /* 外设数据长度:16位 */
    g_dma_nch_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;       /* 存储器数据长度:16位 */
    g_dma_nch_adc_handle.Init.Mode = DMA_NORMAL;                                /* 外设流控模式 */
    g_dma_nch_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;                   /* 中等优先级 */
    HAL_DMA_Init(&g_dma_nch_adc_handle);                                        /* 初始化DMA */
    
     //5.1 HAL_ADC_Start 函数开启 ADC 转换
    HAL_DMA_Start(&g_dma_nch_adc_handle, (uint32_t)&ADC_ADCX->DR, mar, 0);      /* 配置DMA传输参数 */
    
    //HAL_ADC_Init 函数,设置 ADCx 时钟分频系数、分辨率、模式、扫描方式、对齐方式等信息。
    g_adc_nch_dma_handle.DMA_Handle = &g_dma_nch_adc_handle;    /* 设置ADC对应的DMA */

    g_adc_nch_dma_handle.Instance = ADC_ADCX;
    g_adc_nch_dma_handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;            /* 4分频,ADCCLK = PCLK2/4 = 84/4 = 21Mhz */
    g_adc_nch_dma_handle.Init.Resolution = ADC_RESOLUTION_12B;                      /* 12位模式 */
    g_adc_nch_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;                      /* 右对齐 */
    g_adc_nch_dma_handle.Init.ScanConvMode = ENABLE;                                /* 扫描模式 */
    g_adc_nch_dma_handle.Init.ContinuousConvMode = ENABLE;                          /* 连续转换模式,转换完成之后接着继续转换 */
    g_adc_nch_dma_handle.Init.DiscontinuousConvMode = DISABLE;                      /* 禁止不连续采样模式 */
    g_adc_nch_dma_handle.Init.NbrOfConversion = ADC_CH_NUM;                         /* 使用转换通道数,需根据实际转换通道去设置 */
    g_adc_nch_dma_handle.Init.NbrOfDiscConversion = 0;                              /* 不连续采样通道数为0 */
    g_adc_nch_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;                /* 软件触发 */
    g_adc_nch_dma_handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* 使用软件触发, 此位忽略 */
    g_adc_nch_dma_handle.Init.DMAContinuousRequests = ENABLE;                       /* 开启DMA连续转换 */
    HAL_ADC_Init(&g_adc_nch_dma_handle);                                            /* 初始化ADC */
    
    adc_nch_dma_gpio_init();    /* GPIO 初始化 */
    adc_channel_set(&g_adc_nch_dma_handle, ADC_CHANNEL_0,1, ADC_SAMPLETIME_480CYCLES);// 设置采样规则序列1~6 
    adc_channel_set(&g_adc_nch_dma_handle, ADC_CHANNEL_1,2, ADC_SAMPLETIME_480CYCLES);
    adc_channel_set(&g_adc_nch_dma_handle, ADC_CHANNEL_2,3, ADC_SAMPLETIME_480CYCLES);
    adc_channel_set(&g_adc_nch_dma_handle, ADC_CHANNEL_3,4, ADC_SAMPLETIME_480CYCLES);
    adc_channel_set(&g_adc_nch_dma_handle, ADC_CHANNEL_4,5, ADC_SAMPLETIME_480CYCLES);
    adc_channel_set(&g_adc_nch_dma_handle, ADC_CHANNEL_5,6, ADC_SAMPLETIME_480CYCLES);
    
    //5 使能 DMA 对应数据流中断,配置 DMA 中断优先级,使能 ADC,使能并启动 DMA
   
    //5.2 HAL_DMA_Start_IT 函数启动 DMA 读取,使能 DMA 中断。
    //5.3 HAL_NVIC_EnableIRQ 函数使能 DMA 数据流中断。
    //5.4 HAL_NVIC_SetPriority 函数设置中断优先级

    HAL_NVIC_SetPriority(ADC_ADCX_DMASx_IRQn, 3, 3);    /* 设置DMA中断优先级为3,子优先级为3 */
    HAL_NVIC_EnableIRQ(ADC_ADCX_DMASx_IRQn);            /* 使能DMA中断 */    
    HAL_ADC_Start_DMA(&g_adc_nch_dma_handle, &mar, sizeof(uint16_t));   /* 开始DMA数据传输 */
    __HAL_DMA_ENABLE_IT(&g_dma_nch_adc_handle, DMA_IT_TC);              /* TCIE=1, 使能传输完成中断 */

}

/**
 * @brief       设置ADC通道采样时间
 * @param       adcx : adc句柄指针,ADC_HandleTypeDef
 * @param       ch   : 通道号, ADC_CHANNEL_0~ADC_CHANNEL_17
 * @param       stime: 采样时间  0~7, 对应关系为:
 *   @arg       ADC_SAMPLETIME_3CYCLES,  3个ADC时钟周期        ADC_SAMPLETIME_15CYCLES, 15个ADC时钟周期
 *   @arg       ADC_SAMPLETIME_28CYCLES, 28个ADC时钟周期       ADC_SAMPLETIME_56CYCLES, 56个ADC时钟周期
 *   @arg       ADC_SAMPLETIME_84CYCLES, 84个ADC时钟周期       ADC_SAMPLETIME_112CYCLES,112个ADC时钟周期
 *   @arg       ADC_SAMPLETIME_144CYCLES,144个ADC时钟周期      ADC_SAMPLETIME_480CYCLES,480个ADC时钟周期
 * @param       rank: 多通道采集时需要设置的采集编号,
                假设你定义channel1的rank=1,channel2 的rank=2,
                那么对应你在DMA缓存空间的变量数组AdcDMA[0] 就i是channel1的转换结果,AdcDMA[1]就是通道2的转换结果。 
                单通道DMA设置为 ADC_REGULAR_RANK_1
 *   @arg       编号1~16:ADC_REGULAR_RANK_1~ADC_REGULAR_RANK_16
 * @retval      无
 */

//3.配置 ADC 通道并启动 AD 转换器
//3.1在 HAL 库中,通过 HAL_ADC_ConfigChannel 函数来设置配置 ADC 的通道,根据需求设
//置通道、序列、采样时间和校准配置单端输入模式或差分输入模式等。这里配置多通道输出,
//需要多次调用该函数
//3.2 配置好 ADC 通道之后,通过 HAL_ADC_Start 函数启动 AD 转换器
void adc_channel_set(ADC_HandleTypeDef *adc_handle, uint32_t ch, uint32_t rank, uint32_t stime)
{
    /* 配置对应ADC通道 */
    ADC_ChannelConfTypeDef adc_channel;
    adc_channel.Channel = ch;               /* 设置ADCX对通道ch */
    adc_channel.Rank = rank;                /* 设置采样序列 */
    adc_channel.SamplingTime = stime;       /* 设置采样时间 */
    HAL_ADC_ConfigChannel(adc_handle, &adc_channel); /* 初始化ADC通道 */
}
/**
 * @brief       多通道ADC的gpio初始化函数
 * @param       无
 * @note        此函数会被adc_nch_dma_init()调用
 * @note        PA0-ADC_CHANNEL_0、PA1-ADC_CHANNEL_1、PA2-ADC_CHANNEL_2
                PA3-ADC_CHANNEL_3、PA4-ADC_CHANNEL_4、PA5-ADC_CHANNEL_5
* @retval       无
 */
//2.2对 ADC 底层以及其输入通道 IO的初始化,包括:ADC 及 GPIO 时钟使能、GPIO 模式设置等
void adc_nch_dma_gpio_init()
{
    GPIO_InitTypeDef gpio_init_struct;

    __HAL_RCC_GPIOA_CLK_ENABLE();                    /* 开启GPIOA引脚时钟 */

    /* ADC采集引脚模式设置,模拟输入 */
    gpio_init_struct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5; /* GPIOA0~5 */;
    gpio_init_struct.Mode = GPIO_MODE_ANALOG;
    gpio_init_struct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &gpio_init_struct);

}
/**
 * @brief       使能一次ADC DMA传输
 * @param       ndtr: DMA传输的次数
 * @retval      无
 */
void adc_nch_dma_enable(uint16_t ndtr)
{
    __HAL_ADC_DISABLE(&g_adc_nch_dma_handle);       /* 先关闭ADC */
    
    __HAL_DMA_DISABLE(&g_dma_nch_adc_handle);       /* 关闭DMA传输 */
    g_dma_nch_adc_handle.Instance->NDTR = ndtr;     /* 重设DMA传输数据量 */
    __HAL_DMA_ENABLE(&g_dma_nch_adc_handle);        /* 开启DMA传输 */
    
    __HAL_ADC_ENABLE(&g_adc_nch_dma_handle);        /* 重新启动ADC */
    ADC_ADCX->CR2 |= 1 << 30;                       /* 启动规则转换通道 */
}
/**
 * @brief       ADC DMA采集中断服务函数
 * @param       无
 * @retval      无
 */

void ADC_ADCX_DMASx_IRQHandler(void)
{
    if (ADC_ADCX_DMASx_IS_TC())    //是否传输完成
    {
        g_adc_dma_sta = 1;          /* 标记DMA传输完成 */
        ADC_ADCX_DMASx_CLR_TC();    /* 清除DMA2 数据流4 传输完成中断 */
    }
}


10.3 main.c



#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/ADC/adc.h"
#include "./BSP/DMA/dma.h"


#define ADC_DMA_BUF_SIZE        50 * 6      /* ADC DMA采集 BUF大小, 应等于ADC通道数的整数倍 */
uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE];   /* ADC DMA BUF */

extern uint8_t g_adc_dma_sta;               /* DMA传输状态标志, 0, 未完成; 1, 已完成 */

int main(void)
{
    uint16_t i, j;
    uint16_t adcx;
    uint32_t sum;
    float temp;

    HAL_Init();                             /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7);     /* 设置时钟,168Mhz */
    delay_init(168);                        /* 延时初始化 */
    usart_init(115200);                     /* 串口初始化为115200 */
    led_init();                             /* 初始化LED */
    lcd_init();                             /* 初始化LCD */
    
    adc_nch_dma_init((uint32_t)&g_adc_dma_buf);

    lcd_show_string(30,  50, 200, 16, 16, "STM32", RED);
    lcd_show_string(30,  70, 200, 16, 16, "ADC 6CH DMA TEST", RED);
    lcd_show_string(30,  90, 200, 16, 16, "ATOM@ALIENTEK", RED);

    lcd_show_string(30, 110, 200, 12, 12, "ADC1_CH0_VAL:", BLUE);
    lcd_show_string(30, 122, 200, 12, 12, "ADC1_CH0_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */
    
    lcd_show_string(30, 140, 200, 12, 12, "ADC1_CH1_VAL:", BLUE);
    lcd_show_string(30, 152, 200, 12, 12, "ADC1_CH1_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */

    lcd_show_string(30, 170, 200, 12, 12, "ADC1_CH2_VAL:", BLUE);
    lcd_show_string(30, 182, 200, 12, 12, "ADC1_CH2_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */

    lcd_show_string(30, 200, 200, 12, 12, "ADC1_CH3_VAL:", BLUE);
    lcd_show_string(30, 212, 200, 12, 12, "ADC1_CH3_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */

    lcd_show_string(30, 230, 200, 12, 12, "ADC1_CH4_VAL:", BLUE);
    lcd_show_string(30, 242, 200, 12, 12, "ADC1_CH4_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */

    lcd_show_string(30, 260, 200, 12, 12, "ADC1_CH5_VAL:", BLUE);
    lcd_show_string(30, 272, 200, 12, 12, "ADC1_CH5_VOL:0.000V", BLUE); /* 先在固定位置显示小数点 */

    adc_nch_dma_enable(ADC_DMA_BUF_SIZE);   /* 启动ADC DMA多通道采集 */

    while (1)
    {
        if (g_adc_dma_sta == 1)
        {
            /* 循环显示通道0~通道5的结果 */
            for(j = 0; j < 6; j++)  /* 遍历6个通道 */
            {
                sum = 0; /* 清零 */
                for (i = 0; i < ADC_DMA_BUF_SIZE / 6; i++)  /* 每个通道采集了10次数据,进行10次累加 */
                {
                    sum += g_adc_dma_buf[(6 * i) + j];  /* 相同通道的转换数据累加 */
                }
                adcx = sum / (ADC_DMA_BUF_SIZE / 6);    /* 取平均值 */
                
                /* 显示结果 */
                lcd_show_xnum(108, 110 + (j * 30), adcx, 4, 12, 0, BLUE);   /* 显示ADC采样后的原始值 */

                temp = (float)adcx * (3.3 / 4096);      /* 获取计算后的带小数的实际电压值,比如3.1111 */
                adcx = temp;    /* 赋值整数部分给adcx变量,因为adcx为u16整形 */
                lcd_show_xnum(108, 122 + (j * 30), adcx, 1, 12, 0, BLUE);   /* 显示电压值的整数部分,3.1111的话,这里就是显示3 */

                temp -= adcx;   /* 把已经显示的整数部分去掉,留下小数部分,比如3.1111-3=0.1111 */
                temp *= 1000;   /* 小数部分乘以1000,例如:0.1111就转换为111.1,相当于保留三位小数。 */
                lcd_show_xnum(120, 122 + (j * 30), temp, 3, 12, 0X80, BLUE);/* 显示小数部分(前面转换为了整形显示),这里显示的就是111. */
            }
 
            g_adc_dma_sta = 0;  /* 清除DMA采集完成状态标志 */
            adc_nch_dma_enable(ADC_DMA_BUF_SIZE);   /* 启动下一次ADC DMA多通道采集 */
        }
        
        LED0_TOGGLE();
        delay_ms(100);
    }
}

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

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

相关文章

JNI笔记

JNI笔记 背景Demo代码JNI.javaMainActivity.javaAndroid.mkApplication.mkcom_stone_javacallc_JNI.hjavacallc.cbuild.gradle 背景 Demo代码 代码结构 JNI.java package com.stone.javacallc;/*** Created by stoneWang* Created on 2024/1/16* java调用C*/ public class …

mysql常见的需求,对于关键字的使用

如何使用MySQL将列数据转化为逗号分隔的形式。我们可以使用内置函数GROUP_CONCAT()来实现这个功能 如何使用MySQL将列数据转化为逗号分隔的形式。我们可以使用内置函数GROUP_CONCAT()来实现这个功能&#xff0c;也可以根据实际需求自定义一个函数。这种技术在一些需要对数据进…

架构师之超时未支付的订单进行取消操作的几种解决方案

今天给大家上一盘硬菜&#xff0c;并且是支付中非常重要的一个技术解决方案&#xff0c;有这块业务的同学注意自己尝试一把哈&#xff01; 一、需求如下&#xff1a; 生成订单30分钟未支付&#xff0c;自动取消 生成订单60秒后,给用户发短信 对上述的需求&#xff0c;我们给…

leetcode—矩阵

1 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 方法一&#xf…

知识库建设教程来啦,赶紧收藏起来

播种知识&#xff0c;收获效率。知识库&#xff0c;这个企业内部服务的“大百科”&#xff0c;可能是你下一步需要建立的重要工具哦&#xff01;今天&#xff0c;就让我们一起来看一下如何进行知识库的建设和维护。 首先&#xff0c;让我们理解一下知识库的定义。知识库就像是一…

探索Python数据结构与算法:解锁编程的无限可能

文章目录 一、引言1.1 数据结构与算法对于编程的重要性1.2 Python作为实现数据结构与算法的强大工具 二、列表和元组2.1 列表&#xff1a;创建列表、索引、切片和常用操作2.2 元组&#xff1a;不可变序列的特性和使用场景 三、字符串操作和正则表达式3.1 字符串的常见操作和方法…

第36期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大型语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以…

c语言-库函数strstr()、strtok()、strerror()介绍

文章目录 前言一、库函数strstr()1.1 strstr()介绍1.2 strstr()模拟实现 二、库函数strtok()2.1 strtok()介绍 三、库函数strerror()3.1 strerror()介绍 总结 前言 本篇文章介绍c语言库函数strstr()、strtok()、strerror()的使用。 一、库函数strstr() 1.1 strstr()介绍 str…

Linux/Networked

Enumeration nmap 网站更新之后有了一个引导模式&#xff0c;更利于学习了&#xff0c;之前看ippsec的视频&#xff0c;要不总是没有思路&#xff0c;现在出现的问题多了提示也更多了&#xff0c;还没有使用&#xff0c;一会用用再说 首先&#xff0c;第一个问题是“目标上正…

RocketMQ源码阅读-Producer消息发送

RocketMQ源码阅读-Producer消息发送 1. 从单元测试入手2. 启动过程3. 同步消息发送过程4. 异步消息发送过程5. 小结 Producer是消息的生产者。 Producer和Consummer对Rocket来说都是Client&#xff0c;Server是Broker。 客户端在源码中是一个单独的Model&#xff0c;目录为rock…

WordPress后台仪表盘自定义添加删除概览项目插件Glance That

成功搭建WordPress站点&#xff0c;登录后台后可以在“仪表盘 – 概览”中看到包括多少篇文章、多少个页面、多少条评论和当前WordPress版本号及所使用的主题。具体如下图所示&#xff1a; 但是如果我们的WordPress站点还有自定义文章类型&#xff0c;也想在概览中显示出来应该…

《计算机视觉处理设计开发工程师》

计算机视觉&#xff08;Computer Vision&#xff09;是一门研究如何让计算机能够理解和分析数字图像或视频的学科。简单来说&#xff0c;计算机视觉的目标是让计算机能够像人类一样对视觉信息进行处理和理解。为实现这个目标&#xff0c;计算机视觉结合了图像处理、机器学习、模…

我的年终总结2023

As a DBA 从2023年初开始&#xff0c;我就给自己定下了23年的主要任务——学习PostgreSQL数据库。虽然没有定下细致的计划&#xff0c;但总体的目标是把PG的一些基础知识学完。后来发现我想简单了&#xff0c;学习PG的成本比我想象的多的多&#xff0c;导致23年这个目标没有完…

【CSP】2023年12月真题练习(更新到202312-2)

试题编号&#xff1a;202312-1试题名称&#xff1a;仓库规划时间限制&#xff1a;1.0s内存限制&#xff1a;512.0MB问题描述&#xff1a; 问题描述 西西艾弗岛上共有 n 个仓库&#xff0c;依次编号为 1⋯n。每个仓库均有一个 m 维向量的位置编码&#xff0c;用来表示仓库间的物…

汽车生产污废水处理需要哪些工艺设备

对于汽车生产过程中产生的污废水处理&#xff0c;需要运用一系列的工艺设备来实现有效的清洁和回收利用。下面让我们一起来探索一下吧&#xff01; 首先&#xff0c;汽车生产工艺设备中最常见的是物理处理设备。物理处理包括沉淀、过滤和吸附等过程。其中&#xff0c;沉淀操作可…

Angular系列教程之观察者模式和RxJS

文章目录 引言RxJS简介RxJS中的设计模式观察者模式迭代器模式 示例代码RxJS 在 Angular 中的应用总结 引言 在Angular开发中&#xff0c;我们经常需要处理异步操作&#xff0c;例如从后端获取数据或与用户的交互。为了更好地管理这些异步操作&#xff0c;Angular中引入了RxJS&…

Java、C#、Python间的Battle

一、编译原理和开发效率 编译速度&#xff1a; C# &#xff08;约大于等于&#xff09; JAVA > Python python的编译原理 前提&#xff1a;python 3.6 python不会直接编译源码 而是把源码直接扔给解释器&#xff0c;这种方式 使得python非常灵活&#xff0c;让它的开发效…

从零开始:生产环境如何部署 Bytebase

Bytebase 是面向研发和 DBA 的数据库 DevOps 和 CI/CD 协同平台。目前 Bytebase 在全球类似开源项目中 GitHub Star 数排名第一且增长最快。 Bytebase 的架构 Bytebase 是一个单体架构 (monolith)&#xff0c;前端是 Vue3 TypeScript&#xff0c;后端是 Go。前端利用 Go 1.6 …

好用的内外网快速传输大文件方法

在信息化时代&#xff0c;数据已经成为各行各业的关键资产&#xff0c;数据的传输和交换方式直接影响着数据价值的体现。在众多场景下&#xff0c;我们需要在不同的网络环境中进行文件传输&#xff0c;如同一个局域网内或者互联网上。这时涉及到内外网的概念。 内外网指的是在不…

UE5 nDisplay群集事件的发送和接收

注意&#xff1a; 1.只能在投屏模式下生效 2.需要监听的机器都要执行“1.打开监听”