学习型遥控器C语言编程

学习型遥控器C语言编程
学习型遥控器C语言编程

`/*************************************************************** 名称:红外线遥控发射(NEC编码)

单片机:STC89C52RC

晶振:12M

编译环境:Keil uVision4 V9.00

主程序如下所示,附录中为两个头文件,里面包含参数设定和LCD屏显示。***************************************************************/

// 发射引脚(接PNP三极管b极与1K欧电阻)

// PNP三极管e极接电源,c极接红外发射管与51欧电阻

#include

#include "INC\MY_SET.h"

#include "INC\LCD1602_6IO.h"

sbit IR = P3^6; //发射引脚(接PNP三极管基极)

sbit LED1=P2^0;

sbit LED2=P2^1;

sbit LED3=P2^2;

sbit LED4=P2^3;

sbit KEY1=P1^0;

sbit KEY2=P1^1;

sbit KEY3=P1^2;

sbit KEY4=P1^3;

sbit KEY5=P1^4;

#define USER_H P2 //用户码高8位

#define USER_L P0 //用户码低8位

uint8 tab[16] = { //操作码

0x12,0x05,0x1e,0x55,

0x01,0x1b,0x03,0x6b,

0x07,0x08,0x09,0x68,

0x22,0xE6,0x33,0xe2};

uint16 M = 0;

#define m9 (65536-9000) //9mS

#define m4_5 (65536-4500) //4.5mS

#define m1_6 (65536-1650) //1.65mS

#define m_56 (65536-560) //0.56mS

#define m40 (65536-40000) //40mS

#define m56 (65536-56000) //56mS

#define m2_25 (65536-2250) //2.25mS

void SanZhuan();

uint8 KEY(void);

void ZZ(uint8 x); //NEC编码发送程序

void Z0(uint8 temp); //单帧(8位数据)发送程序

void TT0(bit BT,uint16 x); //38KHz载波发射+ 延时程序

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈函数:主程序

┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void main(void)

{

uchar m;

TMOD = 0x01;

IE = 0x81; //允许总中断中断,使能INT0 外部中断TCON = 0x01; //触发方式为脉冲负边沿触发

IRIN=1; //I/O口初始化

BEEP=1;

IR = 1;

delay1(10); //延时

lcd_init(); //初始化LCD

lcd_pos(0); //设置显示位置为第一行的第1个字符m = 0;

while(cdis1[m] != '\0')

{ //显示字符

lcd_wdat(cdis1[m]);

m++;

}

lcd_pos(0x40); //设置显示位置为第二行第1个字符m = 0;

while(cdis2[m] != '\0')

{

lcd_wdat(cdis2[m]); //显示字符

m++;

}

while(1) {

if(LED4 == 0){IE = 0x00;}

else{IE = 0x81;}

SanZhuan();

}

}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈函数:4*2独立键盘

入口:void

┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ uint8 KEY(void)

{

uint8 Key = 0xff;

if(KEY1 == 0)

{Key = 0; LED1 =~ LED1;}

if(KEY2 == 0)

{Key = 1; LED2 =~ LED2;}

if(KEY3 == 0)

{Key = 2; LED3 =~ LED3;}

if(KEY4 == 0)

{Key = 3; LED3 =~ LED3;}

if(KEY5 == 0)

{ LED4 =~ LED4;}

return Key; //返回键值

}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈函数:散转程序

入口:void

┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ voidSanZhuan()

{

uint8 v;

//TMOD = 0x01;

v = KEY(); //键盘检测

switch(v)

{

case 0:ZZ(tab[0]);break;

case 1:ZZ(tab[1]);break;

case 2:ZZ(tab[2]);break;

case 3:ZZ(tab[3]);break;

/* case 0x7d:ZZ(tab[4]);break;

case 0xbd:ZZ(tab[5]);break;

case 0xdd:ZZ(tab[6]);break;

case 0xed:ZZ(tab[7]);break;

case 0x7b:ZZ(tab[8]);break;

case 0xbb:ZZ(tab[9]);break;

case 0xdb:ZZ(tab[10]);break;

case 0xeb:ZZ(tab[11]);break;

case 0x77:ZZ(tab[12]);break;

case 0xb7:ZZ(tab[13]);break;

case 0xd7:ZZ(tab[14]);break;

case 0xe7:ZZ(tab[15]);break; */

default:break;

}

v=0;

}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈函数:NEC编码发送程序

入口:八位操作码

┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/ void ZZ(uint8 Value)

{

TT0(1,m9); //高电平9mS

TT0(0,m4_5); //低电平4.5mS

/*┈发送4帧数据┈*/

Z0(USER_H); //用户码高8位

Z0(USER_L); //用户码低8位

Z0(Value); //操作码

Z0(~Value); //操作码反码

/*┈┈结束码┈┈*/

TT0(1,m_56);

TT0(0,m40);

/*┈┈重复码┈┈*/

while(KEY() != 0xFF)

{

TT0(1,m9);

TT0(0,m2_25);

TT0(1,m_56);

TT0(0,m40);

TT0(0,m56);

}

}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

函数:单帧(8位数据)发送程序

入口:temp

┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/

void Z0(uint8 temp)

{

uint8 v;

for (v=0;v<8;v++) //循环8次移位

{

TT0(1,m_56); //高电平0.65mS

if(temp&0x01) TT0(0,m1_6); //发送最低位

else TT0(0,m_56);

temp >>= 1; //右移一位

}

}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

函数:38KHz载波发射+ 延时程序

入口:(是否发射载波,延时约x (uS))

┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/

void TT0(bit BT,uint16 x)

{

TH0 = x>>8; //输入T0初始值

TL0 = x;

TF0=0; //清0

TR0=1; //启动定时器0

if(BT == 0) while(!TF0); //BT=0时,不发射38KHz载波只延时;BT=1发射38KHz脉冲且延时;else while(1) //38KHz载波,(低电平)占空比5:26

{

IR = 0;

if(TF0)break;if(TF0)break;

IR = 1;

if(TF0)break;if(TF0)break;

if(TF0)break;if(TF0)break;

if(TF0)break;if(TF0)break;

if(TF0)break;if(TF0)break;

if(TF0)break;if(TF0)break;

}

TR0=0; //关闭定时器0

TF0=0; //标志位溢出则清0

IR =1; //载波停止后,发射端口常态为高

}

/*┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

函数:外部中断函数

入口:void

┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈*/

void IR_IN(void) interrupt 0 //外部中断服务程序

{

unsigned char j,k,N=0;

EX0 = 0;

delay(15);

if (IRIN==1)

{ EX0 =1;

return;

}

//确认IR信号出现

while (!IRIN) //等IR变为高电平,跳过9ms的前导低电平信号。

{delay(1);}

for (j=0;j<4;j++) //收集四组数据

{

for (k=0;k<8;k++) //每组数据有8位

{

while (IRIN) //等IR 变为低电平,跳过4.5ms的前导高电平信号。

{delay(1);}

while (!IRIN) //等IR 变为高电平

{delay(1);}

while (IRIN) //计算IR高电平时长

{

delay(1);

N++;

if (N>=30)

{ EX0=1;

return;} //0.14ms计数过长自动离开。

} //高电平计数完毕

IRCOM[j]=IRCOM[j] >> 1; //数据最高位补“0”

if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;} //数据最高位补“1”

N=0;

}//end for k

}//end for j

if (IRCOM[2]!=~IRCOM[3]) //按位取反

{ EX0=1;

return; }

IRCOM[5]=IRCOM[2] & 0x0F; //取键码的低四位

IRCOM[6]=IRCOM[2] >> 4; //右移4次,高四位变为低四位

if(IRCOM[5]>9)

{ IRCOM[5]=IRCOM[5]+0x37;}

else

IRCOM[5]=IRCOM[5]+0x30;

if(IRCOM[6]>9)

{ IRCOM[6]=IRCOM[6]+0x37;}

else

IRCOM[6]=IRCOM[6]+0x30;

lcd_pos(0x4b);

lcd_wdat(IRCOM[6]); //第一位数显示

lcd_pos(0x4c);

lcd_wdat(IRCOM[5]); //第二位数显示

Y0=0;

switch(IRCOM[2])

{

case 0x09: Y0=0x01; break;

case 0x1D: Y0=0x02; break;

case 0x1F: Y0=0x03; break;

case 0x0D: Y0=0x04; break;

case 0x19: Y0=0x05; break;

case 0x1B: Y0=0x06; break;

case 0x11: Y0=0x07; break;

case 0x15: Y0=0x08; break;

case 0x17: Y0=0x09; break;

default:break;

//case 0x13: RELAY=1; break;

// case 0x14: RELAY=1; break;

// case 0x51: RELAY=0; break;

}

tab[M] = IRCOM[2];

M = (M+1)%4;

beep();

EX0 = 1;

}

附录1

//头文件,包含各类定义

#ifndef __MY_SET_H__

#define __MY_SET_H__

// data 固定指片内RAM:0x00~0x7F

// bdata固定指片内RAM:0x20~0x2F

// idata固定指片内RAM:0x00~0xFF

// xdata一般指内部扩展RAM:0x0000~0xFFFF,也指内部扩展RAM:0x0000~0xFFFF // code 指程序存储区ROM:0x0000~0xFFFF

//无符号类型

#define uint8 unsigned char

#define uint8b unsigned char bdata

#define uint8i unsigned char idata

#define uint8x unsigned char xdata

#define uint8c unsigned char code

#define uint16 unsigned int

#define uint16i unsigned intidata

#define uint16x unsigned intxdata

#define uint16c unsigned int code

#define uint32 unsigned long

#define uint32i unsigned long idata

#define uint32x unsgined long xdata

#define uint32c unsgined long code

//有符号类型

#define int8 char

#define int8x char xdata

#define int8c char code

#define int16 int

#define int16x intxdata

#define int16c int code

#define int32 long

#define int32x long xdata

#define int32c long code

/////////////

#include

#define NOP _nop_()

#define NOP_12 _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_no p_()

#define NOP() _nop_() /* 定义空指令*/

#define uchar unsigned char

#define uint unsignedint

#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

#endif

//头文件2,LCD的全部函数

#ifndef __LCD1602_6IO_H__

#define __LCD1602_6IO_H__

sbit IRIN = P3^2; //红外接收器数据线

uchar IRCOM[7];

uchar cdis1[] = {" REMOTE CONTROL "};

uchar cdis2[] = {" IR-CODE: ----H"};

//LCD IO

sbit LCD_RW = P2^5;

sbit LCD_RS = P2^6;

sbit LCD_EN = P2^7;

sbit BEEP = P1^5;

void delay(uchar x); //x*0.14MS

void delay1(intms);

void beep(void);

unsigned char Y0;

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

/* */

/*检查LCD忙状态*/

/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。*/ /* */ /*******************************************************************/

bitlcd_busy()

{

bit result;

LCD_RS = 0;

LCD_RW = 1;

LCD_EN = 1;

delayNOP();

result = (bit)(P0&0x80);

LCD_EN = 0;

return(result);

}

/*******************************************************************/ /* */ /*写指令数据到LCD */ /*RS=L,RW=L,E=高脉冲,D0-D7=指令码。*/ /* */ /*******************************************************************/

voidlcd_wcmd(ucharcmd)

{

while(lcd_busy());

LCD_RS = 0;

LCD_RW = 0;

LCD_EN = 0;

_nop_();

_nop_();

P0 = cmd;

delayNOP();

LCD_EN = 1;

delayNOP();

LCD_EN = 0;

}

/*******************************************************************/ /* */ /*写显示数据到LCD */ /*RS=H,RW=L,E=高脉冲,D0-D7=数据。*/ /* */

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

voidlcd_wdat(uchardat)

{

while(lcd_busy());

LCD_RS = 1;

LCD_RW = 0;

LCD_EN = 0;

P0 = dat;

delayNOP();

LCD_EN = 1;

delayNOP();

LCD_EN = 0;

}

/*******************************************************************/ /* */ /* LCD初始化设定*/ /* */ /*******************************************************************/

voidlcd_init()

{

delay1(15);

lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据

delay1(5);

lcd_wcmd(0x38);

delay1(5);

lcd_wcmd(0x38);

delay1(5);

lcd_wcmd(0x0c); //显示开,关光标

delay1(5);

lcd_wcmd(0x06); //移动光标

delay1(5);

lcd_wcmd(0x01); //清除LCD的显示内容

delay1(5);

}

/*******************************************************************/ /* */ /* 设定显示位置*/ /* */ /*******************************************************************/

voidlcd_pos(ucharpos)

{

lcd_wcmd(pos | 0x80); //数据指针=80+地址变量

}

/**********************************************************/ void delay(unsigned char x) //x*0.14MS

{

unsigned char i;

while(x--)

{

for (i = 0; i<13; i++) {}

}

}

/**********************************************************/ void delay1(intms)

{

unsigned char y;

while(ms--)

{

for(y = 0; y<250; y++)

{

_nop_();

_nop_();

_nop_();

_nop_();

}

}

}

void beep(void)

{

unsigned char i;

for (i=0;i<100;i++)

{

delay(4);

BEEP=!BEEP; //BEEP取反

}

BEEP=1; //关闭蜂鸣器

}

#endif

相关主题
相关文档
最新文档