利用STM32开发板制作简易电压表
开发板电压表制作教程
1、需要材料
- STM32芯片的开发板
- SPI通讯协议的0.96寸OLED显示屏
- 导线若干
2、配置开发板硬件
(1)初始化ADC模块
- 可以去看我之前的帖子,这里就不过多赘述该步骤了
(2)配置SPI通讯模块
I(粘贴)
- OLED显示屏的厂商一般会提供显示屏的驱动,我们需要将代码复制粘贴到自己的项目中
II(移植)
如果是硬件SPI驱动的可以忽略该步骤
- 由于厂商提供给我的驱动是软件模拟的,所以需要根据开发板的实际情况改动宏定义
![img]()
- 这里我们选择
PA1作为SCL端,PC2作为SDA端,PC3作为RES端,PA4作为DC端,PA5作为CS端
![img]()
- 根据原理图进行接线
PA1
PC2,PC3
PA4
PA5
- 根据找到的管脚进行接线
![img]()
- 在驱动代码中宏定义的部分重构
#define OLED_SCLK_Clr() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET)//CLK
#define OLED_SCLK_Set() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET)
#define OLED_SDIN_Clr() HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET)//DIN
#define OLED_SDIN_Set() HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET)
#define OLED_RST_Clr() HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET)//RES
#define OLED_RST_Set() HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET)
#define OLED_DC_Clr() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)//DC
#define OLED_DC_Set() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)
#define OLED_CS_Clr() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET)//CS
#define OLED_CS_Set() HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET)
#define OLED_CMD 0 //写命令
#define OLED_DATA 1 //写数据
3、写入代码
(1)定义变量
- 在主函数外侧定义全局变量
/* USER CODE BEGIN 0 */
uint32_t ADC_Value;//ADC模块的采样值
uint32_t Voltage;//计算后的电压值
/* USER CODE END 0 */
(2)初始化硬件
- 在主循环外则写入以下内容
/* USER CODE BEGIN 2 */
OLED_Init();//OLED厂商提供的库函数,用于完成OLED的初始化
//启用ADC模块
HAL_Delay(10);//等待ADC模块稳定
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
OLED_ShowString(0, 4, "Simple Voltmeter", 1);//显示字符串,表明该程序为"简易电压表"
HAL_Delay(999);//显示1秒
OLED_Clear();//OLED厂商的库函数,用于清屏
(3)计算并显示结果
I计算浮点数
- 由于库函数中不支持直接显示浮点数,所以我们需要手写一个显示浮点数的函数
- 具体过程为:将采样值乘1000,分别计算出整数位和小数点后三位,用小数点隔开后依次显示
- 在
adc.h中声明该函数
/* USER CODE BEGIN Prototypes */
uint32_t ADC_Analyse(uint32_t value);//用于计算去掉小数点后电压的函数
/* USER CODE END Prototypes */
- 在
adc.c中定义该函数
/* USER CODE BEGIN 1 */
//用于计算去掉小数点后电压的函数,需要参数value,返回去掉小数点的电压值
uint32_t ADC_Analyse(uint32_t value){
uint32_t Voltage;
value *= 3150;//最大采样电压
Voltage = value / 4096;
return Voltage;
}
计算方法为:
- 在主循环内写入以下内容
while (1)
{
//启动ADC模块,不然采样值会保持以一次的结果
HAL_Delay(10);
HAL_ADC_Start(&hadc1);
ADC_Value = HAL_ADC_GetValue(&hadc1);//获取采样值
Voltage = ADC_Analyse(ADC_Value);//计算去掉小数点后的电压值
//依次输出电压值的各位数
OLED_ShowNum(4, 4, (Voltage / 1000), 1, 3);
OLED_ShowChar(12, 4, '.');//用小数点隔开整数和小数位
Voltage = Voltage - (Voltage / 1000) * 1000;
OLED_ShowNum(20, 4, (Voltage / 100), 1, 3);
Voltage = Voltage - (Voltage / 100) * 100;
OLED_ShowNum(28, 4, Voltage, 1, 3);
Voltage = Voltage - (Voltage / 10) * 10;
OLED_ShowNum(36, 4, Voltage, 1, 3);
OLED_ShowChar(44, 4, 'V');//显示单位
HAL_Delay(989);//显示1秒
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
II滤波
- 编译并烧录代码后,已经能显示电压了,但显示的结果会一直会产生很大的变动,这就需要写入滤波算法了
- 考虑到要测量不同的目标,这里采用算术平均滤波
算术平均滤波
- 重构主循环的内容,加上滤波的算法
/* USER CODE BEGIN WHILE */
while (1)
{
ADC_Value = 0;//清空采样值
for(uint8_t i = 0; i < 10; i++){
uint16_t Value;//定义单次采样值
HAL_Delay(10);
HAL_ADC_Start(&hadc1);
Value = HAL_ADC_GetValue(&hadc1);
ADC_Value += Value;//自加
}
ADC_Value /= 10;//除去样本数,得出采样平均值
Voltage = ADC_Analyse(ADC_Value);
- 将加入滤波的程序编译并烧录后,测试相应的电压显示的结果就会相对稳定了
3、实验效果
- 在开发板启动的并完成初始化后,屏幕会产生
Simple Voltmeter的字符串
![img]()
- 1秒后,会开始显示电压
测量干电池电压

实际测量的干电池电压
流程图

4、代码清单
OLED.h
void OLED_Init(void);//初始化屏幕
void OLED_Clear(void);//清屏
void OLED_ShowCHinese(u8 x,u8 y,u8 no,u8 mod);//显示汉字,需要x,y坐标,汉字的编码,字体大小
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 mod);//显示字符串,需要x,y坐标,字符串,字体大小
void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size);//显示数字,需要x,y坐标,数字,位数,字体大小
ADC.c
//计算出去掉小数点的,精确到小数点后三位的电压值,需要采样值作为参数
uint32_t ADC_Analyse(uint32_t value){
uint32_t Voltage;
value *= 3300;
Voltage = value / 4096;
return Voltage;
}












浙公网安备 33010602011771号