N年前在网上买了一个TM1650的测试版,今天突然看到了,倒腾了一下。写了个程序。希望对大家有用,不喜勿喷。
单片机源程序如下:
- /*程序功能:TM1650驱动程序加红外遥控解码程序 。遥控解码后显示在数码管上
- IO 分配:查看位定义
- 时钟频率:11.0592MHz
- 版 本:VER0
- 作 者:刘海兰
- 日 期:2021.03.06
- 备 注:如果要在程序中使用此代码,请在程序中注明使用了51黑单片机liuhailan5757博主的程序
- 但是由此造成的后果与本博主无关,
- */
- #include<stc15.h>
- sbit scl = P3^3; //TM1650时钟通讯IO
- sbit sda = P3^2;//TM1650数据通讯IO
- sbit ir = P3^4;//红外输入口
- sbit led = P3^5;//测试用指示灯,在调试红外遥控时可用
- unsigned char ir_time = 0; //红外信号的时间,这个寄存器是为了在解码0/1(数据)的时候,用来计低电平的时间
- bit ir_d = 0;//红外信号的高低标志位,
- bit ir_ok = 0;//解码OK
- unsigned char shuwei = 0;//解码的长度
- unsigned char shuwei1 = 0;//解码的长度
- unsigned char buzhou = 0;//解码的步骤
- unsigned char ir_dat = 0;//红外的8位数据
- unsigned char num[]={0,0,0,0};//红外的4组8位的数据,就是用户码,用户码反码,数据码,数据码反码
- code unsigned char shuma[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //子模0-9,A,B,C,D,E,F
- unsigned char reg1 = 0; //通用寄存器1
- unsigned char reg2 = 0; //通用寄存器2 这两个寄存器在转换成可显示的数据要用到
- void delay(unsigned int time)
- {
- while(time--);
- }
- void tm1650_start(); //TM1650通讯的开始信号
- void tm1650_end();//TM1650通讯的结束信号
- void tm1650_ack();//TM1650通讯的应答信号
- void write_1();//TM1650数据通讯 写1
- void write_0();//TM1650数据通讯 写0
- void write_byte(unsigned char tem);//写一个字节
- void TM0_Isr() interrupt 1 //红外解码,定时器的时基是50us中断一次
- {
- INT_CLKO &= 0xef; //关闭外部中断
- if(buzhou==0) //步骤0,判断9ms的低电平
- {
- if(!ir)
- {
- ir_time++;
- if(ir_time>185) //低电平超时,每一次因为错误退出解码时,一点要清掉用到的那些寄存器!!!!!!这里一点要注意,下面的退出里面也是要清掉
- {
- ir_d = 0;
- ir_time = 0;
- buzhou = 0;
- TR0 = 0;
- INT_CLKO |= 0x10;
- }
- }
- else
- {
- if((ir_time>175)&&(ir_time<185)) //低电平OK,是正确的9ms ,就跳到步骤1 (9mS除以50uS=180,所以这里的值就设为175和185之间,因为要考虑到一点的误差)
- {
- ir_time = 0;
- //led ^= 1;
- buzhou = 1;
- }
- else //不是正确的9ms
- {
- buzhou = 0;
- TR0 = 0;
- INT_CLKO |= 0x10;
- }
- }
- }
- if(buzhou==1) //步骤1,判断4.5ms的高电平
- {
- if(ir)
- {
- ir_time++;
- if(ir_time>95) //高电平超时
- {
- ir_d = 0;
- ir_time = 0;
- buzhou = 0;
- TR0 = 0;
- INT_CLKO |= 0x10;
- }
- }
- else
- {
- if((ir_time>85)&&(ir_time<95)) //4.5ms高电平OK,就跳到步骤2 这里还可以添加判断连码的程序,如果这里的时间是2mS 那就是连码
- {
- ir_time = 0;
- // led ^= 1;
- buzhou = 2;
- ir_d = 0;
- }
- else //不OK
- {
- buzhou = 0;
- TR0 = 0;
- INT_CLKO |= 0x10;
- }
- }
- }
- if(buzhou==2) //步骤2开始解码数据
- {
- if(!ir_d) //如果低电平标志为0时,这里是用来判断低电平的时间
- {
- if(!ir) //如果红外端口为低
- {
- ir_time++; //计低电平的时间
- if(ir_time>13) //低电平时间超时,就退出解码
- {
- ir_d = 0;
- ir_time = 0;
- buzhou = 0;
- TR0 = 0;
- INT_CLKO |= 0x10;
- shuwei = 0;
- shuwei1 = 0;
- }
- }
- else //如果转为高电平了,
- {
- ir_d = 1; //低电平标志位置一,要去判断高电平的时间了
- ir_time = 0;//时间清零
- }
- }
- else //如果低电平标志位为1,就是进入判断IR高电平的时间了,这个高电平的时间就是判断数据是0还是1
- {
- if(ir) //如果IR为高
- {
- ir_time++;//计高电平的是按
- if(ir_time>34) //超时了就退出解码
- {
- ir_d = 0;
- ir_time = 0;
- buzhou = 0;
- TR0 = 0;
- INT_CLKO |= 0x10;
- shuwei = 0;
- shuwei1 = 0;
- }
- }
- else //如果IR为低了,就可以判断高电频的时间了
- {
- if(ir_time>16) //时间大于16*50us 就是数据1
- ir_dat |= 0x80;
- else //否则就是数据0
- ir_dat &= 0x7f;
- shuwei++;
- if(shuwei==8) //8bit 组成1byte
- {
- num[shuwei1]=ir_dat;
- shuwei = 0;
- shuwei1++; //总共4byte
- if(shuwei1==4) //4组数据接收完了就接收解码
- {
- // if(num[2]==0x45)
- // led = 0;
- // else
- // led = 1;
- ir_ok = 1; //解码成功标志位置一
- buzhou = 0;
- TR0 = 0;
- INT_CLKO |= 0x10;
- shuwei1 = 0;
- }
- }
- ir_dat>>=1;
- ir_time = 0;
- ir_d = 0;
- }
- }
- }
- }
- void INT2_Isr() interrupt 10 //IR为低 就进入此中断,开启解码,解码中这个中断是关闭的,只有退出了解码,才会进入这个中断
- {
- if(!ir)
- {
- buzhou = 0;
- ir_d = 0;
- shuwei = 0;
- shuwei1 = 0;
- ir_time = 0;
- TR0 = 1;
- }
- }
- void main()
- {
- P3M0 = 0x00;
- P3M1 = 0x00;
- P3 = 0xff;
- AUXR |= 0x80; //定时器时钟1T模式
- TMOD = 0x00; //模式0
- TL0 = 0xD7; //设置定时初值
- TH0 = 0xFD; //定时器0设为50us中断一次
- TR0 = 0; //启动定时器
- ET0 = 1; //使能定时器中断
- INT_CLKO |= 0x10; //(EX2 = 1)使能INT2中断
- EA = 1;
- while(1)
- {
- tm1650_start();
- write_byte(0x48); //数码显示模式
- tm1650_ack();
- write_byte(0x11); //1级亮度,开显示。这里的指令数据 详情参阅TM1650的datasheet
- tm1650_ack();
- tm1650_end();
- tm1650_start();
- write_byte(0x68);
- tm1650_ack();
- write_byte(shuma[reg1]);
- tm1650_ack();
- tm1650_end();
- tm1650_start();
- write_byte(0x6a);
- tm1650_ack();
- write_byte(shuma[reg2]);
- tm1650_ack();
- tm1650_end();
- tm1650_start();
- write_byte(0x6c);
- tm1650_ack();
- write_byte(0x5b);//固定显示2
- tm1650_ack();
- tm1650_end();
- tm1650_start();
- write_byte(0x6e);
- tm1650_ack();
- write_byte(0x3f); //固定显示0,这里固定显示02,是因为我们解码的数据是第2组数据,也就是数据码(第0组数据是用户码,1是用户码反码,2是数据码,3是数据码反码)
- tm1650_ack();
- tm1650_end();
- if(ir_ok)
- {
- ir_ok = 0; //清掉解码标志位
- reg1 = (num[2]&0x0f); // 数据低4位送显示 把数据转为0-F
- reg2 = (num[2]&0xf0);//数据的高四位送显示
- reg2>>=4;
- }
- }
- }
- void tm1650_start()
- {
- sda = 1;
- scl = 1;
- delay(10);
- sda = 0;
- delay(5);
- }
- void tm1650_end()
- {
- sda = 0;
- scl = 1;
- delay(6);
- sda = 1;
- delay(2);
- }
- void tm1650_ack()
- {
- while(sda);
- delay(5);
- scl = 1;
- delay(5);
- scl = 0;
- delay(5);
- }
- void write_1()
- {
- sda = 1;
- scl = 0;
- delay(5);
- scl = 1;
- delay(10);
- scl = 0;
- delay(5);
- sda = 0;
- }
- void write_0()
- {
- sda = 0;
- scl = 0;
- delay(5);
- scl = 1;
- delay(10);
- scl = 0;
- }
- void write_byte(unsigned char tem)
- {
- unsigned char i;
- for(i=8;i>0;i--)
- {
- if(tem&0x80)
- write_1();
- else
- write_0();
- tem<<=1;
- }
- }
复制代码
以上程序下载:
TM1650+红外解码.zip
(150.58 KB, 下载次数: 93)
|