找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 798|回复: 4
收起左侧

关于51单片机使用TM1637模块实现计数的功能 附程序

[复制链接]
ID:718523 发表于 2024-1-17 02:50 | 显示全部楼层 |阅读模式
下面的代码运行后数据码也不动 显示的半个1和234 折腾不动了希望大佬路过看下谢谢。就是检测p3^1的按键,按一下TM1637模块加1

51hei.jpg
单片机源程序如下:
  1. #include <reg51.h>

  2. sbit CLK = P1^2;
  3. sbit DIO = P1^1;

  4. sbit insys = P3^1;

  5. void delay(unsigned int ms)  // 延时函数
  6. {
  7.     unsigned int i, j;
  8.     for(i = 0; i < ms; i++)
  9.         for(j = 0; j < 120; j++);
  10. }

  11. void TM1637_Start()  // 起始信号
  12. {
  13.     CLK = 1;
  14.     DIO = 1;
  15.     delay(1);
  16.     DIO = 0;
  17. }

  18. void TM1637_Stop()  // 停止信号
  19. {
  20.     CLK = 0;
  21.     delay(1);
  22.     DIO = 0;
  23.     delay(1);
  24.     CLK = 1;
  25.     delay(1);
  26.     DIO = 1;
  27. }

  28. void TM1637_WriteByte(unsigned char dataaa)  // 写入一个字节
  29. {
  30.     unsigned char i;
  31.     for(i = 0; i < 8; i++)
  32.     {
  33.         CLK = 0;
  34.         DIO = (dataaa & 0x01);
  35.         delay(1);
  36.         dataaa >>= 1;
  37.         CLK = 1;
  38.         delay(1);
  39.     }
  40.     CLK = 0;
  41.     DIO = 1;
  42.     CLK = 1;
  43.     delay(1);
  44.     CLK = 0;
  45. }

  46. void TM1637_Init()  // 初始化设置
  47. {
  48.     TM1637_Start();
  49.     TM1637_WriteByte(0x8F);  // 固定写入0x8F,设置显示亮度为最高
  50.     TM1637_Stop();
  51. }

  52. void TM1637_Display(unsigned char displayData)  // 数码管显示函数
  53. {
  54.     TM1637_Start();
  55.     TM1637_WriteByte(0x40);  // 写入地址命令,地址为0
  56.     TM1637_Stop();
  57.     TM1637_Start();
  58.     TM1637_WriteByte(displayData);  // 写入要显示的数据
  59.     TM1637_Stop();
  60. }

  61. void main()
  62. {
  63.         unsigned char num = 0;
  64.     TM1637_Init();  // 初始化设置
  65.         insys = 1;   
  66.     while(1)
  67.     {
  68.          if(insys = 0){
  69.         TM1637_Display(num);
  70.         num++;
  71.         if(num > 9)
  72.             num = 0;
  73.         delay(1000);  // 延时1秒
  74.                 }
  75.     }
  76. }
复制代码
回复

使用道具 举报

ID:718523 发表于 2024-1-17 15:50 | 显示全部楼层
程序可以了,但是有中断会触发很多次甚至是十几次,请问要怎么用定时器消抖动呢,不用软件延时,我写的定时器好像不起作用。程序如下:
  1. #include<reg52.h>
  2. //#include <STC8G.h>
  3. #include <intrins.h>

  4. #define u8 unsigned char
  5. #define u16 unsigned int

  6. unsigned char  flagkey =0;


  7. sbit DIO = P1^1;
  8. sbit CLK = P1^2;
  9. sbit p00 = P0^0;

  10. //u8 num[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7f,0x6F};
  11. u8 num[10]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFf,0xEF};
  12. u16 ms,second,min,hour;
  13. u16 dingshinum;

  14. void Delay2us()                //@12.01MHz
  15. {
  16.         unsigned char i;      
  17.         i = 6;
  18.         while (--i);
  19. }

  20. void Delay3us()                //@12MHz
  21. {
  22.         unsigned char i;

  23.         i = 10;
  24.         while (--i);
  25. }

  26. void Delay5us()                //@12MHz
  27. {
  28.         unsigned char i;        
  29.         i = 18;
  30.         while (--i);
  31. }

  32. void I2CStart()
  33. {
  34.         CLK = 1;
  35.         DIO = 1;
  36.         Delay2us();
  37.         DIO = 0;
  38. }

  39. void I2CAsk()
  40. {
  41.         CLK = 0;
  42.         Delay5us();
  43.         while(DIO);
  44.         CLK = 1;
  45.         Delay2us();
  46.         CLK = 0;
  47. }

  48. void I2CStop()
  49. {
  50.         CLK = 0;
  51.         Delay2us();
  52.         DIO = 0;
  53.         Delay2us();
  54.         CLK = 1;
  55.         Delay2us();
  56.         DIO = 1;
  57. }

  58. void I2CWriteByte(u8 dat)
  59. {
  60.         u8 i;
  61.         for(i=0;i<8;i++)
  62.         {
  63.                 CLK = 0;
  64.                 if(dat&0x01)
  65.                 {
  66.                         DIO = 1;
  67.                 }
  68.                 else
  69.                 {
  70.                         DIO = 0;
  71.                 }
  72.                 Delay3us();
  73.                 dat>>=1;
  74.                 CLK = 1;
  75.                 Delay3us();
  76.         }
  77. }

  78. void Display(u8 m,u8 s)
  79. {
  80.         I2CStart();        //1637 开始
  81.         I2CWriteByte(0x40);
  82.         I2CAsk();
  83.         I2CStop();
  84.         I2CStart();
  85.         I2CWriteByte(0xC0);        //设置显示首地址即第一个LED
  86.         I2CAsk();

  87.         I2CWriteByte(num[m/10]);
  88.         I2CAsk();
  89.         I2CWriteByte(num[m%10]);
  90.         I2CAsk();
  91.         I2CWriteByte(num[s/10]);
  92.         I2CAsk();

  93.         I2CWriteByte(num[s%10]);
  94.         I2CAsk();
  95.         I2CWriteByte(0xFF);
  96.         I2CAsk();
  97.         I2CWriteByte(0xFF);
  98.         I2CAsk();
  99.         I2CStop();
  100.         I2CStart();
  101.         I2CWriteByte(0x8F);
  102.         I2CAsk();
  103.         I2CStop();
  104. }





  105. void main()
  106. {
  107.   p00 = 1;
  108.   P1=0x55;       //P1口初始值
  109.   EA=1;          //全局中断开
  110.   EX0=1;         //外部中断0开
  111.   IT0=1;         //边沿触发
  112.         
  113.         
  114.         while(1)
  115.         {
  116.                 Display(min,second);
  117.         }
  118. }

  119. /*------------定时器----------------*/
  120. void Timer0Init(void)                //5毫秒@12.01MHz
  121. {
  122.         TMOD = 0x01; // 设置定时器0为模式1
  123.     TH0 = 0x0EC; // 设置定时器0的初始值,用于产生10ms的定时中断
  124.     TL0 = 0x78;
  125.     EA = 1; // 允许中断
  126.     ET0 = 1; // 允许定时器0中断
  127.     TR0 = 1; // 启动定时器0
  128. }


  129. /*------------外部中断程序----------------*/
  130. void ISR_Key(void) interrupt 0 using 1 {       
  131.         if(flagkey==1){
  132.                 Timer0Init();
  133.                 p00 = ~p00;
  134. second++;
  135.         if(second==60){
  136.         second=0;
  137.         min++;
  138.         if(min==60)
  139.                 {
  140.                     min=0;
  141.                     hour++;
  142.                             if(hour==24)
  143.                             {
  144.                               hour=0;
  145.                             }
  146.                 }                       
  147.                        
  148.     }

  149.         }                    
  150.          
  151. }


  152. /*------------定时器中断子程序----------------*/
  153. void Timer0_isr(void) interrupt 1 using 1
  154. {
  155. TH0=0x0EC;                  //重新赋值
  156. TL0=0x78;
  157. dingshinum++;
  158. if(dingshinum<100){
  159.          flagkey = 0;                
  160. }else{
  161.           flagkey = 0;
  162.           dingshinum = 1;           
  163. }
  164. }
复制代码
回复

使用道具 举报

ID:213173 发表于 2024-1-17 17:05 | 显示全部楼层
TM1637是2线式通讯接口,对时序要求较高。易受中断干扰。你驱动程序中1ms延时太长,一般就几us延时。
回复

使用道具 举报

ID:213173 发表于 2024-1-17 17:32 | 显示全部楼层
forest415 发表于 2024-1-17 15:50
程序可以了,但是有中断会触发很多次甚至是十几次,请问要怎么用定时器消抖动呢,不用软件延时,我写的定时 ...

定时器和外部中断不是这么玩的 TM1637驱动共阳数码管时钟示例 仿真.rar (879.07 KB, 下载次数: 16)
回复

使用道具 举报

ID:718523 发表于 2024-1-17 20:06 | 显示全部楼层
可以了感谢资料,这个程序可以实现按键自动加1,上电的时候是0000累计加到9999试了下没有抖动了。源程序如下给需要的人
  1. #include<reg52.h>
  2. #include <intrins.h>

  3. #define u8 unsigned char
  4. #define u16 unsigned int

  5. unsigned char  flagkey =0;         //按键标志
  6. unsigned char Timer0Init_count = 0;//定时器溢出计数

  7. sbit DIO = P1^1; //TM1637
  8. sbit CLK = P1^2; //TM1637
  9. sbit P10 = P1^0; //led
  10. sbit p01 = P0^1; //按键

  11. u8 num[10]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFf,0xEF}; //0-9
  12. u16 second,min,hour;        //TM1637六段


  13. /*------------TM1637----------------*/
  14. void Delay2us()                //@12.01MHz
  15. {
  16.         unsigned char i;      
  17.         i = 6;
  18.         while (--i);
  19. }

  20. void Delay3us()                //@12MHz
  21. {
  22.         unsigned char i;

  23.         i = 10;
  24.         while (--i);
  25. }

  26. void Delay5us()                //@12MHz
  27. {
  28.         unsigned char i;        
  29.         i = 18;
  30.         while (--i);
  31. }

  32. void I2CStart()
  33. {
  34.         CLK = 1;
  35.         DIO = 1;
  36.         Delay2us();
  37.         DIO = 0;
  38. }

  39. void I2CAsk()
  40. {
  41.         CLK = 0;
  42.         Delay5us();
  43.         while(DIO);
  44.         CLK = 1;
  45.         Delay2us();
  46.         CLK = 0;
  47. }

  48. void I2CStop()
  49. {
  50.         CLK = 0;
  51.         Delay2us();
  52.         DIO = 0;
  53.         Delay2us();
  54.         CLK = 1;
  55.         Delay2us();
  56.         DIO = 1;
  57. }

  58. void I2CWriteByte(u8 dat)
  59. {
  60.         u8 i;
  61.         for(i=0;i<8;i++)
  62.         {
  63.                 CLK = 0;
  64.                 if(dat&0x01)
  65.                 {
  66.                         DIO = 1;
  67.                 }
  68.                 else
  69.                 {
  70.                         DIO = 0;
  71.                 }
  72.                 Delay3us();
  73.                 dat>>=1;
  74.                 CLK = 1;
  75.                 Delay3us();
  76.         }
  77. }

  78. void Display(u8 m,u8 s)
  79. {
  80.         I2CStart();        //1637 开始
  81.         I2CWriteByte(0x40);
  82.         I2CAsk();
  83.         I2CStop();
  84.         I2CStart();
  85.         I2CWriteByte(0xC0);        //设置显示首地址即第一个LED
  86.         I2CAsk();

  87.         I2CWriteByte(num[m/10]);
  88.         I2CAsk();
  89.         I2CWriteByte(num[m%10]);
  90.         I2CAsk();
  91.         I2CWriteByte(num[s/10]);
  92.         I2CAsk();

  93.         I2CWriteByte(num[s%10]);
  94.         I2CAsk();
  95.         I2CWriteByte(0xFF);
  96.         I2CAsk();
  97.         I2CWriteByte(0xFF);
  98.         I2CAsk();
  99.         I2CStop();
  100.         I2CStart();
  101.         I2CWriteByte(0x8F);
  102.         I2CAsk();
  103.         I2CStop();
  104. }




  105. /*------------定时器----------------*/
  106. void Timer0Init(void)                //12M晶振,延时10Ms
  107. {
  108.         TMOD = 0x01; // 设置定时器0为模式1
  109.     TH0 = 0x0D8; // 设置定时器0的初始值,用于产生10ms的定时中断
  110.     TL0 = 0x0F0;
  111.     EA = 1; // 允许中断
  112.     ET0 = 1; // 允许定时器0中断
  113.     //TR0 = 1; // 启动定时器0
  114. }


  115. /*------------检察按键----------------*/
  116. void anjian(void)
  117. {
  118.           if(p01 == 0){  // 检测按键是否按下
  119.                   TR0 = 1;//按键按下开始计时,溢出后中断
  120.           }else{
  121.                             flagkey=0;
  122.                   }
  123. }

  124. /*------------主程序----------------*/
  125. void main()
  126. {
  127.   Timer0Init(); //定时器初始化
  128.   P10 = 1;//led关        
  129.         while(1)
  130.         {
  131.             Display(min,second);
  132.                         anjian();
  133.         }
  134. }




  135. /*------------定时器中断子程序----------------*/
  136. void Timer0Interrupt(void) interrupt 1{
  137. if(flagkey==0){
  138. flagkey=1;       
  139. Timer0Init_count ++;
  140. if(Timer0Init_count>5){
  141. TR0 = 0;//关定时器
  142. TH0 = 0x0D8;//赋初值
  143. TL0 = 0x0F0;       

  144. Timer0Init_count=0;

  145. P10 = ~P10;

  146. second++;
  147. if(second==100){
  148.         second=0;
  149.         min++;
  150.         if(min==100)
  151.             {
  152.                 //min=0;
  153.                         min=99;
  154.                         second=99;
  155.                 //hour++;
  156.                 //if(hour==100){hour=0;}
  157.             }                               
  158.                        
  159. }}}}
复制代码
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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