
我们先看一段波形
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);
}