原创 DVD遥控学习机(c语言51单片机)

2007-5-29 23:19 8735 6 6 分类: MCU/ 嵌入式

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

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
6
关闭 站长推荐上一条 /3 下一条