圣源电子制作

标题: HT6121/6122 ICNEC的编码格式- 汇编,C语言程序 C51单片机 [打印本页]

作者: sydz    时间: 2011-10-10 14:37
标题: HT6121/6122 ICNEC的编码格式- 汇编,C语言程序 C51单片机
(, 下载次数: 57)

功能说明
红外接收程序。适用于市场上用量最大的HT6121/6122及其兼容IC的编码。
对于用户码与User_code定义不同的遥控器,程序会将用户码一起从串口输出。
使用模拟串口发送监控显示编码,显示内容为ASCII码和中文。
本接收程序基于状态机的方式,占用CPU的时间非常少。

C程序
  1. /*************    用户系统配置    **************/

  2. #define MAIN_Fosc        12000000L    //定义主时钟, 模拟串口和红外接收会自动适应。5~36MHz

  3. #define D_TIMER0        125            //选择定时器时间, us, 红外接收要求在60us~250us之间

  4. #define    User_code        0xFD02        //定义红外接收用户码


  5. /*************    以下宏定义用户请勿修改    **************/
  6. #include    "reg51.H"
  7. #define    uchar    unsigned char
  8. #define uint    unsigned int

  9. #define freq_base            (MAIN_Fosc / 1200)
  10. #define Timer0_Reload        (65536 - (D_TIMER0 * freq_base / 10000))




  11. /*************    本地常量声明    **************/



  12. /*************    本地变量声明    **************/
  13. sbit    P_TXD1 = P3^1;        //定义模拟串口发送脚,打印信息用
  14. sbit    P_IR_RX = P0^1;        //定义红外接收输入端口

  15. bit        P_IR_RX_temp;        //Last sample
  16. bit        B_IR_Sync;            //已收到同步标志
  17. uchar    IR_SampleCnt;        //采样计数
  18. uchar    IR_BitCnt;            //编码位数
  19. uchar    IR_UserH;            //用户码(地址)高字节
  20. uchar    IR_UserL;            //用户码(地址)低字节
  21. uchar    IR_data;            //数据原码
  22. uchar    IR_DataShit;        //数据反码

  23. bit        B_IrUserErr;        //User code error flag
  24. bit        B_IR_Press;            //Key press flag,include repeat key.
  25. uchar    IR_code;            //IR code    红外键码


  26. /*************    本地函数声明    **************/
  27. void    Tx1Send(uchar dat);
  28. uchar    HEX2ASCII(uchar dat);
  29. void    InitTimer(void);
  30. void    PrintString(unsigned char code *puts);



  31. /*************  外部函数和变量声明 *****************/



  32. /********************* 主函数 *************************/
  33. void main(void)
  34. {
  35.     InitTimer();        //初始化Timer
  36.    
  37.     PrintString("****** STC系列MCU红外接收程序 2010-12-10 ******\r\n");    //上电后串口发送一条提示信息

  38.     while(1)
  39.     {
  40.         if(B_IR_Press)        //有IR键按下
  41.         {
  42.             PrintString("红外码: 0x");            //提示红外键码
  43.             Tx1Send(HEX2ASCII(IR_code >> 4));    //键码高半字节
  44.             Tx1Send(HEX2ASCII(IR_code));        //键码低半字节
  45.             if(B_IrUserErr)                        //用户码错误,则发送用户码
  46.             {
  47.                 Tx1Send(’ ’);                    //发空格
  48.                 Tx1Send(’ ’);                    //发空格
  49.                 PrintString("用户码: 0x");        //提示用户码
  50.                 Tx1Send(HEX2ASCII(IR_UserH >> 4));    //用户码高字节的高半字节
  51.                 Tx1Send(HEX2ASCII(IR_UserH));        //用户码高字节的低半字节
  52.                 Tx1Send(HEX2ASCII(IR_UserL >> 4));    //用户码低字节的高半字节
  53.                 Tx1Send(HEX2ASCII(IR_UserL));        //用户码低字节的低半字节
  54.             }
  55.             Tx1Send(0x0d);        //发回车
  56.             Tx1Send(0x0a);        //发回车
  57.             B_IR_Press = 0;        //清除IR键按下标志
  58.         }
  59.     }
  60. }


  61. /********************* 十六进制转ASCII函数 *************************/
  62. uchar    HEX2ASCII(uchar dat)
  63. {
  64.     dat &= 0x0f;
  65.     if(dat <= 9)    return (dat + ’0’);    //数字0~9
  66.     return (dat - 10 + ’A’);            //字母A~F
  67. }




  68. //*******************************************************************
  69. //*********************** IR Remote Module **************************

  70. //*********************** IR Remote Module **************************
  71. //this programme is used for Receive IR Remote (HT6121).

  72. //data format: Synchro,AddressH,AddressL,data,/data, (total 32 bit).

  73. //send a frame(85ms), pause 23ms, send synchro of another frame, pause 94ms

  74. //data rate: 108ms/Frame


  75. //Synchro:low=9ms,high=4.5/2.25ms,low=0.5626ms
  76. //Bit0:high=0.5626ms,low=0.5626ms
  77. //Bit1:high=1.6879ms,low=0.5626ms
  78. //frame sPACe = 23 ms or 96 ms

  79. /******************** 红外采样时间宏定义, 用户不要随意修改    *******************/

  80. #if ((D_TIMER0 <= 250) && (D_TIMER0 >= 60))
  81.     #define    D_IR_sample            D_TIMER0        //定义采样时间,在60us~250us之间
  82. #endif

  83. #define D_IR_SYNC_MAX        (15000/D_IR_sample)    //SYNC max time
  84. #define D_IR_SYNC_MIN        (9700 /D_IR_sample)    //SYNC min time
  85. #define D_IR_SYNC_DIVIDE    (12375/D_IR_sample)    //decide data 0 or 1
  86. #define D_IR_DATA_MAX        (3000 /D_IR_sample)    //data max time
  87. #define D_IR_DATA_MIN        (600  /D_IR_sample)    //data min time
  88. #define D_IR_DATA_DIVIDE    (1687 /D_IR_sample)    //decide data 0 or 1
  89. #define D_IR_BIT_NUMBER        32                    //bit number

  90. //*******************************************************************************************
  91. //**************************** IR RECEIVE MODULE ********************************************

  92. void IR_RX_HT6121(void)
  93. {
  94.     uchar    SampleTime;

  95.     IR_SampleCnt++;                            //Sample + 1

  96.     F0 = P_IR_RX_temp;                        //Save Last sample status
  97.     P_IR_RX_temp = P_IR_RX;                    //Read current status
  98.     if(F0 && !P_IR_RX_temp)                    //Last sample is high,and current sample is low, so is fall edge
  99.     {
  100.         SampleTime = IR_SampleCnt;            //get the sample time
  101.         IR_SampleCnt = 0;                    //Clear the sample counter

  102.              if(SampleTime > D_IR_SYNC_MAX)        B_IR_Sync = 0;    //large the Maxim SYNC time, then error
  103.         else if(SampleTime >= D_IR_SYNC_MIN)                    //SYNC
  104.         {
  105.             if(SampleTime >= D_IR_SYNC_DIVIDE)
  106.             {
  107.                 B_IR_Sync = 1;                    //has received SYNC
  108.                 IR_BitCnt = D_IR_BIT_NUMBER;    //Load bit number
  109.             }
  110.         }
  111.         else if(B_IR_Sync)                        //has received SYNC
  112.         {
  113.             if(SampleTime > D_IR_DATA_MAX)        B_IR_Sync=0;    //data samlpe time to large
  114.             else
  115.             {
  116.                 IR_DataShit >>= 1;                    //data shift right 1 bit
  117.                 if(SampleTime >= D_IR_DATA_DIVIDE)    IR_DataShit |= 0x80;    //devide data 0 or 1
  118.                 if(--IR_BitCnt == 0)                //bit number is over?
  119.                 {
  120.                     B_IR_Sync = 0;                    //Clear SYNC
  121.                     if(~IR_DataShit == IR_data)        //判断数据正反码
  122.                     {
  123.                         if((IR_UserH == (User_code / 256)) &&
  124.                             IR_UserL == (User_code % 256))
  125.                                 B_IrUserErr = 0;    //User code is righe
  126.                         else    B_IrUserErr = 1;    //user code is wrong
  127.                            
  128.                         IR_code      = IR_data;
  129.                         B_IR_Press   = 1;            //数据有效
  130.                     }
  131.                 }
  132.                 else if((IR_BitCnt & 7)== 0)        //one byte receive
  133.                 {
  134.                     IR_UserL = IR_UserH;            //Save the User code high byte
  135.                     IR_UserH = IR_data;                //Save the User code low byte
  136.                     IR_data  = IR_DataShit;            //Save the IR data byte
  137.                 }
  138.             }
  139.         }
  140.     }
  141. }


  142. /**************** Timer初始化函数 ******************************/
  143. void InitTimer(void)
  144. {
  145.     TMOD = 0;        //for STC15Fxxx系列    Timer0 as 16bit reload timer.
  146.     TH0 = Timer0_Reload / 256;
  147.     TL0 = Timer0_Reload % 256;
  148.     ET0 = 1;
  149.     TR0 = 1;

  150.     EA  = 1;
  151. }


  152. /********************** Timer0中断函数************************/
  153. void timer0 (void) interrupt 1
  154. {
  155.     IR_RX_HT6121();
  156. }


  157. /********************** 模拟串口相关函数************************/

  158. void    BitTime(void)    //位时间函数
  159. {
  160.     uint i;
  161.     i = ((MAIN_Fosc / 100) * 104) / 140000 - 1;        //根据主时钟来计算位时间
  162.     while(--i);
  163. }

  164. //模拟串口发送
  165. void    Tx1Send(uchar dat)        //9600,N,8,1        发送一个字节
  166. {
  167.     uchar    i;
  168.     EA = 0;
  169.     P_TXD1 = 0;
  170.     BitTime();
  171.     for(i=0; i<8; i++)
  172.     {
  173.         if(dat & 1)        P_TXD1 = 1;
  174.         else            P_TXD1 = 0;
  175.         dat >>= 1;
  176.         BitTime();
  177.     }
  178.     P_TXD1 = 1;
  179.     EA = 1;
  180.     BitTime();
  181.     BitTime();
  182. }

  183. void PrintString(unsigned char code *puts)        //发送一串字符串
  184. {
  185.     for (; *puts != 0;    puts++)  Tx1Send(*puts);     //遇到停止符0结束
  186. }

复制代码

汇编程序

NEC码遥控器解码程序(89S52 汇编语言版)

NEC码的遥控器用单片机解码。

首先解码的必须知道 NEC格式是如何的,红外接收头是接收后是怎样的,程序是把红外接收头接收的信号转变成我们看得懂的16进制通过数码管显示出来。

1.NEC格式:可参考SC6122的规格书,引导码是9ms高电平加4.5ms的低电平

接下来是8位客户码和8位客户码的反码,再接下来就是8位数据码和八位数据码的反码

“0”是0.56ms 的高电平和0.56ms的低电平表示

“1”是0.56ms 的高电平和1.69ms的低电平表示

除引导码外总共16位。

2.红外接收头接收后的数据刚好是跟NEC相反,如下:(若加个反相器的话就是一样的,这块板子上没加)

引导码是9ms低电平加4.5ms的高电平

接下来是8位客户码和8位客户码的反码,再接下来就是8位数据码和八位数据码的反码

“0”是0.56ms 的低电平和0.56ms的高电平表示

“1”是0.56ms 的低电平和1.69ms的高电平表示

3.把红外遥控器的接收的数据装换成我们能看的懂的十六进制从数码管显示(p2口控制8个数码的公共脚,P0 控制笔画A,B,C,D,E,F,G)

P3.2位外部中断口

4.程序的基本思路:

    判断P3.2的是否有脉冲即是否有接收到信号

  再通过判断接收的信号是否符合NEC的引导码的格式,即高低电平的时间是否正确。

不符合的话则判断为干扰信号,不予以处理,等待下次中断

符合则继续解码,通过特定的延时条件去抓到每一位的数据存放与某内存区(此处为1A,1B,1C,1D)共四个八位数据

再把需要显示的客户码和数据码(在1A和1C 存储区里面)通过16进制转换后在数码管显示


如下

  1. ORG 0000H
  2. AJMP MAIN
  3. ORG 0003H
  4. AJMP INT
  5. MAIN: SETB EA
  6. SETB IT0
  7. SETB EX0
  8. MOV P1, #11111111B
  9. AJMP $
  10. INT: CLR EA
  11.      MOV R6,#10
  12.      SB:ACALL YS1
  13.      JB P3.2,EXIT
  14.      DJNZ R6,SB
  15.      JNB P3.2, $
  16.      ACALL YS2
  17.      MOV R1,#1AH
  18.      MOV R2,#4
  19.      PP:MOV R3,#8
  20. JJJJ:JNB P3.2,$
  21.       LCALL YS1
  22.       MOV C,P3.2
  23.       JNC UUU
  24.       LCALL YS3
  25. UUU:  MOV A,@R1
  26.       RRC A
  27.       MOV @R1,A
  28.       DJNZ R3,JJJJ;确定第一个八位是否已经存储完成
  29.       INC R1;存储位置累加放下一个八位
  30.       DJNZ R2,PP;确定四个八位是否已经完成储存
  31.       CLR P3.7
  32.       LCALL YS2
  33.       SETB P3.7;喇叭提示解码成功
  34.       MOV R2,#100
  35. DISPLAY: MOV P1,1AH
  36.       MOV R1,1AH
  37.       MOV A,R1
  38.       MOV B,#16
  39.       DIV AB;十六进制转换
  40.       MOV R6,A;十位送r6
  41.       mov R7,B;十位送r6
  42.       MOV DPTR,#TABLE
  43.       CLR P2.6
  44.       MOV A,R7
  45.       MOVC A,@A DPTR
  46.       MOV P0,A
  47.       LCALL YS3
  48.       LCALL YS3
  49.       SETB P2.6
  50.       CLR P2.7
  51.       MOV A,R6
  52.       MOVC A,@A DPTR
  53.       MOV P0,A
  54.       LCALL YS3
  55.    
  56.       SETB P2.7
  57.       MOV R1,1CH
  58.       MOV A,R1
  59.       MOV B,#16
  60.       DIV AB;十六进制转换
  61.       MOV R7,A;十位送r6
  62.       mov R6,B;GE位送r6
  63.       MOV DPTR,#TABLE
  64.       CLR P2.5
  65.       MOV A,R7
  66.       MOVC A,@A DPTR
  67.       MOV P0,A
  68.       LCALL YS3
  69.    
  70.       SETB P2.5
  71.       CLR P2.4
  72.       MOV A,R6
  73.       MOVC A,@A DPTR
  74.       MOV P0,A
  75.       LCALL YS3
  76.      SETB P2.4
  77.       DJNZ R2,DISPLAY
  78.       EXIT:SETB EA
  79.       RETI


  80. YS1:MOV R4,#20
  81.       D1:MOV R5,#20
  82.       DJNZ R5,$
  83.       DJNZ R4,D1
  84.       RET
  85. YS2:MOV R4,#10
  86.       D2:MOV R5,#235
  87.       DJNZ R5,$
  88.       DJNZ R4,D2
  89.       RET
  90. YS3:MOV R4,#2
  91.       D3:MOV R5,#248
  92.       DJNZ R5,$
  93.       DJNZ R4,D3
  94.       RET

  95. TABLE:DB 3FH,06H,5BH,4FH,66H;0-4
  96.       DB 6DH,7DH,07H,7FH,6FH;5-9
  97.       DB 77H,7CH,39H,5EH;A-D
  98.       DB 79H,71H;E-F

  99.       END
复制代码





作者: sydz    时间: 2011-10-10 14:38
http://bbs.syyyd.com/forum.php?mod=attachment&aid=NjM3OHwyNWJjNTI1OWMxMjU0OGQwYmE0OGE2ODEwYmE2NTU1OHwxNzMxNTU2NTI0&request=yes&_f=.swf





欢迎光临 圣源电子制作 (http://bbs.syyyd.com/) Powered by Discuz! X3.4