本帖最后由 daming 于 2014-12-29 00:30 编辑
(千万注意电压型电路供流能力问题,注意器件属于电压输入型还是电流输入型)
先说一下,交流电压,搞了我几个月,搞死我了,找了好几种方法转直流,进AD,就是不行。NND!!!! 在软件上仿真了好几个电路,都蛮好的波形。焊成板子就是不行,没出来电压,要么就是不滑,进了AD差天上去了,N次想砸了它GOUNIANGYANGDE!!!!!! 今天!!就在今(四声)天!!!!用的运放半波整流加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;
- 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);
- }
复制代码
|