基于stm32的简易电压表## 简易电压表
这是一个基于STM32F1系列的简易的电压表,可以测量0-12电压。并显示在0.96存4脚的OLED上。
一、外围电路
STM32的ADC引脚只能承受3.3V,所以要额外搭建一个降压电路,就是把要测量的电压值将到3.3V以下,然后通过比例计算出当前的电压。这里只用到两三个电阻,按照串联降压的特性计算。(U a = 1/2U)
二、SMT32程序
利用32的ADC模数转换器(12位)采集要测量的电压值,再通过冒泡排序得到一个平均值即可。
void ADC_Sampling (void)
{
u16 ADC1_ConvertedValueTab[CodeSize];
u16 ADC2_ConvertedValueTab[CodeSize];
u16 temp2; // 排序中间变量
u16 adcx[2]; // 数字电压值
u8 i,j,count; // 循环变量
u32 sum[2] = {0LU}; // 求和值
for (count = 0; count < CodeSize; count ++) // 采样N个数据
{
ADC1_ConvertedValueTab[count] = 0;
ADC2_ConvertedValueTab[count] = 0;
}
for (count = 0; count < CodeSize; count ++) // 采样CodeSize个数据
{
ADC_SoftwareStartConvCmd(ADC1,ENABLE); // 启动AD采样
ADC_SoftwareStartConvCmd(ADC2,ENABLE); // 启动AD采样
while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)); // 等待AD转换完成
while(!ADC_GetFlagStatus(ADC2,ADC_FLAG_EOC));
ADC_ClearFlag(ADC1,ADC_FLAG_EOC); // AD转换完成,清除标志位
ADC_ClearFlag(ADC2,ADC_FLAG_EOC);
ADC1_ConvertedValueTab[count]=ADC_GetConversionValue(ADC1);
ADC2_ConvertedValueTab[count]=ADC_GetConversionValue(ADC2);
}
for (j = 0; j < CodeSize - 1; j ++) // 冒泡排序
{
for (i = 0; i < CodeSize - j; i ++)
{
if (ADC1_ConvertedValueTab[i] > ADC1_ConvertedValueTab[i + 1])
{
temp2 = ADC1_ConvertedValueTab[i];
ADC1_ConvertedValueTab[i] = ADC1_ConvertedValueTab[i + 1];
ADC1_ConvertedValueTab[i + 1] = temp2;
}
}
}
for (j = 0; j < CodeSize - 1; j ++) // 冒泡排序
{
for (i = 0; i < CodeSize - j; i ++)
{
if (ADC2_ConvertedValueTab[i] > ADC2_ConvertedValueTab[i + 1])
{
temp2 = ADC2_ConvertedValueTab[i];
ADC2_ConvertedValueTab[i] = ADC2_ConvertedValueTab[i + 1];
ADC2_ConvertedValueTab[i + 1] = temp2;
}
}
}
for(count = 3; count < CodeSize - 3; count ++) // 去除低三位和高三位 余下求和
{
sum[0] += ADC1_ConvertedValueTab[count]; // 求和
sum[1] += ADC2_ConvertedValueTab[count];
}
adcx[0] = (u16)(sum[0] / (CodeSize - 6)); // 取平均值
adcx[1] = (u16)(sum[1] / (CodeSize - 6)); // 取平均值
AnalogVoltage[0] = (adcx[0] * 3300 / 4095); // 求出模拟电压值 mv
AnalogVoltage[1] = (adcx[1] * 3300 / 4095);
}
三、OLED显示
void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 size)
{
//在指定地方显示一个字符,包括部分字符
u8 c=0,i=0;
c=chr-' ';
if(x>127)
{
x=0;
y=y+2;
}
if(size == 16)
{
OLED_Set_Pos(x,y);
for(i=0;i<8;i++)
{
OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
}
OLED_Set_Pos(x,y+1);
for(i=0;i<8;i++)
{
OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
}
}
else
{
OLED_Set_Pos(x,y);
for(i=0;i<6;i++)
{
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
}
}
}
void OLED_ShowStr(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
unsigned char c = 0,i = 0,j = 0;
switch(TextSize)
{
case 1:
{
while(ch[j] != '\0')
{
c = ch[j] - 32;
if(x > 126)
{
x = 0;
y++;
}
//OLED_SetPos(x,y);
OLED_Set_Pos(y,x);
for(i=0;i<6;i++)
OLED_WR_Byte(F6x8[c][i],OLED_DATA);
x += 6;
j++;
}
}break;
case 2:
{
while(ch[j] != '\0')
{
c = ch[j] - 32;
if(x > 120)
{
x = 0;
y++;
}
//OLED_SetPos(x,y);
OLED_Set_Pos(y,x);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i],OLED_DATA);
//OLED_SetPos(x,y+1);
OLED_Set_Pos(y+1,x);
for(i=0;i<8;i++)
OLED_WR_Byte(F8X16[c*16+i+8],OLED_DATA);
x += 8;
j++;
}
}break;
}
}
void OLED_ShowString(u8 x,u8 y,u8 *chr,u8 size)
{
//显示一个汉字串和字符号串
u8 x0=x;
u16 k;
while(*chr!='\0')
{
if((*chr)<128)
{
if(*chr==13)
{
x=x0;
y+=size/8;
}
else
{
OLED_ShowChar(x,y,*chr,size);
x+=8;
if(x>120)
{
x=0;
y+=size/8;
}
}
chr++;
}
else if(size==16) //字体是否为16
{
for(k=0;k<hz16_num;k++) //汉字搜索
{
if ((hz16[k].Index[0]==*(chr))&&(hz16[k].Index[1]==*(chr+1))) //是否是已登记汉字
{
u8 t;
OLED_Set_Pos(x,y);
for(t=0;t<16;t++)
{
OLED_WR_Byte(hz16[k].Msk[t],OLED_DATA);
}
OLED_Set_Pos(x,y+1);
for(t=0;t<16;t++)
{
OLED_WR_Byte(hz16[k].Msk[t+16],OLED_DATA);
}
}
}
if(x>112)
{
x=0;
y+=2;
}
chr+=2;x+=16;
}
else //输入错误,忽略汉字
{
chr+=2;
}
}
}
总结说明、
这是在做学校的综合制作的,小白一个,就想试一下,最后还是实现了0-12V的电压测量,可以支持直流和交流、测交流的时候只需要将交流转成直流的电压值接入即可,这里用到AD637,最后测了一下,误差大概在3%,可以在综合制作课里通过。