单片机TM1650驱动+红外遥控解码源程序 -方新你好影院
设为首页收藏本站
开启辅助访问 切换到宽版

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8159|回复: 2
打印 上一主题 下一主题
收起左侧

单片机TM1650驱动+红外遥控解码源程序

  [复制链接]
跳转到指定楼层
楼主
ID:387856 发表于 2021-3-6 13:20 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
N年前在网上买了一个TM1650的测试版,今天突然看到了,倒腾了一下。写了个程序。希望对大家有用,不喜勿喷。


单片机源程序如下:
  1. /*程序功能:TM1650驱动程序加红外遥控解码程序 。遥控解码后显示在数码管上
  2.   IO  分配:查看位定义
  3.   时钟频率:11.0592MHz
  4.   版    本:VER0
  5.   作    者:刘海兰
  6.   日    期:2021.03.06
  7.   备    注:如果要在程序中使用此代码,请在程序中注明使用了51黑单片机liuhailan5757博主的程序
  8.             但是由此造成的后果与本博主无关,  
  9. */
  10. #include<stc15.h>
  11. sbit scl = P3^3; //TM1650时钟通讯IO
  12. sbit sda = P3^2;//TM1650数据通讯IO
  13. sbit ir  = P3^4;//红外输入口
  14. sbit led = P3^5;//测试用指示灯,在调试红外遥控时可用
  15. unsigned char ir_time = 0;        //红外信号的时间,这个寄存器是为了在解码0/1(数据)的时候,用来计低电平的时间
  16. bit ir_d = 0;//红外信号的高低标志位,
  17. bit ir_ok = 0;//解码OK
  18. unsigned char shuwei = 0;//解码的长度
  19. unsigned char shuwei1 = 0;//解码的长度
  20. unsigned char buzhou = 0;//解码的步骤
  21. unsigned char ir_dat = 0;//红外的8位数据
  22. unsigned char num[]={0,0,0,0};//红外的4组8位的数据,就是用户码,用户码反码,数据码,数据码反码
  23. 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
  24. unsigned char reg1 = 0;        //通用寄存器1
  25. unsigned char reg2 = 0;        //通用寄存器2  这两个寄存器在转换成可显示的数据要用到
  26. void delay(unsigned int time)
  27. {
  28. while(time--);
  29. }
  30. void tm1650_start(); //TM1650通讯的开始信号
  31. void tm1650_end();//TM1650通讯的结束信号
  32. void tm1650_ack();//TM1650通讯的应答信号
  33. void write_1();//TM1650数据通讯 写1
  34. void write_0();//TM1650数据通讯 写0
  35. void write_byte(unsigned char tem);//写一个字节
  36. void TM0_Isr() interrupt 1 //红外解码,定时器的时基是50us中断一次
  37. {
  38.   INT_CLKO &= 0xef;        //关闭外部中断
  39.   if(buzhou==0)                  //步骤0,判断9ms的低电平
  40.   {
  41.    if(!ir)
  42.    {
  43.     ir_time++;
  44.         if(ir_time>185)                 //低电平超时,每一次因为错误退出解码时,一点要清掉用到的那些寄存器!!!!!!这里一点要注意,下面的退出里面也是要清掉
  45.         {
  46.          ir_d = 0;
  47.          ir_time = 0;
  48.          buzhou = 0;
  49.      TR0 = 0;
  50.          INT_CLKO |= 0x10;
  51.     }
  52.    }
  53.    else
  54.    {
  55.     if((ir_time>175)&&(ir_time<185)) //低电平OK,是正确的9ms ,就跳到步骤1    (9mS除以50uS=180,所以这里的值就设为175和185之间,因为要考虑到一点的误差)
  56.     {
  57.          ir_time = 0;
  58.      //led ^= 1;
  59.          buzhou = 1;
  60.     }
  61.     else                 //不是正确的9ms
  62.     {
  63.          buzhou = 0;
  64.      TR0 = 0;
  65.          INT_CLKO |= 0x10;
  66.     }
  67.    }
  68.   }
  69.   if(buzhou==1)                 //步骤1,判断4.5ms的高电平
  70.   {
  71.    if(ir)
  72.    {
  73.     ir_time++;
  74.         if(ir_time>95)           //高电平超时
  75.         {
  76.          ir_d = 0;
  77.          ir_time = 0;
  78.          buzhou = 0;
  79.      TR0 = 0;
  80.          INT_CLKO |= 0x10;
  81.     }
  82.    }
  83.    else
  84.    {
  85.     if((ir_time>85)&&(ir_time<95))         //4.5ms高电平OK,就跳到步骤2  这里还可以添加判断连码的程序,如果这里的时间是2mS 那就是连码
  86.         {
  87.          ir_time = 0;
  88. //     led ^= 1;
  89.          buzhou = 2;
  90.          ir_d = 0;
  91.         }
  92.         else                          //不OK
  93.         {
  94.          buzhou = 0;
  95.      TR0 = 0;
  96.          INT_CLKO |= 0x10;
  97.         }
  98.    }
  99.   }
  100.   if(buzhou==2)           //步骤2开始解码数据
  101.   {
  102.    if(!ir_d)         //如果低电平标志为0时,这里是用来判断低电平的时间
  103.    {
  104.     if(!ir)           //如果红外端口为低
  105.     {
  106.      ir_time++;                //计低电平的时间
  107.          if(ir_time>13)        //低电平时间超时,就退出解码
  108.          {
  109.           ir_d = 0;
  110.           ir_time = 0;
  111.           buzhou = 0;
  112.       TR0 = 0;
  113.           INT_CLKO |= 0x10;
  114.           shuwei = 0;
  115.           shuwei1 = 0;
  116.          }
  117.     }
  118.     else           //如果转为高电平了,
  119.     {
  120.          ir_d = 1;        //低电平标志位置一,要去判断高电平的时间了
  121.          ir_time = 0;//时间清零
  122.     }
  123.    }
  124.    else           //如果低电平标志位为1,就是进入判断IR高电平的时间了,这个高电平的时间就是判断数据是0还是1
  125.    {
  126.     if(ir) //如果IR为高
  127.         {
  128.          ir_time++;//计高电平的是按
  129.          if(ir_time>34)         //超时了就退出解码
  130.          {
  131.           ir_d = 0;
  132.           ir_time = 0;
  133.           buzhou = 0;
  134.       TR0 = 0;
  135.           INT_CLKO |= 0x10;
  136.           shuwei = 0;
  137.           shuwei1 = 0;
  138.          }
  139.         }
  140.         else         //如果IR为低了,就可以判断高电频的时间了
  141.         {
  142.          if(ir_time>16)                 //时间大于16*50us  就是数据1
  143.           ir_dat |= 0x80;
  144.          else                                 //否则就是数据0
  145.           ir_dat &= 0x7f;
  146.         shuwei++;
  147.         if(shuwei==8)           //8bit 组成1byte
  148.         {
  149.          num[shuwei1]=ir_dat;
  150.          shuwei = 0;
  151.          shuwei1++;                 //总共4byte
  152.          if(shuwei1==4)         //4组数据接收完了就接收解码
  153.          {
  154. //          if(num[2]==0x45)
  155. //           led = 0;
  156. //          else
  157. //           led = 1;
  158.       ir_ok = 1;        //解码成功标志位置一
  159.           buzhou = 0;
  160.       TR0 = 0;
  161.           INT_CLKO |= 0x10;
  162.           shuwei1 = 0;
  163.          }
  164.         }
  165.         ir_dat>>=1;
  166.         ir_time = 0;
  167.         ir_d = 0;
  168.         }
  169.    }
  170.   }
  171. }
  172. void INT2_Isr() interrupt 10   //IR为低 就进入此中断,开启解码,解码中这个中断是关闭的,只有退出了解码,才会进入这个中断
  173. {
  174.   if(!ir)
  175.   {
  176.    buzhou = 0;
  177.    ir_d = 0;
  178.    shuwei = 0;
  179.    shuwei1 = 0;
  180.    ir_time = 0;
  181.    TR0 = 1;
  182.   }
  183. }

  184. void main()
  185. {
  186. P3M0 = 0x00;
  187. P3M1 = 0x00;
  188. P3 = 0xff;
  189. AUXR |= 0x80;                //定时器时钟1T模式
  190. TMOD = 0x00;                                //模式0
  191. TL0 = 0xD7;                //设置定时初值
  192. TH0 = 0xFD;       //定时器0设为50us中断一次
  193. TR0 = 0;                                    //启动定时器
  194. ET0 = 1;                                    //使能定时器中断
  195. INT_CLKO |= 0x10;               //(EX2 = 1)使能INT2中断
  196. EA = 1;
  197. while(1)
  198. {
  199.   tm1650_start();
  200.   write_byte(0x48);        //数码显示模式
  201.   tm1650_ack();
  202.   write_byte(0x11);        //1级亮度,开显示。这里的指令数据 详情参阅TM1650的datasheet
  203.   tm1650_ack();
  204.   tm1650_end();

  205.   tm1650_start();
  206.   write_byte(0x68);
  207.   tm1650_ack();
  208.   write_byte(shuma[reg1]);
  209.   tm1650_ack();
  210.   tm1650_end();

  211.   tm1650_start();
  212.   write_byte(0x6a);
  213.   tm1650_ack();
  214.   write_byte(shuma[reg2]);
  215.   tm1650_ack();
  216.   tm1650_end();

  217.   tm1650_start();
  218.   write_byte(0x6c);
  219.   tm1650_ack();
  220.   write_byte(0x5b);//固定显示2
  221.   tm1650_ack();
  222.   tm1650_end();

  223.   tm1650_start();
  224.   write_byte(0x6e);
  225.   tm1650_ack();
  226.   write_byte(0x3f);         //固定显示0,这里固定显示02,是因为我们解码的数据是第2组数据,也就是数据码(第0组数据是用户码,1是用户码反码,2是数据码,3是数据码反码)
  227.   tm1650_ack();
  228.   tm1650_end();
  229.   if(ir_ok)
  230.   {
  231.    ir_ok = 0; //清掉解码标志位
  232.    reg1 = (num[2]&0x0f);  //  数据低4位送显示              把数据转为0-F
  233.    reg2 = (num[2]&0xf0);//数据的高四位送显示
  234.    reg2>>=4;
  235.   }
  236. }
  237. }
  238. void tm1650_start()
  239. {
  240. sda = 1;
  241. scl = 1;
  242. delay(10);
  243. sda = 0;
  244. delay(5);
  245. }
  246. void tm1650_end()
  247. {
  248. sda = 0;
  249. scl = 1;
  250. delay(6);
  251. sda = 1;
  252. delay(2);
  253. }
  254. void tm1650_ack()
  255. {
  256. while(sda);
  257. delay(5);
  258. scl = 1;
  259. delay(5);
  260. scl = 0;
  261. delay(5);
  262. }
  263. void write_1()
  264. {
  265. sda = 1;
  266. scl = 0;
  267. delay(5);
  268. scl = 1;
  269. delay(10);
  270. scl = 0;
  271. delay(5);
  272. sda = 0;
  273. }
  274. void write_0()
  275. {
  276. sda = 0;
  277. scl = 0;
  278. delay(5);
  279. scl = 1;
  280. delay(10);
  281. scl = 0;
  282. }
  283. void write_byte(unsigned char tem)
  284. {
  285. unsigned char i;
  286. for(i=8;i>0;i--)
  287. {
  288.   if(tem&0x80)
  289.    write_1();
  290.   else
  291.    write_0();
  292.   tem<<=1;
  293. }
  294. }
复制代码

以上程序下载:
TM1650+红外解码.zip (150.58 KB, 下载次数: 93)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏11 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:424598 发表于 2021-7-15 16:42 来自手机 | 只看该作者
单片机用的是什么型号的
回复

使用道具 举报

ID:387856 当前离线
积分
1822
查看详细资料
板凳
ID:387856 发表于 2021-8-14 15:02 | 只看该作者
STC15W104,,STC的单片机都可以,IO口对应好就行,看宏定义。
回复

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回列表