單片機編碼、解碼2262用單片機編碼2262來發射,2272接收成功;現在用單片機編碼2262來發射,單片機解碼2272來接收。
同步碼頭波形:
這是自己按照波形圖寫的解碼,大家指教!!這樣解碼可以不??沒有用到2272了,接收模塊輸出直接到單片機的I/O口,然后判斷I/O口的高低電平來解碼?
#include<reg52.h>
#define uchar unsigned char
void display();
void delay_1s(uchar);
bit T0Action;
bit Action;
bit RECEIVE; //接收標志
sbit P1_0=P1^0;
sbit P1_1=P1^1;
sbit P1_2=P1^2;
sbit P1_3=P1^3;
sbit P1_7=P1^7; //接收腳
sbit P3_5=P3^5; //發光二極管
sfr AUXR =0x8E;
sfr P1M0 =0x91;
sfr P1M1 =0x92;
sfr P3M0 =0xb1;
sfr P3M1 =0xb2;
void main()
{
uchar i;
uchar temp,data0,data1,counttime;
unsigned int time,time1,time2;
// AUXR=0x80; //定時器0不分頻
T0Action=0;
RECEIVE=0; //接收標志位
Action=0;
TMOD = 0x01; // 定時器0 工作方式1
TH0=0x00;
TL0=0x00;
P1_0=0;
P1_1=0;
P1_2=0;
P1_3=0;
P3_5=0;
while(1)
{
do{}while(P1_7==1);
if((P1_7==0) && (T0Action==0)) //等待低電平,低電平開始記時
{
TR0=0;
TH0=0x00;
TL0=0x00;
TF0=0;
TR0=1;
T0Action=1;
while(1)
{
if((P1_7==1) && (T0Action==1))
{
TR0=0;
time=TH0*256+TL0; //記下低電平寬度時間
T0Action=0;
break;
}
}
}
if((time>9000) && (time<12000)) //檢測同步碼約11ms
{
counttime=0;
data0=0;
data1=0;
time=0;
RECEIVE=1; //檢測到同步碼時 置標志位 RECEIVE=1
P3_5=1; //綠發光二極管燈亮(調試用)
}
if(RECEIVE==1) //檢測到同步碼后開始解碼
{
RECEIVE=0;
while(1)
{
L1:do{}while(P1_7==1);
if((P1_7==0) && (T0Action==0)) //等待第一個低電平,一有低電平馬上記時
{
TR0=0;
T0Action=1;
TH0=0x00;
TL0=0x00;
TF0=0;
TR0=1;
while(1)
{
if((P1_7==1) && (T0Action==1))
{
TR0=0;
time=TH0*256+TL0; //記下第一個低電平寬度時間
T0Action=0;
TH0=0x00;
TL0=0x00;
TF0=0;
TR0=1; //開始記高電平時間
break;
}
}
}
do{}while(P1_7==1);
if((P1_7==0) && (T0Action==0)) //等待第二個低電平,一有低電平馬上記時
{
TR0=0;
time2=TH0*256+TL0; //記下一個高電平寬度時間
T0Action=1;
TH0=0x00;
TL0=0x00;
TF0=0;
TR0=1;
while(1)
{
if((P1_7==1) && (T0Action==1))
{
TR0=0;
time1=TH0*256+TL0; //記下第二個低電平寬度時間
T0Action=0;
break;
}
}
}
if((time==time1) && (time<1500)) //判斷兩個低電平寬度時間是否相等,限時1500us
{
if((time>780) && (time<1150)) //低電平寬度時間
{
if((time2>210) && (time2<450)) //高電平寬度時間
{
temp=0x00; //0
}
else goto L1; //誤碼,返回重新接收數據
}
else if((time>210) && (time<450)) //低電平寬度時間
{
if((time2>780) && (time2<1150)) //高電平寬度時間
{
temp=0x01; //1
}
else goto L1; //誤碼,返回重新接收數據
}
else goto L1; //誤碼,返回重新接收數據
counttime++;
if(counttime<=8) //開始接收前8位 地址碼
{
data0=(data0<<1)|temp;
}
else if((counttime>8) && (counttime<=12)) //開始接收后4位 數據碼
{
data1=(data1<<1)|temp;
if(counttime==12) // 第12位
{
Action=1;
break; //接收完畢,退出解碼程序
}
}
}
else goto L1; //誤碼,返回重新接收數據
}
最近要做一個用單片機模擬2272來解碼2262的項目,F在剛剛有些結果,發現了一些問題,同大家分享。
1由于廠家是設定2262 2272配對使用,因此對一般應用來講,不需要考慮中間詳細的通信格式,所以在廠家(普城)的資料上沒有相應的編碼格式。我只好在網上找到了第三方的更詳細的波形圖。但是我找的兩份資料上在細節上都有表述錯誤的地方。通過比較,得出了正確的結果。其中之一就是對于2262的振蕩頻率公式:f=32000/R(R是振蕩電阻,以M為單位),所以如果為3.2M的振蕩電阻,那么振蕩頻率為10kHZ,周期為T=100us,則窄脈沖是4倍的周期,寬脈沖為12倍周期,計算結果寬窄脈沖分別為:400us,1200us;這與實際的脈沖寬度有一定的差別,實際的是359us,1078us.由于2262是三進制,所以需要兩位的二進制表示。表現在編碼波形上,如果取窄高脈沖+寬低脈沖(--______)代表0(16倍T),寬高脈沖+窄低脈沖(-----__)代表1(16倍T),那么2262的三種管腳狀態:接高電平、懸空、接地電平可以用11,01,00表示,所以每個碼長度是32T,而不是其他。
2在寫完解碼并修正程序后,發現我的解碼距離特別短。而且有的甚至只有幾厘米。我先是在接收模塊加上了一段30cm的天線。結果僅有的幾個感應比較長的遙控器距離更短。接下來我發現我用的單片機是51的,從資料上看到這種單片機的輻射干擾很大。于是我就把接收模塊拉遠。供電隔離,但是仍然效果很差。離幾百米的標稱距離差距幾個數量級,也滿足不了本項目的要求。接著,我把焦點放在其他用電器的干擾上,因為旁邊有好幾臺電腦,有可能是他們的原因。所以我就把實驗裝置放到比較干凈的地方。增加天線到1M,并把天線豎起來,結果仍然沒有什么明顯改善。
最后,我沮喪地把天線扔到地上,結果發現這時候距離比前面遠多了。感應距離3-10M,基本上滿足了應用要求。我又觀察了一下天線,發現感應距離有方向性,天線指向的方向感應距離比較,。垂直的方向比較短。
3我在測量接收模塊輸出端的時候,由于設備簡陋,只能測直流電壓,發現平常的時候2.5V左右隨機波動,而且用單片機監測數據發現,明顯有大量的亂碼出現。而當按動遙控器的時候,發現直流電平下降到1.8V左右。從直流電平上看,好像是平常處于高電平,數據到來時為低電平。而實際上,單片機解碼時必須采用高電平解碼。否則解不出來。這種矛盾的現象可能是由于平時的雜波信號產生的。
4幾米的的解碼距離相比專用芯片的解碼距離相差還是有一個數量級的差距,F在我還不知道到底是那個原因的使得傳播距離這么短?紤]的因素接下來可能是傳輸速率的問題,我現在采用的振蕩頻率大概20K.還有就是增加天線的長度。
5續:對于距離太短也不能解碼的解決。后來我發現了一個很奇怪的現象,就是對于大部分的遙控器,解碼距離不能太短。太短的時候也不能解碼。后來我發現2262的編碼值也影響解碼距離。全接高電平解碼距離可以很近,全接低電平解碼靈敏度很低,幾乎解不出來。如果距離太短解不出碼是因為信號太強,導致振蕩間歇期太短,信號阻塞,那么應該是全接高電平解碼效果最差,全接低電平效果最好。因為接高電平的振蕩間歇期最短,最容易被強信號淹沒。全接低電平恰好相反,因為振蕩期窄,間歇期長,不容易形成阻塞。
所以問題應該在其他的方面。前面脈沖寬度都是按照理論值計算的,并沒有直接測量具體的實際寬度值。這時候我采取檢測實際脈沖寬度的方法。通過與pc連接,實時的查看實際的脈沖寬度。結果讓我大吃一驚,寬高脈沖實際值與理論基本符合,而窄脈沖實際值竟然只是理論值的一半左右,而且,隨著解碼距離的遠近不同,脈沖寬度大約有30%的變化。所以,實際的脈沖寬度接近程序中的
極限值,對于不同的編碼值,其窄電平脈沖數量不一樣,例如:全接高電平,窄脈沖最少(0個),結果就容易解;全接低電平窄脈沖最多,解碼就非常難(只要所有的窄脈沖中一個出現錯誤就解不出來)。對于距離太近也不能解碼,也是因為脈沖寬度隨距離發生變化,導致超過極限寬度,結果就不能解碼。