完整程序文件下載:https://cos.mcmxzl.com/%E5%85...函數
主程序:學習
/*********************************************************************** 超聲波測距儀 MCU是STC89C52RC LCD1602A(16*2)模擬口線接線方式 鏈接線圖: --------------------------------------------------- |LCM-----51 | LCM-----51 | LCM------51 | --------------------------------------------------| |DB0-----P2.0 | DB4-----P2.4 | RS-------P1.4 | |DB1-----P2.1 | DB5-----P2.5 | RW-------P1.5 | |DB2-----P2.2 | DB6-----P2.6 | E--------P1.6 | |DB3-----P2.3 | DB7-----P2.7 | VLCD接1K電阻到GND| --------------------------------------------------- 接線:模塊TRIG接 P1.0 ECH0 接P1.1 本程序源碼只供學習參考,不得應用於商業用途,若有須要請聯繫做者。 ***********************************************************************/ #include <reg52.H> //器件配置文件 #include <intrins.h> #include "LCD1602.h" #define uchar unsigned char #define uint unsigned int sbit RX = P1^1; sbit TX = P1^0; unsigned char code mcustudio[] ={"www.mcmxzl.com"}; unsigned char code email[] = {"676672384@qq.com "}; unsigned char code ASCII[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','M'}; static unsigned char DisNum = 0; //顯示用指針 unsigned int time=0; unsigned long S=0; bit flag=1; unsigned char disbuff[4] ={ 0,0,0,0,}; void Delay5Ms(void) { unsigned char i, j; i = 10; j = 183; do { while (--j); } while (--i); } //400ms延時 void Delay400Ms(void) { unsigned char i, j, k; _nop_(); i = 4; j = 11; k = 45; do { do { while (--k); } while (--j); } while (--i); } void delayms(unsigned int ms) { for(;ms;ms--) { unsigned char i, j; i = 2; j = 239; do { while (--j); } while (--i); } } void InitTimer0(void) { TMOD = 0x09; TH0=0; //設置初值 TL0=0; EA = 1; ET0 = 1; } void Timer0Interrupt(void) interrupt 1 { TH0=0; //設置初值 TL0=0; flag=1; } void Conut(void) { time=TH0*256+TL0; TH0=0; TL0=0; S=(time*1.7)/100; //算出來是CM Init_LCD1602(); //LCD初始化 if((S>=500)) //超出測量範圍顯示「-」 { displaystring(0, 0,"Error:"); displaystring(0, 1,"Out of range!"); /*displaychar(0, 0, ASCII[11]); displaychar(1, 0, ASCII[10]); //顯示點 displaychar(2, 0, ASCII[11]); displaychar(3, 0, ASCII[11]); displaychar(4, 0, ASCII[12]); //顯示M*/ } else { displaystring(0, 0,"Distance:"); disbuff[0]=S%1000/100; disbuff[1]=S%1000%100/10; disbuff[2]=S%1000%10 %10; displaychar(10, 0, ASCII[disbuff[0]]); displaychar(11, 0, ASCII[10]); //顯示點 displaychar(12, 0, ASCII[disbuff[1]]); displaychar(13, 0, ASCII[disbuff[2]]); displaychar(14, 0, ASCII[12]); //顯示M } } /*********************************************************/ void main(void) { uchar i=0; InitTimer0(); //初始化定時器 Delay400Ms(); //啓動等待,等LCD講入工做狀態 Init_LCD1602(); //LCD初始化 Delay5Ms(); //延時片刻(可不要) displaystring(0, 0, mcustudio);//顯示網站 displaystring(0, 1, email);//顯示電子郵箱 delayms(1000);//延時1s Init_LCD1602();//LCD清屏 Delay5Ms(); /****************************************** 顯示 歡迎使用超聲波測距儀 ******************************************/ displaystring(0, 0,"Welcome to use U"); displaystring(0, 1,"ltrasonic distan"); delayms(2000); Init_LCD1602(); Delay5Ms(); displaystring(0, 0,"ce measuring ins"); displaystring(0, 1,"trument!"); delayms(2000); /*******************************************/ Init_LCD1602(); //LCD初始化 delayms(5); while(1) { TX=1; _nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); TX=0; while(!RX); //當RX爲零時等待 TR0=1; //開啓計數 while(RX); //當RX爲1計數並等待 TR0=0; //關閉計數 Conut(); //計算 delayms(280); //延時,反正發射信號對迴響信號的影響 } }
LCD1602顯示程序:網站
//使用方法: 使用前調用Init_LCD1602()初始化,顯示方法displaystring(0, 0, "This is a test."); #ifndef _LCD1602_ #define _LCD1602_ #define uchar unsigned char #define uint unsigned int //#define _PORT_REV_ //若是數據端口高低位交換,請去掉此註釋 #include <intrins.h> //包含_nop_()指令 sbit LCD1602_RS = P1^4; //控件引腳定義,移植請修改 sbit LCD1602_RW = P1^5; sbit LCD1602_E = P1^6; #define LCD_PORT P2 //輸出數據總線端口定義,移植請修改 #define LCD_COMMAND 0 // Command #define LCD_DATA 1 // Data #define LCD_CLEAR_SCREEN 0x01 // 清屏 #define LCD_HOMING 0x02 // 光標返回原點 #define LCD_SHOW 0x04 //顯示開 #define LCD_HIDE 0x00 //顯示關 #define LCD_CURSOR 0x02 //顯示光標 #define LCD_NO_CURSOR 0x00 //無光標 #define LCD_FLASH 0x01 //光標閃動 #define LCD_NO_FLASH 0x00 //光標不閃動 #define LCD_AC_UP 0x02 #define LCD_AC_DOWN 0x00 // default #define LCD_MOVE 0x01 // 畫面可平移 #define LCD_NO_MOVE 0x00 //default void delay10us(unsigned char t) //偏差 -0.234375us { while(--t) { unsigned char a,b; for(b=1;b>0;b--) /* for(a=1;a>0;a--)*/;} } /********************************************************************************************* 函數名:8位數據高低位交叉互換 調 用:uchar = DataReverse(uchar); 參 數:輸入的端口(0000 0XXX 其中XXX是設置輸入端口號,可用十進制0~7表示,0表示P1.0,7表示P1.7) 返回值:交換後的8位數據 結 果:交換數據高低位D7→D0,D6→D1.....,D0→D7,並返回交換後的結果 備 注: /**********************************************************************************************/ unsigned char DataReverse(unsigned char datOld) { unsigned char datNew=0,i; for (i=0; i<8; i++) { if (datOld & (1<<i)) //若是某位爲1,則或上一個1 datNew |= (0x80>>i); } return datNew; } /**********************************************************************************************/ /********************************************************************************************* 函數名:LCD1602等待函數 調 用:uchar = LCD_Wait(); 參 數:無 返回值:LCD1602數據總線的值 結 果:等待LCD1602內部指令執行完成 備 注:返回結果可不用 /**********************************************************************************************/ unsigned char LCD_Wait(void) { LCD1602_RS = 0; LCD1602_RW = 1; delay10us(1); LCD1602_E = 1; delay10us(1); #ifdef _PORT_REV_ //若是數據線高低位交換,則須要處理數據 while(DataReverse(LCD_PORT)&0x80); LCD1602_E = 0; return DataReverse(LCD_PORT); #else //正常狀況下不須要交換 while(LCD_PORT&0x80); LCD1602_E = 0; return LCD_PORT; #endif } /**********************************************************************************************/ /********************************************************************************************* 函數名:LCD1602數據寫函數 調 用:LCD_Wait(bit, uchar); 參 數:數據類型,數據值 返回值:無 結 果:將指定數據類型的數據寫入1602 備 注:數據類型:LCD_COMMAND(0)、LCD_DATA(1) /**********************************************************************************************/ void LCD_Write(bit DataStyle, unsigned char DAT) { LCD1602_E = 0; LCD1602_RS = DataStyle; LCD1602_RW = 0; delay10us(1); #ifdef _PORT_REV_ LCD_PORT = DataReverse(DAT); #else LCD_PORT = DAT; #endif _nop_(); LCD1602_E = 1; delay10us(1);//注意順序 LCD1602_E = 0; delay10us(1); LCD_Wait(); //等待1602內部執行完,Proteus仿真時請註釋此句 } /**********************************************************************************************/ /********************************************************************************************* 函數名:LCD1602顯示設置函數 調 用:LCD_SetDisplay(uchar); 參 數:顯示模式 返回值:無 結 果:正常設置1602顯示模式 備 注:內部函數,初始化時調用 /**********************************************************************************************/ void LCD_SetDisplay(unsigned char DisplayMode) { LCD_Write(LCD_COMMAND, 0x08|DisplayMode); } /**********************************************************************************************/ /********************************************************************************************* 函數名:LCD1602顯示設置函數 調 用:LCD_SetInput(uchar); 參 數:顯示模式 返回值:無 結 果:正常設置1602顯示模式 備 注:內部函數,初始化時調用 /**********************************************************************************************/ void LCD_SetInput(unsigned char InputMode) { LCD_Write(LCD_COMMAND, 0x04|InputMode); } /**********************************************************************************************/ /********************************************************************************************* 函數名:LCD1602初始化函數 調 用:Init_LCD1602(); 參 數:無 返回值:無 結 果:初始化1602函數 備 注: /**********************************************************************************************/ void Init_LCD1602() { LCD_Write(LCD_COMMAND, 0x38); //8位數據端口,2行顯示,5*7點陣 LCD_Write(LCD_COMMAND, 0x38); LCD_Write(LCD_COMMAND, 0x38); LCD_SetDisplay(LCD_SHOW | LCD_NO_CURSOR); //開啓顯示, 無光標 LCD_Write(LCD_COMMAND, LCD_CLEAR_SCREEN); //清屏 LCD_SetInput(LCD_AC_UP | LCD_NO_MOVE); //AC遞增, 畫面不動 } /**********************************************************************************************/ /********************************************************************************************* 函數名:LCD1602數據寫函數 調 用:LCD1602_DispString(uchar, uchar, *uchar); 參 數:x座標,y座標,字符串 返回值:無 結 果:在指定座標顯示字符串 備 注:x: 0~15; y:0、1 /**********************************************************************************************/ void displaystring(unsigned char x, unsigned char y, unsigned char *s) { if(y == 0) LCD_Write(LCD_COMMAND, 0x80|x); if(y == 1) LCD_Write(LCD_COMMAND, 0x80|(x-0x40)); while(*s != '\0') { LCD_Write(LCD_DATA, *s); s++; } } /**********************************************************************************************/ //字符顯示初始地址設置 void LCD_SET_XY(uchar X,uchar Y) { if(Y == 0) LCD_Write(LCD_COMMAND, 0x80|X); if(Y == 1) LCD_Write(LCD_COMMAND, 0x80|(X-0x40)); } //在第X行Y列開始顯示Wdata所對應的單個字符 void displaychar(uchar X,uchar Y,uchar Wdata) { LCD_SET_XY(X,Y);//寫地址 LCD_Write(LCD_DATA, Wdata);//寫入當前字符並顯示 } #endif