一、系统方案
1、本设计采用这STM32单片机作为主控器。
2、液晶1602显示。
3、内部ADC采集电压0-12V,自动切换档位。
二、硬件设计
原理图如下:
三、单片机软件设计
1、首先是系统初始化
u8 i;
u16 a,b,c,d;
u16 adcx;
float adc;
unsigned char datas[4];
InitGPIO();
LcdInit();
Adc_Init();
LcdWriteCom(0xc0); //设置数据指针起点
for(i=0;i<16;i++)
{
LcdWriteData(Disp_Vol[i]);
}
2、液晶显示程序
/*******************************************************************************
- 函 数 名 : LcdWriteCom
- 函数功能 : 向LCD写入一个字节的命令
- 输 入 : com
- 输 出 : 无
/
void LcdWriteCom(uchar com) //写入命令
{
// LCD1602_E = 0; //使能
GPIO_ResetBits(GPIOB,GPIO_Pin_3);
// LCD1602_RS = 0; //选择发送命令
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
// LCD1602_RW = 0; //选择写入
GPIO_ResetBits(GPIOB,GPIO_Pin_2);
// LCD1602_DATAPINS = com; //放入命令
GPIO_Write(GPIOC,0X00FF&com);
Lcd1602_Delay1ms(1); //等待数据稳定
// LCD1602_E = 1; //写入时序
GPIO_SetBits(GPIOB,GPIO_Pin_3);
Lcd1602_Delay1ms(5); //保持时间
// LCD1602_E = 0;
GPIO_ResetBits(GPIOB,GPIO_Pin_3);
}
/ - 函 数 名 : LcdWriteData
- 函数功能 : 向LCD写入一个字节的数据
- 输 入 : dat
- 输 出 : 无
*******************************************************************************/
void LcdWriteData(uchar dat) //写入数据
{
// LCD1602_E = 0; //使能清零
GPIO_ResetBits(GPIOB,GPIO_Pin_3);
// LCD1602_RS = 1; //选择输入数据
GPIO_SetBits(GPIOB,GPIO_Pin_1);
// LCD1602_RW = 0; //选择写入
GPIO_ResetBits(GPIOB,GPIO_Pin_2);
// LCD1602_DATAPINS = dat; //写入数据
GPIO_Write(GPIOC,0X00FF&dat);
Lcd1602_Delay1ms(1);
// LCD1602_E = 1; //写入时序
GPIO_SetBits(GPIOB,GPIO_Pin_3);
Lcd1602_Delay1ms(5); //保持时间
// LCD1602_E = 0;
GPIO_ResetBits(GPIOB,GPIO_Pin_3);
}
3、ADC程序
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)
{
//设置指定ADC的规则组通道,一个序列,采样时间
ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期
ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果
}
u16 Get_Adc_Average(u8 ch,u8 times)
{
u32 temp_val=0;
u8 t;
for(t=0;t<times;t++)
{
temp_val+=Get_Adc(ch);
delay_ms(5);
}
return temp_val/times;
}
4、核心算法程序
int main(void)
{
u8 i;
u16 a,b,c,d;
u16 adcx;
float adc;
unsigned char datas[4];
InitGPIO();
LcdInit();
Adc_Init();
LcdWriteCom(0xc0); //设置数据指针起点
for(i=0;i<16;i++)
{
LcdWriteData(Disp_Vol[i]);
}
while(1)
{
adcx=Get_Adc_Average(ADC_Channel_1,10);
adc=(float)adcx*(5.0/4096);
adcx=adc;
a=adcx;
adc-=adcx;
adcx=adc*100; //1位有效数字
b=adcx;
c=a*100+b;
d=c*24/10;
if(d<500)
{
LcdWriteCom(0x80); //设置数据指针起点
for(i=0;i<16;i++)
{
LcdWriteData(Disp_Vol1[i]);
}
}
else
{
LcdWriteCom(0x80); //设置数据指针起点
for(i=0;i<16;i++)
{
LcdWriteData(Disp_Vol2[i]);
}
}
LcdWriteCom(0xc9);
LcdWriteData('0'+d/1000);
LcdWriteData('0'+d%1000/100);
LcdWriteCom(0xcc);
LcdWriteData('0'+d%1000%100/10);
LcdWriteData('0'+d%10);
}
}
四、 proteus仿真设计
Proteus软件是一款应用比较广泛的工具,它可以在没有硬件平台的基础上通过自身的软件仿真出硬件平台的运行情况,这样就可以通过软件仿真来验证我们设计的方案有没有问题,如果有问题,可以重新选择器件,连接器件,直到达到我们设定的目的,避免我们搭建实物的时候,如果当初选择的方案有问题,我们器件都已经焊接好了,再去卸载下去,再去焊接新的方案的器件,测试,这样会浪费人力和物力,也给开发者带来一定困惑,Proteus仿真软件就很好的解决这个问题,我们在设计之初,就使用该软件进行模拟仿真,测试,选择满足我们设计的最优方案。最后根据测试没问题的仿真图纸,焊接实物,调试,最终完成本设计的作品。