下面的是程序,和仿真,是之前一位坛友分享的,我画了一个PCB,PCB的原理图如下:
#include<reg51.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int /***************引脚声明*********************/ #define lcd P0 sbit rs=P2^7; //LCD液晶控制端 sbit en=P2^6; sbit SPK=P1^7; //蜂鸣器引脚 sbit CS=P1^2; //将CS位定义为P1.2引脚 sbit CLK=P1^0; //将CLK位定义为P1.0引脚 sbit DIO=P1^1; //将DIO位定义为P1.1引脚 sbit key=P2^5; //定义按键引脚 sbit a=P2^0; //模拟量通道选择端 sbit b=P2^1; //模拟量通道选择端 sbit c=P2^2; //模拟量通道选择端
/***********LCD显示数组**************************/ uchar code table0[]=" DCV(0-5V) "; uchar table1[]=" V=0000.00 v"; uchar code table2[]=" DCI(0-100mA)"; uchar table3[]=" I=0000.00mA"; uchar code table4[]=" R(0-1k) "; uchar table5[]=" R=000.0 ";
/***************全局变量************************/ uchar flag=0; //换挡标志位
void delay(uint count) //延时 { uint i,j; for(i=0;i<count;i++) for(j=0;j<120;j++); }
/*************LCD1602驱动程序************************/ void w_cmd(uchar com) //lcd1602写命令 { rs=0; lcd=com; en=1; delay(5); en=0; }
void w_data(uchar dat) //lcd1602读数据 { rs=1; lcd=dat; en=1; delay(5); en=0; }
void w_str(uchar *s) //lcd1602写字符串 { while(*s) w_data(*s++); }
void init() //lcd1602初始化 { en=0; w_cmd(0x38); w_cmd(0x0c); w_cmd(0x06); w_cmd(0x01); }
/***************************************************** 函数功能:将模拟信号转换成数字信号 ***************************************************/ unsigned char A_D() { unsigned char i,dat; CS=1; //一个转换周期开始 CLK=0; //为第一个脉冲作准备 CS=0; //CS置0,片选有效 DIO=1; //DIO置1,规定的起始信号 CLK=1; //第一个脉冲 CLK=0; //第一个脉冲的下降沿,此前DIO必须是高电平 DIO=1; //DIO置1, 通道选择信号 CLK=1; //第二个脉冲,第2、3个脉冲下沉之前,DI必须跟别输入两位数据用于选择通道,这里选通道CH0 CLK=0; //第二个脉冲下降沿
DIO=0; //DI置0,选择通道0 CLK=1; //第三个脉冲 CLK=0; //第三个脉冲下降沿 DIO=1; //第三个脉冲下沉之后,输入端DIO失去作用,应置1 CLK=1; //第四个脉冲 for(i=0;i<8;i++) //高位在前 { CLK=1; //第四个脉冲 CLK=0; dat<<=1; //将下面储存的低位数据向右移 dat|=(unsigned char)DIO; //将输出数据DIO通过或运算储存在dat最低位 } CS=1; //片选无效 return dat; //将读书的数据返回 } /**********************报警程序************************/ void BaoJing(void) { uinti, j; for(i = 0; i < 200; i++) //产生脉冲使蜂鸣器发出声音 { SPK = 0; for (j = 0; j < 100; j++); SPK = 1; for (j = 0; j < 100; j++); } } /*********************按键判定************************************/ void keyscan() { if(key==0) //判断是否按下 { delay(10); if(key==0) { while(!key); flag++; if(flag>3)flag=0;
} } } /*******************定时器1初始化程序******************/ void Timer1_Init(void) // { TMOD=0x11; TH1= ( 65535 - 50000 ) / 256; //0.2ms TL1= ( 65535 - 50000 ) % 256; ET1=1; TR1=1; EA=1; } /*******************定时器1中断程序********************/ void Timer1 ( void ) interrupt 3 //定时器1中断函数 0.2ms { TH1= ( 65535 - 50000) / 256; TL1= ( 65535 - 50000 ) % 256; keyscan(); //按键判定 }
/*主函数*/ void main() { uint adval; unsigned long int temp; init(); //液晶初始化 Timer1_Init(); //定时器1初始化 while(1) {
if(flag==0) //直流电压测量 { c=0;b=0;a=0; //通道选择 w_cmd(0x80); w_str(table0); adval=A_D(); //进行A/D转换 temp=adval*5.0/255* 2*100; //转换成实际电压并放大100倍 if(temp>500) { BaoJing(); //超量程报警 w_cmd(0xc0+0x00); w_str(" V= .OL v "); delay(500); } else { table1[4]=temp/100000+0x30; table1[5]=temp%100000/10000+0x30; table1[6]=temp%10000/1000+0x30; table1[7]=temp%1000/100+0x30; table1[9]=temp%100/10+0x30; table1[10]=temp%10+0x30; w_cmd(0xc0+0x00); w_str(table1); delay(10); } }
if(flag==1) // 直流电流测量 { c=0;b=0;a=1; //通道选择 w_cmd(0x80); w_str(table2); adval=A_D(); //进行A/D转换 temp=adval*0.1/255*5000000/10; if(temp>10000) { BaoJing(); //超量程报警 w_cmd(0xc0+0x00); w_str(" I= .OL mA "); delay(500); } else { table3[4]=temp/100000+0x30; table3[5]=temp%100000/10000+0x30; table3[6]=temp%10000/1000+0x30; table3[7]=temp%1000/100+0x30; table3[9]=temp%100/10+0x30; table3[10]=temp%10+0x30; w_cmd(0xc0+0); w_str(table3);
delay(10); } } if(flag==2) // 电阻测量 { c=0;b=1;a=0; //通道选择 adval=A_D(); //进行A/D转换 temp=adval*1.0/(255-adval)*1000; if(temp>50000) { BaoJing(); //超量程报警 w_cmd(0xc0+0x00); w_str(" R= .OL k "); delay(500); } else { w_cmd(0x80); w_str(table4);
table5[4]=temp/1000+0x30; table5[5]=temp%1000/100+0x30; table5[6]=temp%100/10+0x30; table5[8]=temp%10+0x30; w_cmd(0xc0+0); w_str(table5); delay(10); } } } }
|