找回密码
 立即注册

QQ登录

只需一步,快速开始

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

我的单片机DS1302时钟,和数模转换的程序

[复制链接]
跳转到指定楼层
楼主
ID:216965 发表于 2018-6-16 16:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
上个月刚做的关于Ds1302时钟和数模转换的设计,
检测电池电压,自我供电的 包含源码和工程。

单片机源程序如下:
  1. /*
  2. *******************************************************************************
  3. *
  4. * 文件名:main.c
  5. 用DS1302实现简易电子钟
  6. *         用液晶显示日期时间,并可通过按键校时
  7. *******************************************************************************
  8. */

  9. #include <reg52.h>

  10. struct sTime {  //日期时间结构体定义
  11.     unsigned int  year;
  12.     unsigned char mon;
  13.     unsigned char day;
  14.     unsigned char hour;
  15.     unsigned char min;
  16.     unsigned char sec;
  17.     unsigned char week;
  18. };

  19. bit flag300ms = 1;       //300ms定时标志
  20. bit flag200ms = 1;  //200ms定时标志
  21. unsigned char T0RH = 0;  //T0重载值的高字节
  22. unsigned char T0RL = 0;  //T0重载值的低字节
  23. struct sTime bufTime;  //日期时间缓冲区
  24. unsigned char setIndex = 0;  //时间设置索引

  25. void ConfigTimer0(unsigned int ms);
  26. unsigned char GetADCValue(unsigned char chn);
  27. void ValueToString(unsigned char *str, unsigned char val);
  28. extern void I2CStart();
  29. extern void I2CStop();
  30. extern unsigned char I2CReadACK();
  31. extern unsigned char I2CReadNAK();
  32. extern bit I2CWrite(unsigned char dat);
  33. extern void InitLcd1602();
  34. extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
  35. void ConfigTimer0(unsigned int ms);
  36. void RefreshTimeShow();
  37. extern void InitDS1302();
  38. extern void GetRealTime(struct sTime *time);
  39. extern void SetRealTime(struct sTime *time);
  40. extern void KeyScan();
  41. extern void KeyDriver();
  42. extern void InitLcd1602();
  43. extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
  44. extern void LcdSetCursor(unsigned char x, unsigned char y);
  45. extern void LcdOpenCursor();
  46. extern void LcdCloseCursor();

  47. void main()
  48. {
  49.     unsigned char psec=0xAA;  //秒备份,初值AA确保首次读取时间后会刷新显示
  50.         unsigned char val;
  51.     unsigned char str[10];

  52.     EA = 1;           //开总中断
  53.     ConfigTimer0(1);  //T0定时1ms
  54.     InitDS1302();     //初始化实时时钟
  55.     InitLcd1602();    //初始化液晶
  56.    
  57.     //初始化屏幕上固定不变的内容
  58.     LcdShowStr(0, 0, "20  -  -  ");
  59.     LcdShowStr(1, 1, "  :  :  ");
  60.         LcdShowStr(11, 0, "Vol");  //显示通道指示
  61.    
  62.     while (1)
  63.     {
  64.         KeyDriver();  //调用按键驱动
  65.         if (flag200ms && (setIndex == 0))
  66.         {                             //每隔200ms且未处于设置状态时,
  67.             flag200ms = 0;
  68.             GetRealTime(&bufTime);    //获取当前时间
  69.             if (psec != bufTime.sec)  //检测到时间有变化时刷新显示
  70.             {
  71.                 RefreshTimeShow();
  72.                 psec = bufTime.sec;   //用当前值更新上次秒数
  73.             }
  74.         }
  75.                 if (flag300ms)
  76.         {
  77.             flag300ms = 0;
  78.             //显示通道0的电压
  79.             val = GetADCValue(0);     //获取ADC通道0的转换值
  80.             ValueToString(str, val);  //转为字符串格式的电压值
  81.             LcdShowStr(11, 1, str);    //显示到液晶上
  82.             //显示通道1的电压
  83.             /*val = GetADCValue(1);
  84.             ValueToString(str, val);
  85.             LcdShowStr(6, 1, str);
  86.             //显示通道3的电压
  87.             val = GetADCValue(3);
  88.             ValueToString(str, val);
  89.             LcdShowStr(12, 1, str);           */
  90.         }
  91.     }
  92. }
  93. /* 将一个BCD码字节显示到屏幕上,(x,y)-屏幕起始坐标,bcd-待显示BCD码 */
  94. void ShowBcdByte(unsigned char x, unsigned char y, unsigned char bcd)
  95. {
  96.     unsigned char str[4];
  97.    
  98.     str[0] = (bcd >> 4) + '0';
  99.     str[1] = (bcd&0x0F) + '0';
  100.     str[2] = '\0';
  101.     LcdShowStr(x, y, str);
  102. }
  103. /* 刷新日期时间的显示 */
  104. void RefreshTimeShow()
  105. {
  106.     ShowBcdByte(2,  0, bufTime.year);
  107.     ShowBcdByte(5,  0, bufTime.mon);
  108.     ShowBcdByte(8, 0, bufTime.day);
  109.     ShowBcdByte(1,  1, bufTime.hour);
  110.     ShowBcdByte(4,  1, bufTime.min);
  111.     ShowBcdByte(7, 1, bufTime.sec);
  112. }
  113. /* 刷新当前设置位的光标指示 */
  114. void RefreshSetShow()
  115. {
  116.     switch (setIndex)
  117.     {
  118.         case 1:  LcdSetCursor(2,  0); break;
  119.         case 2:  LcdSetCursor(3,  0); break;
  120.         case 3:  LcdSetCursor(5,  0); break;
  121.         case 4:  LcdSetCursor(6,  0); break;
  122.         case 5:  LcdSetCursor(8, 0); break;
  123.         case 6:  LcdSetCursor(9, 0); break;
  124.         case 7:  LcdSetCursor(1,  1); break;
  125.         case 8:  LcdSetCursor(2,  1); break;
  126.         case 9:  LcdSetCursor(4,  1); break;
  127.         case 10: LcdSetCursor(5,  1); break;
  128.         case 11: LcdSetCursor(7, 1); break;
  129.         case 12: LcdSetCursor(8, 1); break;
  130.         default:  break;
  131.     }
  132. }
  133. /* 递增一个BCD码的高位 */
  134. unsigned char IncBcdHigh(unsigned char bcd)
  135. {
  136.     if ((bcd&0xF0) < 0x90)
  137.         bcd += 0x10;
  138.     else
  139.         bcd &= 0x0F;
  140.    
  141.     return bcd;
  142. }
  143. /* 递增一个BCD码的低位 */
  144. unsigned char IncBcdLow(unsigned char bcd)
  145. {
  146.     if ((bcd&0x0F) < 0x09)
  147.         bcd += 0x01;
  148.     else
  149.         bcd &= 0xF0;
  150.    
  151.     return bcd;
  152. }
  153. /* 递减一个BCD码的高位 */
  154. unsigned char DecBcdHigh(unsigned char bcd)
  155. {
  156.     if ((bcd&0xF0) > 0x00)
  157.         bcd -= 0x10;
  158.     else
  159.         bcd |= 0x90;
  160.    
  161.     return bcd;
  162. }
  163. /* 递减一个BCD码的低位 */
  164. unsigned char DecBcdLow(unsigned char bcd)
  165. {
  166.     if ((bcd&0x0F) > 0x00)
  167.         bcd -= 0x01;
  168.     else
  169.         bcd |= 0x09;
  170.    
  171.     return bcd;
  172. }
  173. /* 递增时间当前设置位的值 */
  174. void IncSetTime()
  175. {
  176.     switch (setIndex)
  177.     {
  178.         case 1:  bufTime.year = IncBcdHigh(bufTime.year); break;
  179.         case 2:  bufTime.year = IncBcdLow(bufTime.year);  break;
  180.         case 3:  bufTime.mon  = IncBcdHigh(bufTime.mon);  break;
  181.         case 4:  bufTime.mon  = IncBcdLow(bufTime.mon);   break;
  182.         case 5:  bufTime.day  = IncBcdHigh(bufTime.day);  break;
  183.         case 6:  bufTime.day  = IncBcdLow(bufTime.day);   break;
  184.         case 7:  bufTime.hour = IncBcdHigh(bufTime.hour); break;
  185.         case 8:  bufTime.hour = IncBcdLow(bufTime.hour);  break;
  186.         case 9:  bufTime.min  = IncBcdHigh(bufTime.min);  break;
  187.         case 10: bufTime.min  = IncBcdLow(bufTime.min);   break;
  188.         case 11: bufTime.sec  = IncBcdHigh(bufTime.sec);  break;
  189.         case 12: bufTime.sec  = IncBcdLow(bufTime.sec);   break;
  190.         default:  break;
  191.     }
  192.     RefreshTimeShow();
  193.     RefreshSetShow();
  194. }
  195. /* 递减时间当前设置位的值 */
  196. void DecSetTime()
  197. {
  198.     switch (setIndex)
  199.     {
  200.         case 1:  bufTime.year = DecBcdHigh(bufTime.year); break;
  201.         case 2:  bufTime.year = DecBcdLow(bufTime.year);  break;
  202.         case 3:  bufTime.mon  = DecBcdHigh(bufTime.mon);  break;
  203.         case 4:  bufTime.mon  = DecBcdLow(bufTime.mon);   break;
  204.         case 5:  bufTime.day  = DecBcdHigh(bufTime.day);  break;
  205.         case 6:  bufTime.day  = DecBcdLow(bufTime.day);   break;
  206.         case 7:  bufTime.hour = DecBcdHigh(bufTime.hour); break;
  207.         case 8:  bufTime.hour = DecBcdLow(bufTime.hour);  break;
  208.         case 9:  bufTime.min  = DecBcdHigh(bufTime.min);  break;
  209.         case 10: bufTime.min  = DecBcdLow(bufTime.min);   break;
  210.         case 11: bufTime.sec  = DecBcdHigh(bufTime.sec);  break;
  211.         case 12: bufTime.sec  = DecBcdLow(bufTime.sec);   break;
  212.         default:  break;
  213.     }
  214.     RefreshTimeShow();
  215.     RefreshSetShow();
  216. }
  217. /* 右移时间设置位 */
  218. void RightShiftTimeSet()
  219. {
  220.     if (setIndex != 0)
  221.     {
  222.         if (setIndex < 12)
  223.             setIndex++;
  224.         else
  225.             setIndex = 1;
  226.         RefreshSetShow();
  227.     }
  228. }
  229. /* 左移时间设置位 */
  230. void LeftShiftTimeSet()
  231. {
  232.     if (setIndex != 0)
  233.     {
  234.         if (setIndex > 1)
  235.             setIndex--;
  236.         else
  237.             setIndex = 12;
  238.         RefreshSetShow();
  239.     }
  240. }
  241. /* 进入时间设置状态 */
  242. void EnterTimeSet()
  243. {
  244.     setIndex = 2;       //把设置索引设置为2,即可进入设置状态
  245.     LeftShiftTimeSet(); //再利用现成的左移操作移到位置1并完成显示刷新
  246.     LcdOpenCursor();    //打开光标闪烁效果
  247. }
  248. /* 退出时间设置状态,save-是否保存当前设置的时间值 */
  249. void ExitTimeSet(bit save)
  250. {
  251.     setIndex = 0;     //把设置索引设置为0,即可退出设置状态
  252.     if (save)         //需保存时即把当前设置时间写入DS1302
  253.     {
  254.         SetRealTime(&bufTime);
  255.     }
  256.     LcdCloseCursor(); //关闭光标显示
  257. }
  258. /* 按键动作函数,根据键码执行相应的操作,keycode-按键键码 */
  259. void KeyAction(unsigned char keycode)
  260. {
  261.     if  ((keycode>='0') && (keycode<='9'))  //本例中不响应字符键
  262.     {
  263.     }
  264.     else if (keycode == 0x26)  //向上键,递增当前设置位的值
  265.     {
  266.         IncSetTime();
  267.     }
  268.     else if (keycode == 0x28)  //向下键,递减当前设置位的值
  269.     {
  270.         DecSetTime();
  271.     }
  272.     else if (keycode == 0x25)  //向左键,向左切换设置位
  273.     {
  274.         LeftShiftTimeSet();
  275.     }
  276.     else if (keycode == 0x27)  //向右键,向右切换设置位
  277.     {
  278.         RightShiftTimeSet();
  279.     }
  280.     else if (keycode == 0x0D)  //回车键,进入设置模式/启用当前设置值
  281.     {
  282.         if (setIndex == 0)  //不处于设置状态时,进入设置状态
  283.         {
  284.             EnterTimeSet();
  285.         }
  286.         else                //已处于设置状态时,保存时间并退出设置状态
  287.         {
  288.             ExitTimeSet(1);
  289.         }
  290.     }
  291.     else if (keycode == 0x1B)  //Esc键,取消当前设置
  292.     {
  293.         ExitTimeSet(0);
  294.     }
  295. }
  296. /* 读取当前的ADC转换值,chn-ADC通道号0~3 */
  297. unsigned char GetADCValue(unsigned char chn)
  298. {
  299.     unsigned char val;
  300.    
  301.     I2CStart();
  302.     if (!I2CWrite(0x48<<1))  //寻址PCF8591,如未应答,则停止操作并返回0
  303.     {
  304.         I2CStop();
  305.         return 0;
  306.     }
  307.     I2CWrite(0x40|chn);        //写入控制字节,选择转换通道
  308.     I2CStart();
  309.     I2CWrite((0x48<<1)|0x01);  //寻址PCF8591,指定后续为读操作   
  310.     I2CReadACK();              //先空读一个字节,提供采样转换时间
  311.     val = I2CReadNAK();        //读取刚刚转换完的值
  312.     I2CStop();
  313.    
  314.     return val;
  315. }
  316. /* ADC转换值转为实际电压值的字符串形式,str-字符串指针,val-AD转换值 */
  317. void ValueToString(unsigned char *str, unsigned char val)
  318. {
  319.     //电压值=转换结果*2.5V/255,式中的25隐含了一位十进制小数
  320.     val = (val*50) / 255;
  321.     str[0] = (val/10) + '0';  //整数位字符
  322.     str[1] = '.';             //小数点
  323.     str[2] = (val%10) + '0';  //小数位字符
  324.     str[3] = 'V';             //电压单位
  325.     str[4] = '\0';            //结束符
  326. }
  327. ……………………

  328. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
kechuang1.zip (83.42 KB, 下载次数: 6)


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

使用道具 举报

沙发
ID:352962 发表于 2018-6-16 20:02 | 只看该作者
很赞的 ,感谢
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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