#include <iom16v.h>
#include <macros.h>
#define IR_ON PORTB|=BIT(1) //紅外發射管接在PB1口上
#define IR_OFF PORTB&=~BIT(1)
#define K1 (PIND&BIT(7)) //K1鍵PD7
#define LED_0 PORTB&=~BIT(0) //指示燈
#define LED_1 PORTB|=BIT(0)
//延時n毫秒
//51單片機下是115(11.0592M晶振,用51單片機的人自己改吧)
void delay(unsigned int n)
{
unsigned int i;
while (n--)
for (i=0;i<1140;i++); //1ms基準延時
}
//延時0.5ms
void delay500us(void)
{
unsigned int i;
for (i=0;i<570;i++); //1140*0.5=570
}
//延遲0.56ms
void delay560us(void)
{
unsigned int i;
for (i=0;i<638;i++); //1140*0.56=638.4
}
/* 本電路使用了硬體調製38khz而非軟體,本人推薦用硬體調製
* 如果用軟體來調製的話會使得接收端接收到的時間誤差很大
* 比如發射9ms高電平,接收端收到的可能就是10ms的高電平,導致出錯
**/
//LED指示燈亮、滅
void led(void)
{
//埠設為輸出時也可以用PINB暫存器讀埠,但讀出的是用PORTB暫存器設置的狀態
//外部電平無法改變PORTB暫存器的狀態
if (PINB&BIT(0))
LED_0;
else
LED_1;
}
//引導碼
void send_first(void)
{
IR_ON;
delay(9); //9ms高電平
IR_OFF;
delay(4); //4.5ms低電平
delay500us();
//與單片機I/O口接的那個三極體最好是使用NPN的
//否則這裡的電平就反了,因為PNP三極體是低電平導通,NPN三極體是高電平導通
}
//發送0
void send_0(void)
{
IR_ON;
delay560us();
IR_OFF;
delay560us();
}
//發送1
void send_1(void)
{
IR_ON;
delay560us();
IR_OFF;
delay560us();
delay560us();
delay560us();
}
//發送一個位元組
void send_byte(unsigned char Data)
{
unsigned char i;
for (i=0;i<8;i++)
{
if (Data&BIT(i))
send_1();
else
send_0();
}
}
//發送尾碼,使接收端能確定最後一位是0還是1
void send_end(void)
{
IR_ON;
delay560us();
IR_OFF;
}
//★發送一個完整的按鍵碼
//usercode為用戶碼,16位
//keycode為鍵碼,8位
void send(unsigned int usercode, unsigned char keycode)
{
send_first();
send_byte(usercode/256); //用戶碼高8位
send_byte(usercode%256); //用戶碼低8位
send_byte(keycode); //鍵碼
send_byte(~keycode); //鍵碼的反碼
send_end();
}
//按下按鍵K1後執行的操作
void execute(void)
{
unsigned char i;
//範例1:下面這條語句可以實現靜音功能
//send(0x01fd,0x12); //我的電視的靜音鍵的用戶碼是0x01fd,鍵碼是0x12
//範例2:下面的程序可以讓dvd反覆出/入倉
/*while (1)
{
send(0x00ff,0x0c); //我的DVD機的出倉鍵
delay(2500);
}*/
//範例3:下面的程序可以讓電視機顯示菜單,並自動地不停地移動游標
/*send(0x01fd,0x50); //顯示菜單
while (1)
{
send(0x01fd,0x14); //不停地按「下鍵」
delay(1000);
}*/
//範例4:下面的程序可以使電視的音量來回加減
while (1)
{
for (i=0;i<10;i++)
{
send(0x01fd,0x55); //加音量
delay(200);
}
delay(500);
for (i=0;i<10;i++)
{
send(0x01fd,0x56); //減音量
delay(200);
}
delay(500);
}
//你們的電視機和dvd的鍵碼肯定跟我的不一樣,只需要把用戶碼和鍵碼改成你們的就行了
//反正我測試了是完全正常運行的
}
void main(void)
{
DDRB=0xff; //PB口全部設置為輸出
PORTB=0x00;
DDRD=0x00; //PD口全部設置為輸入,儘管我只弄了一個按鍵在PD7口上
PORTD=0xff;
while (1)
{
//按鍵K1
if (!K1)
{
delay(15);
if (!K1)
{
led(); //LED亮/滅
execute(); //執行相應的遙控發射操作
//用戶一直按住鍵不鬆手的程序我就不寫了
//具體是:每隔108ms發射9ms高電平和2.25ms低電平再0.56ms高電平再拉低
while (!K1); //要寫就寫在這裡
delay(5); //按鍵鬆開後等待,防止抖動
}
}
}
}
//本程序作者:巨大八爪魚
//QQ:970349094
//2013年10月4日21:26:00