找回密码
 立即注册

QQ登录

只需一步,快速开始

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

我用单片机+TM1638做的时钟程序有问题希望大师指点

[复制链接]
跳转到指定楼层
楼主
ID:39720 发表于 2023-2-11 14:39 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  1. #include        <reg52.h>
  2. #include        <tm1638.h>
  3. #include <ds1302.h>
  4. void main(void)
  5. {
  6.         unsigned char i;        
  7.         init_TM1638();        //初始化TM1638
  8.         Ds1302Init();
  9.         for(i=0;i<8;i++)
  10.         Write_DATA(i<<1,tab[16]);                       //初始化寄存器        
  11.         while(1)
  12.         {
  13.                 Ds1302ReadTime();
  14.                 i=Read_key();                //读按键值
  15.                
  16.                 switch(i)
  17.          {
  18.                         case 0:if(i==0)
  19.                                                  {        
  20.                                                                 temp=4567;                        
  21.                                                                 while(Read_key()==i);                       //等待按键释放
  22.                                                                 Write_allLED(1);  //八只LED灯
  23.                                                                 Display();
  24.                                                                 Write_DATA(0*2,tab[1]);
  25.                                                                 Write_DATA(1*2,tab[12]);        
  26.                                                         } break;
  27.       case 1:if(i==1)
  28.                                                         {
  29.                                                                 while(Read_key()==i);
  30.                                                                 Write_allLED(2);
  31.                                                                 TimDisplay();
  32.                                                         } break;
  33.                         case 2:if(i==2)
  34.                                                         {        
  35.                                                                 while(Read_key()==i);
  36.                                                                 Write_allLED(3);
  37.                                                                 for(i=0;i<8;i++)
  38.                                                                 Write_DATA(i<<1,tab[16]);                                                        
  39.                                                         } break;        
  40.                                                         default:break;
  41.          }
  42.                
  43.                         
  44.          
  45.                
  46.         }
  47. }
  48. ds1302.c
  49. #include"ds1302.h"

  50. //---DS1302写入和读取时分秒的地址命令---//
  51. //---秒分时日月周年 最低位读写位;-------//
  52. uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
  53. uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};

  54. //---DS1302时钟初始化2013年1月1日星期二12点00分00秒。---//
  55. //---存储顺序是秒分时日月周年,存储格式是用BCD码---//
  56. uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01, 0x02, 0x13};

  57. /*******************************************************************************
  58. * 函 数 名         : Ds1302Write
  59. * 函数功能                   : 向DS1302命令(地址+数据)
  60. * 输    入         : addr,dat
  61. * 输    出         : 无
  62. *******************************************************************************/

  63. void Ds1302Write(uchar addr, uchar dat)
  64. {
  65.         uchar n;
  66.         RST = 0;
  67.         _nop_();

  68.         SCLK = 0;//先将SCLK置低电平。
  69.         _nop_();
  70.         RST = 1; //然后将RST(CE)置高电平。
  71.         _nop_();

  72.         for (n=0; n<8; n++)//开始传送八位地址命令
  73.         {
  74.                 DSIO = addr & 0x01;//数据从低位开始传送
  75.                 addr >>= 1;
  76.                 SCLK = 1;//数据在上升沿时,DS1302读取数据
  77.                 _nop_();
  78.                 SCLK = 0;
  79.                 _nop_();
  80.         }
  81.         for (n=0; n<8; n++)//写入8位数据
  82.         {
  83.                 DSIO = dat & 0x01;
  84.                 dat >>= 1;
  85.                 SCLK = 1;//数据在上升沿时,DS1302读取数据
  86.                 _nop_();
  87.                 SCLK = 0;
  88.                 _nop_();        
  89.         }        
  90.                  
  91.         RST = 0;//传送数据结束
  92.         _nop_();
  93. }

  94. /*******************************************************************************
  95. * 函 数 名         : Ds1302Read
  96. * 函数功能                   : 读取一个地址的数据
  97. * 输    入         : addr
  98. * 输    出         : dat
  99. *******************************************************************************/

  100. uchar Ds1302Read(uchar addr)
  101. {
  102.         uchar n,dat,dat1;
  103.         RST = 0;
  104.         _nop_();

  105.         SCLK = 0;//先将SCLK置低电平。
  106.         _nop_();
  107.         RST = 1;//然后将RST(CE)置高电平。
  108.         _nop_();

  109.         for(n=0; n<8; n++)//开始传送八位地址命令
  110.         {
  111.                 DSIO = addr & 0x01;//数据从低位开始传送
  112.                 addr >>= 1;
  113.                 SCLK = 1;//数据在上升沿时,DS1302读取数据
  114.                 _nop_();
  115.                 SCLK = 0;//DS1302下降沿时,放置数据
  116.                 _nop_();
  117.         }
  118.         _nop_();
  119.         for(n=0; n<8; n++)//读取8位数据
  120.         {
  121.                 dat1 = DSIO;//从最低位开始接收
  122.                 dat = (dat>>1) | (dat1<<7);
  123.                 SCLK = 1;
  124.                 _nop_();
  125.                 SCLK = 0;//DS1302下降沿时,放置数据
  126.                 _nop_();
  127.         }

  128.         RST = 0;
  129.         _nop_();        //以下为DS1302复位的稳定时间,必须的。
  130.         SCLK = 1;
  131.         _nop_();
  132.         DSIO = 0;
  133.         _nop_();
  134.         DSIO = 1;
  135.         _nop_();
  136.         return dat;        
  137. }

  138. /*******************************************************************************
  139. * 函 数 名         : Ds1302Init
  140. * 函数功能                   : 初始化DS1302.
  141. * 输    入         : 无
  142. * 输    出         : 无
  143. *******************************************************************************/

  144. void Ds1302Init()
  145. {
  146.         uchar n;
  147.         Ds1302Write(0x8E,0X00);                 //禁止写保护,就是关闭写保护功能
  148.         for (n=0; n<7; n++)//写入7个字节的时钟信号:分秒时日月周年
  149.         {
  150.                 Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);        
  151.         }
  152.         Ds1302Write(0x8E,0x80);                 //打开写保护功能
  153. }

  154. /*******************************************************************************
  155. * 函 数 名         : Ds1302ReadTime
  156. * 函数功能                   : 读取时钟信息
  157. * 输    入         : 无
  158. * 输    出         : 无
  159. *******************************************************************************/

  160. void Ds1302ReadTime()
  161. {
  162.         uchar n;
  163.         for (n=0; n<7; n++)//读取7个字节的时钟信号:分秒时日月周年
  164.         {
  165.                 TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);
  166.         }
  167.                
  168. }
  169. ds1302.h
  170. #ifndef __DS1302_H_
  171. #define __DS1302_H_

  172. //---包含头文件---//
  173. #include<reg52.h>
  174. #include<intrins.h>

  175. //---重定义关键词---//
  176. #ifndef uchar
  177. #define uchar unsigned char
  178. #endif

  179. #ifndef uint
  180. #define uint unsigned int
  181. #endif

  182. //---定义ds1302使用的IO口---//
  183. sbit DSIO=P3^4;
  184. sbit RST=P3^5;
  185. sbit SCLK=P3^6;

  186. //---定义全局函数---//
  187. void Ds1302Write(uchar addr, uchar dat);
  188. uchar Ds1302Read(uchar addr);
  189. void Ds1302Init();
  190. void Ds1302ReadTime();

  191. //---加入全局变量--//
  192. extern uchar TIME[7];        //加入全局变量

  193. #endif
  194. tm1638.h
  195. #ifndef        _TM1638_H
  196. #define        _TM1638_H

  197. #include        <reg52.h>
  198. #include <ds1302.h>
  199. #define        DATA_COMMAND        0X40
  200. #define        DISP_COMMAND        0x80
  201. #define        ADDR_COMMAND        0XC0

  202. //TM1638模块引脚定义
  203. sbit        DIO=P2^0;
  204. sbit        CLK=P2^1;
  205. sbit        STB=P2^2;
  206. unsigned char num[8];                //各个数码管显示的值
  207. unsigned int temp;
  208. //共阴数码管显示代码
  209. unsigned char code tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
  210.                           0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x00,0x40};


  211. void TM1638_Write(unsigned char        DATA)                        //写数据函数
  212. {
  213.         unsigned char i;
  214.         for(i=0;i<8;i++)
  215.         {
  216.                 CLK=0;
  217.                 if(DATA&0X01)
  218.                         DIO=1;
  219.                 else
  220.                         DIO=0;
  221.                 DATA>>=1;
  222.                 CLK=1;
  223.         }
  224. }
  225. unsigned char TM1638_Read(void)                                        //读数据函数
  226. {
  227.         unsigned char i;
  228.         unsigned char temp=0;
  229.         DIO=1;        //设置为输入
  230.         for(i=0;i<8;i++)
  231.         {
  232.                 temp>>=1;
  233.                 CLK=0;
  234.                 if(DIO)
  235.                         temp|=0x80;
  236.                 CLK=1;
  237.         }
  238.         return temp;
  239. }
  240. void Write_COM(unsigned char cmd)                //发送命令字
  241. {
  242.         STB=0;
  243.         TM1638_Write(cmd);
  244.         STB=1;
  245. }
  246. unsigned char Read_key(void)
  247. {
  248.         unsigned char c[4],i,key_value=0;
  249.         STB=0;
  250.         TM1638_Write(0x42);                           //读键扫数据 命令
  251.         for(i=0;i<4;i++)               
  252.                 c[i]=TM1638_Read();
  253.         STB=1;                                                   //4个字节数据合成一个字节
  254.         for(i=0;i<4;i++)
  255.                 key_value|=c[i]<<i;
  256.         for(i=0;i<8;i++)
  257.                 if((0x01<<i)==key_value)
  258.                         break;
  259.         return i;
  260. }
  261. void Write_DATA(unsigned char add,unsigned char DATA)                //指定地址写入数据
  262. {
  263.         Write_COM(0x44);
  264.         STB=0;
  265.         TM1638_Write(0xc0|add);
  266.         TM1638_Write(DATA);
  267.         STB=1;
  268. }
  269. void Display()
  270. {
  271.         
  272.         num[0] = temp % 10000 / 1000;
  273.         num[1] = temp % 1000 / 100;
  274.         num[2] = temp % 100 / 10;
  275.         num[3] = temp % 10;
  276.         Write_DATA(4*2,tab[num[0]]);
  277.         Write_DATA(5*2,tab[num[1]]|0x80);
  278.         Write_DATA(6*2,tab[num[2]]);
  279.         Write_DATA(7*2,tab[num[3]]);        
  280. }
  281. void TimDisplay()
  282. {        
  283.         Write_DATA( 0*2,tab[num[TIME[0]/16]]);
  284.         Write_DATA( 1*2,tab[num[TIME[0]%16]]);
  285.         Write_DATA( 2*2,tab[17]);
  286.         Write_DATA( 3*2,tab[num[TIME[1]/16]]);
  287.         Write_DATA( 4*2,tab[num[TIME[1]%16]]);
  288.         Write_DATA( 5*2,tab[17]);
  289.         Write_DATA( 6*2,tab[num[TIME[2]/16]]);
  290.         Write_DATA( 7*2,tab[num[TIME[2]%16]]);
  291.         /*LcdWriteData('0'+TIME[2]/16);                                //时
  292.         LcdWriteData('0'+(TIME[2]&0x0f));                                 
  293.         LcdWriteData('-');
  294.         LcdWriteData('0'+TIME[1]/16);                                //分
  295.         LcdWriteData('0'+(TIME[1]&0x0f));        
  296.         LcdWriteData('-');
  297.         LcdWriteData('0'+TIME[0]/16);                                //秒
  298.         LcdWriteData('0'+(TIME[0]&0x0f));

  299.         LcdWriteCom(0x80);
  300.         LcdWriteData('2');
  301.         LcdWriteData('0');
  302.         LcdWriteData('0'+TIME[6]/16);                        //年
  303.         LcdWriteData('0'+(TIME[6]&0x0f));
  304.         LcdWriteData('-');
  305.         LcdWriteData('0'+TIME[4]/16);                        //月
  306.         LcdWriteData('0'+(TIME[4]&0x0f));
  307.         LcdWriteData('-');
  308.         LcdWriteData('0'+TIME[3]/16);                        //日
  309.         LcdWriteData('0'+(TIME[3]&0x0f));
  310.         LcdWriteCom(0x8D);
  311.         LcdWriteData('0'+(TIME[5]&0x07));        //星期        */                 
  312. }

  313. /*
  314. void Write_oneLED(unsigned char num,unsigned char flag)        //单独控制一个LED函数,num为需要控制的led序号,flag为0时熄灭,不为0时点亮
  315. {
  316.         if(flag)
  317.                 Write_DATA(2*num+1,1);
  318.         else
  319.                 Write_DATA(2*num+1,0);
  320. }          */
  321. void Write_allLED(unsigned char LED_flag)                                        //控制全部LED函数,LED_flag表示各个LED状态
  322. {
  323.         unsigned char i;
  324.         for(i=0;i<8;i++)
  325.                 {
  326.                         if(LED_flag&(1<<i))
  327.                                 //Write_DATA(2*i+1,3);
  328.                                 Write_DATA(2*i+1,1);
  329.                         else
  330.                                 Write_DATA(2*i+1,0);
  331.                 }
  332. }


  333. //TM1638初始化函数
  334. void init_TM1638(void)
  335. {
  336.         unsigned char i;
  337.         Write_COM(0x8b);       //亮度 (0x88-0x8f)8级亮度可调
  338.         Write_COM(0x40);       //采用地址自动加1
  339.         STB=0;                           //
  340.         TM1638_Write(0xc0);    //设置起始地址

  341.         for(i=0;i<16;i++)           //传送16个字节的数据
  342.                 TM1638_Write(0x00);
  343.         STB=1;
  344. }
  345. #endif

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

使用道具 举报

沙发
ID:748788 发表于 2023-2-11 17:31 | 只看该作者
问题在哪?如果是1638有问题,就先解决1638的问题,不要考虑1302
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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