STM32 使用ADC中断(非DMA)读取传感器数据
这里使用STM32F103C8T6开发板和灰度传感器测试STM32的ADC功能。软件上使用CubeMax快速生成相应代码,在ADC中断中读取传感器数值
灰度传感器
这里使用的是这种灰度传感器,接线简单,除了供电只需要将OUT引脚接到STM32的ADC引脚即可。如果模块的白灯效果不好,还可以把灯拆下来,换成别的LED。
CubeMax ADC配置
Number Of Conversion中,使用了多少路ADC就选择多少
Rank中的Channel不要选重复,周期越长测得越准
时钟树中,如果STM32主频配成了72MHz,那么ADC最快只能有12MHz,但F103C8T6的ADC最高频率为14MHz,想要追求极致的ADC采样速度就要降低STM32的主频在配置ADC分频系数像这样
根据实际情况取舍就好
STM32 代码编写
g_sensor.c
#include "g_sensor.h"
uint16_t g_sensor_value[3] = {0};
uint16_t g_sensor_value_new[3] = {0};
uint8_t alpha = 0.1;
uint16_t gs_white_standar[3] = {0};
uint16_t gs_red_standar[3] = {0};
uint8_t gs_1_check = 0,gs_2_check = 0,gs_3_check = 0;
void ADC_Init(void)
{
HAL_ADCEx_Calibration_Start(&hadc1);
}
void G_Sensor_Read(void)
{
for(int i=0;i<3;i++)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1,0xffff);
g_sensor_value_new[i]=HAL_ADC_GetValue(&hadc1);
g_sensor_value[i] = g_sensor_value_new[i] * (1-alpha) + g_sensor_value[i] * alpha;
}
Red_Line_Check();
HAL_ADC_Stop(&hadc1);
}
void Line_Sensor_Check(void)
{
uint16_t sensor1_value = 0,sensor2_value = 0,sensor3_value = 0;
OLED_ShowString(0,0,(unsigned char *)"gs w check",16);
printf("g_sensor white line check\r\n");
do{}while(!Button_1_Check());
for(int i = 0;i<CHECH_TIMES;i++)
{
G_Sensor_Read();
sensor1_value += g_sensor_value[0];
sensor2_value += g_sensor_value[1];
sensor3_value += g_sensor_value[2];
}
gs_white_standar[0] = sensor1_value/CHECH_TIMES;
gs_white_standar[1] = sensor2_value/CHECH_TIMES;
gs_white_standar[2] = sensor3_value/CHECH_TIMES;
printf("white line check finish\r\n");
sensor1_value = 0;sensor2_value = 0;sensor3_value = 0;
printf("g_sensor red line check\r\n");
do{}while(!Button_1_Check());
for(int i = 0;i<CHECH_TIMES;i++)
{
G_Sensor_Read();
sensor1_value += g_sensor_value[0];
sensor2_value += g_sensor_value[1];
sensor3_value += g_sensor_value[2];
}
gs_red_standar[0] = sensor1_value/CHECH_TIMES;
gs_red_standar[1] = sensor2_value/CHECH_TIMES;
gs_red_standar[2] = sensor3_value/CHECH_TIMES;
printf("red line check finish\r\n");
}
void Red_Line_Check(void)
{
if( g_sensor_value[0] < (GS_1_WHITE_VALUE+GS_1_RED_VALUE) / 2)
{
gs_1_check = 1;
}
else
{
gs_1_check = 0;
}
if(g_sensor_value_new[1] < (GS_2_WHITE_VALUE+GS_2_RED_VALUE) / 2)
{
gs_2_check = 1;
}
else
{
gs_2_check = 0;
}
if(g_sensor_value_new[2] < (GS_3_WHITE_VALUE+GS_3_RED_VALUE) / 2)
{
gs_3_check = 1;
}
else
{
gs_3_check = 0;
}
}
g_sensor.h
#ifndef _G_SENSOR_H_
#define _G_SENSOR_H_
#include "stm32f1xx.h"
#include "adc.h"
#include "oled.h"
#include <stdio.h>
#include "button.h"
#define CHECH_TIMES 5
#define GS_1_WHITE_VALUE 2400
#define GS_2_WHITE_VALUE 2800
#define GS_3_WHITE_VALUE 2400
#define GS_1_RED_VALUE 1900
#define GS_2_RED_VALUE 2000
#define GS_3_RED_VALUE 1500
void ADC_Init(void);
void G_Sensor_Read(void);
void Line_Sensor_Check(void);
void Red_Line_Check(void);
#endif
使用说明:
- 在main.c的while前调用ADC_Init进行ADC校准
- 在定时器中断中调用G_Sensor_Read()函数即可连续读取传感器数值
|