N年前在網上買了一個TM1650的測試版,今天突然看到了,倒騰了一下。寫了個程序。希望對大家有用,不喜勿噴。
TM1650測試板.jpg (148.66 KB, 下載次數: 95)
下載附件
TM1650顯示驅動加紅外解碼
2021-3-6 13:11 上傳
單片機源程序如下:
- /*程序功能: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)
2021-3-6 13:19 上傳
點擊文件名下載附件
TM1650+紅外解碼 下載積分: 黑幣 -5
|