找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于51单片机的12864串行模式显示万年历实现代码

[复制链接]
跳转到指定楼层
楼主
ID:226407 发表于 2017-8-10 08:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
全部资料下载地址:
12864显示万年历.rar (3.53 KB, 下载次数: 44)

单片机源程序如下:
  1. /***************************************************************
  2. 系统名称:电子万年历
  3. 日期:2008,7,18
  4. 功能描述:LCD12864串行模式显示,DS1302读取时间年月份,
  5. 18B20 读取温度
  6. ****************************************************************/
  7. #include <reg51.h>
  8. #include <intrins.h>
  9. #include <stdio.h>
  10. #define uchar unsigned char
  11. #define uint unsigned int
  12. /*------------LCD12864相关声明-----------------------------*/
  13. #define com 0
  14. #define dat 1
  15. sbit cs =P1^6;
  16. sbit sid=P1^4;
  17. sbit sck=P1^2;
  18. uchar code TAB1[]={"电字钟w418781840"};//第一行初始化.
  19. uchar code TAB2[]={"20 年 月 日"}; //第二行
  20. uchar code TAB3[]={"星期 : : "}; //第三行
  21. uchar code TAB4[]={"室温: ℃"}; //第四行
  22. /*----------------------DS1302相关声明-------------------------*/
  23. char TAB_1302[]={ 0x00,0x29,0x02, //秒:分:时.
  24. 0x18,0x06,0x06,0x08}; //日:月:星期:年.
  25. uchar code TAB_XQ[]={"一二三四五六日"};//把DS1302数字日期转换为中文字符.
  26. sbit T_CLK=P2^4; /* 实时时钟的时钟线引脚*/
  27. sbit T_IO=P2^5; /* 实时时钟的数据线*/
  28. sbit T_RST=P2^6; /* 实时时钟的复位线引脚*/
  29. uchar bdata datbyte;
  30. sbit datbyte0=datbyte^0;
  31. sbit datbyte7=datbyte^7;
  32. /*--------------18B20相关声明-------------------------------*/
  33. uchar dis1[16];
  34. sbit DQ=P1^0; /*DS18B20温度检测*/
  35. /*----------键盘相关声明-------------------------------------*/
  36. sbit key=P3^2; //功能键
  37. sbit key1=P3^3; //只有加1键
  38. uchar sum,keyflag=0; //调用时,分,秒,标志,调用键盘处理标志.
  39. /*--------------以下为LCD12864相关函数--------------------------*/
  40. /**************************************************************
  41. 函数名称:void delay1ms(uint x)
  42. 函数功能: 延时1MS
  43. ***************************************************************/
  44. void delay1ms(uint x)
  45. {
  46. uint i,j;
  47. for(i=0;i<x;i++)
  48. for(j=0;j<120;j++);
  49. }
  50. /**************************************************************
  51. 函数名称:void w_12864byte(uchar byte)
  52. 函数功能: 写字节
  53. **************************************************************/
  54. void w_12864byte(uchar byte)
  55. {
  56. uchar i;
  57. for(i=0;i<8;i++)
  58. {
  59. sck=0;
  60. byte<<=1;
  61. sid=CY;
  62. sck=1;
  63. }
  64. }
  65. /**************************************************************
  66. 函数名称:uchar r_12864byte(void)
  67. 函数功能: 读字节
  68. ***************************************************************/
  69. uchar r_12864byte(void)
  70. {
  71. uchar i,temp1,temp2;
  72. temp1 = 0;
  73. temp2 = 0;
  74. for(i=0;i<8;i++)
  75. {
  76. temp1=temp1<<1;
  77. sck = 0;
  78. sck = 1;
  79. sck = 0;
  80. if(sid) temp1++;
  81. }
  82. for(i=0;i<8;i++)
  83. {
  84. temp2=temp2<<1;
  85. sck = 0;
  86. sck = 1;
  87. sck = 0;
  88. if(sid) temp2++;
  89. }
  90. return ((0xf0&temp1)+(0x0f&temp2));
  91. }
  92. /**************************************************************
  93. 函数名称:void c_12864busy( void )
  94. 函数功能: 检测忙函数
  95. **************************************************************/
  96. void c_12864busy( void )
  97. {
  98. do
  99. w_12864byte(0xfc); //11111,RW(1),RS(0),0
  100. while(0x80&r_12864byte());
  101. }
  102. /**************************************************************
  103. 函数名称:void w_12864(bit dat_com,uchar byt)
  104. 函数功能: 写入函数
  105. ***************************************************************/
  106. void w_12864(bit dat_com,uchar byt)
  107. {
  108. uchar temp;
  109. if(dat_com==0) //为零,写入指令
  110. temp=0xf8; //11111,RS(0),RW(0),0
  111. else //否则,写入数据
  112. temp=0xfa; //11111,RS(1),RW(0),0
  113. cs=1;
  114. c_12864busy();
  115. w_12864byte(temp);
  116. w_12864byte(byt&0xf0); //写入高四位
  117. w_12864byte(byt<<4); //写入低四位
  118. cs=0;
  119. }
  120. /**************************************************************
  121. 函数名称:void init_12864(void)
  122. 函数功能:初始化12864
  123. ***************************************************************/
  124. void init_12864(void)
  125. {
  126. w_12864(com,0x30); //基本指令功能.
  127. w_12864(com,0x0c); //显示打开,关光标,反白关.
  128. w_12864(com,0x01); //清屏指令.
  129. w_12864(com,0x06); //AC自动加一
  130. }
  131. /*----------------以下为DS1302相关函数-------------------------*/
  132. /**************************************************************
  133. 函数名称:void w_1302byte(uchar date)
  134. 函数功能:写一个字节(上升沿)
  135. ***************************************************************/
  136. void w_1302byte(uchar date)
  137. { uchar i;
  138. datbyte=date;
  139. for(i=0;i<8;i++)
  140. { T_IO=datbyte0; //写最低位
  141. T_CLK=0;
  142. T_CLK=1;
  143. datbyte>>=1;
  144. }
  145. }
  146. /**************************************************************
  147. 函数名称:uchar r_1302byte(void)
  148. 函数功能:读一个字节(下降沿)
  149. ***************************************************************/
  150. uchar r_1302byte(void)
  151. { uchar i;
  152. datbyte=0;
  153. for(i=0;i<8;i++)
  154. { datbyte7=T_IO; //读最低位
  155. T_CLK=1;
  156. T_CLK=0;
  157. datbyte>>=1;
  158. }
  159. return(datbyte);
  160. }
  161. /***************************************************************
  162. 函数名称:void write_1302(uchar addr,uchar date)
  163. 函数功能: 指定位置写数据
  164. ****************************************************************/
  165. void write_1302(uchar addr,uchar date)
  166. { T_RST=0;
  167. T_CLK=0;
  168. T_RST=1;
  169. w_1302byte(addr);
  170. w_1302byte(date);
  171. T_CLK=0;
  172. T_RST=0;
  173. }
  174. /**************************************************************
  175. 函数名称:uchar read_1302(uchar addr)
  176. 函数功能: 指定位置读数据
  177. ****************************************************************/
  178. uchar read_1302(uchar addr)
  179. { uchar dat1,dat2,temp;
  180. T_RST=0;
  181. T_CLK=0;
  182. T_RST=1;
  183. w_1302byte(addr);
  184. temp=r_1302byte();
  185. T_RST=0;
  186. T_CLK=0;
  187. dat1=temp/16;
  188. dat2=temp%16;
  189. temp=dat1*10+dat2;
  190. return(temp);
  191. }
  192. /***************************************************************
  193. 函数名称:void init_1302(void)
  194. 函数功能: 初始化
  195. *****************************************************************/
  196. void init_1302(void)
  197. { uchar i;
  198. uchar addr=0x80;
  199. write_1302(0x8e,0x00);
  200. for(i=0;i<7;i++)
  201. {
  202. write_1302(addr,TAB_1302[i]);
  203. addr+=2;
  204. }
  205. write_1302(0x8e,0x80);
  206. }
  207. /****************************************************************
  208. 函数名称:void get_1302(void)
  209. 功能说明:读取DS1302时钟信息.
  210. *****************************************************************/
  211. void get_1302(void)
  212. { uchar i,addr=0x81;
  213. for(i=0;i<7;i++)
  214. { TAB_1302[i]=read_1302(addr);
  215. addr+=2;
  216. }
  217. }
  218. /*---------------以下为18B20相关函数-----------------------------*/
  219. /******************************************************************
  220. 函数名称:void delay (uint x)
  221. 功能说明:若机器周期为1us,则本延时程序为延时 4*x(us)
  222. ******************************************************************/
  223. void delay (uint x) //本板延时8us
  224. {
  225. while (--x);
  226. }

  227. /*****************************************************************
  228. 函数名称:uchar bus_rest(void)
  229. 功能说明:产生单总线系统信号的总线复位信号,并返回
  230. 总线上是否存在单总线器件信息
  231. ******************************************************************/
  232. uchar bus_rest(void)
  233. {
  234. uchar presence;
  235. DQ=0; //将DQ信号线拉低
  236. delay(29); //持续48US
  237. DQ=1; //释放总线
  238. delay(3); //等待从设备将总线拉低
  239. presence=DQ; //保存当前总线状态
  240. delay(25); //等待总线初始化过程结束
  241. return presence;//返回是否有从设备将总线拉低

  242. }

  243. /****************************************************************
  244. 函数名称:uchar r_1820BYTE(void)
  245. 功能说明:向单总线读取一个数据字节
  246. *****************************************************************/
  247. uchar r_1820BYTE(void)
  248. {
  249. uchar i=0;
  250. uchar date = 0;
  251. for (i=8;i>0;i--)
  252. {
  253. DQ = 0; // 将DQ信号线拉低启动读时隙
  254. DQ=1;// 释放总线,等待从机动车辆返回数据位
  255. delay(1); //越接近15us越好; 准备采样总线上的信号
  256. date>>=1 ;
  257. if (DQ)
  258. date=date|0x80;
  259. delay(6);
  260. }
  261. return(date);
  262. }

  263. /*****************************************************************
  264. 函数名称:void w_1280Byte(uchar bytevalue)
  265. 功能说明:向单总线写一个数据字节
  266. ******************************************************************/
  267. void w_1280Byte(uchar bytevalue)
  268. {
  269. uchar i;
  270. for(i=0;i<8;i++)
  271. {
  272. DQ=0; // 将DQ信号线拉低启动读时隙
  273. DQ=bytevalue&0x01; //
  274. delay(5);//等待写时隙结束
  275. DQ=1; //释放
  276. bytevalue>>=1;
  277. }
  278. delay(5); ////等待写时隙结束
  279. }
  280. /*****************************************************************
  281. 函数名称:uint read_T(void)
  282. 功能说明:读取1820温度
  283. *******************************************************************/
  284. uint read_T(void)
  285. {
  286. uchar a=0;
  287. uchar b=0;
  288. uint t=0;
  289. bus_rest();
  290. w_1280Byte(0xCC); // 跳过读序号列号的操作 ;
  291. w_1280Byte(0x44); // 启动温度转换,模数转化;
  292. bus_rest();
  293. w_1280Byte(0xCC); //跳过读序号列号的操作 ;
  294. w_1280Byte(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度 ;
  295. a=r_1820BYTE();// 低8位
  296. b=r_1820BYTE();// 高8位
  297. t=(b*256)+a;
  298. return(t);
  299. }
  300. /**************************************************************
  301. 函数名称:void show_T(uint temp)
  302. 函数功能:显示温度
  303. **************************************************************/
  304. void show_T(uint temp)
  305. {
  306. int i;
  307. float ftemp;
  308. ftemp = temp* 0.0625;
  309. sprintf(dis1,"%f",ftemp);//把温度值写入数组内存
  310. w_12864(com,0x98+3);
  311. for(i=0;i<5;i++)
  312. w_12864(dat,dis1[i]); //写入温度
  313. }
  314. /*---------------以下为显示相关函数--------------------------*/
  315. /******************************
  316. 函数名称: void fenli(uchar x,uchar y,uchar val)
  317. 功能描述: 指定位置写入数据
  318. ********************************/
  319. void fenli(uchar x,uchar y,uchar val)
  320. { uchar ge,shi,addr,i=0;
  321. if(val==5)//这里把星期数字显示的转换为中文
  322. {
  323. w_12864(com,0x88+2);
  324. for(i=0;i<2;i++)
  325. { //一个汉字写两次
  326. if(TAB_1302[5]==0)w_12864(dat,TAB_XQ[i]);
  327. if(TAB_1302[5]==1)w_12864(dat,TAB_XQ[2+i]); //
  328. if(TAB_1302[5]==2)w_12864(dat,TAB_XQ[3+i]); //!!??星期三显示没规律,不知咋回事.
  329. if(TAB_1302[5]==3)w_12864(dat,TAB_XQ[5+i]);
  330. if(TAB_1302[5]==4)w_12864(dat,TAB_XQ[7+i]);
  331. if(TAB_1302[5]==5)w_12864(dat,TAB_XQ[9+i]);
  332. if(TAB_1302[5]==6)w_12864(dat,TAB_XQ[11+i]);
  333. }
  334. }
  335. else
  336. {
  337. shi=TAB_1302[val]/10;//分离十位
  338. ge=TAB_1302[val]%10;
  339. if(x==1)x=0x80;
  340. if(x==2)x=0x90;
  341. if(x==3)x=0x88;
  342. if(x==4)x=0x98;
  343. addr=x+y;
  344. w_12864(com,addr);//指定位置
  345. w_12864(dat,0x30+shi);//写入
  346. w_12864(dat,0x30+ge);
  347. }
  348. }
  349. /*************************************************************
  350. 函数名称:void display(void)
  351. 功能描述: 显示函数
  352. **************************************************************/
  353. void display(void)
  354. { get_1302(); //读1302
  355. fenli(3,7,0); //读秒
  356. fenli(3,5,1); //读分
  357. fenli(3,3,2); //读时
  358. fenli(2,5,3); //读日
  359. fenli(2,3,4); //读月
  360. fenli(3,2,5); //读星期
  361. fenli(2,1,6); //读年
  362. }
  363. /*---------------按键处理相关函数--------------------------*/
  364. /************************************************************
  365. 函数名称:void scanner()
  366. 功能描述: 按键函数
  367. *************************************************************/
  368. void scanner()
  369. { uchar i,j;
  370. if(!key) //功能键按下
  371. { delay1ms(500); //延时500MS
  372. if(!key) //还按下,退出时间调整
  373. { keyflag=0; //标志位为0
  374. sum=0; //清0
  375. w_12864(com,0x0c);//清闪烁
  376. for(i=0;i<7;i++)//十进制转十六进制
  377. { j=TAB_1302[i]/10;
  378. TAB_1302[i]=TAB_1302[i]%10;
  379. TAB_1302[i]=TAB_1302[i]+16*j;
  380. }
  381. init_1302(); //写入1302
  382. while(!key); //等待释放
  383. delay1ms(10); //延时消抖
  384. }
  385. else //500MS内放开
  386. { keyflag=1; //标志为1,进行时间调整
  387. sum++; //功能键加1
  388. if(sum==8)
  389. sum=0;
  390. switch(sum)
  391. { case 1: //
  392. { w_12864(com,0x98+7);
  393. w_12864(com,0x0f);
  394. break;
  395. }
  396. case 2: //为2,年闪烁
  397. w_12864(com,0x90+1);
  398. break;
  399. case 3: //月闪烁
  400. w_12864(com,0x90+3);
  401. break;
  402. case 4: //日闪烁
  403. w_12864(com,0x90+5);
  404. break;
  405. case 5: //星期闪烁
  406. w_12864(com,0x88+2);
  407. break;
  408. case 6: //分闪烁
  409. w_12864(com,0x88+5);
  410. break;
  411. case 7: //时闪烁
  412. w_12864(com,0x88+3);
  413. break;
  414. }
  415. }
  416. }
  417. if(sum) //功能键按下
  418. {
  419. if(!key1)
  420. { delay1ms(10);
  421. if(!key1)
  422. { while(!key1);//等待加1键释放
  423. delay1ms(10);
  424. if(sum==1)
  425. { //备用
  426. }
  427. if(sum==2)
  428. { TAB_1302[6]++;
  429. if(TAB_1302[6]==100)
  430. TAB_1302[6]=0;
  431. fenli(2,1,6);
  432. w_12864(com,0x90+1);//闪烁归位
  433. }
  434. if(sum==3)
  435. { TAB_1302[4]++;
  436. if(TAB_1302[4]==13)
  437. TAB_1302[4]=1;
  438. fenli(2,3,4);
  439. w_12864(com,0x90+3);
  440. }
  441. if(sum==4)
  442. { TAB_1302[3]++;
  443. if(TAB_1302[3]==32)
  444. TAB_1302[3]=1;
  445. fenli(2,5,3);
  446. w_12864(com,0x90+5);
  447. }
  448. if(sum==5)
  449. { TAB_1302[5]++;
  450. if(TAB_1302[5]==7)
  451. TAB_1302[5]=0;
  452. fenli(3,2,5);
  453. w_12864(com,0x88+2);
  454. }
  455. if(sum==6)
  456. { TAB_1302[1]++;
  457. if(TAB_1302[1]==60)
  458. TAB_1302[1]=0;
  459. fenli(3,5,1);
  460. w_12864(com,0x88+5);
  461. }
  462. if(sum==7)
  463. { TAB_1302[2]++;
  464. if(TAB_1302[2]==24)
  465. TAB_1302[2]=0;
  466. fenli(3,3,2);
  467. w_12864(com,0x88+3);
  468. }
  469. }
  470. }

  471. }
  472. }
  473. //=============================================================
  474. void init(void)
  475. {
  476. uchar i;
  477. init_12864();
  478. init_1302();
  479. while(TAB1[i]!='\0')
  480. {
  481. w_12864(dat,TAB1[i]);
  482. i++;
  483. }
  484. i=0;
  485. w_12864(com,0x90);
  486. while(TAB2[i]!='\0')
  487. {
  488. w_12864(dat,TAB2[i]);
  489. i++;
  490. }
  491. i=0;
  492. w_12864(com,0x88);
  493. while(TAB3[i]!='\0')
  494. {
  495. w_12864(dat,TAB3[i]);
  496. i++;
  497. }
  498. i=0;
  499. w_12864(com,0x98);
  500. while(TAB4[i]!='\0')
  501. {
  502. w_12864(dat,TAB4[i]);
  503. i++;
  504. }
  505. }
  506. /*************************************************************
  507. 函数名称:主函数
  508. 函数功能:
  509. **************************************************************/
  510. main()
  511. {
  512. init();
  513. while(1)
  514. {
  515. scanner(); //检测键盘
  516. if(!keyflag) //标志为0
  517. { display(); //调用显示
  518. show_T(read_T()); //显示温度
  519. delay1ms(500);
  520. }
  521. }
  522. }
复制代码




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

使用道具 举报

沙发
ID:112242 发表于 2017-8-10 21:15 | 只看该作者
收藏了 谢谢LZ的分享
回复

使用道具 举报

板凳
ID:212052 发表于 2017-8-11 12:54 | 只看该作者
详细的代码。太有参考价值了。
回复

使用道具 举报

地板
ID:276685 发表于 2018-1-16 18:00 | 只看该作者
不错,谢谢分享
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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