基于stc15w的红外控制程序(实测stc15w408as、15w204s、15w4k56s4均可用,使用外中断P3.3接收信号),可以和万能红外遥控器和智能音箱结合实现远程控制和语音控制,前提需要知道红外码
红外解码16位解码.zip
(57.26 KB, 下载次数: 113)
红外接收(P3.3中断).zip
(46.72 KB, 下载次数: 105)
单片机源程序如下:
- /*********************************************************************************************
- 程序名: DHT11-1602
- 编写人: fby
- 硬件支持: STC89C52RC DHT11 LCD1602
- 接口说明: DHT11:VCC DATA NC GND
- *********************************************************************************************
- 说明:1、单片机是STC89C52RC,晶振频率11.0592MHz,实验成功。
- 2、好东西要共享,大家随意折腾~~
- *********************************************************************************************/
- #include<reg51.h>
- #include<intrins.h>
- #include<stdio.h>
- #define uchar unsigned char //无符号字符型类型数据
- #define uint unsigned int //无符号整型数据
- #define ulong unsigned long //无符号整型数据
- #define xiao float //xiaoshu
- #define IODATA P0
- unsigned char IrValue[24]; //接收收据
- unsigned char Time;
- sbit RS=P2^6; //定义rs端口
- sbit RW=P2^5; //定义rw端口
- sbit E=P2^7;
-
- sbit IRIN=P3^2;//红外数据io
-
- /*******************************************************************************
- * 函数名 : DelayMs()
- * 函数功能 : 延时
- * 输入 : x
- * 输出 : 无
- *******************************************************************************/
- void DelayMs(unsigned int x) //0.14ms误差 0us
- {
- unsigned char i;
- while(x--)
- {
- for (i = 0; i<13; i++)
- {}
- }
- }
- /*******************************************************************************
- * 函数名 : IrInit()
- * 函数功能 : 初始化红外线接收
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void IrInit()
- {
- IT0=1;//下降沿触发
- EX0=1;//打开中断0允许
- EA=1; //打开总中断
- IRIN=1;//初始化端口
- }
- /*******************************************************************************
- * 函数名 : ReadIr()
- * 函数功能 : 读取红外数值的中断函数
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void ReadIr() interrupt 0
- {
- unsigned char j,k;
- unsigned int err;
- Time=0;
- DelayMs(70);
- if(IRIN==0) //确认是否真的接收到正确的信号
- {
-
- err=1000; //1000*10us=10ms,超过说明接收到错误的信号
- /*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时
- 侯,程序死在这里*/
- while((IRIN==0)&&(err>0)) //等待前面9ms的低电平过去
- {
- DelayMs(1);
- err--;
- }
- if(IRIN==1) //如果正确等到9ms低电平
- {
- err=500;
- while((IRIN==1)&&(err>0)) //等待4.5ms的起始高电平过去
- {
- DelayMs(1);
- err--;
- }
- for(k=0;k<8;k++) //共有4组数据
- {
- for(j=0;j<8;j++) //接收一组数据
- {
- err=60;
- while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去
- // while (!IRIN)
- {
- DelayMs(1);
- err--;
- }
- err=500;
- while((IRIN==1)&&(err>0)) //计算高电平的时间长度。
- {
- DelayMs(1);//0.14ms
- Time++;
- err--;
- if(Time>30)
- {
- EX0=1;
- return;
- }
- }
- IrValue[k]>>=1; //k表示第几组数据
- if(Time>=8) //如果高电平出现大于565us,那么是1
- {
- IrValue[k]|=0x80;
- }
- Time=0; //用完时间要重新赋值
- }
- }
- }
-
- return;
-
- }
- }
- //数据处理
- void sjcl()
- {
- IrValue[8]=IrValue[0]>>4; //高位 用户码
- IrValue[9]=IrValue[0]&0x0f; //低位
- IrValue[10]=IrValue[1]>>4; //高位 用户反码
- IrValue[11]=IrValue[1]&0x0f; //低位
- IrValue[12]=IrValue[2]>>4; //高位 数据码
- IrValue[13]=IrValue[2]&0x0f; //低位
- IrValue[14]=IrValue[3]>>4; //高位 数据反码
- IrValue[15]=IrValue[3]&0x0f; //低位
-
- IrValue[16]=IrValue[4]>>4; //高位 数据反码
- IrValue[17]=IrValue[4]&0x0f; //低位
- IrValue[18]=IrValue[5]>>4; //高位 数据反码
- IrValue[19]=IrValue[5]&0x0f; //低位
- IrValue[20]=IrValue[6]>>4; //高位 数据反码
- IrValue[21]=IrValue[6]&0x0f; //低位
- IrValue[22]=IrValue[7]>>4; //高位 数据反码
- IrValue[23]=IrValue[7]&0x0f; //低位
- }
-
- /*********************************************************************************************
- 函数名:延时函数
- 调 用:Delay30us();/Delay20ms();/Delay1s();
- 参 数:无
- 返回值:无
- 结 果:延时相应时间
- 备 注:振荡晶体为11.0592MHz(所有延时函数Copy自STC-ISP(v6.85).exe)
- **********************************************************************************************/
- void Delay30us() //@11.0592MHz-40
- {
- unsigned char i;
- i = 11;
- while (--i);
- }
- void Delay20ms() //@11.0592MHz
- {
- unsigned char i, j;
- i = 36;
- j = 217;
- do
- {
- while (--j);
- } while (--i);
- }
- void Delay1s() //@11.0592MHz
- {
- unsigned char i, j, k;
- _nop_();
- i = 8;
- j = 1;
- k = 243;
- do
- {
- do
- {
- while (--k);
- } while (--j);
- } while (--i);
- }
- /********************************************************************
- * 名称 : bit Busy(void)
- * 功能 : 这个是一个读状态函数,读出函数是否处在忙状态
- * 输入 : 输入的命令值
- * 输出 : 无
- ***********************************************************************/
- void Busy(void)
- {
- bit busy_flag = 1;
- IODATA = 0xff;
- RS = 0; //指令关
- Delay30us();
- RW = 1; //读状态
- Delay30us();
- E = 1; //使能高电平
- while(1)
- {
- busy_flag = (bit)(IODATA & 0x80); //强制取最高位
- if(busy_flag == 0)
- {
- break;
- }
- }
- E = 0; //E 1->0,rs=0,rw=1,
- //将数据寄存器内的数据读到DB0~DB7,分别将状态标志BF和地址计数器(AC)内容读到DB7和DB6~DB0。
- }
- /********************************************************************
- * 名称 : lcd1602_write_cmd(uchar del)
- * 功能 : 1602命令函数
- * 输入 : 输入的命令值
- * 输出 : 无
- ***********************************************************************/
- void lcd1602_write_cmd(uchar del)
- {
- RS = 0;
- Delay30us();
- RW = 0;
- Delay30us();
- E = 0;
- Delay30us();
- IODATA = del;
- Delay30us();
- E = 1;
- Delay30us();
- E = 0; //E 1->0,rs=0,rw=0, 将指令代码写入指令寄存器中
- }
- /********************************************************************
- * 名称 : lcd1602_write_data(uchar del)
- * 功能 : 1602写数据函数
- * 输入 : 需要写入1602的数据
- * 输出 : 无
- ***********************************************************************/
- void lcd1602_write_data(uchar del)
- {
- Busy();
- Delay30us();
- RS = 1;
- Delay30us();
- RW = 0;
- Delay30us();
- E = 0;
- Delay30us();
- IODATA = del;
- Delay30us();
- E = 1;
- Delay30us();
- E = 0; //E 1->0,rs=1,rw=0, 数据写入数据寄存器中
- }
- /********************************************************************
- * 名称 : lcd1602_init()
- * 功能 : 1602初始化,请参考1602的资料
- * 输入 : 无
- * 输出 : 无
- ***********************************************************************/
- void lcd1602_init(void)
- {
- Delay20ms();
- lcd1602_write_cmd(0x38); //8位数据,双列,5*7字形
- Delay20ms();
- lcd1602_write_cmd(0x38);
- Delay20ms();
- lcd1602_write_cmd(0x38);
- Busy();
- lcd1602_write_cmd(0x08);// 只开显示
- Busy();
- lcd1602_write_cmd(0x01); //清屏
- Busy();
- lcd1602_write_cmd(0x06);//显示地址递增,即写一个数据后,显示位置右移一位
- Busy();
- lcd1602_write_cmd(0x0c); //开启显示屏,关光标,光标不闪烁
- }
- /********************************************************************
- * 名称 : lcd1602_char(uchar hang,uchar lie,char sign)
- * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符显示"b" ,调用该函数如下
- L1602_char(1,5,'b')
- * 输入 : 行,列,需要输入1602的数据
- * 输出 : 无
- ***********************************************************************/
- void lcd1602_char(uchar hang,uchar lie,char sign)
- {
- uchar a;
- if(hang == 1)
- {
- a = 0x80;
- }
- if(hang == 2)
- {
- a = 0xc0;
- }
- a = a + lie - 1;
- Busy();
- lcd1602_write_cmd(a); //置数据存贮器地址
- Busy();
- lcd1602_write_data(sign);
- }
- /********************************************************************
- * 名称 : lcd1602_string(uchar hang,uchar lie,uchar *p)
- * 功能 : 改变液晶中某位的值,如果要让第一行,第五个字符开始显示"ab cd ef" ,调用该函数如下
- L1602_string(1,5,"ab cd ef;")
- * 输入 : 行,列,需要输入1602的数据
- * 输出 : 无
- ***********************************************************************/
- void lcd1602_string(uchar hang,uchar lie,uchar *p)
- {
- uchar a;
- if(hang == 1)
- {
- a = 0x80;
- }
- if(hang == 2)
- {
- a = 0xc0;
- }
- a = a + lie - 1;
- while(1)
- {
- Busy();
- lcd1602_write_cmd(a);
- Busy();
- lcd1602_write_data(*p);
- a++;
- p++;
- if((*p == '\0')||(a==0x90)||(a==0xd0)) //字符结束或每行最后一个字符
- {
- break;
- }
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
|