#include<reg51.h>
#include <At24c08.h> /* 使用At24c08 作存储ic */
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define Key_Study 0x08
#define ms *77
#define mms *7
/* 定义 1 mms = 100us */
#define LEDLen 3
uchar LEDBuf[LEDLen] = {0,0,0} ; /* 显示的数据缓存 */
sbit contro_in = P3^2; /* 外部控制信号输入 */
sbit in = P1^7; /* 外部红外信号输入 */
sbit out = P1^6; /* 红外信号控制输出 */
sbit key_study = P3^3; /* 学习操作按钮 */
//sbit SDA = P3^6; // 24c08 pin 5
//sbit SCL = P3^7; // 24c08 pin 6
void delay(uint delay_time) { uint i; for (i=0; i < delay_time ; i++); } /* 延时程序,最大800ms */
void Ldelay(ulong delay_time){ ulong i; for (i=0; i < delay_time ; i++); } /* 长时间延时,可以秒为单位 */
uchar studing(); /* 接收红外线,返回红外功能码,因为地址码为0xa23d固定 */
void sendPWM(ulong before_delay_time,uchar func); /* 根据前延时,功能码,发送红外线控制码 */
uchar read_num(uchar num); /* 读播码盘 */
void study(); /* 学习操作过程 */
void display(); /* 显示 LEDBuf[LEDLen] 中的数据 */
void send(); /* 发送操作过程 */
bit scan_key( bit Key_state, uchar Key ); /* 键盘扫描 */
void main(){
while(1){
if ( !scan_key(0, Key_Study) ){
while( scan_key(1,Key_Study) ); /* 等待键弹起 */
study();
}
else {
send();
}
}
}
void send() {
/* 根据接收的控制脉冲,发射对应编码 */
#define Time5ms 5000
#define th0 (65535 - Time5ms ) >> 8
#define tl0 65535 - Time5ms
uchar before_delay_time = 0, hongwai_code = 0, num = 0, i = 0, tmp;
uint address_24c08 = 0;
/* 定时器为 16 位 模式, 并允许定时器中断 */
TMOD = 0X01; //GATE C/T M1 M0 time0 enble 16 bit
IE = 0X82; //1000 0010 EA(all) - -(et2) ES ET1 EX1 ET0 EX0 page9
TR0 = 0;
tmp = 0;
LEDBuf[2] = 1;
display();
while(1){
/* 求5ms内,脉冲的个数, 根据 频率 = 12M ,一次溢出为 0xffff(65535) 微秒 */
num = 0;
while(1){
while(contro_in);
TH0 = th0; /* 超出5ms溢出,并产生中断,TR0 将自动为0 */
TL0 = tl0;
TR0 = 1; /* 启动定时器 */
/* 脉冲为低时停止定时器 或 溢出时自动停止 */
while( TR0 & !contro_in );
if ( TR0 ) continue;
else break;
} /* 虑掉脉冲间的间隔 */
TH0 = th0; /* 超出5ms溢出,并产生中断,TR0 将自动为0 */
TL0 = tl0;
while(!contro_in);
TR0 = 1;
while(1){ /* 求 5ms 内脉冲个数 */
while( contro_in );
while( !contro_in & TR0 );
num ++;
if ( !TR0 ) break;
}
LEDBuf[2] = num;
display();
if ( num == tmp ) continue;
tmp = num;
i = 0;
address_24c08 = num * 100;
while(1){ /* 根据脉冲个数,读取通道的红外编码及发射前延时时间 */
hongwai_code = read_random( address_24c08 + i * 2 + 1 );
if ( hongwai_code == 0 ) break;
before_delay_time = read_random( address_24c08 + i * 2 );
sendPWM(before_delay_time, hongwai_code );
i++;
if (i > 40) break;
}
}
}
void study(){
/* 进入学习操作例程 */
#define TongDao 0xef
#define Before_delay_time 0xdf
#define set_display_hongwai_code() { LEDBuf[0] = hongwai_code / 100; LEDBuf[1] = (hongwai_code % 100) / 10; LEDBuf[2] = hongwai_code % 10;}
uchar num = 0, i = 0, curr_num = 0, hongwai_code = 0, before_delay_time = 0;
uint address_24c08 = 0, curr_address =0;
while(1){
while( scan_key(1, Key_Study) ) display(); // key = P1;
curr_num = read_num(TongDao); /* 读通道号 */
if ( curr_num != num ) {
LEDBuf[2] = curr_num;
display();
Ldelay(100ms);
curr_address = curr_num * 100; /* 把新通道的存储区清0 */
for ( i = 0; i < 100; i++ ){
address_24c08 = curr_address;
write_byte( address_24c08 + i, 0 );
LEDBuf[2] = i;
display();
}
i = 0;
num = curr_num;
}
LEDBuf[2] = i % 10 + 1; /* 显示当前通道的第几步 */
display();
hongwai_code = studing(); /* 学习红外线编码 */
address_24c08 = curr_address + i * 2 + 1;
write_byte( address_24c08, hongwai_code ); /* 把编码保存到 24c08 */
before_delay_time = read_num(Before_delay_time ); /* 读播码盘的时间设置 */
address_24c08 = curr_address + i * 2;
write_byte( address_24c08, before_delay_time ); /* 保存前延时时间 以秒为单位 */
set_display_hongwai_code(); /* 显示编码 */
i++;
if ( i >= 40 ) i = 0; /* 最大每通道控制 40 个遥控键 */
}
}
uchar read_num(uchar num){ /* 读播码盘,通道设置号 或 发射一个编码前的延时,以秒为单位 */
uchar tmp;
P1 = P1 & num;
tmp = P1;
P1 = P1 | (0xff - num);
tmp = 0x0f & tmp; /* 屏蔽高4位 */
tmp = 0x0f - tmp; /* 求反 */
return tmp;
}
uchar studing(){
/* 学习编码函数,返回功能码 */
#define Len 32
uint pulse_width;
uchar tmp,i;
while(1){
while(in);
while(!in);
while(in) pulse_width ++;
if (pulse_width < 500 & pulse_width > 600 ) { /* 通过接收红外线信号学习 */
/* pulse_width = 560 时开始 */
pulse_width = 0;
continue;
}
for ( i = 0 ; i < Len ; i++) { /* 根据记录的高电平脉冲宽度,260 为 1, 70 为0 */
pulse_width = 0;
while(!in);
while(in) pulse_width ++;
if (pulse_width > 150 ) tmp = tmp | 1;
if (i < Len -1) tmp = tmp << 1;
}
break;
}
tmp = 0xff - tmp; /* 取最后8位,并求反,因为最后8位为功能反码 */
return tmp; /* 返回功能码 */
}
void sendPWM(ulong before_delay_time, uchar func) {
/* 发送红外控制信号, 控制 4069的 38k 信号的通断, before_delay_time 为发射一个码前延时秒数,func 为功能码 */
// address = 10100010 00111101 = 0xa23d
#define s *7000
#define address 0xa23d
#define head_time 700
#define H_head_time 350
#define low_time 49
#define high0_time 49
#define high1_time 98
#define send_star() out="0";
#define send_stop() out="1";
uchar i;
ulong ul_out, p = 0x80000000;
if ( before_delay_time == 0 ) Ldelay( 1 s / 2 );
Ldelay(before_delay_time s);
ul_out = address ;
ul_out = ul_out << 8;
//ul_out = ul_out | ~address;
//ul_out = ul_out << 8;
ul_out = ul_out | func;
ul_out = ul_out << 8;
ul_out = ul_out | ~func;
//out start
send_star();
delay(head_time); // delay 9 ms
send_stop();
delay(H_head_time); // delay 4.5ms
//out
for(i = 0; i < 32 ;i++){
send_star();
delay(low_time);
send_stop();
// 10100010 00111101 10001000 01110111
if(p & ul_out)
delay(high1_time); //out 1
else
delay(high0_time); //out 0
p = p >> 1;
}
send_star();
delay(low_time);
send_stop();
}
bit scan_key( bit Key_state, uchar Key ){ /* 键盘扫描,Key_state 为1时,等待按键复位 */
#define Port P3
if ( (Port & Key ) == 0 ) {
delay(8ms);
if ( (Port & Key ) == 0 ) {
if ( Key_state) { while(1) if ( (Port & Key ) != 0 ) break; }
return 0;
}
}
return 1;
}
void display(){
uchar i;
for(i = 0; i < LEDLen ; i ++){
P2 = 0xff;
P2 &= 0xf0;
P2 = P2 | LEDBuf ;
if(i==0) P2 = P2 & 0xef; // led_1 = 0; //P2^4
if(i==1) P2 = P2 & 0xdf; // led_10 =0; //P2^5
if(i==2) P2 = P2 & 0xbf; // led_100 = 0; //P2^6
delay(3ms);
}
}
void time0_50ms(void) interrupt 1{
TR0 = 0; //time0 stop
}
文章评论(0条评论)
登录后参与讨论