教训少占鱼之:TLC1543--AD测试(单片机)教训(注意电压型芯片限流问题,器件属于电压输入型还是电流输入型)

来源:互联网 发布:access2003数据库 编辑:程序博客网 时间:2024/03/19 18:44

先说一下,交流电压,搞了我几个月,搞死我了,找了好几种方法转直流,进AD,就是不行。NND!!!!

在软件上仿真了好几个电路,都蛮好的波形。焊成板子就是不行,没出来电压,要么就是不滑,进了AD差天上去了,N次想砸了它GOUNIANGYANGDE!!!!!!

   //少占鱼制作  河北正定欢迎您   长沙航空职业技术学院  2010年5月 QQ:411656434
/*邮箱:ssou_1985@163.com

**************/

今天!!就在今(四声)天!!!!用的运放半波整流加RC滤波,不接入AD,调放大倍数后得到对应直流电压。接入AD后再看,MD!!!电压从珠穆朗玛都拉到贝加尔湖了!!中间串了个20K电阻(看TNND还拉低不!!)终于用表在线量OK了,程序OK了。TLC1543啊!!NNND!!!!让我一度认为运放不合适,想换其他运放,一度换电路,一度迷茫“为嘛仿真的和现实就不符昵”为嘛现实和理想差距这么大哩!!!!!一度认为仿真软件有问题!!!

所以:教训:(单片机) 教训版:

       注意电路供流能力,空载和负载的电压变化受到什么影响!

       注意器件属于电压输入型还是电流输入型,要“限流”,还是增大“供流”!!!

       不要总是考虑电阻大影响电压,人家电流小啊!!uA级别的,TLC1543就需要限流!!!

        以后再不注意这些问题!我就不姓少!!!!!!!!!!!!!

    还有一个待解决问题:运放做的正弦峰值检测电路,仿真蛮好的,焊成板子就是不行,电压直接奔最高了。为嘛!!这一切都是为嘛!!运放我用的LM358,用单电池供电不行,用俩电池供电,也不行!!!

/********多周期测频法,精度与晶振和闸门时间有关。晶振越大,闸门时间越长,都可以提高精度。************************/
/********少占鱼***河北欢迎您***京畿之地 魅力河北***河北正定欢迎您**************************/

#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]={1150.0, 1150.1, 1150.2, 285.0,15000.0, 4000.0,31000.0}; //都放大了10倍  
//       U     V      W      E     N     F   CINT    
// 控制脚

sbit CONTRL=P1^7; //测频控制脚

sbit SCANF =P2^0; //键盘扫描控制脚
sbit LED2  =P2^1; //状态显示控制脚1
sbit LED1  =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,uchar j); //显示函数
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,uchar j)
{

      a1=sx/100000;
      a2=sx%100000/10000;
      a3=sx%10000/1000;//千位
      a4=sx%1000/100;//百位
      a5=sx%100/10;//十位
   a6=sx%10;//个位
 
   switch(j)
 {
    case 0x00: LCD12864_string(2,5,"  Ua    ");break;
    case 0x01: LCD12864_string(2,5,"  Ub    ");break;
    case 0x02: LCD12864_string(2,5,"  Uc    ");break;
    case 0x03: LCD12864_string(2,5,"  E     ");break;
    case 0x04: LCD12864_string(2,5,"  转速  ");break;
 case 0x05: LCD12864_string(2,5,"  频率  ");break;
 case 0x06: LCD12864_string(2,5,"脉冲计数");break;
 case 0x07: LCD12864_string(2,5,"        ");break;
  default :break;
 }
 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]);//小数点,前面测量计算时扩大了10倍,这里缩小回来
 LCD12864_data(num[a6]);

 }


/*********************************
                       主函数入口
/********************************************/
//主函数入口
//
main()
{
 
 uchar ii=0;
 CONTRL=0;
 FLAG=0;
 P0=0x00;
LED1=0;
LED1=1;
P0=0x00;
LED2=0;
LED2=1;
 P0=0x00;
 SHUCHU=0;//打开闸门
 SHUCHU=1;
 baohu();//判断采样数据保护
 Mcu_init();

CLERADISPLAY
delays(1);
display(100000,7);
LCD12864_char(1,2,'A');

LCD12864_string(1,2,"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,"U V W E SP F CT");
LCD12864_char(2,1,'D');
LCD12864_string(4,1,"计数");
LCD12864_string(1,2,"少占鱼做");
delays(1);
/***************8888
    P0=0x10;//怠速,准备打开K5继电器,关闭其他输出继电器
   SHUCHU=0;//打开输出闸门
 SHUCHU=1;//关闭闸门
 outflag=0;//输出标志位
 ******************/
  AD=0.0;
LCD12864_string(1,2,"灯光测试");

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;
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=0x00;
LED1=0;
LED1=1;
P0=0x00;
LED2=0;
LED2=1;
delayms(500);
LCD12864_string(1,2,"测继电器");


 P0=0x04;//启动
 SHUCHU=0;//打开闸门
 delays(3);
 SHUCHU=1;

  P0=0x18;//停机
 SHUCHU=0;//打开闸门
 delays(3);
 SHUCHU=1;

 P0=0x40;//怠速,准备打开K5继电器,关闭其他输出继电器
 SHUCHU=0;//打开输出闸门

 delays(3);
  SHUCHU=1;//关闭闸门
 P0=0xa0;//准备合闸(交流,直流 内控制 )  
 SHUCHU=0;

  delays(3);
   SHUCHU=1;
  P0=0x00;
 SHUCHU=0;//打开闸门
 SHUCHU=1;


keychuli(); //扫描并处理按键
delayms(600);
voltage();
LCD12864_string(3,1,"U V W E SP F ");
LCD12864_char(2,1,'D');
LCD12864_string(1,2,"少氏出品");
delays(11);
///初始化
LCD12864_string(4,1,"直流正常");
init();

 while(1)

 {
   while(!FLAG); //等待频率测出
 
  keychuli(); //扫描并处理按键
LCD12864_string(1,2,"测量电压");
delayms(500);
 voltage();  //采样电压

LCD12864_string(1,2,"转换完成");
delayms(600);
baohu();//判断采样数据保护
 
  for(;ii<6;)
     {
 if(xunhuanflag==0)  //定点
 {display(DAT[ii],ii);
  LCD12864_string(1,2,"定点显示");
  break;
  } 
  display(DAT[ii],ii);
  LCD12864_string(1,2,"循环显示");
    
  delayms(2200);
  keychuli();
  ii++;

 }//循环 显示结束
  if(ii==6)
  ii=0;

 LCD12864_string(1,2,"下轮复位");
   delayms(700);
   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; 

 //定时器初始化不能用前面负号的方式 -(1000/256);错误!!结果不是(65536-1000)/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=0x18;//准备输出K0,K9继电器
   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=0x18;//准备输出K0,K9继电器
   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=0x18;//准备输出K0,K9继电器
   SHUCHU=0;//打开输出闸门
 SHUCHU=1;//关闭闸门
 outflag=0;//输出标志位
 }
     if(key1==0&&key7==1&&DAT[4]>430) //每启动一次都判断是否成功,成功直接跳出
break ;
  
  P0=0x18;//停止
  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=0x00;//准备交直流断闸(交流,直流 内控制 )  
  SHUCHU=0;
  SHUCHU=1;
  delayms(3);
        P0=0x40;//怠速,准备打开K5继电器,关闭其他输出继电器
       SHUCHU=0;//打开输出闸门
     SHUCHU=1;//关闭闸门
     outflag=0;
  delays(29);
    P0=0x18;//准备 输出K0和K9停油继电器
   SHUCHU=0;//打开输出闸门
 SHUCHU=1;//关闭闸门
 outflag=0;//输出标志位
 }

 /*****************/
 //应急键判断
       if(key6==1)//应急/正常,高电位应急
       {
    eding=1;//应急标志

       }
     else if(key6==0) //进入怠速
          {
        eding=0;//怠速标志
          }
   if(eding==0)//对怠速的处理
    {
        P0=0x40;//怠速,准备打开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=0xa0;//准备合闸(交流,直流 内控制 )  
  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]<800||DAT[1]<800||DAT[2]<800) || (DAT[0]>1800||DAT[1]>1800||DAT[2]>1800) || DAT[5]>4450||DAT[5]<3200)//立即断闸保护
  {
 
  P0=0x00;//准备断闸(交流,直流 内控制 )  
  SHUCHU=0;
  SHUCHU=1;
  outflag=0;//断闸后,输出标志位清0
 
  if(DAT[0]>1800||DAT[1]>1800||DAT[2]>1800)
  {
  P0=0x80;//过压
  LED1=0;
  LED1=1;
  }
   if(DAT[5]>4450)
  {
  P0=0x80;//过频灯
  LED2=0;
  LED2=1;
  }
  if(DAT[0]<800||DAT[1]<800||DAT[2]<800)
  {
  P0=0x40;//欠压
  LED1=0;
  LED1=1;
  }
  if(DAT[5]<3200)
  {
  P0=0x40;//欠频灯
  LED2=0;
  LED2=1;
  }

   }//立即保护结束

  // 延时保护值    
if(DAT[0]<1000||DAT[1]<1000||DAT[2]<1000|| DAT[0]>1270||DAT[1]>1270||DAT[2]>1270|| DAT[5]>4300||DAT[5]<3700)
   { 
 
  if(DAT[0]>1270||DAT[1]>1270||DAT[2]>1270)
  {

  P0=0x80;//过压
  LED1=0;
  LED1=1;


  }
   if(DAT[5]>4300)
  {
  P0=0x80;//过频
  LED2=0;
  LED2=1;
  }
  if(DAT[0]<1000||DAT[1]<1000||DAT[2]<1000)
  {
 
  P0=0x40;//欠压
  LED1=0;
  LED1=1;
  }
  if(DAT[5]<3700)
  {
 
  P0=0x40;//欠频
  LED2=0;
  LED2=1;
  }
  delays(4);//等待交流恢复
  voltage();

 if(DAT[0]>1100&&DAT[1]>1100&&DAT[2]>1100&&DAT[5]>3900)//三相交流大于110 ,频率大于390
     {
  P0=0x00;
  LED1=0;
  LED1=1;
  P0=0x00;
  LED2=0;
  LED2=1;
  P0=0xa0;//准备合闸(交流直流内控制 )  
  SHUCHU=0;
  SHUCHU=1;
  outflag=1;//合闸后,输出标志位置1    
        }
 else
 {
 
  P0=0x00;//准备断闸(交流,直流 内控制 )  
  SHUCHU=0;
  SHUCHU=1;
  outflag=0;
 }

   }//交流和频率保护结束
 //直流电压延时保护
   if(DAT[3]>320||DAT[3]<170)
   {if(DAT[3]>320)
  {
  LCD12864_string(4,1,"直流过压");
  }
  delays(4);//等待直流过压恢复
  voltage();
 if(DAT[3]>170&&DAT[3]<320)
 {
  LCD12864_string(4,1,"直流正常"); 
 }
 else
 {P0=0x80;//关闭直流只开交流,因为前面已经检测过交流了,这里就不管了,当他正常   
  SHUCHU=0;
  SHUCHU=1;
  outflag=1;
  LCD12864_string(4,1,"直流故障");
 }
   if(DAT[3]<170)
  {
  LCD12864_string(4,1,"直流欠压");
  }
   delays(2);//等待直流 欠压恢复
   voltage();
 if(DAT[3]>170&&DAT[3]<320)
 {
  LCD12864_string(4,1,"直流正常"); 
 }
 else
 {P0=0x80;//关闭直流只开交流,因为前面已经检测过交流了,这里就不管了,当他正常   
  SHUCHU=0;
  SHUCHU=1;
  outflag=1;
  LCD12864_string(4,1,"直流故障");
 }
   }//直流延时保护结束
 }//总 保护结束
 }//总函数结束
 /*******************************/
 //转速计算  ,频率计算
void zhuansu()
{
 t1h=TH0;
 t1l=TL0;
 t2h=TH1;
 t2l=TL1;
 cnt1=t1l+(t1h<<8);
 cnt2=t2l+(t2h<<8);
 DAT[6]=cnt1/cnt2*1000000.20*10.00;//计数值
 DAT[4]=cnt1/cnt2*1000000.200/124.00*600.00*10.0; //计算转速,信号频率就是单片机计数频率的整数倍   ,这里这样写是怕cnt1 cnt2 超出范围
 //注意这里: cnt1 cnt2  的类型不能是 uint 否则第一步计算除法会得0 , 如果你要先乘1000000.0,也不行。因为超出了uint 范围
 DAT[5]=DAT[4]*16.00/60.000*10.0;//电压频率计算

}

/******************************/
//外部中断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<10;i++)
{
AD+=rd1543(0x08); //读取AD值
}
//
AD=AD/10.0;
X=AD*46.0001*50.00/1023.00;//转换成电压值 ,分辨率是10位
DAT[0]=X;

AD=0.00;

//
for(i=0;i<10;i++)
{
AD+=rd1543(0x08); //读取AD值
}
//
AD=AD/10.0;
X=AD*46.0001*50.00/1023.00;//转换成电压值 ,分辨率是10位
DAT[1]=X;
//
AD=0.00;

//
for(i=0;i<10;i++)
{
AD+=rd1543(0x08); //读取AD值
}
//
AD=AD/10.0;
X=AD*46.0001*50.00/1023.00;//转换成电压值 ,分辨率是10位
DAT[2]=X;
//
/*********
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);
}

原创粉丝点击