![]() |
#2
弟大勿勃2015-06-02 19:14
|

#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;}
}
}
}
#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;}
}
}
}