外观
七、ADC电压采集
1 电路分析
桌面温湿度仪使用两节5号电池用于整个系统供电,这里加入一个分压电阻用于检测电池电压。
注
使用两个10K对电压值进行分压,然后通过单片机ADC进行电压读取,对于3V电池,其实可以直接输入到单片机的IO口进行读取,但是大多数情况都是使用分压电阻来进行,这里我也不做改动。
2 代码编写
2.1 创建工程
2.2 设置参数
根据原理图,设置晶振引脚、下载引脚、移位寄存器控制引脚的参数;
注意打开ADC功能,否则不会生成实际ADC代码,相关设置基本不需要改动,将单次转换时间设置大一些,以获得更好的采样精度;
这里对一些参数进行说明:
- Clock Prescaler:设置ADC时钟频率,这个频率作用与所有ADC通道;
- Resolution:ADC转换分辨率;
- Data Alignment:选择转换后存储的数据的对齐方式;
- Sequencer:转换序列号配置(顺序采集或自行设置,只有ADC_IN0~ADC_IN14通道可自由配置,且最多配置8个通道);
- Scan Conversion Mode:启用或禁用扫描转换模式,启用扫描转换模式时转换次数为> 1;
- Continuous Convsion Mode:启用或禁用连续转换模式;
- Discontinous Conversion Mode:启用或禁用不连续转换模式;
- DMA Continuous Requests:仅当配置DMA请求时使用。否则就不相关了。当此ADC实例的DMA请求时,此参数指定DMA请求是在one shot模式下执行(当达到转换数量时DMA传输停止)还是在连续模式下执行(DMA传输无限制,无论转换数量如何)。注意:在连续模式下,DMA必须配置为循环模式。否则,当DMA缓冲区达到最大值指针时,将触发溢出。
- End Of Conversion Selection:选择何时转换结束;
- Overrun behaviour:选择数据溢出时处理;
- Low Power Auto Wait:低功耗动态等待,新的通道开始转换仅在旧通过转换完成后进行。
- Auto Off:自动休眠,ADC在没有转换时进入休眠,仅在转换时进行唤醒;
- Oversampling Mode:使用或禁用过采样模式;
- SamplingTime Common 1:设置一组通道的采样时间;
- Number Of Conversion: 常规通道转换组数量;
- External Trigger Conversion Source:选择用于触发开始转换常规组的外部事件;
- External Trigger Conversion Edge:触发边沿;
- Trigger Frequency:触发频率,不能小于转换时间。
将SN74HC595引脚设置为推挽输出、快速模式,同时依据原理图对其进行重命名,方便后续代码编写;
配置时钟树,这里主晶振没有使用外部而是内部晶振,外部低速晶振暂时没有使用,先不需要配置;
最后填写输出工程的名称,选择工程输出路径以及适配的IDE;
生成相关文件的.c与.h文件;
选择HAL库;
创建工程,随后打开,这个Cubemx软件就可以关闭了;
2.3 编译配置工程
正常应该是0错误0警告;
点击魔术棒,选择debug,选择合适的下载器,并配置下载器选项;
2.4 编写测试代码
在工程中,会增加一个adc文件,存放ADC相关初始化代码,重要的是ADC句柄,后续启动读取操作通过句柄来进行指定。 注意在gpio.c文件中添加数码管相关驱动代码,这些在之前的课程中都有介绍,我就不重复讲解了。
直接在main.c中添加ADC转换代码,这里配置的是软件触发,若像获得更高的精度,可以在初始化后进行ADC校准;
注
注意此处我们使用DAPLink进行测试,DAPLink是3.3V,所以转换的AD值是✖3.3V,后续使用电池供电是3V,需要进行修改。
且随着电池电压的降低,此处的测量精度也会逐渐下降,准确的测量应该是使用内部基准源做参考。
C
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t ADC_Value = 0;
float Data = 0;
uint16_t Vol_Value = 0;
/* 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_ADC1_Init();
/* USER CODE BEGIN 2 */
HAL_Delay(100);
SN74HC595_Send_Data(SN_DIG,0x00);
SN74HC595_Send_Data(SN_LED1,0x00);
SN74HC595_Send_Data(SN_LED2,0x00);
HAL_ADCEx_Calibration_Start(&hadc1); //ADC校准
HAL_ADC_Start(&hadc1); //启动ADC转换
HAL_ADC_PollForConversion(&hadc1, 50); //等待转换完成,50为最大等待时间,单位为ms
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))
{
ADC_Value = HAL_ADC_GetValue(&hadc1); //获取AD值
Data = (ADC_Value*3.3f)/4095.0f;
}
/* USER CODE END 2 */
Vol_Value = (uint16_t)(Data * 100)*2;
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
ShowNum(1,1,Vol_Value / 100);
ShowNum(1,2,Vol_Value /10 %10);
ShowNum(1,3,Vol_Value % 10);
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60