这里本来是要讲输入捕获的知识点的,但是由于学校校赛时间比较紧,校赛没考到输入捕获,所以先写ADC模拟电压测量的知识点。这里将的是单通道阻塞式采样。
Cubemx配置
点开cubemx。
1.将PB15配置为ADC2-IN15。
2.在Analog中点击ADC2,勾选IN15 Single-ended。
3.配置Paramater Settings中的参数。
Mode(模式):Independent mode
Clock Prescaler(分频):Synchronus clock mode divided by 2(2倍频)
Resolution(分辨率):ADC 12-bit resolution
Data Alignment(数据对齐):Right alignment(右对齐)
Scan Conversion Mode(扫描):Disable
Continuous Conversion Mode(连续模式):Disable
4.配置ADC_Regular_ConversionMode
Enable Regular Conversion(规则转换通道):Enable
Number Of Conversion(转换通道数量):1
External Trigger Conversion Sourse(触发源选择):Regular Conversion launched by software(软件触发)
Sampling Time(采样时间):2.5Cycles。
点击GENERATE CODE.
代码编写
补充知识
HAL_ADC_GetValue(hadc);
功能:当 ADC 完成一次模拟信号到数字信号的转换后,转换得到的数字值就会被存储在相应的寄存器中。而 HAL_ADC_GetValue(hadc)
函数所做的就是从这个与 ADC 对应的寄存器(具体是数据寄存器)里读出刚刚转换好的数字值,方便后续在程序中对这个代表模拟量大小的数字值进行进一步处理。
HAL_ADC_Start(hadc)
功能:主要用于启动模数转换器(ADC)的转换工作。
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED)
功能:启动模数转换器(ADC)校准过程的作用。
my_main.c
#include "my_main.h"
#include "stm32g4xx_hal_adc.h"
#include "adc.h"
uint8_t led_sta=0x10;
char text[30];
extern struct Bkeys bkey[];
void LED_Disp(uint8_t dsLED)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);//所有LED熄灭(l小写)
HAL_GPIO_WritePin(GPIOC,dsLED<<8,GPIO_PIN_RESET);//左移8位:控制C8-15引脚,值为1的点亮
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);//开锁存器
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);//关锁存器
}
float adc_read(ADC_HandleTypeDef *hadc)
{
uint16_t adc_val;
float adc_f;
HAL_ADC_Start(hadc);
adc_val=HAL_ADC_GetValue(hadc);
adc_f=adc_val*3.3f/4096.0f;
return adc_f;
}
void setup()
{
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);
LED_Disp(0x00);//关掉所有LED
LCD_Init();//LCD初始化
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
}
void loop()
{
static uint16_t temp=0;
float frq1=0;
float duty1=0;
float adc_data_PB15;
frq1=1000000.0f/(HAL_TIM_ReadCapturedValue(&htim15,TIM_CHANNEL_1)+1);
duty1=((HAL_TIM_ReadCapturedValue(&htim15,TIM_CHANNEL_2)+1)*100.0f/(HAL_TIM_ReadCapturedValue(&htim15,TIM_CHANNEL_1)+1));
sprintf(text," FRQ=%.2fHz ",frq1);
LCD_DisplayStringLine(Line8,(uint8_t *)text);//局部刷新
sprintf(text," DUTY=%.2fHz ",duty1);
LCD_DisplayStringLine(Line9,(uint8_t *)text);//局部刷新
adc_data_PB15=adc_read(&hadc2);
sprintf(text," PB15=%.4fV ",adc_data_PB15);
LCD_DisplayStringLine(Line5,(uint8_t *)text);//局部刷新
}
拓展:过采样读取ADC
由于蓝桥杯比赛会对精度进行要求,所以我们也就引入了过采样读取ADC。
首先打开前面改过的cubemx,将Paramater Settings中的Enable Regular Oversampling 设置为Enable。然后将Oversampling Right Shift设置为3 bit shift for oversampling,最后将Oversampling Ratio设置为Oversampling Ratio 128x,点击GENERATE CODE.
my_main.c
#include "my_main.h"
#include "stm32g4xx_hal_adc.h"
#include "adc.h"
uint8_t led_sta=0x10;
char text[30];
extern struct Bkeys bkey[];
void LED_Disp(uint8_t dsLED)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);//所有LED熄灭(l小写)
HAL_GPIO_WritePin(GPIOC,dsLED<<8,GPIO_PIN_RESET);//左移8位:控制C8-15引脚,值为1的点亮
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);//开锁存器
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);//关锁存器
}
float adc_read_os(ADC_HandleTypeDef *hadc)//带 过采样
{
uint16_t adc_val;
float adc_f;
HAL_ADC_Start(hadc);
adc_val=HAL_ADC_GetValue(hadc);
adc_f=adc_val*3.3f/65536.0f;
return adc_f;
}
void setup()
{
HAL_ADCEx_Calibration_Start(&hadc2,ADC_SINGLE_ENDED);
LED_Disp(0x00);//关掉所有LED
LCD_Init();//LCD初始化
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
}
void loop()
{
static uint16_t temp=0;
float frq1=0;
float duty1=0;
float adc_data_PB15;
frq1=1000000.0f/(HAL_TIM_ReadCapturedValue(&htim15,TIM_CHANNEL_1)+1);
duty1=((HAL_TIM_ReadCapturedValue(&htim15,TIM_CHANNEL_2)+1)*100.0f/(HAL_TIM_ReadCapturedValue(&htim15,TIM_CHANNEL_1)+1));
sprintf(text," FRQ=%.2fHz ",frq1);
LCD_DisplayStringLine(Line8,(uint8_t *)text);//局部刷新
sprintf(text," DUTY=%.2fHz ",duty1);
LCD_DisplayStringLine(Line5,(uint8_t *)text);//局部刷新
adc_data_PB15=adc_read_os(&hadc2);
sprintf(text," PB15=%.4fV ",adc_data_PB15);
LCD_DisplayStringLine(Line5,(uint8_t *)text);//局部刷新
}