单片机学久了,就想动动手,实战一番
以下的这款这款电压电流表的制作文件,希望对大家有参考意义和帮助~
先看一下实际运行效果图:
PCB图:
原理图:
源码如下:
//stc12c5a60
#include<STC12C5A60S2.h>
#include<stdio.h>
#include<intrins.h>//头文件
#define uchar unsigned char//宏定义
#define uint unsigned int//宏定义
#define ulint unsigned long int//宏定义
#define N 21//ADC中值滤波次数,必须为基数
#define ISP_TRIG() ISP_TRIG=0x5A,ISP_TRIG=0xA5//ISP触发命令
sbit rs=P3^5;//液晶RS
sbit rw=P3^6;//液晶RW
sbit e=P3^4;//液晶E
void AD_init(void);//ADC初始化
void delay(uint z);//延时函数
uint AD_get(uchar haha );//读ADC的数值
void LCD_data(uchar shuju);//写数据
void zhiling(uchar zhilin);//写指令
void LCD_init(void);//初始化LCD
void tablex(uint tab);//数据分解
uint filter(uchar dat);//中值滤波
void timer_init(void);//定时器初始化
uchar h1,h2,h3,h4;//LCD显示变量
ulint mas,maz;//容量计算
uchar table[]="0123456789";//显示数组
uchar table1[]=".VAWa";
void main()
{
ulint tempv,tempa;//存放电压电流值
AD_init();//ADC初始化
timer_init();//定时器初始化
LCD_init();//LCD初始化
while(1)
{
tempv=filter(0x88);//设置ADC通道0、开始转换
tablex(tempv*3);//分解数据
zhiling(0x80);//LCD地址
LCD_data(table[h1]);//
LCD_data(table[h2]);//
LCD_data(table1[0]);//
LCD_data(table[h3]);//
LCD_data(table[h4]);//
LCD_data(table1[1]);//显示
tempa=filter(0x8f);//设置ADC通道7、开始转换
if(tempa<=10)//防止数据成负数
tempa=10;
mas=tempa*3-30;//计算容量取样赋值
tablex(tempa*3-30);//减去LM358失调的数值
zhiling(0x88);//LCD地址
LCD_data(table[h1]);
LCD_data(table1[0]);
LCD_data(table[h2]);
LCD_data(table[h3]);
LCD_data(table[h4]);
LCD_data(table1[2]);
tablex((tempv*3/10)*((tempa*3-30)/10)/10);//计算功率
zhiling(0x80+0x40);
LCD_data(table[h1]);
LCD_data(table[h2]);
LCD_data(table1[0]);
LCD_data(table[h3]);
LCD_data(table[h4]);
LCD_data(table1[3]);
tablex(maz/1000);//显示MAH
zhiling(0x88+0x40);
LCD_data(table[h1]);
LCD_data(table1[0]);
LCD_data(table[h2]);
LCD_data(table[h3]);
LCD_data(table[h4]);
LCD_data(table1[4]);
}
}
//-------------------------------------------------------------
void delay(uint z)///////////////延时程序
{
uint x,y;
for(x=z;x>0;x--)
for(y=19;y>0;y--);
}
void AD_init(void)/////////////////////初始化ADC
{
P1ASF=0xff;//P1口全部作为模拟功能AD使用
ADC_RES=0;//清零转换结果寄存器高8位
ADC_RESL=0;//清零转换结果寄存器低2位
ADC_CONTR=0x80;//开启AD电源
delay(5);//等待1ms,让AD电源稳定
}
uint AD_get(uchar haha )//ADC读数
{
uint rew;
ADC_CONTR=haha;//开启AD转换
_nop_(); _nop_(); _nop_(); _nop_();//要经过4个CPU时钟的延时
while(!(ADC_CONTR&0x10));//等待转换完成
ADC_CONTR&=0xe7;//关闭AD转换,ADC_FLAG位由软件清0
rew=ADC_RES*4+ADC_RESL;//组合成10位
delay(1);//等待
return rew;//返回ADC值
}
void zhiling(uchar zhilin)//写指令
{
e=0;
rs=0;
rw=0;
P0=zhilin;
delay(20);
e=1;
delay(20);
e=0;
}
void LCD_data(uchar shuju)//写数据
{
e=0;
rs=1;
rw=0;
P0=shuju;
delay(20);
e=1;
delay(20);
e=0;
}
void LCD_init(void)//初始化LCD
{
delay(300);
zhiling(0x38);
delay(100);
zhiling(0x38);
delay(100);
zhiling(0x38);
delay(100);
zhiling(0x38);
zhiling(0x38);
zhiling(0x08);
zhiling(0x01);
zhiling(0x06);
zhiling(0x0c);
}
void tablex(uint tab1)//数据分解
{
h1=tab1/1000;//1023//1
h2=tab1%1000/100;//023//0
h3=tab1%100/10;//23//2
h4=tab1%10;//3
}
uint filter(uchar dat)//中位值滤波
{
uint value_buf[N];
uint count,i,j,temp;
for(count=0;count<N;count++)
{
AD_init();//初始化ADC
value_buf[count] = AD_get(dat);//读ADC数值
delay(1);
}
for (j=0;j<N-1;j++)
{
for (i=0;i<N-j;i++)
{
if ( value_buf[i]>value_buf[i+1] )
{
temp = value_buf[i];
value_buf[i] = value_buf[i+1];
value_buf[i+1] = temp;
}
}
}
return value_buf[(N-1)/2];
}
void timer_init(void)//定时器初始化
{
TMOD=0x01;/////////设置工作方式1
TH0=(65536-50000)/256;///////赋值
TL0=(65536-50000)%256;
EA=1;ET0=1;//开总中断;开定时器中断
TR0=1;////////启动计数器
}