日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

单片机练习-RC-5红外遥控器程序及简单制造DIY PC遥控器

發布時間:2023/11/27 生活经验 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单片机练习-RC-5红外遥控器程序及简单制造DIY PC遥控器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本程序采用的芯片為SAA3010, 參考資料有:
1. 常用紅外遙控接收頭引腳圖解
2. 紅外遙控編碼資料
3. RC-5紅外遙控程序
4. GIRDER中文教程與電腦遙控器制作資料
5. Girder網站 (一個需要錢買的遙控)
6. 再度出擊,20元打造經典PC遙控器!
7. SAA3010 DataSheet

這次主要是完成單片機接收紅外搖控器發出的數據. 在此基礎上, 我們可DIY出自己的PC搖控器, 也可自行發揮一些, 做出類似于很多Club里的點歌系統的硬件外紅信號轉換裝置....

本次實驗依舊采用TX-1B實驗板, 只需增加一個一體化紅外接收頭, 如下圖:


本程序中, DataOut引腳接到P3.2口. 在接收頭的電源和地端接上濾波電容會使誤碼率更加低....

SAA3010芯片:


(圖中位時間1.688ms, 而根據DataSheet里描述的位時間為1.788ms,? 但實際中我使用的時間為1.651ms )

我使用的鍵盤編碼如下:

鍵盤外觀:

編碼:


一體化紅外接收頭的數據輸出的判斷思路: (手畫, 太難看也別見怪:) )
Tb = 1.778ms = 1.780ms (實際中測試為1.651ms)
T1/4b = 445us (實際中413ms)
T3/4b = 1.335ms (實際1.239ms)


在等待第一次低電平到來后, 定時器開始第一次定時T1/4b時間, 然后到達第一次數據的T3/4b時刻, 讀取該位電平狀態;
以后定時器每次定時Tb時間, 這樣到達對應每位的T3/4時刻, 并可讀取該位電平狀態.

具體邏輯請看代碼中的詳細注釋:

?采用程序查詢方式:

SAA3010_RC5
//接收紅外遙控器(Infrared?remote?control?transmitter)發出的數據
//芯片型號:?SAA3010,?它采用RC-5協議
//芯片資料:?http://www.alldatasheet.com/datasheet-pdf/pdf/18953/PHILIPS/SAA3010.html

//利用與P1口相連的發光二極管輸出接收到的按鍵對應碼,?并將它輸出到串口,?用于遙控
//PC使用了Girder來觸發自定義的功能

#include?
"reg51.h"
#include?
"?intrins.h?"

#define?uchar?unsigned?char

/*********************IRC?RC-5****************************************/

uchar?YKDatas[
3];???//遙控碼(一幀14位),YKDatas[0]:?0,1為start?bits,?2?為control?bit,?YKtype=0
????????????????????
//YKDatas[1]:?3~7為system?bits,?YKtype=1
????????????????????
//YKDatas[2]:?8~13為command?bits,?YKtype=2
sbit?YKIn?=?P3^2;?????//數據輸入位

uchar?YKcount,?YKtype;????????????
//遙控已接收位數,?一幀的各段標志
bit?YKend;?//接收結束標志

//延時?a?*?1ms
void?delayMs(unsigned?int?a)
{
????unsigned?
int?i,?j;
????
for(i?=?a;?i?>?0;?i--)
????????
for(j?=?100;?j?>?0;?j--);
}

void?YKInit()??????????????????//遙控接收初始化
{
????YKDatas[
0]?=?YKDatas[1]?=?YKDatas[2]?=?0;
????YKcount?
=?0;
????YKtype?
=?0;
????YKend?
=?0;
}

void?time0()?interrupt?1?
{
????
//第一次進入中斷前,?定時1/4位的時間:445us,?以后則定時一位時間1.778ms
????
//即在3/4位時間時,?判斷該位是1還是0
????
//實際測試中,?位時間只在1.651ms(+-?1ms),?定時1/4位的時間:413us
????bit?in?=?~YKIn;?//一體化解碼后,?有載頻部分變為低電平,?即低電平實際為1,?高電平實際為0
????
//設置定時器初值
????
//模式1:?TH0?=?(2^16?-?(1651/1.085))?/?2^8?=?(65536?-?1651/1.085)?/?256?=??250;
????
//TL0?=?(65536?-?1651/1.085)?%?256?=?14
????TH0?=?250;
?????TL0?
=?14;
????
????YKDatas[YKtype]?
=?YKDatas[YKtype]?|?in;?//將數據放入最低位
????YKcount++;
????
if(YKcount?==?3)?//獲取完Start?bits?和control?bit,?共3位
????{
????????YKtype?
=?1;
????}
????
else?if(YKcount?==?8)?//獲取完system?bits,?共5位
????{
????????YKtype?
=?2;
????}
????
else?if(YKcount?==?14)?//獲取完commond?bits,?共6位
????{
????????YKtype?
=?3;
????}
????
else?if(YKtype?==?3)?//等待最后1/4位時間結束,?實際延時1位時間
????{
????????YKend?
=?1;
????????YKcount?
=?0;
????????YKtype?
=?0;
????????TR0?
=?0;?//接收結束,?停止定時器0
????????return;?
????}
????
else??//將數據左移一位,?以便將一下位數據并于最低位
????{
????????YKDatas[YKtype]?
=?YKDatas[YKtype]?<<?1;
????}
}

/*********************IRC?RC-5****************************************/


/*********************RS232****************************************/
//初始化串口
void?RSInit()
{
????TMOD?
|=?0x20;?//T1工作方式2
????TH1?=?TL1?=?0xfd;?//裝入初值,?以后是自動重載的8位計數器
????TR1?=?1;?//啟動T1
????SM0?=?0;
????SM1?
=?1;?//方式1
????REN?=?1;?//允許接收
????EA?=?1;????//開中斷
????ES?=?1;?//允許串口中斷
????PCON?=?0x00;?//串口波特率不加倍.?即設置SMOD?=?0;
}

//寫一字節數據到串口,?使用程序查詢方式檢測發送情況
void?RsWriteByte(unsigned?char?byte)
{
????ES?
=?0;?//關中斷
????SBUF?=?byte;
????
while(!TI);?//檢測是否發送完
????TI?=?0;?//清0發送中斷標志
????ES?=?1;?//開中斷,?以允許接收數據時使用中斷方式
}

void?serial()?interrupt?4?//串口中斷是4
{
????P1?
=?SBUF;
????RI?
=?0;?//清0接收中斷標志
}

/*********************RS232****************************************/
void?display()?//顯示接收的數據
{
????P1?
=?~YKDatas[2];
/*????switch(YKDatas[2])
????{
????????case?0x3f?:
????????case?0x0c?:?RsWriteByte(YKDatas[0]);?break;
????????default?:?break;
????}
*/
//????RsWriteByte(YKDatas[1]);
????RsWriteByte(YKDatas[2]);
}


void?main(void)
{
????TMOD
=0x01;????????????????//T0選用方式1(16位定時)
????IE?=?0x82;?//開總中斷,?開定時器0中斷?
????YKIn?=?1;
????RSInit();
????
while(1)????????????????
????{????
????????YKInit();????
????????
//模式1:?TH0?=?(2^16?-?(413/1.085))?/?2^8?=?(65536?-?381)?/?256?=??255;
????????
//TL0?=?(65536?-?381)?%?256?=?131
????????TH0?=?255;
????????TL0?
=?131;
????????
while(YKIn);?//等待低電平,?一幀開始
????????TR0?=?1;?//啟動定時器0,?接收紅外遙控器發來的數據
????????while(!YKend);?//等待接收結束
????????display();
????????delayMs(
200);
????}
}


改進代碼: 由原來的程序查詢方式, 換成中斷方式:? 成功接收到數據后, 會自動調用YKSuccess()方法.

IRC_RC5_Interrupt_module
//接收紅外遙控器(Infrared?remote?control?transmitter)發出的數據
//芯片型號:?SAA3010,?它采用RC-5協議
//芯片資料:?http://www.alldatasheet.com/datasheet-pdf/pdf/18953/PHILIPS/SAA3010.html

//利用與P1口相連的發光二極管輸出接收到的按鍵對應碼,?并將它輸出到串口,?用于遙控
//PC使用了Girder來觸發自定義的功能

#include?
"reg51.h"
#include?
"?intrins.h?"

#define?uchar?unsigned?char

void?display();

/*********************IRC?RC-5****************************************/

uchar?YKDatas[
3];???//遙控碼(一幀14位),YKDatas[0]:?0,1為start?bits,?2?為control?bit,?YKtype=0
????????????????????
//YKDatas[1]:?3~7為system?bits,?YKtype=1
????????????????????
//YKDatas[2]:?8~13為command?bits,?YKtype=2
sbit?YKIn?=?P3^2;?????//數據輸入位
uchar?YKcount,?YKtype;????????????//遙控已接收位數,?一幀的各段標志

//延時?a?*?1ms
void?delayMs(unsigned?int?a)
{
????unsigned?
int?i,?j;
????
for(i?=?a;?i?>?0;?i--)
????????
for(j?=?100;?j?>?0;?j--);
}

//重置所有數據
void?YKReset()
{
????delayMs(
200);?//去重復
????YKDatas[0]?=?YKDatas[1]?=?YKDatas[2]?=?0;
????YKcount?
=?0;
????YKtype?
=?0;
????EX0?
=?1;?//開外部中斷0,?檢測是否有數據輸入
}

void?YKInit()??????????????????//遙控接收初始化
{
????TMOD?
=?0x01;????????????????//T0選用方式1(16位定時)
????IE?=?0x82;??????????????????//開總中斷,?開定時器0中斷?
????YKIn?=?1;
????YKReset();
}

void?YKSuccess()??//接收到數據后會自動被調用
{
????display();
????YKReset();
}

void?ex0()?interrupt?0
{
????EX0?
=?0;??//關閉外部中斷0
????
//模式1:?TH0?=?(2^16?-?(413/1.085))?/?2^8?=?(65536?-?381)?/?256?=??255;
????
//TL0?=?(65536?-?381)?%?256?=?131
????TH0?=?255;
????TL0?
=?131;
????TR0?
=?1;??//啟動定時器0,?定時1/4位周期
}

void?time0()?interrupt?1?
{
????
//第一次進入中斷前,?定時1/4位的時間:445us,?以后則定時一位時間1.778ms
????
//即在3/4位時間時,?判斷該位是1還是0
????
//實際測試中,?位時間只在1.651ms(+-?1ms),?定時1/4位的時間:413us
????bit?in?=?~YKIn;?//一體化解碼后,?有載頻部分變為低電平,?即低電平實際為1,?高電平實際為0
????
//設置定時器初值
????
//模式1:?TH0?=?(2^16?-?(1651/1.085))?/?2^8?=?(65536?-?1651/1.085)?/?256?=??250;
????
//TL0?=?(65536?-?1651/1.085)?%?256?=?14
????TH0?=?250;
????TL0?
=?14;
????
????YKDatas[YKtype]?
=?YKDatas[YKtype]?|?in;?//將數據放入最低位
????YKcount++;
????
if(YKcount?==?1?||?YKcount?==?2)
????{
????????
if(in?==?0)??//起始兩位必須都為1
????????{
????????????TR0?
=?0;
????????????EX0?
=?1;
????????????
return;
????????}
????}
????
if(YKcount?==?3)?//獲取完Start?bits?和control?bit,?共3位
????{
????????YKtype?
=?1;
????}
????
else?if(YKcount?==?8)?//獲取完system?bits,?共5位
????{
????????
if(YKDatas[1]?!=?0)?//系統碼全為0才是正確的
????????{
????????????TR0?
=?0;
????????????EX0?
=?1;
????????????
return;
????????}
????????YKtype?
=?2;
????}
????
else?if(YKcount?==?14)?//獲取完commond?bits,?共6位
????{
????????YKtype?
=?3;
????}
????
else?if(YKtype?==?3)?//等待最后1/4位時間結束,?實際延時1位時間
????{
????????TR0?
=?0;?//接收結束,?停止定時器0
????????YKSuccess();
????????
return;?
????}
????
else??//將數據左移一位,?以便將一下位數據并于最低位
????{
????????YKDatas[YKtype]?
=?YKDatas[YKtype]?<<?1;
????}
}

/*********************IRC?RC-5****************************************/


/*********************RS232****************************************/
//初始化串口
void?RSInit()
{
????TMOD?
|=?0x20;?//T1工作方式2
????TH1?=?TL1?=?0xfd;?//裝入初值,?以后是自動重載的8位計數器
????TR1?=?1;?//啟動T1
????SM0?=?0;
????SM1?
=?1;?//方式1
????REN?=?1;?//允許接收
????EA?=?1;????//開中斷
????ES?=?1;?//允許串口中斷
????PCON?=?0x00;?//串口波特率不加倍.?即設置SMOD?=?0;
}

//寫一字節數據到串口,?使用程序查詢方式檢測發送情況
void?RsWriteByte(unsigned?char?byte)
{
????ES?
=?0;?//關中斷
????SBUF?=?byte;
????
while(!TI);?//檢測是否發送完
????TI?=?0;?//清0發送中斷標志
????ES?=?1;?//開中斷,?以允許接收數據時使用中斷方式
}

void?serial()?interrupt?4?//串口中斷是4
{
????P1?
=?SBUF;
????RI?
=?0;?//清0接收中斷標志
}

/*********************RS232****************************************/

void?display()?//顯示接收的數據
{
????P1?
=?~YKDatas[2];
????RsWriteByte(YKDatas[
2]);
}


void?main(void)
{
????YKInit();?
????RSInit();
????
while(1);
}



效果圖:

按下9鍵:


PC上利用Girder響應事件:

轉載于:https://www.cnblogs.com/fengmk2/archive/2007/04/01/Infrared_remote_control_transmitter_rc5.html

總結

以上是生活随笔為你收集整理的单片机练习-RC-5红外遥控器程序及简单制造DIY PC遥控器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。