原理图和程序是买实物时送的,但我照原理图搭了仿真,把hex文件导进去LCD没有显示,大哥们这是为啥?这是单片机程序:
#include <REG52.H> //器件配置文件 #include <intrins.h> #define uint unsigned int #define uchar unsigned char
sbit RX = P2^1; sbit TX = P2^0;
sbit LCM_RW = P2^6; //定义LCD引脚 sbit LCM_RS = P2^5; sbit LCM_E =P2^7; #define LCM_Data P0
sbit K1= P3^2; //定义Keyboard引脚 sbit K2= P3^3; uchar Slong=30; // 报警距离值 如果需要修改报警距离,则改此处数值就可。 sbit speak=P1^7; //蜂鸣器报警的口线定义
#define Busy 0x80 //用于检测LCM状态字中的Busy标识
void LCMInit(void); void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData); void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData); void Delay5Ms(void); void Delay400Ms(void); void Decode(unsigned char ScanCode); void WriteDataLCM(unsigned char WDLCM); void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void); unsigned char ReadStatusLCM(void); unsigned char code juli[] ={"The distance is"}; unsigned char code kaiji[] = {" "};
unsigned char code ASCII[15] = {'0','1','2','3','4','5','6','7','8','9','.','-','M','S'};
static unsigned char DisNum = 0; //显示用指针 unsigned int time=0; unsigned char timer=0; unsigned char pinlv=0; unsigned char cishu=0; unsigned long S=0; bit flag =0; bit flag_one=0; bit flag_two=0; unsigned char disbuff[4]={ 0,0,0,0,};
#include "eeprom52.h"
void delayms(unsigned int ms) { unsigned char i=100,j; for(;ms;ms--) { while(--i) { j=10; while(--j); } } }
/******************把数据保存到单片机内部eeprom中******************/ void write_eeprom() { SectorErase(0x2000); byte_write(0x2001, Slong); byte_write(0x2060, a_a); }
/******************把数据从单片机内部eeprom中读出来*****************/ void read_eeprom() {
Slong = byte_read(0x2001); a_a = byte_read(0x2060); }
/**************开机自检eeprom初始化*****************/ void init_eeprom() { read_eeprom(); //先读 if(a_a != 2) //新的单片机初始单片机内问eeprom { Slong = 30; a_a = 2; write_eeprom(); } }
//写数据 void WriteDataLCM(unsigned char WDLCM) { ReadStatusLCM(); //检测忙 LCM_Data = WDLCM; LCM_RS = 1; LCM_RW = 0; LCM_E = 0; //若晶振速度太高可以在这后加小的延时 LCM_E = 0; //延时 LCM_E = 1; }
//写指令 void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测 { if (BuysC) ReadStatusLCM(); //根据需要检测忙 LCM_Data = WCLCM; LCM_RS = 0; LCM_RW = 0; LCM_E = 0; LCM_E = 0; LCM_E = 1; }
//读数据 unsigned char ReadDataLCM(void) { LCM_RS = 1; LCM_RW = 1; LCM_E = 0; LCM_E = 0; LCM_E = 1; return(LCM_Data); }
//读状态 unsigned char ReadStatusLCM(void) { LCM_Data = 0xFF; LCM_RS = 0; LCM_RW = 1; LCM_E = 0; LCM_E = 0; LCM_E = 1; while (LCM_Data & Busy); //检测忙信号 return(LCM_Data); }
void LCMInit(void) //LCM初始化 {
WriteCommandLCM(0x38);//设置模式 WriteCommandLCM(0x0c);//不显示光标 WriteCommandLCM(0x06);//设置指针自加 WriteCommandLCM(0x01);//清屏 }
//按指定位置显示一个字符 void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData) { Y &= 0x1; X &= 0xF; //限制X不能大于15,Y不能大于1 if (Y) X |= 0x40; //当要显示第二行时地址码+0x40; X |= 0x80; //算出指令码 WriteCommandLCM(X, 1); //发命令字 WriteDataLCM(DData); //发数据 }
//按指定位置显示一串字符 void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData) { unsigned char ListLength;
ListLength = 0; Y &= 0x1; X &= 0xF; //限制X不能大于15,Y不能大于1 while (DData[ListLength]>0x19) //若到达字串尾则退出 { if (X <= 0xF) //X坐标应小于0xF { DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符 ListLength++; X++; } } }
//5ms延时 void Delay5Ms(void) { unsigned int TempCyc = 5552; while(TempCyc--); }
//400ms延时 void Delay400Ms(void) { unsigned char TempCycA = 5; unsigned int TempCycB; while(TempCycA--) { TempCycB=7269; while(TempCycB--); }; }
void key() { if(!K1) //按下按键 { delayms(5); //延时去抖 if(!K1) { Slong+=1; //每按下一次,数值加10 write_eeprom(); //保存数据 flag_one=0; } while(!K1); //等待按键弹起 }
if(!K2) //按下按键 { delayms(5); //延时去抖 if(!K2) { Slong-=1; //每按下一次,数值加10 write_eeprom(); //保存数据 flag_one=0; } while(!K2); //等待按键 弹起 }
if(flag_one==0) { flag_one=1; disbuff[0]=Slong%1000/100; disbuff[1]=Slong%1000%100/10; disbuff[2]=Slong%1000%10 %10; DisplayOneChar(9, 1, ASCII[13]); //显示S DisplayOneChar(10, 1, ':'); //显示M DisplayOneChar(11, 1, ASCII[disbuff[0]]); DisplayOneChar(12, 1, ASCII[10]); //显示点 DisplayOneChar(13, 1, ASCII[disbuff[1]]); DisplayOneChar(14, 1, ASCII[disbuff[2]]); DisplayOneChar(15, 1, ASCII[12]); //显示M
}
}
warn() //报警函数 { if( S>Slong*4/5 && S<=Slong*5/5 ) //当距离小于等于设定的报警值时 { pinlv=1; //蜂咛器报警等级 }
if( S>Slong*3/5 && S<=Slong*4/5 ) //当距离小于等于设定的报警值时 { pinlv=2; //蜂咛器报警等级 }
if( S>Slong*2/5 && S<=Slong*3/5 ) //当距离小于等于设定的报警值时 { pinlv=3; //蜂咛器报警等级 }
if( S>Slong*1/5 && S<=Slong*2/5 ) //当距离小于等于设定的报警值时 { pinlv=4; //蜂咛器报警等级 }
if( S<=Slong*1/5 ) //当距离小于等于设定的报警值时 { pinlv=5; //蜂咛器报警等级 }
if(S>Slong) //当距离大于设定的报警值时 { pinlv=0; // 蜂咛器不报警。 } }
/********************************************************/ void Conut(void) { time=TH0*256+TL0; TH0=0; TL0=0;
S=(time*1.7)/100; //算出来是CM if((S>=700)||flag==1) //超出测量范围显示“-” { flag=0;
DisplayOneChar(0, 1, ASCII[11]); DisplayOneChar(1, 1, ASCII[10]); //显示点 DisplayOneChar(2, 1, ASCII[11]); DisplayOneChar(3, 1, ASCII[11]); DisplayOneChar(4, 1, ASCII[12]); //显示M } else { disbuff[0]=S%1000/100; disbuff[1]=S%1000%100/10; disbuff[2]=S%1000%10 %10; DisplayOneChar(0, 1, ASCII[disbuff[0]]); DisplayOneChar(1, 1, ASCII[10]); //显示点 DisplayOneChar(2, 1, ASCII[disbuff[1]]); DisplayOneChar(3, 1, ASCII[disbuff[2]]); DisplayOneChar(4, 1, ASCII[12]); //显示M } } /********************************************************/ void zd0() interrupt 1 //T0中断用来计数器溢出,超过测距范围 { flag=1; //中断溢出标志 } /********************************************************/ void StartModule() //启动模块 { TX=1; //启动一次模块 _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); TX=0; } /********************************************************/
/*********************************************************/ void main(void) {
unsigned char TempCyc; Delay400Ms(); //启动等待,等LCM讲入工作状态 LCMInit(); //LCM初始化 Delay5Ms(); //延时片刻(可不要) DisplayListChar(0, 0, juli); DisplayListChar(0, 1, kaiji); //ReadDataLCM();//测试用句无意义 //for (TempCyc=0; TempCyc<10; TempCyc++) Delay400Ms(); //延时 init_eeprom(); //读eeprom数据 while(1) { TMOD=0x11; //设T0为方式1,GATE=1; TH0=0; TL0=0; TH1=0xf8; //2MS定时 TL1=0x30; ET0=1; //允许T0中断 ET1=1; //允许T1中断 TR1=1; //开启定时器 EA=1; //开启总中断
while(1) { key(); if(flag_two==0) { flag_two=1; StartModule(); while(!RX); //当RX为零时等待 TR0=1; //开启计数 while(RX); //当RX为1计数并等待 TR0=0; //关闭计数 Conut(); //计算 warn(); } } } }
void zd3() interrupt 3 // { TH1=0x3c; TL1=0xb0; cishu++; timer++; if(timer>=10) //500ms刷新一次 { flag_two=0; }
if(pinlv==0) { speak=1; }
if(pinlv==1) { if(cishu>=5) { cishu=0; speak=~speak; } }
if(pinlv==2) { if(cishu>=4) { cishu=0; speak=~speak; } }
if(pinlv==3) { if(cishu>=3) { cishu=0; speak=~speak; } }
if(pinlv==4) { if(cishu>=2) { cishu=0; speak=~speak; } }
if(pinlv==5) { if(cishu>=1) { cishu=0; speak=~speak; } }
}
|