本期目标
理清本工程系统框架
弄懂CubeMx配置相关原理及设置的背后含义
梳理代码设计流程
SAR型 ADC
单片机里的ADC,一般都是SAR型 ADC,是逐次逼近型ADC 吗这种类型的ADC精度一般都不是很高 ,但是成本都比较低
CubeMx配置
DMA设置
对DMA不熟悉的可以参考以下文章 , 详细讲解了DMA的具体设置、FIFO的作用及其具体操作
DMA初学者必看!帮小白从系统CPU层理解DMA原理-CSDN博客
小白也能看懂!从底层原理深入理解DMA控制器的内部架构图及其构成,加深对DMA的掌控-CSDN博客
打开中断
时钟设置
NVIC![]()
ADC设置
![]()
串口设置
Freertos设置![]()
代码部分
hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.ScanConvMode = DISABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; if (HAL_ADC_Init(&hadc1) != HAL_OK)PCLK2 divided by 4
ADC也需要动力 , 时钟就是他的动力, 对PCLK2 , 进行四分频
Rigiht alignment
右对齐
Scan Conversion Mode
Scan Conversion Mode 是控制:ADC 是否按照配置的通道序列,对多个通道进行依次转换。(我们本次就一个通道,所以未开启)
如果是 Enable,ADC 将按照在规则通道(Regular Channels)中配置的通道序列,依次对多个通道进行转换。 每次触发(无论是软件触发还是硬件触发),ADC都会按照顺序对所有配置的通道进行一次完整的转换序列。适用于需要同时采集多个模拟信号的情况,例如多传感器数据采集、数据监测等。
如果同时启用了 Continuous Conversion Mode(连续转换模式), ADC 会在完成一次完整的通道序列转换后,立即开始下一次序列的转换,形成一个连续的循环。如果没有启用 Continuous ConversionMode(连续转换模式),ADC在完成一次通道序列转换后停止,等待下一个触发事件。
如果同时启用了 Discontinuous Conversion Mode(非连续转换模式),会将通道序列分成若干组,每次触发事件只转换一组通道,
如果是 Disable,ADC 仅对配置的一个通道进行转换,没有通道序列的概念。每次触发只转换一个通道,简单高效。适用于只需要采集一个模拟信号的简单应用,例如单一传感器的读取。
Continuous Conversion Mode(连续转换模式)是控制:是否持续的对某一个通道不停地转换,你会在 DR 里面一直看到数据更新,EOC 标志位一直会产生。于是你可以通过轮询或者中断的方式一直来取 ADC 的数据。
Discontinuous Conversion Mode(非连续转换模式)是控制:是否 ADC 将进入 非连续转换模式
(Discontinuous Conversion Mode).
在非连续转换模式下(Enable),ADC 会将配置的通道序列分成若干个小组,每个小组的大小由Discontinuous Number(非连续数目)参数确定,范围是1到8。(应确保 Scan Conversion Mode 也是Enable 的)
ADC会在每个触发事件(比如软件或硬件触发)下,仅转换一个小组的通道,然后停止,等待下一个触发事件。每次非连续转换都需要新的触发事件,这种模式适用于需要在多个触发事件下分批次采样的情况。
例如,在实时控制系统中,可能希望在每个控制周期内只采样部分通道(而不是 全部通道),以减少 CPU 负担。比如说,如果你配置了6个通道的序列,且将 Discontinuous Number 设置为 2,那么 ADC 会将这 6个通道分成3组,每组 2个通道。每次触发事件会启动一组(2 个通道)的转换需要 3 次触发事件才能完成所有通道的转换。
sConfig.Channel = ADC_CHANNEL_0; sConfig.Rank = 1; sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;ADC_SAMPLETIME_3CYCLES
将逐次逼近设置成大概3个周期之后就将值给计算出来 ,这个值越大越准确 , 有时候ADC数据出问题 , 就是这里设置的太快了
1.申请buffer
freertos.c
定义
/* USER CODE BEGIN Includes */ #include <stdlib.h> /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ #define BUFFER_SIZE 1 uint32_t * buffer1 = NULL; uint32_t * buffer2 = NULL; /* USER CODE END PTD */task
/* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void *argument) { /* USER CODE BEGIN StartDefaultTask */ buffer1 = (uint32_t *)malloc((sizeof(uint32_t)* BUFFER_SIZE)); buffer2 = (uint32_t *)malloc((sizeof(uint32_t)* BUFFER_SIZE)); if(NULL == buffer1) { printf("buffer1 malloc failed \r\n"); } if(NULL == buffer2) { printf("buffer2 malloc failed \r\n"); return; } printf("buffer1 , buffer2 malloc success\r\n "); memset(buffer1, 0xff , (sizeof(uint32_t)* BUFFER_SIZE)); memset(buffer2, 0xff , (sizeof(uint32_t)* BUFFER_SIZE)); /* Infinite loop */ for(;;) { printf("hello world \r\n"); osDelay(1000); } /* USER CODE END StartDefaultTask */ }至此
本期将前置设置配好了 , 并且成功分配了buffer数据 ,打印至串口
下一步我们将启动DMA传输并且进入中断