#include<reg52.h> #include<intrins.h> #define uint8 unsigned char #define uint16 unsigned int #define CMD 0x00 #define DAT 0x01 #define DataPort P0//LCD數據口 sbit RW=P2^6; sbit RS=P2^5; sbit E=P2^7; uint16 N=0; uint8 C_50ms; uint8 Z=0; uint8 count=0; bit flag_1s=0; /**ms級延時子程序**/ void delay(uint16 t) { uint16a; for(;t>0;t--) for(a=123;a>0;a--); } /**LCD時序**/ void write_LCD(uint8 dat,bit rs) { E=0; RW=0; RS=rs;//選擇指令or數據 _nop_(); _nop_(); _nop_(); E=1; _nop_();//delay(1); _nop_(); _nop_(); DataPort=dat;//將數據送到LCD數據口 _nop_(); _nop_(); _nop_(); E=0; delay(1); } /**LCD選擇顯示位置子函數**/ void SetXY(uint8 x,uint8 y) { x=x&0x0f;//防止X、Y 超過量程 y=y&0x01; if(y) { write_LCD(0x80+x,CMD); } else { write_LCD(0xc0+x,CMD); } } /**轉速數值轉換子函數**/ void disload(uint16 a) { SetXY(4,0); write_LCD(a/1000+'0',DAT); write_LCD(a%1000/100+'0',DAT); write_LCD(a%100/10+'0',DAT); write_LCD(a%10+'0',DAT); write_LCD('r',DAT); write_LCD('/',DAT); write_LCD('m',DAT); write_LCD('i',DAT); write_LCD('n',DAT); } /**LCD字符指針函數**/ void LCD_wrstr(uint8*str) { while(*str!='\0') { write_LCD(*str,DAT); str++; } } /**初始化子程序**/ void All_init() { delay(500); write_LCD(0x38,CMD); write_LCD(0x38,CMD); write_LCD(0x0c,CMD); write_LCD(0x01,CMD); delay(10); SetXY(0,1);//設置標題顯示位置 LCD_wrstr("Tachometer:"); TMOD=0x01;//設置T0位工作方式1——作為16位定時器 ET0=1;//打開定時器0的中斷 TR0=1;//打開定時器0 TH0=(65536-50000)/256;//裝入初值 TL0=(65536-50000)%256; IT0=1;//外部中斷0為下降沿中斷 EX0=1;//打開外部中斷 EA=1;//打開總中斷 } void main() { All_init();//先進行初始化 while(1) { if(flag_1s==1) { flag_1s=0;//1s標志位清零 disload(N); } } } /**定時器0中斷服務子程序**/ void timer0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; if(++C_50ms>19) { EX0=0;//關閉外部中斷0 C_50ms=0;//定時1s之后C_50ms清零 N=60*Z;//計算轉速 Z=0;//初始化圈數 flag_1s=1;//1s標志位置1 TH0=0x3c;//重新賦值 TL0=0xb0; EX0=1;//打開外部中斷0,開始計數。 } } void wai0() interrupt 0 { count++; if(count==2)//兩次外部脈沖,電機轉一圈。 { Z++;//轉圈+1 count=0;//初始計數值 } }
|