目录
CubeMX配置工程
配置时钟
编辑
配置串口
配置LED灯
配置ADC
代码编写
重定向
定义如下全局变量
ADC中断
实物展示
工程文件
配置主频和ADC采样时钟
把主频设置为72M,经过6分频后ADC采样时钟为12M
开启串口作为显示输出
笔者把ADC1的所有通道都打开了,包括一个内部温度采集也开启了,这样就是有11路adc需要采集
把Number Of Conversion设置为11再分别设置每个rank采集ADC的哪个通道
每个通道采样239.5个cycle约为20us,再加上转换时间为21us,采样率大约为47.6KHz,采样11个通道耗时大约231us即0.23ms。开启DMA,选择周期模式,数据宽度为半字
将串口重定向代码复制到usart.c文件底部,添加stdio.h头文件
/**
* 函数功能: 重定向c库函数printf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
/**
* 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
勾选Use MicroLIB
volatile uint16_t ADC_Buffer[11];
uint32_t cnt;
uint8_t led_flag;
一个数组ADC_Buffer[11]用于存放DMA采集的ADC值,还有一个变量cnt用于ADC转换结束计数以及led_flag用于判断LED标志位
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
cnt++;
led_flag=!led_flag;
}
ADC中断内进行cnt的增加和LED闪烁标志位的翻转。
需要注意的是如下
如果不开启持续转换模式的话,主函数里就要不停得HAL_ADC_Start_DMA了
代码如下
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC_Buffer,11);
for(uint8_t i=0;i<10;i++)
{
printf("[%d]%d--",i,ADC_Buffer[i]);
}
printf("||TEMP-->%d %d\r\n",ADC_Buffer[10],cnt);
led_flag?HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET):
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);
HAL_Delay(400);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
反之如果开启持续转换模式,那么只需在main函数内开启一次HAL_ADC_Start_DMA即可
代码如下
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)ADC_Buffer,11);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
for(uint8_t i=0;i<10;i++)
{
printf("[%d]%d--",i,ADC_Buffer[i]);
}
printf("||TEMP-->%d %d\r\n",ADC_Buffer[10],cnt);
led_flag?HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET):
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET);
HAL_Delay(400);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
笔者将PA0~PA7,PB0,PB1分别依次接VCC和GND,这样相邻的引脚电平就是一高一低,方便演示和观察,打开串口,效果如下
在单片机运行中,如果改变某个引脚的电平(原本接VCC的改为接GND)串口显示的ADC量也会跟着发生变化
在每一条串口数据的最右侧是ADC采样完成的次数,由于开启的是持续转换模式,因此单片机会以ADC的时钟进行采样,转换,DMA自动搬运等等,速度非常滴快,上文已经估算过转换一次大概需要0.23ms,那么一秒就是进入中断4348次左右
图中可以看到,到第7.8秒时计数值到了33853,与4348*7.8=33914.4非常接近
CubeMXSTM32F103C8T6单片机多路ADC+DMA采集HAL库资源-CSDN文库
或者如下
链接:https://pan.baidu.com/s/16oghY5oypwfEIszo2m8aNw?pwd=pg4i
提取码:pg4i
点个赞吧,你的支持是对我最大的鼓励