找回密码
 立即注册

QQ登录

只需一步,快速开始

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

用无字库12864改的大屏万年历(带农历,年属性,温度)用单片机定时器

  [复制链接]
跳转到指定楼层
楼主
用单片机定时器本人是一名电子爱好者,用业余时间自学的单片机,原来只是想玩玩而已,不过现在才发现自己不知不觉已深陷其中,不能自拔,大家是否有同感?
       在网上买的几块钱的3.8寸12864液晶屏,不带字库




用3D打印的外壳,元件不多,没用PCB直接焊接,单片机被我搞成这样


完成后的成品前面


背面


运行效果



https://v.youku.com/v_show/id_XNDQ3ODM1MTA0NA==.html?spm=a2h0k.11417342.soresults.dposter
程序自己加了些注释,水平有限,应该有不少错误,希望大家能够多多指教。
代码:

主程序:
/******************************************************************************
Copyright 2007
All rights reserved.

文件名        :12864.c
模块名称:
功能概要:C51写的公历转农历,并驱动12864(KS0108)汉字液晶显示。

取代版本:0.0.1
修改人        :pulan
完成日期:2007.07.08
升级说明:create
CPU: stc89c58   主频:11.0592M
液晶型号:       生产厂家:        驱动芯片:KS0108
硬件连接:
---------------------------------------------------------------
|DB0-----P0.0 | DB4-----P0.4 | RW-------P2.2 |
|DB1-----P0.1 | DB5-----P0.5 | RS-------P2.1 |
|DB2-----P0.2 | DB6-----P0.6 | E -------P2.5 |
|DB3-----P0.3 | DB7-----P0.7 | Vo接1k电阻到地
---------------------------------------------------------------
******************************************************************************/
#include <reg52.h>
#include <intrins.h>
#include <stdio.h>
#include "shijian.c"
void main(void)
{
  initial();

  while(1)
  {
    read_temp();
        ds1820disp();
        verify_time();                              //确认时间正确性
        key();
        if(setflag==0)
    disp_time();                                //这里调用显示时间程序
  }
}


显示驱动
/******************************************************************************
Copyright 2007
All rights reserved.

文件名        :12864.c
模块名称:
功能概要:C51写的公历转农历,并驱动12864(KS0108)汉字液晶显示。

取代版本:0.0.1
修改人        :pulan
完成日期:2007.07.08
升级说明:create
CPU: stc89c58   主频:11.0592M
液晶型号:       生产厂家:        驱动芯片:KS0108
硬件连接:
---------------------------------------------------------------
|DB0-----P0.0 | DB4-----P0.4 | RW-------P2.2 |
|DB1-----P0.1 | DB5-----P0.5 | RS-------P2.1 |
|DB2-----P0.2 | DB6-----P0.6 | E -------P2.5 |
|DB3-----P0.3 | DB7-----P0.7 | Vo接1k电阻到地
---------------------------------------------------------------
******************************************************************************/
#define uchar unsigned char
sbit LCD_csa=P2^7;                   //定义左屏开关
sbit LCD_csb=P2^6;                   //定义右屏开关
sbit LCD_rs =P2^5;                   //定义数据或指令,1=数据,0=指令
sbit LCD_rw =P2^4;                   //定义读或写?    1=读,  0=写   
sbit LCD_e  =P2^3;                   //定义使能操作, 1=能,  0=否
//sbit LCD_rst = P2^0;               //定义复位
sfr  LCD_db=0x80;                    //定义数据端口  
/******************************************************************************************
* 函数名称    :lcd_busy
* 功能描述    :判别LCD12864忙否?不忙才跳出此程序
* 参数        :  参数名称:        输入/输出?        类型                描述
*
* 返回值      :
* 作者        :
* 创建日期    :2006-12-19
* 全局变量    :
* 全局静态变量:
* 局部静态变量:
*----------------------------------------修改历史------------------------------------------
* 当前版本    :                          修改人:                  修改日期:
* 修改说明    :
******************************************************************************************/
void lcd_busy(void)
{
  LCD_rs=0;
  LCD_rw=1;
  LCD_db=0xff;
  while (1)
  {
    LCD_e=1;
    if (LCD_db<0x80)                        //如果要进行简单的软件调试,可在这句前面加"//"跳过
    break;
    LCD_e=0;
  }
  LCD_e=0;
}

/******************************************************************************************
* 函数名称    :set_xy
* 功能描述    :设置显示位置! X,Y分别代表横纵坐标!
* 参数        :  参数名称:        输入/输出?        类型                描述
******************************************************************************************/
void set_xy(unsigned char x,unsigned char y)
{
  if (x>=64)   {LCD_csa=0;LCD_csb=1;}
  else         {LCD_csa=1;LCD_csb=0;}       //判别是左半屏,还是右半屏
  lcd_busy();
  LCD_rs=LCD_rw=0;
  LCD_db=0x40|x;                            //列地址赋值,x取值0----64
  LCD_e=1;LCD_e=0;
  lcd_busy();
  LCD_rs=LCD_rw=0;
  LCD_db=0xb8|y;                            //页面地址赋值,y取值0----8
  LCD_e=1;LCD_e=0;
  LCD_db=0xff;
}

/******************************************************************************************
* 函数名称    :lw
* 功能描述    :在指定的位置显示数据
* 参数        :  参数名称:        输入/输出?        类型                描述
******************************************************************************************/
void lw(uchar x,uchar y,uchar dd)
{
  set_xy(x,y);
  lcd_busy();
  LCD_rs=1;
  LCD_rw=0;
  LCD_db=dd;                                //数据送显
  LCD_e=1;
  LCD_e=0;
  LCD_db=0xff;
}

/******************************************************************************************
* 函数名称    :lcd_init
* 功能描述    :显示初始化
* 参数        :  参数名称:        输入/输出?        类型                描述
******************************************************************************************/
#pragma disable
void lcd_init(void)
{
  unsigned char x,y;
  /*开显示*/
//   LCD_rst=0;
//         Delay12864(100);
//         LCD_rst=1;
//         Delay12864(100);
  LCD_e=LCD_rs=LCD_rw=0;
  LCD_csa=LCD_csb=0;
  LCD_csa=1;                                //选择左半屏显示
  LCD_db=0x3f;                              //打开左半屏显示
  LCD_e=1;LCD_e=0;LCD_csa=0;
  LCD_csb=1;                                //选择右半屏显示
  LCD_db=0x3f;                              //打开右半屏显示
  LCD_e=1;LCD_e=0;LCD_csb=0;
  /*0行开始显示*/
  LCD_csa=1;lcd_busy();
  LCD_rs=LCD_rw=0;LCD_db=0xc0;              //设置左半屏起始行,是第一行
  LCD_e=1;LCD_e=0;LCD_csa=0;
  LCD_csb=1;lcd_busy();
  LCD_rs=LCD_rw=0;LCD_db=0xc0;              //设置右半屏起始行,是第一行
  LCD_e=1;LCD_e=0;LCD_csb=0;
  for (y=0;y<8;y++)
  {
    for (x=0;x<128;x++) lw(x,y,0);          //全屏清零显示
  }
}


按键程序:
#include<reg52.h>
#include<delayms.h>
#include"xs.c"

sbit  set =P3^7;                //设置
sbit  key1=P3^6;                //加           
sbit  key2=P3^5;                           //减
sbit  key3=P3^4;                        //蜂鸣开关
sbit  key4=P3^3;                        //背光开关

uchar setflag=0;                       //按键计数
sbit  bl=P2^0;                                //背光控制端
sbit  bz=P2^1;                                //蜂鸣控制端

void key()                                                //按键程序
{                                                                        
  if(set==0)                                        //如果设置键按下
  {
        delayms(5);                                        //延时消抖
        if(set==0)                                        //再次确认设置键按下
        {
          setflag++;                                //按键计数加1
          while(!set);                                //等待按键松开
          switch(setflag)
          {
                case 1:// TR0=0;                                          //定时器0关闭
                dashuzi(4,2,10,0);                //显示时与分中间的冒号
                    dashuzi(10,2,10,0);     //显示分与秒中间的冒号
                dispmiao(sec,1);                //秒反显
                            break;
            case 2: dispmiao(sec,0);                //秒正显
                        dispfen(min,1);                        //分反显
                    break;
            case 3: dispfen(min,0);                        //分正显
                        dispshi(hour,1);//                //时反显
                            break;
                case 4: dispshi(hour,0);                //时正显
                        dispri(day,1);                         //日反显
                                break;
                case 5: dispri(day,0);                        //日正显
                        dispyue(month,1);                //月反显
                                break;
                case 6: dispyue(month,0);                //月正显
                        dispnian(year,1);       //年反显
                                break;
                case 7:        setflag=0;                                //按键计数变为0
                        dispnian(year,0);                //年正显
                   // TR0=1;                                        //定时器0启动
                                break;
                default:;
          }
    }
  }
  if(setflag!=0)                                        //如果按键计数不为0
  {
        if(key1==0)                                                //如果加键按下
        {
          delayms(5);                                            //延时消抖
          if(key1==0)                                          //再次确认加键按下
          {
                while(!key1);                                //等待加键松开
                switch(setflag)
                {
                  case 1:// sec++;                                //秒加1
                         // if(sec==60)
                                  sec=0;        //如果秒加到60,秒归0
                          dispmiao(sec,1);                //调用秒反显
                                  break;
                  case 2: min++;                                //分加1
                          if(min==60) min=0;        //如果分加到60,分归0
                          dispfen(min,1);            //调用分反显
                                  break;
                  case 3: hour++;                                //小时加1
                          if(hour==24) hour=0;        //如果小时加到24,小时归0
                          dispshi(hour,1);                //调用小时反显
                                  break;
                  case 4: day++;                                //日加1
                          if(day==32) day=1;         //如果日加到32,日变为1
                          dispri(day,1);                //调用日反显
                                  break;
                  case 5: month++;                                //月加1
                          if(month==13)        month=1;//如果月加到13
                          dispyue(month,1);                //调用月反显
                                  break;
                  case 6: year++;                                //年加1
                          if(year==100)        year=0;        //如果年加到100,年归0
                          dispnian(year,1);                //调用年反显
                                  break;
                  default:;
                }
      }
    }
        if(key2==0)                                                        //如果减键按下
        {
          delayms(5);                                                        //延时消抖
          if(key2==0)                                                //再次确认减键按下
          {
                while(!key2) ;                                        //等待减键松开
            switch(setflag)
            {
              case 1:// sec--;                                //秒减1
                         // if(sec<0)        
                                  sec=0;//59;            //如果秒小于0,秒变为59
                          dispmiao(sec,1);                //调用秒反显
                                  break;
                  case 2: min--;                                //分减1
                          if(min<0)        min=59;            //如果分小于0,分变为59
                          dispfen(min,1);                //调用分反显
                                    break;
                  case 3: hour--;                                //小时减1
                          if(hour<0) hour=23;        //如果小时小于0,小时变为23
                          dispshi(hour,1);                //调用小时反显
                                    break;
                  case 4: day--;                                //日减1
                          if(day==0) day=31;        //如果日减到0,日变为31
                          dispri(day,1);                //调用日反显
                                  break;
                  case 5: month--;                                //月减1
                          if(month==0) month=12;//如果月减到0,月变为12
                          dispyue(month,1);                //调用月反显
                                  break;
                  case 6: year--;                                //年减1
                          if(year<0) year=99;        //如果年小于0,年变为99
                          dispnian(year,1);                //
                                  break;
                  default:;
            }
          }
    }
  }  
  if(setflag==0&&key3==0)                                //走时状态且蜂鸣开关按下时
  {
    delayms(5);                                                        //延时消抖
        if(setflag==0&&key3==0)                                //再次确认走时状态且蜂鸣开关按下时
        {
          while(!key3);                                                //等待蜂鸣开关松开
          bz=~bz;                                                        //蜂鸣输出取反
        }
  }                                                                                
  if(setflag==0&&key4==0)                                //走时状态且背光开关按下时
  {
    delayms(5);                                                        //延时消抖
        if(setflag==0&&key4==0)                                //再次确认走时状态且背光开关按下时
        {
          while(!key4);                                                //等待背光开关松开
          bl=~bl;                                                        //背光输出取反
        }
  }
}
下面是完整程序和仿真:

★★3-带农历万年历.zip (118.95 KB, 下载次数: 243)

随后再加上闹钟和整点报时。

评分

参与人数 3黑币 +80 收起 理由
lyxxzrb + 15
1339337425 + 15 很给力!
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

来自 2#
ID:333678 发表于 2020-1-2 13:35 | 只看该作者
用前面发的程序在修改日期时,发现农历月份显示不正常,仔细察看显示程序xianshi.c有个地方写错了,现把更正后的程序发上来,并修改了字库,使农历1月显示为正月。

★★3-带农历万年历.zip

119.78 KB, 下载次数: 172, 下载积分: 黑币 -5

回复

使用道具 举报

板凳
ID:333678 发表于 2019-12-22 10:44 | 只看该作者
第一次在论坛上发这么长的贴子,没编辑好。最后多了几张图片。
回复

使用道具 举报

地板
ID:475247 发表于 2019-12-22 14:50 | 只看该作者
cb474265474265 发表于 2019-12-22 10:44
第一次在论坛上发这么长的贴子,没编辑好。最后多了几张图片。

还不错,加油!
回复

使用道具 举报

5#
ID:333678 发表于 2019-12-22 14:57 | 只看该作者
多谢版主奖励!
回复

使用道具 举报

6#
ID:32289 发表于 2019-12-22 20:30 | 只看该作者
电路板创意不错!
回复

使用道具 举报

7#
ID:207882 发表于 2019-12-22 22:24 | 只看该作者
建议按键不要做死等,按键的检测用中断处理,纯娱乐还行,但从产品的角度是不行,你按键按死不松开,程序就死在哪里了,这些显示也会不正常了,假如按键坏了刚好处于闭合作态,你这个东西不就废了,连玩都不能玩。
回复

使用道具 举报

8#
ID:333678 发表于 2019-12-23 05:17 | 只看该作者
2448289424 发表于 2019-12-22 22:24
建议按键不要做死等,按键的检测用中断处理,纯娱乐还行,但从产品的角度是不行,你按键按死不松开,程序就 ...

谢谢你的提醒,确实是这样,以后我会尽力改进的。
回复

使用道具 举报

9#
ID:58110 发表于 2019-12-23 08:22 | 只看该作者
谢谢分享
第一次见这种单片机
回复

使用道具 举报

10#
ID:333678 发表于 2019-12-26 07:26 来自手机 | 只看该作者
lyMarvin 发表于 2019-12-23 08:22
谢谢分享
第一次见这种单片机

没用PCB,一个是没几个元件,二是为了减小整体厚度,另外我还在里面加了充电电池。用电池有个缺陷是没电了屏不显示,时钟也不走了,还要重新调时,用时钟芯片可解决这问题,但电路又多了元件,走时也不太准,有点纠结。我想是不是可以加上自动充电电路和程序?
回复

使用道具 举报

11#
ID:760161 发表于 2020-6-11 23:03 来自手机 | 只看该作者
这个程序为什么在编译的时候会出错,说delayms    missing function-prototype
回复

使用道具 举报

12#
ID:760161 发表于 2020-6-11 23:04 来自手机 | 只看该作者
这个程序为什么在编译的时候会出错,说delayms    missing function-prototype      而且如果自己添加了delayms.h文件之后,仿真点一下设置就停止不动了再点哪个按键都没反应是怎么回事
回复

使用道具 举报

13#
ID:88256 发表于 2020-6-13 00:29 | 只看该作者
感觉布局有点太规矩了点
回复

使用道具 举报

14#
ID:787528 发表于 2020-6-27 19:29 | 只看该作者
会有proteus仿真吗?
回复

使用道具 举报

15#
ID:529213 发表于 2020-8-3 16:49 来自手机 | 只看该作者
请问屏在哪里买的,能给个链接吗,非常想做一个,谢谢楼主
回复

使用道具 举报

16#
ID:246635 发表于 2020-9-4 18:03 | 只看该作者
cb474265474265 发表于 2020-1-2 13:35
用前面发的程序在修改日期时,发现农历月份显示不正常,仔细察看显示程序xianshi.c有个地方写错了,现把更 ...

做得不错,感谢分享
回复

使用道具 举报

17#
ID:333678 发表于 2020-9-20 18:48 | 只看该作者
hnxtlxx 发表于 2020-8-3 16:49
请问屏在哪里买的,能给个链接吗,非常想做一个,谢谢楼主

隔壁论坛老王电子数码DIY  shop154838422点taobao点com
在这里抢购的,现在没有了,但有别的型号,只要工作电压和驱动芯片一样,都可以,差不多的。
回复

使用道具 举报

18#
ID:125719 发表于 2020-9-23 09:38 | 只看该作者
这个很厉害了,使用元器件很简单,而且是全部捡漏利用,打印的外壳也不错,
回复

使用道具 举报

19#
ID:529213 发表于 2021-1-9 00:38 来自手机 | 只看该作者
cb474265474265 发表于 2020-9-20 18:48
隔壁论坛老王电子数码DIY  shop154838422点taobao点com
在这里抢购的,现在没有了,但有别的型号,只要 ...

谢谢大佬,非常感谢
回复

使用道具 举报

20#
ID:98875 发表于 2021-1-17 12:33 | 只看该作者
对比度没有调节好,图片显示有“”鬼影“
回复

使用道具 举报

21#
ID:333678 发表于 2021-1-18 08:24 来自手机 | 只看该作者
dajingjiu 发表于 2021-1-17 12:33
对比度没有调节好,图片显示有“”鬼影“

背光打开时,显示有的地方不均匀,关了背光后效果好些,不知道是不是液晶屏自身原因。另外感觉这个屏的反应有点慢。
回复

使用道具 举报

22#
ID:879141 发表于 2021-1-20 23:48 来自手机 | 只看该作者
外觀不錯!
回复

使用道具 举报

23#
ID:765218 发表于 2021-1-29 15:04 | 只看该作者
挺nice
回复

使用道具 举报

24#
ID:765218 发表于 2021-1-29 18:33 | 只看该作者
橙七 发表于 2020-6-11 23:03
这个程序为什么在编译的时候会出错,说delayms    missing function-prototype

刚开始我也和你一样 后面在keil工程下那些.c  .h 文件要包含在12864.c下面 就行了
回复

使用道具 举报

25#
ID:529213 发表于 2021-6-10 14:25 来自手机 | 只看该作者
这个万年历的字体是我见过的12864万年历中,最漂亮的,要是能够把时钟芯片ds3231加入就更完美了
回复

使用道具 举报

26#
ID:74784 发表于 2021-6-11 17:01 | 只看该作者
我也整过:




回复

使用道具 举报

27#
ID:529213 发表于 2021-7-12 00:20 来自手机 | 只看该作者
楼主什么时候改成用ds3231做定时器的,肯定会成为大作,楼主,加油,改动一下,造福坛友
回复

使用道具 举报

28#
ID:243267 发表于 2021-8-15 21:54 来自手机 | 只看该作者
谢谢分享!我正想做一个练练手,苦于没有范例参考
回复

使用道具 举报

29#
ID:333678 发表于 2021-12-25 15:06 来自手机 | 只看该作者
dajingjiu 发表于 2021-1-17 12:33
对比度没有调节好,图片显示有“”鬼影“

用电脑USB供电电流小,电压下降,改用单独电源供电就好了。
回复

使用道具 举报

30#
ID:673920 发表于 2022-4-21 18:28 | 只看该作者
把I/O口改了一下,就成了。谢谢!!      
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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