交直流电压及测频板(单片机)

来源:互联网 发布:access2003数据库 编辑:程序博客网 时间:2024/03/19 18:50
   功能:按键8个,测频计数,交流电压 ,直流电压,及相应保护判断亮灯指示,用ST7920-12864液晶显示  
  硬件:测频计数用到  单运放迟滞比较器、555波形陡处理、 CD4013做的D触发器;交流电压用到 
             LM358单运放半波整流,输出加一级RC滤波.调节运放可以调节电压、AD转换芯片TLC1543(0-5V)。
             直流电压就没嘛说的,电阻分压就行了。
            按键用74HCT245双向数据芯片,蛮好。
            继电器控制,液晶并口数据线,保护灯,按键都是用P0口,用74HC573锁存切换,AD转换口用P1口。计数用T0  INT0  INT1 ,其他的控制脚接P2口,所以没有做单片机口扩展,那样到更麻烦些
    补充:灯光显示和继电器的74HC573控制脚接到反向器74HC04,加大驱动能力。
   备注:由于硬件电路做的简单,所以,程序繁琐,待优化中。。。。。。。。。。。。。
上个仿真的类似图,液晶没找到,用的数码管。
  
交直流电压及测频板(单片机) - 少占鱼-网易 - 少占鱼

交直流电压及测频板(单片机) - 少占鱼-网易 - 少占鱼

交直流电压及测频板(单片机) - 少占鱼-网易 - 少占鱼


交直流电压及测频板(单片机) - 少占鱼-网易 - 少占鱼

     /********关于多周期测频法,精度与晶振和闸门时间有关。晶振越大,闸门时间越长,都可以提高精度。**********/
#include <stc89c52.h>
#include <intrins.h>
#define uchar  unsigned char
#define uint  unsigned int
#define LCD12864_IO    P0
#define CLERADISPLAY   LCD12864_command(0x01);
int a1=0,a2=0,a3=0,a4=0,a5=0,a6=0;//存储电压值的每一位,设计a4,a5是小数位. 
const uchar num[]="0123456789. ";

//AD转换控制脚 
sbit  CLK = P1^0; //TLC1543 18P
sbit  ADDRESS = P1^1; //17P
sbit  SDATA = P1^2; //16P
sbit  CS  = P1^3; //15P 
/********************************************************************/
sbit LCD12864_RS=P2^5;  // 12864-st7920 4P RS 
sbit LCD12864_RW=P2^6;  //RW(5P) 
sbit LCD12864_EN=P2^7;   //E(6P)    
/********************************************************************/
void LCD12864_busy(void);
void LCD12864_command(unsigned char command);
void LCD12864_data(unsigned char dat);
void LCD12864_address(unsigned char row,unsigned char line);
void LCD12864_string(unsigned char row,unsigned char line,unsigned char *s);
void LCD12864_picture(unsigned char *gImage);
void LCD12864_init(void);
void LCD12864_char (unsigned char row,unsigned char line,unsigned char a);
unsigned char LCD12864_ReadData();
void LCD12864_Drawpoint(uchar X,uchar Y);
void LCD12864_LineX(unsigned char X0, unsigned char X1, unsigned char Y);
void LCD12864_LineY( unsigned char X, unsigned char Y0, unsigned char Y1);
void LCD12864_DrawPicture( unsigned char code *pic);
void clrgdram();
/********************************************************************/
//
double DAT[7]={115.0, 115.1, 115.2, 285.0,1500.0, 400.0,3100.0};
//       U     V      W      E     N     F   CINT     
// 控制脚 
sbit CONTRL=P1^7; //测频控制脚 
sbit SCANF =P2^0; //键盘扫描控制脚 
sbit LED1  =P2^1; //状态显示控制脚1 
sbit LED2  =P2^2; //状态显示控制脚2 
sbit SHUCHU=P2^3; //继电器输出控制脚 
//
bit FLAG; //测频标志位
bit xunhuanflag;//显示方式标志位 
bit outflag; //允许输出标志 
bit  eding;//额定状态标志   
// 按键存储   
bdata uchar key; //键值存储 
sbit key0=key^0;//停机    
sbit key1=key^1;//启动按钮 
sbit key2=key^2; //显示方式(高循环) 
sbit key3=key^3; //自检    
sbit key4=key^4;//灯检   
sbit key5=key^5;//复位    
sbit key6=key^6;//应急  (高应急)  
sbit key7=key^7;//油压(高有油压)    
uint t1h,t1l,t2h,t2l;//测频变量 
double cnt1,cnt2;
double AD; //定义为float 类型,可以防止下面做四则运算时每一步的值超出 范围 
unsigned long int  X;
/****************************************************************/         
uint rd1543(uchar address);//AD转换程序 
void voltage(); //电压检测 
void init();   //初始化 
void zhuansu();   //计算转速 
void reset();//测频计数定时复位 
uchar scanf(); //键盘扫描 
void keychuli();  //按键处理程序 
void baohu();
void display(unsigned long int sx); //显示函数 
void displayFX(unsigned long int sx);
/*************************************************************/
void delayus(uint);
void delayms(uint);
void delays(uint m); //延时秒 

unsigned char code Bmp019[]=
{
/*------------------------------------------------------------------------------
;  若数据乱码,请检查字模格式设置,注意选择正确的取模方向和字节位顺序。
;  源文件 / 文字 : C:\Documents and Settings\Administrator\桌面\888.bmp字模
;  宽×高(像素): 128×64
;  字模格式/大小 : 单色点阵液晶字模,横向取模,字节正序/1024字节
;  数据转换日期  : 2010-7-26 20:46:48
------------------------------------------------------------------------------*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0xF8,0x00,0x00,0x00,0x3E,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x08,0x00,0x00,0x00,0x03,0x00,0x08,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
0x00,0x00,0x08,0x00,0x00,0x00,0x02,0x00,0x08,0x00,0x00,0x00,0x08,0x08,0x00,0x00,
0x00,0x20,0x18,0x00,0x00,0x00,0x08,0x00,0x1F,0x80,0x00,0x00,0x08,0x1F,0x80,0x00,
0x00,0x3D,0xF8,0x00,0x08,0x00,0x08,0xE0,0x02,0x00,0x00,0x7F,0xFF,0x00,0x80,0x00,
0x00,0x38,0x38,0x00,0x18,0x00,0x00,0x30,0x02,0x00,0x00,0x80,0x00,0x00,0x80,0x00,
0x00,0x30,0x08,0x01,0xF0,0x00,0x20,0x30,0x0F,0xF8,0x00,0x80,0x0F,0xE0,0x80,0x00,
0x00,0x30,0x38,0x00,0xFC,0x30,0x20,0xE0,0x83,0x80,0x00,0x00,0x00,0x20,0x00,0x00,
0x00,0x3F,0xF8,0x00,0x0C,0x30,0x01,0xE0,0x00,0xF0,0x00,0x02,0x00,0x20,0x00,0x00,
0x00,0x30,0x18,0x66,0xBF,0xF0,0x00,0xE0,0x0F,0xE0,0x00,0x07,0xFF,0xC0,0x00,0x00,
0x00,0x30,0x18,0x3F,0xFF,0xF0,0x00,0xC0,0x38,0x20,0x00,0x00,0x22,0x00,0x00,0x00,
0x00,0x20,0x00,0x00,0x00,0x30,0x00,0x80,0x00,0x00,0x00,0x00,0x83,0x00,0xFC,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xFF,0xFE,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xFF,0xF0,0x00,0x7F,0xFF,0xFC,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xFF,0xC3,0xF0,0x00,0x03,0xE0,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xFF,0x8C,0x00,0x00,0x00,0x03,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xFE,0x00,0x03,0xFF,0xE0,0x0F,0xFF,0x87,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xFE,0x00,0xFF,0xFF,0xFE,0x1F,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xFE,0x03,0xFF,0xFF,0xFF,0x1F,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0x1F,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0x87,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x81,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0x83,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x7F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFC,0x00,0x03,0xFF,0xFF,0xFD,0x80,0x0F,0xF8,0x1F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xF8,0x00,0x03,0xFF,0xFF,0xF8,0xFF,0x87,0xFC,0x0F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xF8,0x03,0xFF,0xFF,0xFF,0xFF,0x00,0x1F,0xFE,0x0F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xF8,0x7F,0xF0,0x0F,0xFF,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xF8,0x3F,0xF0,0x1F,0xFF,0xFF,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0x87,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x83,0xC0,0xFF,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x07,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFF,0xFF,0xFC,0x07,0xFF,0xC3,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xFE,0x03,0xFF,0xFF,0xFF,0xFF,0xF0,0x3F,0xFF,0xE1,0xFF,0xFF,0xC0,
0x03,0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFF,0xC3,0xFF,0xFF,0xE1,0xFF,0xFF,0xC0,
0x03,0x01,0xFF,0xF0,0x7F,0x03,0xFF,0xFF,0xFF,0xFF,0xF0,0x00,0x03,0xFF,0xFF,0xC0,
0x00,0x00,0x00,0x03,0xFD,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x3F,0xFF,0xFF,0xFF,0xC0,
0x00,0x3F,0x00,0x3F,0x80,0xFF,0xFF,0xFF,0xFF,0x10,0x1F,0xFF,0xFF,0xFF,0xFF,0xC0,
0x02,0x1F,0xFF,0xFE,0x03,0xFF,0xFF,0xFF,0xFE,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,
0x03,0x81,0xF8,0x00,0x03,0xFF,0xFF,0xFF,0xFE,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
//
 void delayms(uint k)
 {
uint data i,j;
for(i=0;i<k;i++)
  {
    for(j=0;j<121;j++)
     {;}
   }
 }
 //
void delayus(uint x)      
 {
    while(--x);
 }
 /***********************/
 void delays(uint m)
{
uint i,j;
for(i=0;i<m;i++)
  {
   for(i=0;i<1000;i++)
  {
    for(j=0;j<121;j++)
     {;}
   }
   }
}
 

void Mcu_init(void)
{
 
 LCD12864_init();
 
 
 CLERADISPLAY  
 CLERADISPLAY  
 LCD12864_init();
}

/*******************************************************************/
void LCD12864_busy(void)
{
    bit BF = 0;
    LCD12864_EN=0; 
    LCD12864_RS=0;
    LCD12864_RW=1;
    LCD12864_IO=0xff;  //单片机读数据之前必须先置高位
    do
    {
     LCD12864_EN=1;
        BF=LCD12864_IO&0x80;
        LCD12864_EN=0;
    } while(BF);
    
}
/*******************************************************************/
//          写入命令  
/*******************************************************************/
void LCD12864_command(unsigned char command)
{
    LCD12864_busy();
    LCD12864_EN=0;
    LCD12864_RS=0;
    LCD12864_RW=0;  
   LCD12864_IO=0xff;
    LCD12864_EN=1;
    LCD12864_IO=command;
    LCD12864_EN=0;
}

//读数据函数
unsigned char LCD12864_ReadData()
{
  unsigned char read_data;
   LCD12864_busy();
    LCD12864_IO=0xff;
 LCD12864_RS=1;
 LCD12864_RW=1;
 LCD12864_EN=0;
 LCD12864_EN=1;
 read_data=LCD12864_IO;
    LCD12864_EN=0;
    
 return(read_data);
}
/*******************************************************************/
//          写入一字节数据
/*******************************************************************/
void LCD12864_data(unsigned char dat)
{
   
    LCD12864_busy();
    LCD12864_EN=0;
    LCD12864_RS=1;
    LCD12864_RW=0;
    LCD12864_IO=0xff;
    LCD12864_EN=1;
    LCD12864_IO=dat;
    LCD12864_EN=0;
}

/*******************************************************************/
//          设置显示位置    row(1~4),line(1~8)
/*******************************************************************/
void LCD12864_address(unsigned char row,unsigned char line)
{
    switch(row) 
    {
        case 1:LCD12864_command(0x7f + line);
        break;
        case 2:LCD12864_command(0x8f + line);
        break;
        case 3:LCD12864_command(0x87 + line);
        break;
        case 4:LCD12864_command(0x97 + line);
        default:
        break;
    }
}
 /*****************显示 一个 字符  **************/
  void LCD12864_char (unsigned char row,unsigned char line,unsigned char a)

 
    LCD12864_address(row,line); 
    LCD12864_data(a);
}
/*******************************************************************/
//          在指定位置显示字符串
/*******************************************************************/
void LCD12864_string(unsigned char row,unsigned char line,unsigned char *s)

    unsigned char LCD12864_temp; 
    LCD12864_address(row,line); 
    LCD12864_temp=*s;
    while(LCD12864_temp != 0x00) 
    { 
        LCD12864_data(LCD12864_temp);
        LCD12864_temp=*(++s);
    }  
}
/****************************
0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 上半屏行坐标,表示的是多少列 
0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 下半屏行坐标,每组8列,每列16位,共128位, 
0x80
0x81
0x82
0x83
........
0x9f    //列坐标,共32个,表示的是行数 ,分两个半屏,每个32行,共64行 
         //Y坐标 只是用来确定具体坐标,在哪一行    
   功能:图形模式下,显示(X,Y)点    
        输入:X(0~127) Y(0~63) 相对屏幕坐标  
        输出:无
点亮某一点的操作步骤: 1.求出水平坐标X对应的地址和是哪一位  0x80-----0x8f  (范围0-15) X/16求地址 X%16求该地址哪一位
         2.求垂直坐标Y对应的地址和上下半屏  0x80------0x9f(范围0-63) Y本身就是8位地址,Y=63-Y ,Y--(0-31)
         3.写入行列地址(Y是行X是列),0x80+Y  ,0X80+X/16
                       4.读要显示的数据 DAT
                       5.区分上下半屏(X%16<=7&&X%16>=0是上半屏)写入数据每一位 DAT|0x80 ;DAT<<1
             注意:这个函数显示某一点时,可能会把上次显示的处于同一地址的其他位的点擦掉,所以先保存所有数据,最后显示,就连贯起来了

 *******************************/
/*******************************************************************/
  /**************************************************************/
//------------------清整个GDRAM空间----------------------------
/**************************************************************/
void clrgdram()
{
    unsigned char x,y ;
    for(y=0;y<64;y++)
    for(x=0;x<16;x++)
    {
       LCD12864_command(0x34);
       LCD12864_command(y+0x80);
       LCD12864_command(x+0x80);
       LCD12864_command(0x30);
      LCD12864_data(0x00);
      LCD12864_data(0x00);
    }
}
/******************************************/
/*******8==========================================================================
功能:图形模式下,显示(X,Y)点    
输入:X(0~127) Y(0~63)     
输出:无  
0x80 0x81 0x82 0x83 0x84 0x85 0x86 0x87 上半屏行坐标,表示的是多少列,X地址 
0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 下半屏行坐标,X地址 (水平地址 )     
0x80  (垂直地址) 
0x81
0x82
0x83
........
0x9f    //列坐标,共32个,表示的是行数 ,分两个半屏,每个32行,共64行 
====================================================================**********/   
void LCD12864_Drawpoint(uchar X,uchar Y)
{
     uchar i= 0, j = 0,ok=0;
     uchar temp1 = 0x00,temp2 = 0x00;   
     LCD12864_command(0x34);  //8位,扩充指令,绘图关 
     LCD12864_command(0x36);  //8位,扩充指令,绘图开 
     i = X/16;  //计算出X字节地址(0X80-0X8F) 
     j = X%16;  //计算出该字节的具体位(0-15)       
     //Y = 63 - Y;
   if(Y>=0 && Y<=31)//判断上下半屏 
      {
        ok=1;
      }
   else if(Y>=32 && Y<=63)//下半屏
     {
       Y = Y - 32;//Y只有0-31共32个 地址 
       i = i + 8;//X地址进入下半屏 (0X88-0X8F)
    ok=1;
     }
      
   if(ok)
    { 
     //读数据操作
        LCD12864_command(0x80+Y);   //第一步:设置Y坐标,读数据先写地址,写GDRAM时先写垂直地址(0X80-0X9F)
        LCD12864_command(0x80+i);  //第二步:设置X坐标   
        LCD12864_ReadData();    //第三步:空读取一次   
        temp1 =LCD12864_ReadData();    //第四步:读取高字节,先读高字节 
        temp2 =LCD12864_ReadData();   //第五步:读取低字节    
          //图形模式下的写数据操作    
        LCD12864_command(0x80+Y);    //第一步:设置Y坐标  
        LCD12864_command(0x80+i);   //第二步:设置X坐标  
         if(j>=0 && j<=7)   //判断是高字节 
          {  
         LCD12864_data(temp1|(0x80>>j));  //第三步:写高字节数据  
         LCD12864_data(temp2);      //第四步:写低字节数据     
          }
         else if(j>7 && j<=15)   //判断是低字节 
           {   
              j = j - 8;  
            LCD12864_data(temp1);
            LCD12864_data(temp2|(0x80>>j));  //改变字节里的位   
           }   
      }

      
    
}
/******************************************/
//画线 
/********************************************/
//画水平线
void LCD12864_LineX(unsigned char X0, unsigned char X1, unsigned char Y)
{
 unsigned char Temp ;
 if( X0 > X1 )
 {
 Temp = X1 ;    //交换X0 X1值  
 X1 = X0 ;     //大数存入X1
 X0 = Temp;   //小数存入X0
 }
for( ; X0 <= X1 ; X0++ )
LCD12864_Drawpoint(X0,Y);
}
//画垂直线  
void LCD12864_LineY( unsigned char X, unsigned char Y0, unsigned char Y1)
{
unsigned char Temp ;
if( Y0 > Y1 )//交换大小值 
{
Temp = Y1 ;
Y1 = Y0 ;
Y0 = Temp ;
}
for(; Y0 <= Y1 ; Y0++)
LCD12864_Drawpoint( X, Y0) ;
}

/******************************************/
/**************画图************************/

  void LCD12864_DrawPicture( unsigned char code *pic)
{
    unsigned char i, j, k ;
        LCD12864_command(0x34);//开扩充指令 
        LCD12864_command(0x36);//开绘图功能   
for( i = 0 ; i < 2 ; i++ )//分上下两屏写    
{
for( j = 0 ; j < 32 ; j++)//垂直地址递加 ,行扫方式 
{
  LCD12864_command( 0x80 + j ) ;//写Y坐标(Y的范围: 0X80-0X9F )
if( i == 0 ) //写X坐标 
{
LCD12864_command(0x80);//上半屏 
}
else
{
LCD12864_command(0x88);//下半屏开始地址 
}
for( k = 0 ; k < 16 ; k++ ) //写一整行数据 
{
 LCD12864_data( *pic++ );//前面只写入首地址,后面依次写入数据,地址会自动递增  
}
}
}
LCD12864_command( 0x30);//恢复到一般模式 
}
//
//          初始化设置
/*******************************************************************/
void LCD12864_init(void)
{
    CLERADISPLAY      //  clear DDRAM
    LCD12864_command(0x30);     //  8 bits unsigned interface,basic instrument
    LCD12864_command(0x02);     //  cursor return
    LCD12864_command(0x0c);     //  display,cursor on
    LCD12864_command(0x03);   
    LCD12864_command(0x06);
    CLERADISPLAY       //  clear DDRAM
}
//
//显示函数
void display(unsigned long int sx)
{
      a1=sx/100000;
      a2=sx%100000/10000;
      a3=sx%10000/1000;//千位 
      a4=sx%1000/100;//百位 
      a5=sx%100/10;//十位 
   a6=sx%10;//个位 
 
 LCD12864_command(0x90); //指定显示位置 
 LCD12864_data(num[a1]); //从最高位开始显示 
 LCD12864_data(num[a2]);
 LCD12864_data(num[a3]);
 LCD12864_data(num[a4]);
 LCD12864_data(num[a5]);
 LCD12864_data(num[10]);//小数点 
 LCD12864_data(num[a6]);
 }
void displayFX(unsigned long int sx)
{
      a1=sx/100000;
      a2=sx%100000/10000;
      a3=sx%10000/1000;
      a4=sx%1000/100;
      a5=sx%100/10;
   a6=sx%10;
 
 LCD12864_command(0x98); //指定显示位置 
 LCD12864_data(num[a1]); //从最高位开始显示 
 LCD12864_data(num[a2]);
 LCD12864_data(num[a3]);
 LCD12864_data(num[a4]);
 LCD12864_data(num[a5]);
 LCD12864_data(num[a6]);
}
/*********************************
                       主函数入口 
/********************************************/ 
//主函数入口 
// 
main()
{
 
 uchar ii=0;
 CONTRL=0;
 Mcu_init();
CLERADISPLAY 
delays(1);
LCD12864_char(1,2,'A');
LCD12864_string(1,4,"shaozhanyu");
delays(2);
clrgdram();

CLERADISPLAY
delays(1);
clrgdram();
delays(1);
LCD12864_LineX(8,113,25);
clrgdram();
CLERADISPLAY
delays(2);
clrgdram();
LCD12864_LineY(55,29,57);
delays(2);
clrgdram();
delays(1);
LCD12864_DrawPicture(Bmp019);
delays(3);

Mcu_init();
CLERADISPLAY 
LCD12864_string(3,1,"N F U V W E");
LCD12864_char(2,1,'D');
LCD12864_string(4,1,"计数");
LCD12864_string(1,3,"少占鱼做");
display(123456); 
/***************8888
    P0=0x10;//怠速,准备打开K5继电器,关闭其他输出继电器 
   SHUCHU=0;//打开输出闸门 
 SHUCHU=1;//关闭闸门 
 outflag=0;//输出标志位
 ******************/ 
  AD=0.0;
P0=0x41;
LED1=0;
LED1=1;
delayms(1000);
P0=0x42;
LED1=0;
LED1=1;
delayms(1000);
P0=0x44;
LED1=0;
LED1=1;
delayms(1000);
P0=0x48;
LED1=0;
LED1=1;
delayms(1000);
P0=0x50;
LED1=0;
LED1=1;
delayms(1000);
P0=0x60;
LED1=0;
LED1=1;
delayms(1000);
P0=0x41;
LED1=0;
LED1=1;
delayms(1000);
P0=0x41;
LED2=0;
LED2=1;
delayms(1000);
P0=0x42;
LED2=0;
LED2=1;
delayms(1000);
P0=0x44;
LED2=0;
LED2=1;
delayms(1000);
P0=0x48;
LED2=0;
LED2=1;
delayms(1000);
P0=0x50;
LED2=0;
LED2=1;
delayms(1000);
P0=0x60;
LED2=0;
LED2=1;
delayms(1000);
P0=0x42;
LED2=0;
LED2=1;
delayms(6000);
keychuli(); //扫描并处理按键 
delayms(5200);
///初始化 
init();
 while(1)
 { 
   while(!FLAG); //等待频率测出 
  
  keychuli(); //扫描并处理按键 
LCD12864_string(1,3,"开始转换");
delayms(300);
 voltage();  //采样电压 
LCD12864_string(1,3,"转换完成");
delayms(400);
baohu();//判断采样数据保护 
 
  for(;ii<6;ii++)
     {
  
  display(DAT[ii]);
  LCD12864_string(1,3,"显示下组");
     
  delayms(1200);
 //  keychuli();
 if(xunhuanflag==0)  //定点 
 {display(DAT[ii]);
  break;
  }
  }
  if(ii==6)
  ii=0;
    display(DAT[ii]);
 displayFX(DAT[6]);
 LCD12864_string(1,3,"下轮复位");
     delayms(1000);
   init();
 
}
}
 /*************************************/
//初始化函数  
 void init()
{  
 /******T1定时器模式,外部INT1控制开启,T0计数器不允许中断,外部控制
INTO开启,外部中断0允许(EX0=1),   
     定时器T2中断允许 (ET2=1) ************/  
   CONTRL=0;
      FLAG=0;
   EX0=0;
      ET2=0;
      //三个定时器方式设置 
      TMOD=0x9d; //T0T1方式控制    
      T2MOD=0x00;
      T2CON=0x00;//定时器2,16位定时方式,自动重装。      
    
      TH0= 0x00; // T0高8位
      TL0= 0x00; // T0低8位
                      
      TH1= 0x00; // T1高8位
      TL1= 0x00; // T1低8位
   EXEN2=0;  
      TH2=256/256;
      TL2=256%256; 
   RCAP2H=256/256;
   RCAP2L=256%256;
      //中断设置        5
      EX0=1;//允许外部0输入中断(INT0引脚)
      ET2=1; //开定时中断2 
      IT0=1; //外部中断0边沿触发,下降沿到来触发 
      //优先级设置
   PX0=1;
      //预置T0,T1
      TR1=1;//先允许T1定时,因T1的GATE=1,还要等外部INT1高电平才计数
      TR0=1;//先允许T0计数 ,同T1一样,等待INTO高电平     
      TR2=1;//启动T2定时,不用外部控制,直接启动   
      EA=1; //开全局中断 
   CONTRL=1;
 
      //初始化完成......
}
 /**********************************
void reset()
 {
  CONTRL=0;
  FLAG=0;
  TL0=0x00;
  TH0=0x00;
  TL1=0x00;
  TH1=0x00;
  TF2=0;
  TH2=256/256;
  TL2=256%256;
  TR1=1;//先允许T1定时,因T1的GATE=1,还要等外部INT1高电平才计数
  TR0=1;//先允许T0计数 ,同T1一样,等待INTO高电平     
  TR2=1;//启动T2定时,不用外部控制,直接启动     
  EA=1; //开全局中断 
  CONTRL=1;
  
 }
*******************************/
 //键盘扫描 
 uchar scanf()
 {
  uchar value;
  P0=0xff;
  delayms(1);
  SCANF=0;//打开键扫闸门 
  value=P0;
  delayms(2);
  value=P0;
  SCANF=1;
  return  value;
 }
 /********************************/
 //键处理 
 void keychuli()
 {
   uchar k;
   //关于指示灯,交流和频率是一组,直流和其他项是一组 
    /***************************************/
   /******************/
   key=scanf();
   /******************/
   //启动键判断 
   if(key1==0&&key7==0&&DAT[4]==0)//启动位 ,油压和转速为0 
 {
for(k=0;k<3;k++)//三次启动循环 
{
     P0=0x04;//准备 输出K6继电器 
     SHUCHU=0;//打开闸门 
 delays(3);//隔三秒响应一次停机键    
   //响应停机键     
  key=scanf();
     if(key0==0&&key7==1&&DAT[4]>500)//停机开关状态,油压高,转速达到500,其他继电器都停止工作 ,所以 ,P0=0x08 
   {
    P0=0x03;//准备 输出K0继电器 
   SHUCHU=0;//打开输出闸门 
 SHUCHU=1;//关闭闸门 
 outflag=0;//输出标志位 
 }
 if(key1==0&&key7==1&&DAT[4]>430) //每启动一次都判断是否成功,成功直接跳出 
break ; //判断启动成功,立即跳出启动for 循环 
  delays(3);//没有启动成功,继续启动3秒 
  key=scanf();
     if(key1==0&&key0==0&&key7==1&&DAT[4]>500)//停机,油压高,转速达到500,其他继电器都停止工作 ,所以 ,P0=0x08 
   {
    P0=0x03;//准备 输出K0继电器 
   SHUCHU=0;//打开输出闸门 
 SHUCHU=1;//关闭闸门 
 outflag=0;//输出标志位 
 }
  if(key1==0&&key7==1&&DAT[4]>430) //每启动一次都判断是否成功,成功直接跳出 
break ;
  delays(3);
  key=scanf();
     if(key0==0&&key7==1&&DAT[4]>500)//停机,油压高,转速达到500,其他继电器都停止工作 ,所以 ,P0=0x08 
   {
    P0=0x03;//准备 输出K0继电器 
   SHUCHU=0;//打开输出闸门 
 SHUCHU=1;//关闭闸门 
 outflag=0;//输出标志位 
 }
     if(key1==0&&key7==1&&DAT[4]>430) //每启动一次都判断是否成功,成功直接跳出 
break ;
   
  P0=0x00;//停止启动 
  SHUCHU=0;
  SHUCHU=1;
  delays(9);
}//for启动循环结束 
     SHUCHU=1;//关闭闸门 
 
   /**********************/
   //启动失败判断 
    if(key7==0) //油压低 
    if(DAT[4]<440)
     {
 P0=0x01;//点亮启动失败灯 
 LED1=0;//开启573输入 
 LED1=1;//关闭使能,74HC573锁定状态 
 outflag=0;//输出标志位清0,表示输出未允许 
     }
 }
   //停机键判断 
  /********************/
   if(key0==0&&key7==1&&DAT[4]>500)//停机,油压高,转速达到500,其他继电器都停止工作 ,所以 ,P0=0x08 
   {
    P0=0x03;//准备 输出K0继电器 
   SHUCHU=0;//打开输出闸门 
 SHUCHU=1;//关闭闸门 
 outflag=0;//输出标志位 
 }
 /*****************/
 //应急键判断 
       if(key6==1)//应急/正常,高电位应急 
       {
    eding=1;//应急标志 
       }
     else if(key6==0) //进入怠速 
          {
        eding=0;//怠速标志 
          }
   if(eding==0)//对怠速的处理 
    {
        P0=0x08;//怠速,准备打开K5继电器,关闭其他输出继电器 
       SHUCHU=0;//打开输出闸门 
     SHUCHU=1;//关闭闸门 
     outflag=0;
       }
  if(eding==1&&outflag==0)//对额定的处理 
    {
 P0=0x00;//额定,准备关闭K5继电器,进入额定,其他继电器都停止工作 ,所以 ,P0=0x00
   SHUCHU=0;//打开输出闸门 
 SHUCHU=1;//关闭闸门 
 delayms(2);
 if(DAT[0]>110&&DAT[1]>110&&DAT[2]>110&&DAT[5]>390)//三相交流大于110 ,频率大于390 
     {
  P0=0x30;//准备合闸(交流,直流 内控制 )   
  SHUCHU=0;
  SHUCHU=1;
  outflag=1;//合闸后,输出标志位置1
     }
     }
 /******************************/
 //循环键 
 if(key2==1) //处理循环定点显示标志位
 xunhuanflag=1;
 else if(key2==0)
 xunhuanflag=0;
   /*********************/
 //灯光检查键 
   if(key4==0)//灯光检查 
   {
    LED1=1;
 LED2=1;
    P0=0x7f;
    LED1=0;
 delayus(10);
 LED1=1;
 delayms(1000);
 P0=0x7f;
 LED2=0;
 delayus(10);
 LED2=1;
 }
 /************************/
 //复位键 
   if(key5==0)//复位 
   { 
    P0=0x00;
    LED1=0;
 delayus(10);
 LED1=1;
 P0=0x00;
 LED2=0;
 delayus(10);
 LED2=1;
 }
   /****************/
   //自检键 
   if(key3==0) //自检 
   { }
 
 }
 /**********保护函数*******************/
 void baohu()
 {
if(outflag==1)
{
 //立即保护值 
 if((DAT[0]<80||DAT[1]<80||DAT[2]<80) || (DAT[0]>180||DAT[1]>180||DAT[2]>180) || DAT[5]>445||DAT[5]<320)//立即断闸保护 
  {
 {
  P0=0x00;//准备断闸(交流,直流 内控制 )   
  SHUCHU=0;
  SHUCHU=1;
  outflag=1;//合闸后,输出标志位清0 
  }
  if((DAT[0]>180||DAT[1]>180||DAT[2]>180)&&DAT[5]>445)
  {P0=0x05;
  LED1=0;
  LED1=1; 
  } 
   if((DAT[0]>180||DAT[1]>180||DAT[2]>180)&&DAT[5]<320)
  {
  P0=0x06;
  LED1=0;
  LED1=1; 
  }
  if((DAT[0]<80||DAT[1]<80||DAT[2]<80)&&DAT[5]>445)
  {
  P0=0x09;
  LED1=0;
  LED1=1;
  }
  if((DAT[0]<80||DAT[1]<80||DAT[2]<80)&&DAT[5]<320)
  {
  P0=0x0a;
  LED1=0;
  LED1=1;
  }
  if(DAT[0]>180||DAT[1]>180||DAT[2]>180)
  {
  P0=0x04;
  LED1=0;
  LED1=1;
  }
  if(DAT[5]>445)
  {
  P0=0x01;
  LED1=0;
  LED1=1;  
  }
  if(DAT[0]<80||DAT[1]<80||DAT[2]<80)
  {
  P0=0x08;
  LED1=0;
  LED1=1;
  }
  if(DAT[5]<320)
  {
  P0=0x02;
  LED1=0;
  LED1=1;
  }
   }
  // 延时保护值     
if((DAT[0]<100||DAT[1]<100||DAT[2]<100) || (DAT[0]>127||DAT[1]>127||DAT[2]>127) || DAT[5]>430||DAT[5]<370)
   {  
  {delays(3);
   voltage();
   }
  if((DAT[0]>127||DAT[1]>127||DAT[2]>127)&&DAT[5]>430)
  {
  P0=0x05;
  LED1=0;
  LED1=1; 
  } 
   if((DAT[0]>127||DAT[1]>127||DAT[2]>127)&&DAT[5]<370)
  {
  P0=0x06;
  LED1=0;
  LED1=1; 
  }
  if((DAT[0]<100||DAT[1]<100||DAT[2]<100)&&DAT[5]>430)
  {
 
  P0=0x09;
  LED1=0;
  LED1=1;
  }
  if((DAT[0]<100||DAT[1]<100||DAT[2]<100)&&DAT[5]<370)
  {
  
  P0=0x0a;
  LED1=0;
  LED1=1;
  }
  if(DAT[0]>127||DAT[1]>127||DAT[2]>127)
  {
  
  P0=0x04;
  LED1=0;
  LED1=1;
  }
  if(DAT[5]>430)
  {
  
  P0=0x01;
  LED1=0;
  LED1=1;  
  }
  if(DAT[0]<100||DAT[1]<100||DAT[2]<100)
  {
 
  P0=0x08;
  LED1=0;
  LED1=1;
  }
  if(DAT[5]<370)
  {
  
  P0=0x02;
  LED1=0;
  LED1=1;
  }
   }
  
 }
 }
 /*******************************/
 //转速计算  ,频率计算 
void zhuansu()
{
 t1h=TH0;
 t1l=TL0;
 t2h=TH1;
 t2l=TL1;
 cnt1=t1l+(t1h<<8);
 cnt2=t2l+(t2h<<8);
 DAT[6]=cnt1/cnt2*1000000.200;//计数值 
 DAT[4]=cnt1/cnt2*1000000.200/124.00*600.00; //计算转速,信号频率就是单片机计数频率的整数倍   ,这里这样写是怕cnt1 cnt2 超出范围 
 //注意这里: cnt1 cnt2  的类型不能是 uint 否则第一步计算除法会得0 , 如果你要先乘1000000.0,也不行。因为超出了uint 范围 
 DAT[5]=DAT[4]*16.00/60.000;//电压频率计算 
}
/******************************/
//外部中断0,调用转速计算 
void interint0()  interrupt 0 //using **
      //外部中断0处理      
{
 EA=0;
 zhuansu();//调用转速函数 
  FLAG=1;
 /***注意:因为TO T1是外部引脚控制的,所以,这时外部低电平,自动停止。不用软件停止**/  
}     
void intertimer2()  interrupt 5 //using **
      //T2定时中断处理      
{  
  TR2=0;
  CONTRL=0;//关闭闸门信号   
}     
/*******************************/
//AD转换程序 
/************************************************/
//常测数据函数 
void voltage() //电压测量 
{
 uchar i;
 AD=0.00;
 X=0;
for(i=0;i<20;i++)
{
AD+=rd1543(0x08); //读取AD值 
}
//
AD=AD/20;
X=AD*46.0001*50.00/1023.00;//转换成电压值 ,分辨率是10位 
DAT[0]=X;
AD=0.00;
delayus(2);
//
for(i=0;i<20;i++)
{
AD+=rd1543(0x08); //读取AD值 
}
//
AD=AD/20;
X=AD*46.0001*50.00/1023.00;//转换成电压值 ,分辨率是10位 
DAT[1]=X;
//
AD=0.00;
delayus(2);
//
for(i=0;i<20;i++)
{
AD+=rd1543(0x08); //读取AD值 
}
//
AD=AD/20;
X=AD*46.0001*50.00/1023.00;//转换成电压值 ,分辨率是10位 
DAT[2]=X;
//
AD=0.00;
delayus(2);
//
/*********
for(i=0;i<20;i++)
{
AD+=rd1543(0x07); //读取AD值 
}
//
AD=AD/20;
X=AD*50.000/1023.000*28.500/4.000;
DAT[3]=X;
//
**********/
}
/***********************************************/

//TLC1543输入模拟电压范围: 0-4.9152 V 
//TLC1543AD 10个时钟方式  方式1 。 LC1543 有四位精度 。  输入 0.0024v 时,AD值为0000000001  
//0.0048时,还为1。  0.0072为 2    也就是0.0048 为一个 宽度  0.0048*AD 就是电压值 . 
uint rd1543(uchar addr)
{
     uint date_out=0;
  uchar k;
    
    // uchar j;
     CLK=0;
     CS=0;
 
          ADDRESS=(bit)(addr&0x08); //用这种愚蠢的方法比用FOR循环快的多 。 
    CLK=1;
    CLK=0;
          addr=addr*2; //用乘法比用左移快 
     
          ADDRESS=(bit)(addr&0x08);
    CLK=1;
    CLK=0;
          addr=addr*2; //用乘法比用左移快 
    ADDRESS=(bit)(addr&0x08);
    CLK=1;
    CLK=0;
          addr=addr*2; //用乘法比用左移快 
    ADDRESS=(bit)(addr&0x08);
    CLK=1;
    CLK=0;
          addr=addr*2; //用乘法比用左移快 
      
  
 // for (j=0;j<6;j++)     //填充6 个CLOCK     
   // {
      CLK=1;CLK=0;   //这里不用循环,省时间 
   CLK=1;CLK=0;
   CLK=1;CLK=0;
   CLK=1;CLK=0;
   CLK=1;CLK=0;
   CLK=1;CLK=0;
      CLK=0;
   // }
      CS=1;
      delayus(8);  //等待AD 转换
      CS=0;                   
  for(k=0;k<10;k++)
     {
    SDATA=1;                 //非P0口作为数据总线使用时,读入数据前要赋值1,特别
       CLK = 1;         //是既用于写有用于读的情况下.
       date_out<<=1;
       if(SDATA) date_out += 1;  //这样写法比下面的方法速度快(5us)
  // date_out=date_out|SDATA;//用时6US 
       CLK = 0;
     }
     return(date_out);
}
原创粉丝点击