要準備的實驗器材如(圖1)
DIY 線路請參考(圖2)
我接一個座,方便日後可替換IR Receiver (圖3)
由上一篇文章 紅外線遙控器(1/2) IR(Infrared ) NEC Protocol
幾個波形
依下列原理:
Projedt IR_Capture 介紹:
main.c中:
初始化cpu clock 48Mhz.
週邊設定:
uart 115200
32 bit timmer 0,每一個counter 同於一個cpu clock ,啟動 capture pin1_5/CT32B0_CAP0 ,啟動timer0
若IR 解碼有效,從uart送出資料,並且讓LED閃爍
Timer32.c中:
fuction void TIMER32_0_IRQHandler(void)s內,
Faling edge時候會進入這段code,
接著就做解碼動作.
ir_decoder_nec.c 中
void IR_decoder(uint32_t cnt)
計算前次與今次counter誤差,並紀錄counter值,
判斷兩個Faling edge的寬度
state machine 來做不狀態處理
Idle模式處理,
若decode為start訊號,進入下個state
若進入start 階段,
decode為 '1' or '0' 進入Address decode狀態
若否則回到idle狀態
進入Address or Commad decode狀態時,處理方式概念是相同.
若是前8個bit,且若decode為1,因為訊號的的順序是MSB ot LSB.
若以就進1往MSB推一位元入data變數中
若是後8個bit,且若decode為1,因為訊號的的順序是MSB ot LSB.
若以就進1往MSB推一位元入n_data變數中
當讀滿16個bit先判斷data與n_data是否互為1的補數
若是就進入下個階段,Address decode完成就往 Command decode階段.
若Command decode完成就進入idle階段,並且將有效解碼的flag設為1.
若非互為1的補數,資料有誤.
放棄解這次的封包,並且進入idle狀態.等待下次的start 訊號.
若發生未預期狀態則回到idle狀態
用putty (putty不知道怎麼設定使用,可參考 Hello World! UART )來試試看遙控器的解碼結果吧.
見圖5中,Address有兩種值,這是拿了不同遙控器測試解出來的結果.
通常Address就是來區分不同廠家或是不同設備,而Command代表的當然就是不同按鈕的功能.
參考範例請至此下載 Download
- LPCXPresso
- DIY Base board
- USB A to mini(接PC/NB 與LPCXpresso)
- RS232 cable接PC/NB 與 DIY Base board)
- 新的IR Receiver線路(圖2)
- 紅外線遙控器
(圖1) |
DIY 線路請參考(圖2)
(圖2) |
我接一個座,方便日後可替換IR Receiver (圖3)
(圖3) |
由上一篇文章 紅外線遙控器(1/2) IR(Infrared ) NEC Protocol
幾個波形
- 邏輯 "1" 一個560us的high接著low,總長2.25ms
- 邏 輯 "0" 一個560us的high接著low 560us,總長1.12ms
- 開始 9ms的high,接著4.5ms low,總長 13.5ms
- 重複 9ms的high,接著2.25ms low,總長 11.25ms
- 由 protocol得知,完成的一串傳輸會有 一個 開始訊號+4個BYTE,又因為傳輸兩次作增加可靠 性,兩次位址互為1的補數,操作命令亦同.所以4個BYTE綜合為16個'1'與16個'0',因此得到完整傳輸資料總長為 13.5+2.25X16+1.12X16=67.42ms
依下列原理:
- timer中的capture可以設定在pulse的上升緣(Rising edge)或是下降緣 (Failing edge)的時候中斷,並且擷取中斷時候的timer counter值
- 因為timer counter值是cpu 時脈的某種倍數關係.所以每counter 累積1次就是經過固定的時間
- 兩個Rising/Falling edge之間的counter之差就是這個pulse的時間寬度
- 再由時間寬度來判斷,這個pulse是 start , '1' ,'0' or repeat
(圖4) |
main.c中:
初始化cpu clock 48Mhz.
SystemInit();
週邊設定:
uart 115200
UARTInit(115200);
32 bit timmer 0,每一個counter 同於一個cpu clock ,啟動 capture pin1_5/CT32B0_CAP0 ,啟動timer0
init_timer32( 0,period);
enable_timer32(0);
若IR 解碼有效,從uart送出資料,並且讓LED閃爍
while (1) /* Loop forever */
{
#if(UART_ENABLE==1)
if(valid_key ==1)
{
GPIOSetValue(0,7,1);
printf("Address = %x \a",ir_address);
printf("Command = %x \n",ir_command);
valid_key = 0;
GPIOSetValue(0,7,0);
}
#endif
}
Timer32.c中:
fuction void TIMER32_0_IRQHandler(void)s內,
Faling edge時候會進入這段code,
if ( LPC_TMR32B0->IR & (0x1<<4) ) { LPC_TMR32B0->IR = 0x1<<4; /* clear interrupt flag */ IR_decoder(LPC_TMR32B0->CR0);
}
接著就做解碼動作.
ir_decoder_nec.c 中
void IR_decoder(uint32_t cnt)
計算前次與今次counter誤差,並紀錄counter值,
count_new= cnt;
temp = count_new-count_old;
count_old=count_new;
判斷兩個Faling edge的寬度
if((temp>=BIT_START_MIN)&&(temp<=BIT_START_MAX)) { data_decoded = DATA_START; } else if((temp>=BIT_ONE_MIN)&&(temp<=BIT_ONE_MAX)) { data_decoded = DATA_ONE; } else if((temp>=BIT_ZERO_MIN)&&(temp<=BIT_ZERO_MAX)) { data_decoded = DATA_ZERO; } else if((temp>=BIT_REPEAT_MIN)&&(temp<=BIT_REPEAT_MAX)) { data_decoded = DATA_REPEAT; } else data_decoded = DATA_INVALID;
state machine 來做不狀態處理
switch(ir_state)
{
Idle模式處理,
若decode為start訊號,進入下個state
case IR_IDLE:
if(DATA_START==data_decoded)
{
ir_state = IR_START;
timer32_0_capture=0;
valid_key = 0;
}
break;
若進入start 階段,
decode為 '1' or '0' 進入Address decode狀態
若否則回到idle狀態
case IR_START:
if((DATA_ONE!=data_decoded)&&(DATA_ZERO!=data_decoded))
{
ir_state = IR_IDLE;
break;
}
else
ir_state = IR_ADDRESS;
進入Address or Commad decode狀態時,處理方式概念是相同.
case IR_ADDRESS:
case IR_COMMAND:
// timer16_1_capture2[timer32_0_capture] = temp;
timer32_0_capture++;
若是前8個bit,且若decode為1,因為訊號的的順序是MSB ot LSB.
若以就進1往MSB推一位元入data變數中
if(timer32_0_capture<=8)
{
data <<=1;
if(DATA_ONE==data_decoded)
data |= 0x01;
}
若是後8個bit,且若decode為1,因為訊號的的順序是MSB ot LSB.
若以就進1往MSB推一位元入n_data變數中
else if(timer32_0_capture<=16)
{
n_data <<=1;
if(DATA_ONE==data_decoded)
n_data|= 0x01;
}
當讀滿16個bit先判斷data與n_data是否互為1的補數
若是就進入下個階段,Address decode完成就往 Command decode階段.
若Command decode完成就進入idle階段,並且將有效解碼的flag設為1.
若非互為1的補數,資料有誤.
放棄解這次的封包,並且進入idle狀態.等待下次的start 訊號.
if(timer32_0_capture==16)
{
if((data+n_data)==0xff)
{
if(ir_state == IR_ADDRESS)
{
ir_address = data;
}
else
{
ir_command = data;
valid_key =1;
}
}
else
ir_state = IR_IDLE;
if(ir_state == IR_ADDRESS)
ir_state = IR_COMMAND;
else
ir_state = IR_IDLE;
data=0;
n_data=0;
timer32_0_capture = 0;
}
break;
若發生未預期狀態則回到idle狀態
default:
ir_state = IR_IDLE;
break;
}
用putty (putty不知道怎麼設定使用,可參考 Hello World! UART )來試試看遙控器的解碼結果吧.
(圖5) |
見圖5中,Address有兩種值,這是拿了不同遙控器測試解出來的結果.
通常Address就是來區分不同廠家或是不同設備,而Command代表的當然就是不同按鈕的功能.
參考範例請至此下載 Download
0 留言:
張貼留言