QC

Điều khiển từ xa IR với 8051

  ĐIỀU KHIỂN TỪ XA IR VỚI 8051

   Bộ điều khiển từ xa và bộ thu IR tuân theo các giao thức tiêu chuẩn để gửi và nhận dữ liệu. Một số giao thức tiêu chuẩn là NEC, JVC, SIRC (Điều khiển từ xa hồng ngoại của Sony), v.v. Chúng ta sẽ chỉ thảo luận về giao thức NEC. Sau khi hiểu định dạng khung của IR Remote, Chúng tôi sẽ giao tiếp bộ thu IR với 8051 và giải mã phím được nhấn.

NEC Protocol

Giao thức NEC IR mã hóa các khóa bằng định dạng khung 32bit như hình dưới đây.
NEC Frame Format
AddressComplement of AddressCommandComplement of Command
LSB-MSB(0-7)LSB-MSB(8-15)LSB-MSB(16-23)LSB-MSB(24-31)
Mỗi bit được truyền bằng cách sử dụng khoảng cách xung như trong hình.
Logic '0': Một xung 562,5µs theo sau bởi một không gian 562,5µs, với tổng thời gian phát là 1,125ms
Logic '0': Một xung 562,5µs theo sau bởi một không gian 1,6875ms, với tổng thời gian phát là 2,25ms



Khi nhấn một phím trên bộ điều khiển từ xa, thông báo được truyền đi bao gồm những điều sau đây, theo thứ tự:

  1. A 9ms leading pulse burst (16 times the pulse burst length used for a logical data bit)
  2. A 4.5ms space
  3. The 8-bit address for the receiving device
  4. The 8-bit logical inverse of the address
  5. The 8-bit command
  6. The 8-bit logical inverse of the command
  7. A final 562.5µs pulse burst to signify the end of message transmission.

Bốn byte bit dữ liệu là mỗi bit ít quan trọng nhất được gửi đầu tiên. Hình ảnh dưới đây minh họa định dạng của khung truyền NEC IR, cho địa chỉ 00h (00000000b) và lệnh ADh (10101101b).

Tổng cộng 67,5ms được yêu cầu để truyền một khung bản tin. Nó cần 27ms để truyền 16 bit địa chỉ (địa chỉ + nghịch đảo) và 16 bit lệnh (lệnh + nghịch đảo).




IR Key Codes

Bảng dưới đây cung cấp danh sách đầy đủ các Mã cho NEC IR Remote.


KeyEncoded Value
CH-0xFFA25D
CH0xFF629D
CH+0xFFE21D
PREV0xFF22DD
NEXT0xFF02FD
PLAY/PAUSE0xFFC23D
VOL-0xFFE01F
VOL+0xFFA857
EQ0xFF906F
00xFF6897
100+0xFF9867
200+0xFFB04F
10xFF30CF
20xFF18E7
30xFF7A85
40xFF10EF
50xFF38C7
60xFF5AA5
70xFF42BD
80xFF4AB5
90xFF52AD

Sample Code


Dưới đây là mã mẫu để giải mã phím được nhấn trên điều khiển từ xa IR và gửi trên UART. Chúng ta cần một ngắt ngoài để phát hiện các xung và bộ đếm thời gian để đo các độ rộng xung này.

- INT0 (P2.2) sẽ được cấu hình như ngắt cạnh rơi để phát hiện các xung.
- Timer0 (Mode1) sẽ được cấu hình để tạo ngắt định kỳ 1ms.

Hai chuyển tiếp đầu tiên sẽ bị bỏ qua vì chúng sẽ đánh dấu SOF (Bắt đầu của khung). Sau khi thông tin 32-bit liên tục này sẽ được ghi lại trong một biến. Nếu độ rộng xung lớn hơn 2ms thì nó sẽ được coi là LOGIC-1 khác là LOGIC-0. Nếu độ rộng xung lớn hơn 50ms thì nó sẽ được coi là SOF (Bắt đầu của khung).

Tính toán độ trễ 1ms:

Tần số đồng hồ = 11.0592 Mhz
Chu kỳ máy = 12
Độ trễ = 1ms
$$ TimerValue = 65536 - ((Độ trễ * ClockFreq) / Chu kỳ máy) = 65536 - ((1ms * 11.0592Mhz) / 12) = 65536 - 921 = 0xFC67 $$

CODE CHƯƠNG TRÌNH.


/*************************
  NEC IR Remote Codes 
**************************  
0xFFA25D: CH-       
0xFF629D: CH        
0xFFE21D: CH+       
0xFF22DD: PREV      
0xFF02FD: NEXT      
0xFFC23D: PLAY/PAUSE
0xFFE01F: VOL-      
0xFFA857: VOL+      
0xFF906F: EQ        
0xFF6897: 0         
0xFF9867: 100+      
0xFFB04F: 200+      
0xFF30CF: 1         
0xFF18E7: 2         
0xFF7A85: 3         
0xFF10EF: 4         
0xFF38C7: 5         
0xFF5AA5: 6         
0xFF42BD: 7         
0xFF4AB5: 8         
0xFF52AD: 9 
**************************/

#include <reg51.h>
#include "lcd.h"
#include "stdutils.h"

uint32_t bitPattern=0,newKey=0;
uint8_t timerValue;
uint8_t msCount=0;
char pulseCount=0;


void timer0_isr() interrupt 1
{
    if(msCount<50)
        msCount++;

    TH0 = 0xFC;   // Reload the timer value for 1ms Delay
    TL0 = 0x67;
}



void externalIntr0_ISR()  interrupt 0
{
    timerValue = msCount;
    msCount = 0;

    TH0 = 0xFC;  // Reload the timer value for 1ms Delay
    TL0 = 0x67;

    pulseCount++;

    if((timerValue>=50)) // If the pulse width is greater than 50ms, this will mark the SOF
    { 
        pulseCount = -2; // First 2 counts needs to be skipped hence pulse count is set to -2 
        bitPattern = 0;
    }
    else if((pulseCount>=0) && (pulseCount<32)) //Accumulate the bit values between 0-31.
    {  
        if(timerValue>=2)                      //pulse width greater than 2ms is considered as LOGIC1
        {
            bitPattern |=(uint32_t)1<<(31-pulseCount);
        }
        else
        {

        }
    }
    else if(pulseCount>=32)                  //This will mark the End of frame as 32 pulses are received
    {
        newKey = bitPattern;                // Copy the newKey(patter) and set the pulse count to 0;
        pulseCount = 0;
    }
}


void main()
{

    /*Connect RS->P0.0, RW->P0.1, EN->P0.2 and data bus to P0.4 to P0.7*/
    LCD_SetUp(P0_0,P0_1,P0_2,P_NC,P_NC,P_NC,P_NC,P0_4,P0_5,P0_6,P0_7);
    LCD_Init(2,16);

    TMOD |= 0x01; // Timer0 MODE1(16-bit timer)
    TH0 = 0xFC;   //Timer value for 1ms at 11.0592Mhz clock
    TL0 = 0x67;
    TR0 = 1;       // Start the Timer
    ET0 = 1;       // Enable the Timer0 Interrupt
    
    IT0 = 1;       // Configure INT0 falling edge interrupt
    EX0 = 1;       // Enable the INT0 External Interrupt
    
    EA  = 1;       // Enable the Global Interrupt bit

    LCD_DisplayString("Init Done");
    while(1)
    {
        if(newKey!=0)		 //Wait till newKey press is detected
        {  
            LCD_Clear();	 //Clear the LCD and Display the new Key Code
            LCD_Printf("newKey:%X",newKey);
            newKey = 0;		 //CLear the newKey value for next cycle
        }
    }		
}	  

DÙNG THƯ VIỆN.

#include <reg51.h>
#include "stdutils.h"
#include "nec_ir.h"

sbit RELAY_PIN = P3^4;

void main()
{
    uint32_t key;
    RELAY_PIN = 0;	  // Turn OFF the relay during Init
    IR_RemoteInit();  // Initialtile the INTO and Timer0 for decoding the IR pulses

    while(1)
    {
        key = IR_RemoteGetKey();  // Read the key press, it returns key code if key press is detected, else it returns 0

        switch(key)
        {
        case IR_CODE_1: RELAY_PIN = 1; break; /* Turn On Relay(Bulb) if 1 is pressed*/
        case IR_CODE_0: RELAY_PIN = 0; break; /* Turn OFF Relay(Bulb) if 0 is pressed*/
        default: break;
        }
    }		
}	  




Nap Code vào PY32F003 dùng Stlink

 Nap Code vào PY32F003 dùng Stlink Bước 1: Cài đặt  KeilC v5.39 theo link sau ( chú ý 5.39 keil c mới nạp ok). https://edge07.111.ir.cdn.ir/...