温馨提示:本文不会重复之前提到的内容,如需查看,请参考附录
【蓝桥杯嵌入式】附录
目录
重点提炼:
一、需求分析
1、需要的外设资源分析:
2、外设具体分析:
比赛时ADC可能需要配置的部分:
二、软件配置
按照分析配置外设:
ADC2_IN15:采用软件触发的方式
ADC1_IN11:采用TIM6触发的方式
三、程序功能实现
用到的函数:
程序流程:
在MDK中编写代码:
找到ADC的中断回调函数:
四、运行测试
重点提炼:
转换结果电压计算公式:
实际电压值(mV)=ADC读取值*VREF+(mV)/2^(转换精度)
VREF+是ADC转换的正参考电压,开发板上理论是3300mV;转换精度可以在CubeMX中设置;
在代码中描述如下:
uint32_t Volt=3300*HAL_ADC_GetValue(&hadc2);
Volt = Volt>>12;
用到的函数:
一、需求分析
开发板上有两个电压采集R37和R38,如图:
查看原理图可知,R37连接PB15,R38连接PB12.而使用CubeMX可以查到:PB15是ADC2的通道15,PB12是ADC1的通道11。
设计一个示例,使用ADC的软件触发功能和中断触发功能。其中,中断触发包括外部中断触发和定时器中断触发,这里使用定时器触发。使用软件触发的方式检测R37的电压,中断触发方式检测R38的电压。
1、需要的外设资源分析:
- ADC1_IN11——PB12——R38(电压采集2)
- ADC2_IN15——PB15——R37(电压采集1)
- LCD
- TIM6
2、外设具体分析:
查看原理图,和手册:
与LCD的相关的部分请参考附录。
比赛时ADC可能需要配置的部分:
- ADC Mode:选择需要的通道,选择single_ended
- ADCs_Common_Settings:独立模式或多个ADC合作的模式(下一篇文章会用)
- DMA Access Mode(DMA接入方式)
- Delay between 2 sampling phases(2个采样相位之间的间隔)
- Resolution:转换精度
- DMA Continuous Requests:是否连续产生DMA请求(下一篇文章会用)
- External Trigger Conversion Source:中断触发方式
- External Trigger Conversion Edge:外部触发时使用的信号沿
- Rank里的Sampling Time:采样时间,不设置也行,建议比赛时为提高准确性设置为640.5。
二、软件配置
参考附录的内容,建立名为“ADC_SofwareAndTimTrigger_Demo”的项目。
按照分析配置外设:
ADC2_IN15:采用软件触发的方式
软件触发方式很简单,打开ADC2_IN15即可,可以保持默认设置,也可以设置一下Rank里的Sampling Time为640.5。
ADC1_IN11:采用TIM6触发的方式
开启ADC全局中断,ADC1和ADC2 的中断号是同一个,所以需要用到中断回调函数来判断是哪个ADC引起的中断。
TIM6:
按照附录中内容将TIM6设置为500ms一次触发Trigger Event Selection中断设置为Update Event。
无需开启TIM6的中断。
生成项目文件后,打开MDK;
导入LCD驱动程序文件。
三、程序功能实现
用到的函数:
中断回调函数:
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc);
ADC功能函数:
HAL_ADC_Start_IT(&hadc1);//以中断方式启动ADC
HAL_ADC_Start(&hadc2);//以软件方式启动ADC
HAL_ADC_PollForConversion(&hadc2,200);//查看ADC的转换是否完成
HAL_ADC_GetValue(&hadc2);//读取ADC转换后的结果并返回
程序流程:
- 在初始化HAL库后初始化LCD,之前实验发现中断可能会影响LCD初始化。
- 在main函数的while中每次以软件方式启动ADC2,计算并显示电压值。
- 以中断模式启动ADC1,启动定时器TIM6。
- 重新实现ADC中断回调函数,计算并显示电压值。
在MDK中编写代码:
在main.h中
/* USER CODE BEGIN Includes */
#include "lcd.h"
#include <stdio.h>
/* USER CODE END Includes */
初始化HAL库后初始化LCD:
在 main.c 的 /* USER CODE BEGIN WHILE */ 代码段,编写以下代码
/* USER CODE BEGIN WHILE */
HAL_ADC_Start_IT(&hadc1);
HAL_TIM_Base_Start(&htim6);
while (1)
{
HAL_ADC_Start(&hadc2);
if(HAL_ADC_PollForConversion(&hadc2,200)==HAL_OK)
{
uint32_t Volt=3300*HAL_ADC_GetValue(&hadc2);
Volt = Volt>>12;
char str[20];
sprintf(str,"R37 Volt = %d",Volt);
LCD_DisplayStringLine(Line3,str);
}
HAL_Delay(500);
/* USER CODE END WHILE */
找到ADC的中断回调函数:
(详细步骤请查看附录NVIC部分)
在stm32g4xx_it.c 中找到ADC的中断服务函数:
右键函数,点击 GoTo Definition,然后在跳转到的文件中使用
Find模式搜索"HAL_ADC_Con",找到带"__weak"的弱函数定义如图:
复制此函数到stm32g4xx_it.c的最下面的代码段中:
在代码段编写程序:注意这里是HAL_ADC_GetValue(hadc);
/* USER CODE BEGIN 1 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
if(hadc->Instance == ADC1)
{
uint32_t Volt=3300*HAL_ADC_GetValue(hadc);
Volt = Volt>>12;
char str[20];
sprintf(str,"R38 Volt = %d",Volt);
LCD_DisplayStringLine(Line5,str);
}
}
/* USER CODE END 1 */
四、运行测试
编译、下载(见附录)。
运行结果如下:
ADC_SofwareAndTimTrigger_Demo