您的位置:首頁>正文

基於msp430的紅外遙控的編碼與解碼實現(附原始程式碼)

此編碼為常見的紅外遙控編碼, 可以完成紅外遙控或紅外資料的傳輸

主要演算法:

編碼: 用3278Hz頻率(P2.0第二功能輸出ACLK)驅動紅外二極體發送資料(應為38KHz 紅外接收頭要求, 我用的是近距離模擬的, 考慮到計時器資源寶貴, 暫用32K代替, 經驗證近距離可以完成傳輸, 使用是可以改為由TA的P1.2輸出, 稍微改下程式即可:初始化TA, 讓P1.2口輸出38K的pwm波, 巨集定義中的BIT_0/1改為P1.2口的第二功能開關即可)

發送時先由TB的CCR0的中斷控制時間完成9ms的紅外發射和4.5ms的停止 然後用CCR0和CCR4的中斷完成資料的發送

解碼:CCR5定時沒450ms中斷一次對資料進行檢測發現低電平進入資料幀判斷 若引導碼和起始碼正確則進入資料接收邏輯,

完成資料段接收

編解碼波形(NEC)

//________________ __ __ __

// | | | | | |

// | | | | | |

// | | | | | |

// | | | | | |

// | | | | | |.....................................

// | | | | | |

// | | | | | |

// |________| |_| |__| "0"高:0.56ms+低:0.565ms=1.125ms

//|||"0"| "1"| "1"高:0.56ms+低:1.69ms =2.25ms

//||||8位元資料->||

//

//可以完成編碼 解碼 注釋掉#define DECODE移去解碼部分 #define ENCODE移去編碼

//sendFlg是發送完成標誌, 完成後置1 未完成時連發資料無效

//

//佔用資源:TB CCR0中斷 CCR4 CCR5中斷 CCR0賦值為1125 時鐘1MHz

//紅外輸出端P2.0 32768Hz

//P2.1為紅外輸入埠

程式

#define DECODE //解碼

#define ENCODE //編碼

#include "msp430x16x.h"

#include "紅外編解碼.h"

/**********************************巨集定義**************************************/

#ifdef ENCODE/*=======編碼=======*/

#define BIT_0 P2SEL&=~BIT0 //紅外編碼後的低電平

#define BIT_1 P2SEL|=BIT0 //紅外編碼後的高電平

#define SENDDAT TBCCTL0|=CCIE //啟動資料發送 發送已存入addr0和dat0的資料

//發送資料位元高位部分 開始發資料位元

#define SENDBIT TBCCR4=565-1;TBCCTL4|=CCIE

#define SEND_END TBCCTL0&=~CCIE;TBCCTL4&=~CCIE //發送結束 關中斷

#endif/*=======編碼=======*/

#ifdef DECODE/*=======解碼=======*/

#define DATIN ((P2IN&BIT1)>>1) //資料登錄

#endif/*=======解碼=======*/

/******************************************************************************/

#ifdef DECODE/*=======解碼=======*/

//解碼後保存資料

char addr1;

char dat1;

char readFlg = 0;//成功讀紅外資料標誌

#endif/*=======解碼=======*/

#ifdef ENCODE/*=======編碼=======*/

//要編碼的資料 發送緩存

char addr0;

char dat0;

char sendFlg = 1;//發送完成標誌

#endif/*=======編碼=======*/

//初始化TB

void int_TB()

{

TBCTL = TBSSEL_2 + TBCLR + MC_1; //TB時鐘源:SMCLK 增模式

TBCCR0 = 1125 - 1;

TBCCTL5 |= CCIE;

TBCCR5 = 450;

}

//有關埠初始化

void int_io()

{

#ifdef ENCODE/*=======編碼=======*/

//ACLK輸出作為編碼的載波

P2OUT &=~ BIT0;

P2DIR |= BIT0;

#endif/*=======編碼=======*/

#ifdef DECODE/*=======解碼=======*/

//解碼輸入埠P2.1

/*P2IES |= BIT1;

P2IFG &=~ BIT1;

P2IE |=BIT1;*/

#endif/*=======解碼=======*/

}

//初始化紅外相關資源

void int_hw()

{

int_TB();

int_io();

}

#ifdef ENCODE/*=======編碼=======*/

//編碼發送資料,eos標誌最後資料一般為1, 發送多位元組資料時, 最後一位元組是1

void sendDat(char addr,char dat)

{

if(sendFlg)//上次發送完成

{

//資料存入發送緩存

addr0 = addr;

dat0 = dat;

//開始發送

SENDDAT;

}

}

#endif/*=======編碼=======*/

#ifdef DECODE

//紅外資料解碼函數

void datDecode(unsigned int tAddr, unsigned int tDat)

{

if(((tAddr>>8)&0xff)==(tAddr&0xff))//位址高位低位元相等 位址位元資料正確

{

addr1 = tAddr&0xff;

if(((tDat>>8)&0xff)==((~tDat)&0xff))//資料高位低位元反 資料位元資料正確

{

dat1 = ~(tDat&0xff);

readFlg = 1;

}

else

{

readFlg = 2;

}

}

else

{

readFlg = 2;

}

}

#endif

//中斷

#ifdef ENCODE/*=======編碼=======*/

//TB0中斷 編碼

#pragma vector=TIMERB0_VECTOR

__interrupt void Timer_B (void)

{

static char i = 0; //計數 起始

static char state = 0; //狀態 起始:0 數據:1

static char cnt = 0; //發送計數

if(state==0)

{

if(i==0)

{

BIT_1;

//完成標誌置0 開始發送

sendFlg = 0;

}

else if(i==8)

{

BIT_0;

}

else if(i==11)

{

SENDBIT;

state = 1;

i = 255;

}

}

else if(state==1)

{

BIT_0;

if(cnt

{

if(addr0&(1

{

if(i==1)

{

SENDBIT;

i = 255;

cnt++; //發送加1

}

}

else

{

SENDBIT;

i = 255;

cnt++; //發送加1

}

}

else if(cnt

{

if(addr0&(1

{

if(i==1)

{

SENDBIT;

i = 255;

cnt++; //發送加1

}

}

else

{

SENDBIT;

i = 255;

cnt++; //發送加1

}

}

else if(cnt

{

if(dat0&(1

{

if(i==1)

{

SENDBIT;

i = 255;

cnt++; //發送加1

}

}

else //是0延時+1:1.125ms

{

SENDBIT;

i = 255;

cnt++; //發送加1

}

}

else if(cnt

{

if((~dat0)&(1

{

if(i==1)

{

SENDBIT;

i = 255;

cnt++; //發送加1

}

}

else //是0延時+1:1.125ms

{

SENDBIT;

i = 255;

cnt++; //發送加1

}

}

/*else if(cnt==32)//最後多發一位0, 否則無法識別最後一位

{

SENDBIT;

i = 255;

cnt++; //發送加1

}*/

else

{

//完成標誌置1

sendFlg = 1;

//變數歸零

state = 0;

cnt = 0;

i = 255;

SEND_END;//停止發送

BIT_0;

}

}

i++; //計數加1

TBCCTL4 &=~ CCIFG;//中斷標誌清除

}

#endif/*=======編碼=======*/

//TB1中斷

#pragma vector=TIMERB1_VECTOR

__interrupt void Timer_B1(void)

{

static int i = 0; //計數變數 接收用

static char state = 0; //代表接收狀態的變數

static char cnt = 0;//讀取位數計數

switch( TBIV )

{

case 0x08: // TBCCR4 編碼發送資料位元部分

#ifdef ENCODE/*=======編碼=======*/

BIT_1;

TBCCTL4 &=~ CCIE;

#endif/*=======編碼=======*/

break;

case 0x0a: // TBCCR5 解碼用

#ifdef DECODE/*=======解碼=======*/

TBCCR5 = (TBR+440>1124)?(TBR+440-1124):(TBR+440);

if(TBCCR5>1124) TBCCR5 = 1124;//防止TBCCR5出界

i++;

if(DATIN==0&&readFlg>0)//上次讀取完成(可能有錯誤 readFlg=2 錯誤資料) 又有資料到來

{

readFlg = 0;

i = 0;

}

if(state==0&&readFlg == 0)//起始碼

{

if(i

{

readFlg = 2;

}

else if(i>26&&DATIN==0X01)//引導碼正確 準備讀數據

{

state = 1;//1狀態 讀數據

i = 0;

}

}

else if(state==1)//數據

{

static unsigned int tAddr = 0;//位址位元臨時變數

static unsigned int tDat = 0;//資料位元臨時變數

static char datFlg = 0;

if(cnt

{

if(DATIN==0x00&&datFlg==0)

{

datFlg = 1;//有數據

i = 0;

}

if((i==2||i==3)&&datFlg&&DATIN==0X00)

{

tAddr |= (0X00)

i = 0;

datFlg = 1;

cnt++;

return;

}

else if((i==3)&&DATIN==0X01&&datFlg)

{

tAddr |= (0X01)

i = 0;

datFlg = 0;

cnt++;

}

else if(i>3)

{

readFlg = 2;

cnt = 0;

datFlg = 0;

tAddr = 0;

tDat = 0;

state = 0;

}

}

else if(cnt

{

if(DATIN==0x00&&datFlg==0)

{

datFlg = 1;//有數據

i = 0;

}

if((i==2||i==3)&&datFlg&&DATIN==0X00)

{

tDat |= (0X00)

i = 0;

datFlg = 1;

cnt++;

return;

}

else if((i==3)&&DATIN==0X01&&datFlg)

{

tDat |= (0X01)

i = 0;

datFlg = 0;

cnt++;

}

else if(i>3)

{

readFlg = 2;

cnt = 0;

datFlg = 0;

tAddr = 0;

tDat = 0;

state = 0;

}

}

else

{

datDecode(tAddr, tDat);

//解碼結束

i = 0;

cnt = 0;

state = 0;

datFlg = 0;

tAddr = 0;

tDat = 0;

}

}

#endif/*=======解碼=======*/

break;

case 0x0e: //overflow 溢出, 未用

break;

}

}

/*

#ifdef DECODE=======解碼=======*/

//PORT2中斷 此中斷僅解碼接收資料用

/*#pragma vector=PORT2_VECTOR

__interrupt void PORT2_ISR(void)

{

switch(DATIFG&BIT1)

{

case 2:

//開始接收資料

DATREAD;

break;

}

DATIFG = 0;//清除標誌位元

}

#endif=====

本文素材來自電子發燒友論壇

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示