ESP32 手动编码IR NES 信号

我们先看一段波形

NES信号是由下列几个部分组成

9ms引导脉冲
8位地址码
8位地址补码
8位命令
8位命令补码
650µs结束脉冲

NES编码速率位38kHz,那么每个脉冲的持续宽度=1S/38.222kHz/2 = 13µs

逻辑 1 波形是这么组成:
562.5µs脉冲+1.6875ms空隙

逻辑 0 波形是这么组成:
562.5µs脉冲+562.5µs缝隙

下面我们可以手动解码第一张图的波形
引导脉冲部分:


解码地址码:

可以从图上看到我们地址码是00000001b=0x01
解码命令码:

命令码位01011000b =0x58
下面我们开始用程序进行编码
首先我们要定以如何输出一个脉冲

从上面祭算出一个脉冲的宽度位13µs, 我们先要从一个GPIO口上先拉高13µs再拉低13µs总计26µs(这个时间并非一定,不要差距太夸张就没问题)

void ir_nec_pulse(int gpioNumber)
{
  gpio_set_level(gpioNumber, 1);
  usleep(13);
  gpio_set_level(gpioNumber, 0);
  usleep(13);
}

实现引导脉冲:
脉冲数=9ms/26µs=346次

void ir_nec_boot_code(int gpioNumber){
  gpio_set_level(gpioNumber, 0);
  vTaskDelay(100 / portTICK_PERIOD_MS);
  for(int i = 0; i < 346; i++){
    ir_nec_pulse(gpioNumber);
  }
}

实现结束脉冲:
脉冲数=650µs/26µs=25次

void ir_nec_end_code(int gpioNumber){
for(int i = 0; i < 25; i++){
  ir_nec_pulse(gpioNumber);
}
  gpio_set_level(gpioNumber, 0);
  vTaskDelay(300 / portTICK_PERIOD_MS);
}

实现逻辑1

void ir_nec_hight(int gpioNumber)
{
  for(int i = 0; i <= 24; i++){
    ir_nec_pulse(gpioNumber);
  }
    usleep(1690); //1.69ms
  }
  实现逻辑0
  void ir_nec_low(int gpioNumber)
  {
    for(int i = 0; i <= 24; i++){
    ir_nec_pulse(gpioNumber);
  }
  usleep(560); //0.56ms
}

编码数据:

void ir_nec_encode_data(int gpioNumber, unsigned int data)
{
  int num = data;
    for(int i = 7; i >= 0; i--){
    if(num >> i & 0x01){
      ir_nec_hight(gpioNumber);
    }else{
      ir_nec_low(gpioNumber);
    }
  }
  //inverse data
  for(int i = 7; i >= 0; i--){
    if(num >> i & 0x01){
      ir_nec_low(gpioNumber);
    }else{
      ir_nec_hight(gpioNumber);
    }
  }
}

实现完整的编码流程

void ir_nec_encode(int gpioNumber, unsigned int code)
{
  // boot code
  ir_nec_boot_code(gpioNumber);
  usleep(4500); //4.5ms
  // address code
  unsigned char address = (code >> (8*1)) & 0xff;
  ir_nec_encode_data(gpioNumber, address);
  // command code
  unsigned char command = (code >> (8*0)) & 0xff;
  ir_nec_encode_data(gpioNumber, command);
  // end code
  ir_nec_end_code(gpioNumber);
}