日期:2025-07-17 12:38:55 人气:1

    A+
热门评论

急需基于51单片机的红外遥控开关的设计原理图和程序(c语言版)

/*------------------------------------------------*/ #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义 sbit IR=P3^2; //红外接口标志 #define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换 sbit DUAN=P2^6;//定义锁存使能端口 段锁存 sbit WEI=P2^7;// 位锁存 /*------------------------------------------------ 全局变量声明 ------------------------------------------------*/ unsigned char code dofly_DuanMa[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};// 显示段码值0~F unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码 unsigned char TempData[8]; //存储显示值的全局变量 unsigned char irtime;//红外用全局变量 bit irpro_ok,irok; unsigned char IRcord[4]; unsigned char irdata[33]; /*------------------------------------------------ 函数声明 ------------------------------------------------*/ void Ir_work(void); void Ircordpro(void); /*------------------------------------------------ 显示函数,用于动态扫描数码管 输入参数 FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示 如输入0表示从第一个显示。 Num表示需要显示的位数,如需要显示99两位数值则该值输入2 ------------------------------------------------*/ void Display(unsigned char FirstBit,unsigned char Num) { static unsigned char i=0; DataPort=0; //清空数据,防止有交替重影 DUAN=1; //段锁存 DUAN=0; DataPort=dofly_WeiMa[i+FirstBit]; //取位码 WEI=1; //位锁存 WEI=0; DataPort=TempData[i]; //取显示数据,段码 DUAN=1; //段锁存 DUAN=0; i++; if(i==Num) i=0; } /*------------------------------------------------ 定时器0中断处理 ------------------------------------------------*/ void tim0_isr (void) interrupt 1 using 1 { irtime++; //用于计数2个下降沿之间的时间 } /*------------------------------------------------ 定时器中断子程序 ------------------------------------------------*/ void Timer1_isr(void) interrupt 3 { TH1=(65536-2000)/256; //重新赋值 2ms TL1=(65536-2000)%256; Display(0,8); // 调用数码管扫描 } /*------------------------------------------------ 外部中断0中断处理 ------------------------------------------------*/ void EX0_ISR (void) interrupt 0 //外部中断0服务函数 { static unsigned char i; //接收红外信号处理 static bit startflag; //是否开始处理标志位 if(startflag) { if(irtime=33)//引导码 TC9012的头码,9ms+4.5ms i=0; irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1 irtime=0; i++; if(i==33) { irok=1; i=0; } } else { irtime=0; startflag=1; } } /*------------------------------------------------ 定时器0初始化 ------------------------------------------------*/ void TIM0init(void)//定时器0初始化 { TMOD=0x02;//定时器0工作方式2,TH0是重装值,TL0是初值 TH0=0x00; //重载值 TL0=0x00; //初始化值 ET0=1; //开中断 TR0=1; } /*------------------------------------------------ 定时器初始化子程序 ------------------------------------------------*/ void Init_Timer1(void) { TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 //TH1=0x00; //给定初值 //TL1=0x00; EA=1; //总中断打开 ET1=1; //定时器中断打开 TR1=1; //定时器开关打开 } /*------------------------------------------------ 外部中断0初始化 ------------------------------------------------*/ void EX0init(void) { IT0 = 1; //指定外部中断0下降沿触发,INT0 (P3.2) EX0 = 1; //使能外部中断 EA = 1; //开总中断 } /*------------------------------------------------ 键值处理 ------------------------------------------------*/ void Ir_work(void)//红外键值散转程序 { TempData[0]=dofly_DuanMa[IRcord[0]/16]; TempData[1]=dofly_DuanMa[IRcord[0]%16]; TempData[2]=dofly_DuanMa[IRcord[1]/16]; TempData[3]=dofly_DuanMa[IRcord[1]%16]; TempData[4]=dofly_DuanMa[IRcord[2]/16]; TempData[5]=dofly_DuanMa[IRcord[2]%16]; TempData[6]=dofly_DuanMa[IRcord[3]/16]; TempData[7]=dofly_DuanMa[IRcord[3]%16]; //Display(0,8); // 调用数码管扫描 irpro_ok=0;//处理完成标志 } /*------------------------------------------------ 红外码值处理 ------------------------------------------------*/ void Ircordpro(void)//红外码值处理函数 { unsigned char i, j, k; unsigned char cord,value; k=1; for(i=0;i<4;i++) //处理4个字节 { for(j=1;j<=8;j++) //处理1个字节8位 { cord=irdata[k]; if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差 value|=0x80; if(j<8) { value>>=1; } k++; } IRcord[i]=value; value=0; } irpro_ok=1;//处理完毕标志位置1 } /*------------------------------------------------ 主函数 ------------------------------------------------*/ void main(void) { EX0init(); //初始化外部中断 TIM0init();//初始化定时器 Init_Timer1(); while(1)//主循环 { if(irok) //如果接收好了进行红外处理 { Ircordpro(); irok=0; } if(irpro_ok) //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等 { Ir_work(); } } } 51P3^2是外部中断,红外接收管接这个引脚就能接收到数据然后显示在数码管上

阅读全文

51单片机红外遥控程序

#include #include #define uchar unsigned char #define uint unsigned int sbit lcden = P2^7; sbit lcdrs = P2^6; sbit lcdwr = P2^5; sbit IR = P3^2; uchar IRCOM[6];//数组,用于存储红外编码 uchar code table1[] = "remote control"; uchar code table2[] = "CODE:"; void delayms(uchar x)// 延时x*0.14ms { uchar i; while(x--) for(i=0;i<13;i++){} } void delay(uchar x) //延时xms { uchar i,j; for(i=x;i>0;i--) for(j=110;j>0;j--); } /****************************LCD部分***********************************************/ void write_com(uchar com) { lcden = 0; lcdrs = 0; lcdwr = 0; P0 = com; delay(5); lcden = 1; delay(5); lcden = 0; //别忘了lcden拉低 } void write_date(uchar date) { lcden = 0; lcdrs = 1; lcdwr = 0; P0 = date; delay(5); lcden = 1; delay(5); lcden = 0; } void lcd_init(void) { lcden = 0; lcdrs = 0; lcdwr = 0; delay(5); write_com(0x38); write_com(0x0c); write_com(0x06); write_com(0x01); } /*****************main()************************/ void main(void) { uchar count=0; IR = 1; lcd_init(); write_com(0x80); while(table1[count]!='\0') { write_date(table1[count]); count++; delay(5); } count = 0; write_com(0x80+0x40); while(table2[count]!='\0') { write_date(table2[count]); count++; delay(5); } IE = 0x81; //开中断 TCON = 0x01;//脉冲负边沿触发 while(1); } /*********************红外中断**************************/ void IR_time() interrupt 0 { uchar i,j,TimeNum=0;//TimeNum用来计IR高电平次数 从而判断是0还是1 EX0 = 0; //关闭中断 delayms(5); if(1 == IR) { EX0 = 1; return; } while(!IR) //跳过9ms前导低电平 delayms(1); for(i=0;i<4;i++) { for(j=0;j<8;j++) { while(IR) //跳过4.5ms的前导高电平 delayms(1); while(!IR) //跳过0.56ms的低电平 delayms(1); while(IR) { TimeNum++; //计时高电平时间从而判断读取的是0还是1 delayms(1); } if(TimeNum>=30)//按键按下时间过长 跳过 { EX0 = 1; return; } IRCOM[i] = IRCOM[i]>>1; if(TimeNum >= 8) //8*0.14ms 这时读取的是1; { IRCOM[i] = IRCOM[i]|0x80; } TimeNum = 0; } } if(IRCOM[2]!=~IRCOM[3])//判断八位数据和八位数据反码是否相等 { EX0 = 1; return; } IRCOM[4] = IRCOM[2]&0x0f;//取低四位 IRCOM[5] = IRCOM[2]>>4; //IRCOM[5]取IRCOM[2]高四位 if(IRCOM[4] > 9) //转换成字符 { IRCOM[4] = IRCOM[4] + 0x37; } else IRCOM[4] = IRCOM[4] + 0x30; if(IRCOM[5] > 9) { IRCOM[5] = IRCOM[5] + 0x37; } else IRCOM[5] = IRCOM[5] + 0x30; delay(5); write_com(0x80 + 0x40 + 5); write_date(IRCOM[5]); write_date(IRCOM[4]); EX0 = 1; //重新开启外部中断 }

阅读全文