找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3134|回复: 10
收起左侧

单片机tm1637数码管倒计时,如何改成正计时?

  [复制链接]
ID:577423 发表于 2019-10-3 19:50 | 显示全部楼层 |阅读模式
#include <reg52.h>
#include<intrins.h>

sbit CLK = P0^0;  //时钟信号
sbit DIO = P0^1;  //数据/地址数据
                                                                                                                                                                 //共阴极数码管
unsigned char code SEGData[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//1-9
unsigned char code SEGDataDp[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //有小数点只用于地址0xc1

unsigned char dpFlag = 0; //控制第二个数码管的dp的显示

void TM1637_start( void );
void TM1637_stop( void );
void TM1637_write1Bit(unsigned char mBit);
void TM1637_write1Byte(unsigned char mByte);
void TM1637_writeCammand(unsigned char mData);
void TM1637_writeData(unsigned char addr, unsigned char mData);
void time_set(char hour, char min);
void time_judge( void );
void time_display( void );
void timer0_init( void );

void delay_140us( void );
void delay_1ms(unsigned int i);

unsigned int countTime = 0;
unsigned char time, sec;
struct {
        char shi;
        char ge;
}Hour;

struct {
        char shi;
        char ge;
}Min;

/***********************************************************
*****
***** 主函数
*****
***********************************************************/
void main( void )
{
        timer0_init();
        time_set(5, 0);  //设置5小时倒计时
        while(1)
        {
                time_display();         //显示时间
                if(countTime <= 10)
                {
                        dpFlag = 0;                        
                }
                else
                if(countTime <= 20)
                {
                        dpFlag = 1;        
                }
                else
                {
                        countTime = 0;
                        time_judge();
                }
        }
}

void time_set(char hour, char min)
{
        if((hour < 0) || (min<0))
        {
                hour = 0;
                min = 0;
        }
        Hour.shi = hour/10;
        Hour.ge = hour%10;
        Min.shi = min/10;
        Min.ge = min%10;               
}

/*************************************************************
* 名称 : time_judge( void )
* 功能 : 判断时间变化
* 输入 : void
* 输出 : 无
**************************************************************/
void time_judge( void )
{
        if(++sec == 60)           //60秒
        {        
                sec = 0;
                if((Hour.shi || Hour.ge || Min.shi || Min.ge) && (--Min.ge <= -1))
                {
                        Min.ge = 9;
                        if((Hour.shi) ||(Hour.ge) && (--Min.shi <= -1))
                        {
                                Min.shi = 5;
                                if(Hour.shi && (--Hour.ge <= -1))
                                {
                                        Hour.ge = 9;
                                        if(--Hour.shi <= -1)
                                        {
                                                Hour.shi = 0;        
                                        }
                                }
                                else
                                if((!Hour.shi) && (--Hour.ge <= -1))
                                {
                                        Hour.ge = 0;
                                }
                        }
                        else
                        if((!Hour.shi) && (!Hour.ge) && (--Min.shi <= -1))
                        {
                                Min.shi = 0;
                        }
                }
                else
                if(((!Hour.shi) && (!Hour.ge) && (!Min.shi) ) && (Min.ge <= -1))
                {
                        Min.ge = 0;
                }
        }        
}
  /*******************************************************************
* 名称 : void time_display( void )
* 功能 : 显示时间
* 输入 : void
* 输出 : 无
**************************************************************/
void time_display( void )
{
        TM1637_writeCammand(0x44);
        TM1637_writeData(0xc0, SEGData[Hour.shi]);
        if(dpFlag)
                TM1637_writeData(0xc1, SEGDataDp[Hour.ge]); //小数点标志为1则用小数点那个数组
        else
                TM1637_writeData(0xc1, SEGData[Hour.ge]);
        TM1637_writeData(0xc2, SEGData[Min.shi]);
        TM1637_writeData(0xc3, SEGData[Min.ge]);
        TM1637_writeCammand(0x8a);                                
}

/********************************************************************
* 名称 : void TM1637_start( void )
* 功能 : start信号
* 输入 : void
* 输出 : 无
**************************************************************/
void TM1637_start( void )
{
        CLK = 1;
        DIO = 1;
        delay_140us();
        DIO = 0;
        delay_140us();
        CLK = 0;
        delay_140us();
}

/********************************************************************
* 名称 : void TM1637_stop( void )
* 功能 : stop信号
* 输入 : void
* 输出 : 无
**************************************************************/
void TM1637_stop( void )
{
        CLK = 0;
        delay_140us();
        DIO = 0;
        delay_140us();
        CLK = 1;
        delay_140us();
        DIO = 1;
        delay_140us();
}

void TM1637_write1Bit(unsigned char mBit )
{
        CLK = 0;
        delay_140us();
        if(mBit)
                DIO = 1;
        else
                DIO = 0;
        delay_140us();        
        CLK        = 1;
        delay_140us();
}

/********************************************************************
* 名称 : void TM1637_write1Byte(unsigned char mByte)
* 功能 : 写1byte
* 输入 : unsigned char mByte
* 输出 : 无
**************************************************************/
void TM1637_write1Byte(unsigned char mByte)
{
        char loop = 0;
        for(loop = 0; loop < 8; loop++)
        {
                TM1637_write1Bit((mByte>>loop)&0x01); //取得最低位        
        }
        CLK = 0;
        delay_140us();
        DIO = 1;
        delay_140us();
        CLK = 1;
        delay_140us();
        while(DIO == 1);  //获得应答位         
}

/********************************************************************
* 名称 : void TM1637_writeCammand(unsigned char mData)
* 功能 : 写指令1byte
* 输入 : unsigned char mData
* 输出 : 无
**************************************************************/
void TM1637_writeCammand(unsigned char mData)
{
        TM1637_start();
        TM1637_write1Byte(mData);  //数据
        TM1637_stop();        
}

/********************************************************************
* 名称 : void TM1637_writeData(unsigned char addr, unsigned char mData)
* 功能 : 固定地址写数据1byte
* 输入 : unsigned char addr, unsigned char mData
* 输出 : 无
**************************************************************/
void TM1637_writeData(unsigned char addr, unsigned char mData)
{
        TM1637_start();
        TM1637_write1Byte(addr);  //地址
        TM1637_write1Byte(mData);  //数据
        TM1637_stop();        
}


void timer0_init( void )
{
        TMOD=0X01;
        TH0=(65535-50000)/256;
        TL0=(65535-50000)%256;
        ET0=1;
        EA=1;
        TR0=1;        
}              


/********************************************************************
* 名称 :
* 功能 : 定时50ms,实际运行中由于指令运行造成的延时,实际时间肯定大于50ms
* 输入 : 无
* 输出 : 无
**************************************************************/
void timer0_isr() interrupt 1
{
        TH0=(65535-50000)/256;  //50ms
        TL0=(65535-50000)%256;        //
        countTime++;
}


/********************************************************************
* 名称 : Delay_1ms(unsigned int i)
* 功能 : 延时子程序,延时时间为 140us
* 输入 :
* 输出 : 无
**************************************************************/
void delay_140us( void )
{
    int i;
    for(i=0; i<20; i++)
      _nop_();
}

/********************************************************************
* 名称 : Delay_1ms(unsigned int i)
* 功能 : 延时子程序,延时时间为 1ms * x
* 输入 : x (延时一毫秒的个数)
* 输出 : 无
***********************************************************************/
/*
void Delay_1ms(unsigned int i)//1ms延时
{
    unsigned char x,j;
    for(j=0;j<i;j++)
    for(x=0;x<=148;x++);        
}
*/

回复

使用道具 举报

ID:82869 发表于 2019-10-3 23:14 | 显示全部楼层
递减改成递增就可以了吧
回复

使用道具 举报

ID:35873 发表于 2019-10-4 01:11 | 显示全部楼层
把void time_judge( void )里面相关数值改成顺数 比如  0-9  0-23  0-60  等等   然后-1  改成+1  总之反过来就是喽  其实我也不懂  瞎蒙的
回复

使用道具 举报

ID:524818 发表于 2019-10-4 08:40 | 显示全部楼层
数组声明的花括号里次序颠倒一下应该就行了
回复

使用道具 举报

ID:553031 发表于 2019-10-4 09:42 来自手机 | 显示全部楼层
cphnkj188 发表于 2019-10-4 08:40
数组声明的花括号里次序颠倒一下应该就行了

递减改成递增就可以了吧
回复

使用道具 举报

ID:213173 发表于 2019-10-4 17:17 | 显示全部楼层
楼主找的这个示例并不适合初学者参考。原作者把简单问题复杂化,使用了对于初学者不易理解的结构体变量,把非常简单的计时程序写得啰啰嗦嗦一大堆代码。按楼主需求可以找一些秒表程序参考。
回复

使用道具 举报

ID:577423 发表于 2019-10-4 19:07 | 显示全部楼层
void time_judge( void )
{
        if(++sec == 60)           //60秒
        {        
                sec = 0;
                if((Hour.shi || Hour.ge || Min.shi || Min.ge) && (--Min.ge <= -1))
                {
                        Min.ge = 9;
                        if((Hour.shi) ||(Hour.ge) && (--Min.shi <= -1))
                        {
                                Min.shi = 5;
                                if(Hour.shi && (--Hour.ge <= -1))
                                {
                                        Hour.ge = 9;
                                        if(--Hour.shi <= -1)
                                        {
                                                Hour.shi = 0;        
                                        }
                                }
                                else
                                if((!Hour.shi) && (--Hour.ge <= -1))
                                {
                                        Hour.ge = 0;
                                }
                        }
                        else
                        if((!Hour.shi) && (!Hour.ge) && (--Min.shi <= -1))
                        {
                                Min.shi = 0;
                        }
                }
                else
                if(((!Hour.shi) && (!Hour.ge) && (!Min.shi) ) && (Min.ge <= -1))
                {
                        Min.ge = 0;
                }
        }        
}
主要是改这一段,我改过效果不好
回复

使用道具 举报

ID:213173 发表于 2019-10-5 06:53 | 显示全部楼层
越南超级人类 发表于 2019-10-4 19:07
void time_judge( void )
{
        if(++sec == 60)           //60秒

只是简单的改这一部分不能解决问题,给你改了一下,冗余的部分全部去掉,你试试。
  1. #include <reg52.h>
  2. #include<intrins.h>

  3. sbit CLK = P0^0;  //时钟信号
  4. sbit DIO = P0^1;  //数据/地址数据
  5. //这里需要增加一个输出端口
  6. //sbit OUT = P1^0;                                                                                                                                                                 //共阴极数码管

  7. unsigned char code SEGData[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//1-9
  8. unsigned char code SEGDataDp[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; //有小数点只用于地址0xc1

  9. unsigned char dpFlag = 0; //控制第二个数码管的dp的显示

  10. void TM1637_start( void );
  11. void TM1637_stop( void );
  12. void TM1637_write1Bit(unsigned char mBit);
  13. void TM1637_write1Byte(unsigned char mByte);
  14. void TM1637_writeCammand(unsigned char mData);
  15. void TM1637_writeData(unsigned char addr, unsigned char mData);
  16. //void time_set(char hour, char min);
  17. void time_judge( void );
  18. void time_display( void );
  19. void timer0_init( void );

  20. void delay_140us( void );
  21. //void delay_1ms(unsigned int i);

  22. unsigned int countTime = 0;
  23. unsigned char sec,min,hour;
  24. bit time=1;
  25. /*
  26. struct
  27. {
  28.         char shi;
  29.         char ge;
  30. }Hour;

  31. struct
  32. {
  33.         char shi;
  34.         char ge;
  35. }Min;
  36. */
  37. /***********************************************************
  38. *****
  39. ***** 主函数
  40. *****
  41. ***********************************************************/
  42. void main( void )
  43. {
  44.         timer0_init();
  45. //        time_set(5,0);  //设置5小时倒计时
  46. //        OUT=1;//加电输出
  47.         while(1)
  48.         {
  49.                 if(time)//判断停止计时标志
  50.                 {
  51.                         if(countTime <=10)//闪秒
  52.                         {
  53.                                 dpFlag = 0;                        
  54.                         }
  55.                         else
  56.                         {
  57.                                 dpFlag = 1;        
  58.                         }
  59.                         if(countTime >=20)
  60.                         {
  61.                                 countTime = 0;
  62.                                 time_judge();
  63.                         }
  64.                 }
  65.                 time_display();         //显示时间
  66.         }
  67. }
  68. /*
  69. void time_set(char hour, char min)
  70. {
  71.         Hour.shi = hour/10;
  72.         Hour.ge = hour%10;
  73.         Min.shi = min/10;
  74.         Min.ge = min%10;               
  75. }
  76. */
  77. /*************************************************************
  78. * 名称 : time_judge( void )
  79. * 功能 : 判断时间变化
  80. * 输入 : void
  81. * 输出 : 无
  82. **************************************************************/
  83. void time_judge( void )
  84. {
  85.         if(++sec>=60)           //60秒
  86.         {        
  87.                 sec=0;
  88.                 if(++min>=60)
  89.                 {
  90.                         min=0;
  91.                         if(++hour>=5)//正计时5小时到
  92.                         {
  93.                                 time=0;//计时结束
  94. //                                OUT=0;//停止输出
  95.                         }
  96.                 }        
  97. /*
  98.                 if((Hour.shi || Hour.ge || Min.shi || Min.ge) && (--Min.ge <= -1))
  99.                 {
  100.                         Min.ge = 9;
  101.                         if((Hour.shi) ||(Hour.ge) && (--Min.shi <= -1))
  102.                         {
  103.                                 Min.shi = 5;
  104.                                 if(Hour.shi && (--Hour.ge <= -1))
  105.                                 {
  106.                                         Hour.ge = 9;
  107.                                         if(--Hour.shi <= -1)
  108.                                         {
  109.                                                 Hour.shi = 0;        
  110.                                         }
  111.                                 }
  112.                                 else
  113.                                 if((!Hour.shi) && (--Hour.ge <= -1))
  114.                                 {
  115.                                         Hour.ge = 0;
  116.                                 }
  117.                         }
  118.                         else
  119.                         if((!Hour.shi) && (!Hour.ge) && (--Min.shi <= -1))
  120.                         {
  121.                                 Min.shi = 0;
  122.                         }
  123.                 }
  124.                 else
  125.                 if(((!Hour.shi) && (!Hour.ge) && (!Min.shi) ) && (Min.ge <= -1))
  126.                 {
  127.                         Min.ge = 0;
  128.                 }
  129. */
  130.         }
  131. }
  132. /*******************************************************************
  133. * 名称 : void time_display( void )
  134. * 功能 : 显示时间
  135. * 输入 : void
  136. * 输出 : 无
  137. **************************************************************/
  138. void time_display( void )
  139. {
  140.         TM1637_writeCammand(0x44);
  141.         TM1637_writeData(0xc0, SEGData[hour/10]);
  142.         if(dpFlag)
  143.                 TM1637_writeData(0xc1, SEGDataDp[hour%10]); //小数点标志为1则用小数点那个数组
  144.         else
  145.                 TM1637_writeData(0xc1, SEGData[hour%10]);
  146.         TM1637_writeData(0xc2, SEGData[min/10]);
  147.         TM1637_writeData(0xc3, SEGData[min%10]);
  148.         TM1637_writeCammand(0x8a);                     
  149. /*
  150.         TM1637_writeCammand(0x44);
  151.         TM1637_writeData(0xc0, SEGData[Hour.shi]);
  152.         if(dpFlag)
  153.                 TM1637_writeData(0xc1, SEGDataDp[Hour.ge]); //小数点标志为1则用小数点那个数组
  154.         else
  155.                 TM1637_writeData(0xc1, SEGData[Hour.ge]);
  156.         TM1637_writeData(0xc2, SEGData[Min.shi]);
  157.         TM1637_writeData(0xc3, SEGData[Min.ge]);
  158.         TM1637_writeCammand(0x8a);
  159. */
  160. }

  161. /********************************************************************
  162. * 名称 : void TM1637_start( void )
  163. * 功能 : start信号
  164. * 输入 : void
  165. * 输出 : 无
  166. **************************************************************/
  167. void TM1637_start( void )
  168. {
  169.         CLK = 1;
  170.         DIO = 1;
  171.         delay_140us();
  172.         DIO = 0;
  173.         delay_140us();
  174.         CLK = 0;
  175.         delay_140us();
  176. }

  177. /********************************************************************
  178. * 名称 : void TM1637_stop( void )
  179. * 功能 : stop信号
  180. * 输入 : void
  181. * 输出 : 无
  182. **************************************************************/
  183. void TM1637_stop( void )
  184. {
  185.         CLK = 0;
  186.         delay_140us();
  187.         DIO = 0;
  188.         delay_140us();
  189.         CLK = 1;
  190.         delay_140us();
  191.         DIO = 1;
  192.         delay_140us();
  193. }

  194. void TM1637_write1Bit(unsigned char mBit )
  195. {
  196.         CLK = 0;
  197.         delay_140us();
  198.         if(mBit)
  199.                 DIO = 1;
  200.         else
  201.            DIO = 0;
  202.         delay_140us();        
  203.         CLK = 1;
  204.         delay_140us();
  205. }

  206. /********************************************************************
  207. * 名称 : void TM1637_write1Byte(unsigned char mByte)
  208. * 功能 : 写1byte
  209. * 输入 : unsigned char mByte
  210. * 输出 : 无
  211. **************************************************************/
  212. void TM1637_write1Byte(unsigned char mByte)
  213. {
  214.         char loop = 0;
  215.         for(loop = 0; loop < 8; loop++)
  216.         {
  217.                 TM1637_write1Bit((mByte>>loop)&0x01); //取得最低位        
  218.         }
  219.         CLK = 0;
  220.         delay_140us();
  221.         DIO = 1;
  222.         delay_140us();
  223.         CLK = 1;
  224.         delay_140us();
  225.         while(DIO == 1);  //获得应答位         
  226. }
  227. /********************************************************************
  228. * 名称 : void TM1637_writeCammand(unsigned char mData)
  229. * 功能 : 写指令1byte
  230. * 输入 : unsigned char mData
  231. * 输出 : 无
  232. **************************************************************/
  233. void TM1637_writeCammand(unsigned char mData)
  234. {
  235.         TM1637_start();
  236.         TM1637_write1Byte(mData);  //数据
  237.         TM1637_stop();        
  238. }
  239. /********************************************************************
  240. * 名称 : void TM1637_writeData(unsigned char addr, unsigned char mData)
  241. * 功能 : 固定地址写数据1byte
  242. * 输入 : unsigned char addr, unsigned char mData
  243. * 输出 : 无
  244. **************************************************************/
  245. void TM1637_writeData(unsigned char addr, unsigned char mData)
  246. {
  247.         TM1637_start();
  248.         TM1637_write1Byte(addr);  //地址
  249.         TM1637_write1Byte(mData);  //数据
  250.         TM1637_stop();        
  251. }

  252. void timer0_init( void )
  253. {
  254.         TMOD=0X01;
  255.         TH0=(65535-50000)/256;
  256.         TL0=(65535-50000)%256;
  257.         ET0=1;
  258.         EA=1;
  259.         TR0=1;        
  260. }              
  261. /********************************************************************
  262. * 名称 :
  263. * 功能 : 定时50ms,实际运行中由于指令运行造成的延时,实际时间肯定大于50ms
  264. * 输入 : 无
  265. * 输出 : 无
  266. **************************************************************/
  267. void timer0_isr() interrupt 1
  268. {
  269.         TH0=(65535-50000)/256;  //50ms
  270.         TL0=(65535-50000)%256;        //
  271.         countTime++;
  272. }

  273. /********************************************************************
  274. * 名称 : Delay_1ms(unsigned int i)
  275. * 功能 : 延时子程序,延时时间为 140us
  276. * 输入 :
  277. * 输出 : 无
  278. **************************************************************/
  279. void delay_140us( void )
  280. {
  281.         int i;
  282.         for(i=0; i<20; i++)
  283.                 _nop_();
  284. }

  285. /********************************************************************
  286. * 名称 : Delay_1ms(unsigned int i)
  287. * 功能 : 延时子程序,延时时间为 1ms * x
  288. * 输入 : x (延时一毫秒的个数)
  289. * 输出 : 无
  290. ***********************************************************************/
  291. /*
  292. void Delay_1ms(unsigned int i)//1ms延时
  293. {
  294.     unsigned char x,j;
  295.     for(j=0;j<i;j++)
  296.     for(x=0;x<=148;x++);        
  297. }
  298. */

复制代码
回复

使用道具 举报

ID:577423 发表于 2019-10-5 20:02 | 显示全部楼层
其实我想学习tm1537做显示,主要是不懂逻辑,位等等这些东西
回复

使用道具 举报

ID:845657 发表于 2020-11-18 22:33 | 显示全部楼层
wulin 发表于 2019-10-5 06:53
只是简单的改这一部分不能解决问题,给你改了一下,冗余的部分全部去掉,你试试。

大佬,这个能显示秒吗?
回复

使用道具 举报

ID:748788 发表于 2021-1-5 11:02 | 显示全部楼层
越南超级人类 发表于 2019-10-5 20:02
其实我想学习tm1537做显示,主要是不懂逻辑,位等等这些东西

那你不如找x宝tm1637的卖家看看,那里一般都会提供比较简洁的例程
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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