数码之家

 找回密码
 立即注册
搜索
查看: 1164|回复: 12

[C51] 全网首发:TM1639 LED显示和按键程序

[复制链接]
发表于 2024-6-9 22:56:42 | 显示全部楼层 |阅读模式
本帖最后由 广东梁百万 于 2024-6-10 21:02 编辑

之前用TM1640做单片机的外置LED显示驱动,很方便,可以驱动16个8字共阴数码管,

因为有几次用8脚单片机,I/O口少,只能外接一两个按键,  于是想用TM1639做显示驱动和按键输入。
6月6晚开始编写,经过几晚的折腾,终于测试成功了。适用于C51单片机。

现在分享给大家。  我是单片机新手,写的程序很啰嗦,如有错误,欢迎指导,共同学习。
原验证程序有很多,我把与之无关的删除了,下面贴出程序的是TM1639和相关部分, 在SecJC()函数里面有简单测试--用cnt2计数并显示,按键按下情况在第8个数码管(我测试板上是8个LED灯)指示。

使用说明:
数组 TM1639_DATA[8]  里面的数值就是8个数码管,   每个数的8位(b0~b7) 对应数码管的 a , b , c  ,d  ,e , f , g ,  dp ,   
  如果需要显示0~9,ABCDEF 这些数字,那就要先调用 void TM1639_BCD_OUT();  转换函数, 函数里面那个变量 i 是需要转换的数码管数量,
假如我8个数码管全部显示数字,那这个i 就设置8 ,数字内容从LED_BCD[  ]数组输入;   假如我只显示4个数码管, 其他的作指示灯用, 那个 i 就设置4,数字内容从LED_BCD[  ]数组输入, 指示灯内容从TM1639_DATA[  ] 输入。





程序对应这个电路

         






  1. //-------广东梁百万,2024年6月6日
  2. //------STC8H1K_TM1639_验证程序       


  3. /*

  4. 使用说明:
  5. 数组 TM1639_DATA[8]  里面的数值就是8个数码管,   每个数的8位(b0~b7) 对应数码管的 a , b , c  ,d  ,e , f , g ,  dp ,   
  6.   如果需要显示0~9,ABCDEF 这些数字,那就要先调用 void TM1639_BCD_OUT();  转换函数, 函数里面那个变量 i 是需要转换的数码管数量,
  7. 假如我8个数码管全部显示数字,那这个i 就设置8 ,数字内容从LED_BCD[  ]数组输入;   假如我只显示4个数码管, 其他的作指示灯用, 那个 i 就设置4,数字内容从LED_BCD[  ]数组输入, 指示灯内容从TM1639_DATA[  ] 输入。

  8.   */

  9.         #include<stc8g.h>
  10.         #include  "intrins.h"



  11.         sbit TM16_DIN = P1^4;   //TM1640的串口数据输入DI  P14
  12.         sbit TM16_SCK = P1^5;   //TM1640的时钟输入SCK  P15
  13.         sbit TM16_STB = P1^6;   //TM1640的片选端STB  P16
  14.         unsigned int cnt1=0,cnt2=0;

  15.          unsigned char xdata LED_BCD[8] =        {
  16.       0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  17.           };

  18.         unsigned char xdata TM1639_DATA[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};//显示的数据, 可在其他程序里对本数组的内容真的操作改变显示内容, 最前位对应TM1639的GRID1

  19.            unsigned char xdata LED_OF[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,};                //数位熄灭控制,0x00是灭,0xff是显示

  20.           unsigned char xdata  tm16_dp[8]={0,0,0,0,0,0,0,0,};  //存放各数位的小数点
  21.              unsigned char bdata tm16_dp_tmp=0; // 小数点专用
  22.           sbit tm16_tmp_bit7=tm16_dp_tmp^7  ;// 小数点专用位

  23.   unsigned char xdata TM1639_command1=0x40;//数据设置
  24.   unsigned char xdata TM1639_command2=0xc0;//地址设置
  25.   unsigned char xdata TM1639_command3=0x8A;//显示模式与亮度       
  26.         unsigned char bdata TM1639_KEY_DATA=0x00;
  27.          //TM1639的按键数据,对应 B7       B6       B5       B4       B3       B2       B1       B0
  28.                       //       K1-KS4    K1-KS3    K1-KS2   K1-KS1   K0-KS4   K0-KS3   K0-KS2   K0-KS1                                                        
  29.                                //bdata数据类型便于另一个按键扫描程序提取按键值
  30.        
  31.         sbit TM1639_KEY_B0=TM1639_KEY_DATA^0; // 定义位变量,用于另一个按键扫描程序提取按键值
  32.         sbit TM1639_KEY_B1=TM1639_KEY_DATA^1;
  33.         sbit TM1639_KEY_B2=TM1639_KEY_DATA^2;
  34.         sbit TM1639_KEY_B3=TM1639_KEY_DATA^3;
  35.         sbit TM1639_KEY_B4=TM1639_KEY_DATA^4;
  36.         sbit TM1639_KEY_B5=TM1639_KEY_DATA^5;
  37.         sbit TM1639_KEY_B6=TM1639_KEY_DATA^6;
  38.         sbit TM1639_KEY_B7=TM1639_KEY_DATA^7;
  39.        

  40.           //----------------------------
  41.                
  42.                  void TM1639_LED();          //TM1639共阴LED驱动       
  43.                  void TM1639_BCD_OUT();   //TM1639BCD数转显示代码         
  44.                  void TM1639_KEY();          //TM1639按键读出程序

  45. //------------------------------

  46.           void SecJC(); //1ms循环定时处理程序
  47.        

  48.          #define     MAIN_Fosc       11059200L   //定义主时钟,  自定义变量 ,L是长整型的意思


  49.         void main()
  50.         {

  51. P0M0=0x00;
  52. P0M1=0x00;
  53. P1M0=0x00;
  54. P1M1=0x00;
  55. P2M0=0x00;
  56. P2M1=0x00;
  57. P3M0=0x00;
  58. P3M1=0x00;
  59. P5M0=0x00;
  60. P5M1=0x00;

  61.         TM16_DIN =1;
  62.         TM16_SCK =1;
  63.         TM16_STB =1;

  64.             P_SW2 =0xB0;                //D7位控制访问扩展SFR特殊寄存器        ,D4 D5位控制选用某端口做I2C的SCL SDA       
  65.      AUXR |= 0x04;                //定时器时钟1T模式          定时器2设置
  66.          T2L = 0xcd;//                //设置定时初值  0.5ms是0x66;//   1ms是0xcd;          11.0592Mhz
  67.          T2H = 0xd4;//                //设置定时初值  0.5ms是0xea;//   1ms是0xd4;
  68.          AUXR |= 0x10;                //定时器2开始计时
  69.          IE2 = 0x04;         
  70.       EA = 1; //中断使能       




  71.          //主函数//********************
  72.              while (1)      
  73.                 {
  74.                                   //重复循环
  75.                      _nop_();   
  76.           }
  77.           }
  78.          ////////////////***********************

  79.           ///定时处理/

  80.          void SecJC()   //定时处理
  81.          {
  82.            TM1639_KEY();          //TM1639按键读出程序       
  83.            cnt1++;                 
  84.          if(cnt1>=20)
  85.           {               
  86.            TM1639_BCD_OUT();   //TM1639BCD显示代码转换                       
  87.            TM1639_LED();          //TM1639共阴LED驱动***************

  88.            cnt1=0;
  89.            cnt2++;
  90.            LED_BCD[3] =cnt2%10;                           //显示计数
  91.            LED_BCD[2] =cnt2/10%10;
  92.            LED_BCD[1] =cnt2/100%10;
  93.            LED_BCD[0] =cnt2/1000%10;       
  94.                                                
  95.                    TM1639_DATA[7]=TM1639_KEY_DATA;         // 显示按键情况  


  96.           }
  97.            }
  98.            //------------------------------------------------------



  99.                 //* 定时器2中断服务函数 */
  100.                 void InterruptTimer2() interrupt 12
  101.                 {
  102.                  
  103.                 SecJC();//定时处理               

  104.                     }



  105. //**************************************
  106.                
  107.                
  108.                  //TM1639--共阴LED驱动

  109.           void TM1639_LED()          //TM1639共阴LED驱动1
  110.           {
  111.                         unsigned char xdata i,j=0,k=0;
  112.                         unsigned char xdata tmp1;  //临时缓存
  113.                         unsigned char xdata TM1639_DATA_TMP[16];  //临时缓存组,因为TM1639的特性,需把8个字节数据拆分成16个低位半字节
  114.                        
  115.                 for(i=0;i<16;i++)   //这个i是转换的个数
  116.            {
  117.                         TM1639_DATA_TMP[i]=TM1639_DATA[j];
  118.                         i++;
  119.                         TM1639_DATA_TMP[i]=TM1639_DATA[j];
  120.                         TM1639_DATA_TMP[i]=TM1639_DATA_TMP[i]>>4;  //把高4位移到低4位
  121.                         j++;
  122.                  }
  123.                  i=0;
  124.                  j=0;

  125.                  
  126.                         TM16_DIN =1; //数据和时钟端口拉高
  127.                         TM16_SCK =1;
  128.                         TM16_STB =1;  //片选拉高
  129.                        
  130.                        
  131.                         TM16_STB =0;//片选拉低
  132.                         TM16_STB =0;//片选拉低
  133.                         TM16_DIN = 0;  //开始位
  134.                   nop_();
  135.                   TM16_SCK =0;   //开始位
  136.                   nop_();               
  137.                   
  138.                         tmp1=TM1639_command1;  //先发送数设置字节
  139.        for(i=0; i<8; i++)
  140.                         {
  141.                                 tmp1>>=1;//低位移出到CY
  142.                                 TM16_DIN = CY;
  143.                                
  144.                                 TM16_SCK =1;
  145.                     nop_();
  146.                     nop_();
  147.                                
  148.                                 TM16_SCK =0;
  149.                     nop_();
  150.                                
  151.                                 TM16_DIN =0;
  152.                         }

  153.                                 TM16_SCK =1;  //停止位
  154.                     nop_();
  155.                        
  156.         TM16_DIN =1;  //停止位
  157.                     nop_();
  158.                        
  159.                         TM16_STB =1;  //片选拉高
  160.                         nop_();
  161.                         nop_();
  162.                        
  163.                         TM16_STB =0;//片选拉低
  164.                         nop_();
  165.                         nop_();
  166.                        
  167.                           TM16_DIN = 0;  //开始位
  168.                     nop_();
  169.                        
  170.                     TM16_SCK =0;   //开始位
  171.                     nop_();                       

  172.        tmp1=TM1639_command2;  //再发送地址字节
  173.        for(i=0; i<8; i++)
  174.                         {
  175.                                 tmp1>>=1;//低位移出到CY
  176.                                 TM16_DIN = CY;
  177.                                
  178.                                 TM16_SCK =1;
  179.                     nop_();
  180.                     nop_();
  181.                                
  182.                                 TM16_SCK =0;
  183.                     nop_();
  184.                                
  185.                                 TM16_DIN =0;
  186.                         }

  187.        for(j=0; j<16; j++)     //j是LED数码管显示个数***************
  188.        {
  189.                                 tmp1=TM1639_DATA_TMP[k];
  190.                                 for(i=0; i<8; i++)
  191.         {
  192.                                 tmp1>>=1;//低位移出到CY
  193.                                 TM16_DIN = CY;
  194.                                
  195.                                 TM16_SCK =1;
  196.                     nop_();
  197.                     nop_();
  198.                                
  199.                                 TM16_SCK =0;
  200.                     nop_();
  201.                                
  202.                                 TM16_DIN =0;
  203.                         }                                              
  204.       
  205.                         k++;
  206.                        
  207.                 }
  208.                          
  209.                                 TM16_SCK =1;  //停止位
  210.                     nop_();
  211.                        
  212.         TM16_DIN =1;  //停止位
  213.                     nop_();       
  214.                
  215.                     TM16_STB =1;  //片选拉高
  216.                           nop_();
  217.                           nop_();
  218.                    TM16_STB =0;//片选拉低
  219.                          nop_();
  220.                          nop_();
  221.                
  222.                
  223.                           TM16_DIN = 0;  //开始位
  224.                     nop_();
  225.                        
  226.                     TM16_SCK =0;   //开始位
  227.                     nop_();                       

  228.       tmp1=TM1639_command3;  //发送亮度控制字节
  229.        for(i=0; i<8; i++)
  230.                         {
  231.                                 tmp1>>=1;//低位移出到CY
  232.                                 TM16_DIN = CY;
  233.                                
  234.                                 TM16_SCK =1;
  235.                     nop_();
  236.                     nop_();
  237.                                
  238.                                 TM16_SCK =0;
  239.                     nop_();
  240.                                
  241.                                 TM16_DIN =0;
  242.                         }               
  243.                                 TM16_SCK =1;  //停止位
  244.                     nop_();

  245.         TM16_DIN =1;  //停止位
  246.                     nop_();
  247.                        
  248.                         TM16_STB =1;  //片选拉高
  249.                           nop_();
  250.                           nop_();
  251.                        
  252.                 }               
  253.                
  254.                
  255.       //TM1639,BCD数转显示代码
  256.   void TM1639_BCD_OUT()   //TM1639BCD数转显示代码
  257.   {
  258.       unsigned char xdata i=0,j=0;       


  259.             unsigned char code LED_JH[18] = {                                         //数值与显示段码转换
  260.       0x3f,0x06,0x5B,0x4f,0x66,0x6d,0x7d,0x07,
  261.       0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x80
  262.       };  
  263.          
  264.         for(i=0;i<4;i++)   //这个i是转换的显示个数********** 8是8个LED数码管
  265.         {
  266.                 TM1639_DATA[j]=LED_JH[(LED_BCD[j])];  //LED_BCD[k]j是需要显示的数据,LED_JH是预存的转换代码
  267.                                                                                          //LED_OUTA[k]是转换代码结果  //对LED_OUTA[k]某位写入0x00可实现不显示
  268.                 TM1639_DATA[j]=TM1639_DATA[j] & LED_OF[j];//数位熄灭控制,根据需要控制某位熄灭。
  269.                 tm16_dp_tmp=TM1639_DATA[j];//先把显示代码放到可位操作的bdata类型的缓存上
  270.                 tm16_tmp_bit7=tm16_dp[j];//再对小数点bit7位操作,小数点控制数放在tm16_dp[j]数组上。
  271.                 TM1639_DATA[j]=tm16_dp_tmp;//最后再放回到显示代码输出数组
  272.                                                 
  273.                 j++;
  274.         }
  275. }
  276. //******************************************



  277.                        
  278.                         // TM1639按键读出程序
  279.                        
  280.                   void TM1639_KEY()          //TM1639按键读出程序
  281.           {
  282.                         unsigned char xdata i,j=0,k=0;
  283.                         unsigned char xdata TM1639_tmp1;  //临时缓存
  284.                         unsigned char xdata TM1639_tmp2;  //临时缓存
  285.                         unsigned char xdata TM1639_tmp3;  //临时缓存               
  286.       unsigned char xdata TM1639_KEY_N[2];
  287.                        
  288.                         TM16_DIN =1; //数据和时钟端口拉高
  289.                         TM16_SCK =1;
  290.                         TM16_STB =1;  //片选拉高                       
  291.                        
  292.                         TM16_STB =0;//片选拉低
  293.                         TM16_STB =0;//片选拉低
  294.                         TM16_DIN = 0;  //开始位
  295.                   nop_();
  296.                   TM16_SCK =0;   //开始位
  297.                   nop_();               
  298.                   TM1639_command1=0X42;    //  设置命令字节是读出按键
  299.                         TM1639_tmp1=TM1639_command1;  //先发送数设置字节
  300.        for(i=0; i<8; i++)
  301.                         {
  302.                                 TM1639_tmp1>>=1;//低位移出到CY
  303.                                 TM16_DIN = CY;
  304.                                
  305.                                 TM16_SCK =1;
  306.                     nop_();
  307.                     nop_();
  308.                                
  309.                                 TM16_SCK =0;
  310.                     nop_();
  311.                                
  312.                                 TM16_DIN =0;
  313.                         }

  314.                                 TM16_SCK =1;  //停止位
  315.                     nop_();
  316.                        
  317.         TM16_DIN =1;  //停止位
  318.                     nop_();

  319.                         nop_();
  320.                         nop_();
  321.                        
  322.                        
  323.                          // TM16_DIN = 0;  //开始位
  324.                     nop_();
  325.                        
  326.                     TM16_SCK =0;   //开始位
  327.                     nop_();                       

  328.        for(j=0; j<2; j++)     //j读出数据个数***************
  329.        {
  330.                                 //TM1639_KEY_N[k]=tmp1;
  331.                                 for(i=0; i<8; i++)
  332.         {

  333.                                 TM16_SCK =1;
  334.                     nop_();
  335.                     nop_();
  336.                                 nop_();
  337.                     nop_();
  338.                                        
  339.                                 TM1639_KEY_N[k]=(TM1639_KEY_N[k]<<1)| TM16_DIN;       

  340.                                        
  341.                                 TM16_SCK =0;
  342.                     nop_();
  343.                                
  344.                                 //TM16_DIN =0;
  345.                         }                                                 
  346.                         k++;       
  347.                   }

  348.                                 TM16_SCK =1;  //停止位
  349.                     nop_();

  350.         TM16_DIN =1;  //停止位
  351.                     nop_();
  352.                        
  353.                         TM16_STB =1;  //片选拉高
  354.                                  
  355.                 TM1639_tmp1=TM1639_KEY_N[0];  //整理K0-ks1,ks2 数值
  356.                 TM1639_tmp1=TM1639_tmp1>>5;
  357.             TM1639_tmp1=TM1639_tmp1 & 0x01;
  358.                 TM1639_tmp2=TM1639_KEY_N[0];       
  359.                 TM1639_tmp2=TM1639_tmp2&0x02;
  360.                 TM1639_tmp3=TM1639_tmp1|TM1639_tmp2;

  361.                 TM1639_tmp1=TM1639_KEY_N[1];  //整理K0-ks3,ks4 数值
  362.                 TM1639_tmp1=TM1639_tmp1>>3;       
  363.                 TM1639_tmp1=TM1639_tmp1 & 0x04;
  364.                 TM1639_tmp2=TM1639_KEY_N[1];       
  365.                 TM1639_tmp2=TM1639_tmp2<<2;       
  366.                 TM1639_tmp2=TM1639_tmp2&0x08;
  367.                 TM1639_tmp3=TM1639_tmp1|TM1639_tmp2|TM1639_tmp3;
  368.                        
  369.                 TM1639_tmp1=TM1639_KEY_N[0];  //整理K1-ks1,ks2 数值
  370.                 TM1639_tmp1=TM1639_tmp1>>2;       
  371.                 TM1639_tmp1=TM1639_tmp1 & 0x10;
  372.                 TM1639_tmp2=TM1639_KEY_N[0];       
  373.                 TM1639_tmp2=TM1639_tmp2<<3;
  374.                 TM1639_tmp2=TM1639_tmp2 & 0x20;
  375.                 TM1639_tmp2=TM1639_tmp2|TM1639_tmp1;
  376.                 TM1639_tmp3=TM1639_tmp3|TM1639_tmp2;
  377.                
  378.                 TM1639_tmp1=TM1639_KEY_N[1];  //整理K1-ks3,ks4 数值
  379.                 TM1639_tmp1=TM1639_tmp1 & 0x40;
  380.                 TM1639_tmp2=TM1639_KEY_N[1];       
  381.         TM1639_tmp2=TM1639_tmp2<<5;
  382.                 TM1639_tmp2=TM1639_tmp2 & 0x80;
  383.                 TM1639_tmp2=TM1639_tmp2|TM1639_tmp1;
  384.                 TM1639_tmp3=TM1639_tmp3|TM1639_tmp2;
  385.                        
  386.             TM1639_KEY_DATA=        TM1639_tmp3;      //读出的按键值合并在 TM1639_KEY_DATA寄存上。
  387.                             //        TM1639_KEY_DATA的按键数据,          B7       B6       B5       B4       B3       B2       B1       B0
  388.                                  //         对应按键       K1-KS4    K1-KS3   K1-KS2   K1-KS1   K0-KS4   K0-KS3    K0-KS2   K0-KS1  
  389.                                
  390.                 }
复制代码




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

打赏

参与人数 3家元 +90 收起 理由
vip2128 + 30 優秀文章
2n3055 + 30 優秀文章
慕名而来 + 30 原創內容

查看全部打赏

发表于 2024-6-9 23:09:27 | 显示全部楼层
前排观摩学习!
回复 支持 反对

使用道具 举报

发表于 2024-6-10 14:34:08 | 显示全部楼层
不错不错确实很不错,我学习了。
回复 支持 反对

使用道具 举报

发表于 2024-6-10 17:02:20 | 显示全部楼层
定时轮询方式,感觉按键灵敏度不太好,看看有没办法改为外部中断方式。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-6-10 18:31:04 来自手机浏览器 | 显示全部楼层
本帖最后由 广东梁百万 于 2024-6-11 07:37 编辑
cooleaf 发表于 2024-6-10 17:02
定时轮询方式,感觉按键灵敏度不太好,看看有没办法改为外部中断方式。


这里1ms查询一次,已经够快了。
我在另一程序再4次查询是一致那就是确认按下, 我用cnt2变量对按下次数计算测试,看反应速度是挺快了
回复 支持 反对

使用道具 举报

发表于 2024-6-11 17:33:00 | 显示全部楼层
这个不错,能节约很多管脚
回复 支持 1 反对 0

使用道具 举报

发表于 2024-6-12 10:58:37 | 显示全部楼层
谢谢分享,单片机制作
回复 支持 反对

使用道具 举报

发表于 2024-6-13 10:35:43 | 显示全部楼层
谢谢分享,diy高手
回复 支持 反对

使用道具 举报

发表于 2024-6-13 11:42:33 | 显示全部楼层
感谢分享,有需要的上
回复 支持 反对

使用道具 举报

发表于 2024-6-14 08:40:07 | 显示全部楼层
谢谢分享~学习了
回复 支持 反对

使用道具 举报

发表于 2024-6-15 19:56:22 | 显示全部楼层
这个非常实用,MCU引脚的扩展。
回复 支持 反对

使用道具 举报

发表于 2024-7-16 00:19:33 | 显示全部楼层
不错不错确实很不错,我学习了。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-7-27 17:30 , Processed in 0.156000 second(s), 10 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

快速回复 返回顶部 返回列表