谁会这段程序帮我讲解一下,分全给你们了!!!
程序代码:
#include "reg51.h" #include "absacc.h" #include "intrins.h" #define uchar unsigned char #define uint unsigned int sbit IR=P3^2;//红外接口标志 uchar irtime;//红外用全局变量 uchar IRcord[4]; uchar irdata[33]; uchar num; bit irpro_ok,irok; uchar G_sj,Y_sj,R_sj,count=0; bit SN_Pass; bit EW_Pass; //uchar R_sj_T,R_sj_T; uchar digit,Szsj[2],Key_count; /*管脚定义*/ sbit CLK =P2^0;//MAX7219的时钟 sbit DIN =P2^1;//MAX7219的串行数据 sbit LOAD=P2^2;//MAX7219的片选 sbit EW_G=P0^0;//东西绿 sbit EW_Y=P0^1;//东西黄 sbit EW_R=P0^2;//东西红 sbit SN_G=P0^3;//南北绿 sbit SN_Y=P0^4;//南北黄 sbit SN_R=P0^5;//南北红 /*MAX7219寄存器*/ #define NoOp 0x00 //空操作寄存器 #define Digit0 0x01 //数码管1寄存器 #define Digit1 0x02 //数码管2寄存器 #define Digit2 0x03 //数码管3寄存器 #define Digit3 0x04 //数码管4寄存器 #define Digit4 0x05 //数码管5寄存器 #define Digit5 0x06 //数码管6寄存器 #define Digit6 0x07 //数码管7寄存器 #define Digit7 0x08 //数码管8寄存器 #define DecodeMode 0x09 //译码模式寄存器 #define Intensity 0x0a //亮度寄存器 #define ScanLimit 0x0b //扫描位数寄存器 #define ShutDown 0x0c //低功耗模式寄存器 #define DisplayTest 0x0f //显示测试寄存器 #define ShutdownMode 0x00 //低功耗方式 #define NormalOperation 0x01 //正常操作方式 #define ScanDigit 0x07 //扫描位数设置,显示8位数码管 #define DecodeDigit 0xff //译码设置,8位均为BCD码 #define IntensityGrade 0x0a //亮度级别设置 #define TestMode 0x01 //显示测试模式 #define TextEnd 0x00 //显示测试结束,恢复正常工作模式 void delay(uint t); void SendChar(uchar ch); void WriteWord(uchar addr,uchar num); void Init_MAX7219(void); /*液晶1602口地址*/ #define wr_com XBYTE[0xC000] //写命令 #define wr_data XBYTE[0xC100] //写数据 #define rd_com XBYTE[0xC200] //读命令 #define rd_data XBYTE[0xC300] //读数据 void Delay_lcd(uint n); void lcd_init(void);//lcd初始化 void write_cmd(uchar cmd);//lcd写命令 void write_string(uchar *s);//写字符串 void write_data(uchar dat) ;//写数据 void set_display_place(uchar line,uchar column); void write_string_lcd(uchar line,uchar column,uchar *string); void Ircordpro(void); void Hw_Scan(void); void Ir_work(void); void digit_deal(void); void Delay_lcd(uint n) { uint x; while(n--) { x=500; while(x--); } } /*向LCD输入指令*/ void write_cmd(uchar cmd) { uchar dl; do { dl=rd_com; } while((dl&0x80)!=0);//判忙 wr_com=cmd; Delay_lcd(1); } /*向LCD写入数据*/ void write_data(uchar dat) { uchar dl; do { dl=rd_com; } while((dl&0x80)!=0);//判忙 wr_data=dat; Delay_lcd(1); } /*向LCD写入字符串*/ void write_string(uchar *s) { while(*s!='\0')//'\0'字符串结束标志位 { write_data(*s); s++; } } /*设置字符显示位置*/ void set_display_place(uchar line,uchar column) { uchar address; if(line==1) { address=0x80+column; } else if(line==2) { address=0xc0+column; } write_cmd(address); } /*将字符串显示在LCD特定位置*/ void write_string_lcd(uchar line,uchar column,uchar *string) { set_display_place(line,column); write_string(string); Delay_lcd(1); } /*LCD初始化*/ void lcd_init(void) { write_cmd(0x38); write_cmd(0x06); write_cmd(0x0c); write_cmd(0x01); } void delay(uint t) { uint i; while(t--){for(i=0;i<125;i++){}} } /*向MAX7219写入字节(8位)*/ void SendChar(uchar ch) { uchar i,temp; _nop_(); for(i=0;i<8;i++) { temp=ch&0x80;ch=ch<<1; if(temp) {DIN=1;CLK=0;CLK=1;} else {DIN=0;CLK=0;CLK=1;} } } /*向MAX7219写入字(16位)*/ void WriteWord(uchar addr,uchar num) { LOAD=0; _nop_();SendChar(addr); _nop_();SendChar(num); _nop_(); LOAD=1;//锁存进相应寄存器 } /*初始化MAX7219*/ void Init_MAX7219(void) { WriteWord(DecodeMode,DecodeDigit); //设置译码模式 0x09,0xff WriteWord(Intensity,IntensityGrade);//设置亮度 0x0a,0x0a WriteWord(ScanLimit,ScanDigit); //设置扫描界限 0x0b,0x07 WriteWord(ShutDown,NormalOperation);//设置为正常工作模式 0x0c,0x01 } void write_sj(uchar add,uchar num) { uchar shi,ge; shi=num/10;ge=num%10; WriteWord(add,shi);WriteWord(add+1,ge); } /*红外码值处理*/ void Ircordpro(void)//红外码值处理函数 { uchar i,j,k; uchar cord,value; k=1; for(i=0;i<4;i++)//处理4个字节 { for(j=1;j<=8;j++)//处理1个字节8位 { cord=irdata[k]; if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差 value|=0x80; if(j<8) {value>>=1;} k++; } IRcord[i]=value; value=0; } irpro_ok=1;//处理完毕标志位置1 } /*红外扫描*/ void Hw_Scan(void) { if(irok)//如果接收好了进行红外处理 { Ircordpro();irok=0; } if(irpro_ok)//如果处理好后进行工作处理,如按对应的按键后显示对应的数字等 { Ir_work(); } } void Ir_work(void) { switch(IRcord[2]) { case 0x45: EW_Pass=1;SN_Pass=0;break;//先东西通行 case 0x46: EW_Pass=0;SN_Pass=0;break;//停止按键 case 0x47: EW_Pass=0;SN_Pass=1;break;//先南北通行 case 0x44: ;break; case 0x40: ;break; case 0x43: ;break; case 0x07: ;break;//加1按键 case 0x15: ;break;//减0按键 case 0x09: ;break; // if(Key_count==2) // { // R_sj=10*Szsj[0]+Szsj[1]; // // set_display_place(2,4); // write_data(R_sj/10+0x30); // write_data(R_sj%10+0x30); // // }Key_count=0; // case 0x19: ;break; case 0x0d: ;break; case 0x16: digit=0;break;//数字0键 case 0x0C: digit=1;break;//数字1键 case 0x18: digit=2;break;//数字2键 case 0x5E: digit=3;break;//数字3键 case 0x08: digit=4;break;//数字4键 case 0x1C: digit=5;break;//数字5键 case 0x5A: digit=6;break;//数字6键 case 0x42: digit=7;break;//数字7键 case 0x52: digit=8;break;//数字8键 case 0x4A: digit=9;break;//数字9键 default: break; } irpro_ok=0; } //void digit_deal(void) //{ // if(Key_count<2) // { // Szsj[Key_count]=digit; // Key_count++; // } //} /*外部中断0初始化*/ void EX0init(void)//外部中断0初始化 { IT0=1;//指定外部中断0下降沿触发,INT0(P3.2) EX0=1;//使能外部中断 EA=1;//开总中断 } void Init_Time0(void) { TMOD=0X12;//定时器T0工作方式2,TH0是重装值,TL0是初值;定时器T1工作方式1 TH0=0x00;//重载值 TL0=0x00;//初始化值 ET0=1;//打开定时器T0中断 TR0=1;//启动定时器T0 } void Init_Time1(void) { TMOD=0X12;//定时器T0工作方式2,TH0是重装值,TL0是初值;定时器T1工作方式1 TH1=(65536-46083)/256; TL1=(65536-46083)%256; ET1=1;//打开定时器T1中断 TR1=1;//启动定时器T1 } void main() { lcd_init(); Init_MAX7219(); //MAX7219初始化 WriteWord(DisplayTest,TestMode);//开始显示测试,点亮所有LED 0x0f,0x01 SN_G=0;SN_Y=0;SN_R=0;EW_G=0;EW_Y=0;EW_R=0; delay(3000); //延时约3s WriteWord(DisplayTest,TextEnd); //退出显示测试模式 0x0f,0x00 SN_G=1;SN_Y=1;SN_R=1;EW_G=1;EW_Y=1;EW_R=1; G_sj=15;Y_sj=5;R_sj=20; Init_Time0(); Init_Time1(); EX0init(); while(1) { //digit_deal(); Hw_Scan(); } } void EX0_ISR() interrupt 0 //外部中断0服务函数 { static uchar i;//接收红外信号处理 static bit startflag;//是否开始处理标志位 if(startflag) { if(irtime<63&&irtime>=33)//引导码 TC9012的头码,头吗是9ms+4.5ms和4.5ms+4.5ms均可 i=0;irdata[i]=irtime;//头码存储到0位,存储每个电平的持续时间,用于以后判断是0还是1 irtime=0;i++;//调到下一位 if(i==33) { irok=1;i=0;}//表示存储32位完毕 } else { irtime=0;startflag=1;}//装回初值,有其他干扰使为0 } //T0中断服务程序 void Time0() interrupt 1 using 1 { irtime++;//用于计数2个下降沿之间的时间 } //T1中断服务程序 void Time1() interrupt 3 { TH1=(65536-46083)/256; TL1=(65536-46083)%256; count++; if(count==20) { count=0; if(EW_Pass==1)//东西通行 { R_sj--;write_sj(7,R_sj);write_sj(3,R_sj); if(R_sj>=5) { G_sj--;write_sj(5,G_sj);write_sj(1,G_sj);SN_G=1;SN_Y=1;SN_R=0;EW_G=0;EW_Y=1;EW_R=1; if(G_sj==0) {G_sj=15;} } else { Y_sj--;write_sj(5,Y_sj);write_sj(1,Y_sj);SN_G=1;SN_Y=1;SN_R=0;EW_G=1;EW_Y=0;EW_R=1; if(Y_sj==0) {Y_sj=5;} } if(R_sj==0) {R_sj=20;EW_Pass=0;SN_Pass=1;} } if(SN_Pass==1)//南北通行 { R_sj--;write_sj(5,R_sj);write_sj(1,R_sj); if(R_sj>=5) { G_sj--;write_sj(7,G_sj);write_sj(3,G_sj);SN_G=0;SN_Y=1;SN_R=1;EW_G=1;EW_Y=1;EW_R=0; if(G_sj==0) {G_sj=15;} } else { Y_sj--;write_sj(7,Y_sj);write_sj(3,Y_sj);SN_G=1;SN_Y=0;SN_R=1;EW_G=1;EW_Y=1;EW_R=0; if(Y_sj==0) {Y_sj=5;} } if(R_sj==0) {R_sj=20;SN_Pass=0;EW_Pass=1;} } } }