使用Arduino接收紅外遙控編碼并列印到序列槽
IR_PIN 預設為2
/*本程式用來接收NEC紅外編碼
* 程式原理:通過判斷兩次下降沿的周期寬度判斷目前bit是邏輯1還是邏輯0
* 邏輯1 560+1690=2250us 邏輯0 560+560=1120us
* 接收到的資料是低位在前,儲存的bit順序為 0->7
*
*
* 當收到第1個下降沿時認為程式進入等待前導碼階段,即:9ms低+4.5ms高,
* 是以可在下一個下降沿時判斷脈寬是否在13.5ms左右,如果是則标記進入收碼階段,否則傳回重新等待新的下降沿
*
* 進入收碼階段後每次下降沿判斷脈寬,得到邏輯1或0并寫入buf,寫滿1個位元組後轉存至全局變量數組中
*
* 接收IO連續高電平100ms以上時認為收碼結束,标記結束
* loop檢測到收碼結束時列印結果
*
* BH3PXN
* 2020.05.29
*/
#define IR_PIN 2
#define STEP_FREE 0
#define STEP_WAIT_PRECODE 1
#define STEP_RECV_CODE 2
#define STEP_RECV_OVER 3
unsigned char recvStep = STEP_FREE;
unsigned char irCode[100];
unsigned char idx = 0;
void setup() {
// put your setup code here, to run once:
pinMode(IR_PIN, INPUT_PULLUP); //開啟上拉
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
IR_RECV();
outputIRCODE();
}
void outputIRCODE() {
if (recvStep != STEP_RECV_OVER) {
return;
}
recvStep = STEP_FREE; //重置
Serial.print("IR CODE ");
Serial.print(" : ");
for (unsigned char i = 0; i < idx; i++) {
Serial.print(irCode[i],HEX);
Serial.print(" ");
}
Serial.println();
idx = 0;
}
void IR_RECV() {
static unsigned char lastIR = 1;
static unsigned char nowIR = 1;
static unsigned long tus = 0;
static unsigned long tms = 0;
static unsigned long nowus = 0;
static unsigned long t = 0;
static unsigned char irbuf; // 一個位元組的資料
static unsigned char i = 0;
//擷取目前電平
nowIR = digitalRead(IR_PIN);
//高電平維持
if (lastIR && nowIR) {
//大于100ms時傳回
if (millis() - tms > 100) {
t = 0;
if (recvStep == STEP_RECV_CODE) {
recvStep = STEP_RECV_OVER; //接收完成,交給主程式
}
return;
}
}//end lastIR && nowIR
//上升沿 忽略
if (!lastIR && nowIR == HIGH) {
tms = millis();
lastIR = HIGH;
// return;
}
//下降沿
if (lastIR && nowIR == LOW) {
lastIR = LOW;
nowus = micros();
t = nowus - tus;
tus = nowus;
//第1個下降沿
if (recvStep == STEP_FREE) {
tus = nowus;
recvStep = STEP_WAIT_PRECODE; //等待前導碼
return;
}// end recvStep
if (recvStep == STEP_WAIT_PRECODE ) {
if (t >= 12000 && t <= 16000) {
//Serial.print("ir recv begin");
//正确的引導碼
recvStep = STEP_RECV_CODE;
return;
} else {
Serial.print("error pre code,t=");
Serial.print(t);
Serial.println();
recvStep = STEP_FREE;
delay(1000);
return;
}
}
//标準NEC碼:邏輯1 560+1690=2250us 邏輯0 560+560=1120us
//接收到的資料是低位在前,
//邏輯1
if (t >= 1800 && t < 2800) {
irbuf |= 0x01 << i;
i++;
}//end 1
//邏輯0
if (t >= 800 && t < 1800) {
i++;
}//end 0
//接收夠1個位元組,寫入編碼緩存
if (i == 8) {
irCode[idx++] = irbuf;
irbuf = 0x00;
i = 0;
}// end i==8
}// end lastIR && IR == LOW
}// end void IR_RECV()