STC芯 发表于 2024-3-20 14:32:57

OLED12864+DS3231的万年历制作,带农历,大字体(单片机源码+实物)

最近逛论坛,看到有做OLED 屏幕显示的万年历,但都没有把农历加进去;我这个把农历加上了,时分秒大字体显示;温度是读的DS3231的温度显示出来的;OLED12864和DS3231时钟芯片都是IIC通信的,共用时钟线和数据线,接线简单;4个按键(设置,+,-,退出),校时的时候,按设置键,相应的位会闪烁,再按+-调整,设置键按到第8次就退出设置,设置的位较多,中途按退出键也可以退出设置。单片机:用12T,或1T的都可以,我用的STC12C5A60S2,1T刷新快些;DS3231是买的模块;OLED是0.96寸黄蓝双色的,实物比照片好看,就是太小了,{:smile:}{:smile:}
附件里有完整的源代码。

制作出来的实物图如下:




部分源代码:


[*]#include "reg51.h"
[*]#include "intrins.h"
[*]#include "codetab.h"
[*]#include "nongli.h"
[*]
[*]
[*]#define uintunsigned int
[*]#define uchar unsigned char
[*]
[*]// ------------------------------------------------------------
[*]// IO口模拟I2C通信
[*]
[*]// ------------------------------------------------------------
[*]sbit SCL=P3^6; //串行时钟
[*]sbit SDA=P3^7; //串行数据
[*]
[*]sbit KEY1=P3^0;                  //调整
[*]sbit KEY2=P3^1;                  //++
[*]sbit KEY3=P3^2;                  //--
[*]sbit KEY4=P3^3;                  //退出
[*]
[*]uchara1,a2,a3,a4;                      //按键消抖用
[*]uchardisflag=0; //时间调整相关
[*]
[*]
[*]
[*]#define      Brightness      0xcf //
[*]#define X_WIDTH         128
[*]#define Y_WIDTH         64
[*]
[*]/********************************************************************************************************
[*]**         DS3231常数定义
[*]********************************************************************************************************/
[*]#define DS3231_WriteAddress 0xD0    //器件写地址
[*]#define DS3231_ReadAddress0xD1    //器件读地址
[*]#define DS3231_SECOND       0x00    //秒
[*]#define DS3231_MINUTE       0x01    //分
[*]#define DS3231_HOUR         0x02    //时
[*]#define DS3231_WEEK         0x03    //星期
[*]#define DS3231_DAY          0x04    //日
[*]#define DS3231_MONTH      0x05    //月
[*]#define DS3231_YEAR         0x06    //年
[*]
[*]#define DS3231_TEMPERATUREH 0x11    //温度寄存器高字节(8位)      整数部分
[*]#define DS3231_TEMPERATUREL 0x12    //温度寄存器低字节(低2位) 小数部分
[*]
[*]
[*]
[*]#define NACK    1
[*]#define ACK   0
[*]
[*]uchar shan_count; //:号闪烁计时变量
[*]uchar shan_js;    //校时闪烁计时变量
[*]bit flag;                //校时闪烁标志
[*]char hour,minute,second,year,month,day,date,week;
[*]uint TH3231;
[*]bit      ack;                //应答标志位
[*]/*********************OLED驱动程序用的延时程序************************************/
[*]/*void delay(unsigned int z)
[*]{
[*]      unsigned int x,y;
[*]      for(x=z;x>0;x--)
[*]                for(y=1100;y>0;y--);
[*]}      */
[*]void      Delay5US()         //@12.000MHz         延时5us
[*]{
[*]   _nop_(); _nop_();      _nop_();_nop_(); //1T单片机用4个nop,12T用1个nop
[*]}
[*]
[*]
[*]/**************************/
[*]void Timer0Init(void)                //10毫秒@11.0592MHz
[*]{
[*]//      AUXR &= 0x7F;                //定时器时钟12T模式
[*]      TMOD &= 0xF0;                //设置定时器模式
[*]      TMOD |= 0x01;                //设置定时器0,16位模式
[*]      TL0 = 0x00;                //设置定时初值
[*]      TH0 = 0xDC;                //设置定时初值
[*]      TF0 = 0;                //清除TF0标志
[*]      TR0 = 1;                //定时器0开始计时
[*]      ET0 = 1;
[*]      EA = 1;
[*]}
[*]
[*]/**********************************************
[*]//IIC Start
[*]**********************************************/
[*]void IIC_Start()
[*]{
[*]   SCL = 1;
[*]   SDA = 1;
[*]   SDA = 0;
[*]   SCL = 0;
[*]}
[*]
[*]/**********************************************
[*]//IIC Stop
[*]**********************************************/
[*]void IIC_Stop()
[*]{
[*]   SCL = 0;
[*]   SDA = 0;
[*]   SCL = 1;
[*]   SDA = 1;
[*]}
[*]
[*]
[*]/********************************************************************************************************
[*]**         3231
[*]********************************************************************************************************/
[*]
[*]
[*]uchar      BCD2HEX(uchar val)
[*]{
[*]      return      ((val>>4)*10)+(val&0x0f);
[*]}
[*]
[*]uchar      HEX2BCD(uchar val)
[*]{
[*]      return      (((val%100)/10)<<4)|(val%10);
[*]}
[*]
[*]
[*]void SendByte(uchar c)
[*]{
[*]    uchar BitCnt;
[*]
[*]    for(BitCnt=0;BitCnt<8;BitCnt++)         //要传送的数据长度为8位
[*]    {
[*]      if((c<<BitCnt)&0x80)
[*]            SDA=1;                        //判断发送位
[*]      else
[*]            SDA=0;
[*]      SCL=1;                            //置时钟线为高,通知被控器开始接收数据位
[*]      Delay5US();                     //保证时钟高电平周期大于4μs
[*]      SCL=0;
[*]    }
[*]    SDA=1;                                  //8位发送完后释放数据线,准备接收应答位
[*]    SCL=1;
[*]    Delay5US();
[*]    if(SDA==1)
[*]      ack=0;
[*]    else
[*]      ack=1;                              //判断是否接收到应答信号
[*]    SCL=0;
[*]    Delay5US();
[*]}
[*]
[*]uchar RcvByte()
[*]{
[*]   uchar retc;
[*]   uchar BitCnt;
[*]
[*]   retc=0;
[*]   SDA=1;                           //置数据线为输入方式
[*]   for(BitCnt=0;BitCnt<8;BitCnt++)
[*]   {
[*]      SCL=0;                      //置时钟线为低,准备接收数据位
[*]      Delay5US();               //时钟低电平周期大于4.7μs
[*]      SCL=1;                      //置时钟线为高使数据线上数据有效
[*]      Delay5US();
[*]      retc=retc<<1;
[*]      if(SDA==1)
[*]            retc=retc+1;            //读数据位,接收的数据位放入retc中
[*]      Delay5US();
[*]   }
[*]   SCL=0;
[*]   return(retc);
[*]}
[*]
[*]void Ack_I2C(bit a)
[*]{
[*]      SDA      =      a;
[*]    SCL=1;
[*]    Delay5US();             //时钟低电平周期大于4us
[*]    SCL=0;                  //清时钟线,钳住I2C总线以便继续接收
[*]    Delay5US();
[*]}
[*]
[*]uchar write_byte(uchar addr, uchar write_data)
[*]{
[*]    IIC_Start();
[*]    SendByte(DS3231_WriteAddress);
[*]    if (ack == 0)
[*]      return 0;
[*]
[*]    SendByte(addr);
[*]    if (ack == 0)
[*]      return 0;
[*]
[*]    SendByte(write_data);
[*]    if (ack == 0)
[*]      return 0;
[*]
[*]    IIC_Stop();
[*]    Delay5US();
[*]    Delay5US();
[*]    return 1;
[*]}
[*]
[*]uchar read_current()
[*]{
[*]    uchar read_data;
[*]    IIC_Start();
[*]    SendByte(DS3231_ReadAddress);
[*]    if(ack==0)
[*]      return(0);
[*]    read_data = RcvByte();
[*]    Ack_I2C(1);
[*]    IIC_Stop();
[*]    return read_data;
[*]}
[*]
[*]uchar read_random(uchar random_addr)
[*]{
[*]    uchar Tmp;
[*]      IIC_Start();
[*]    SendByte(DS3231_WriteAddress);
[*]    if(ack==0)
[*]      return(0);
[*]    SendByte(random_addr);
[*]    if(ack==0)
[*]      return(0);
[*]      Tmp=read_current();
[*]      if(random_addr==DS3231_HOUR)
[*]                Tmp&=0x3f;
[*]
[*]    return(BCD2HEX(Tmp));//都转10进制输出
[*]}
[*]
[*]/***********************/
[*]uchar read_random1(uchar random_addr)//这个是读温度函数
[*]{
[*]    uchar Tmp;
[*]      write_byte(0x0e,0x20);//0x0e寄存器的CONV位置1开启温度转换,要这句,温度实时刷新,这句不要,温度要64s才刷新1次
[*]      IIC_Start();
[*]    SendByte(DS3231_WriteAddress);
[*]    if(ack==0)
[*]      return(0);
[*]    SendByte(random_addr);
[*]    if(ack==0)
[*]      return(0);
[*]      Tmp=read_current();
[*]      return Tmp;
[*]}
[*]
[*]void ModifyTime(uchar address,uchar num)
[*]{
[*]    uchar temp=0;
[*]         if(address>6 && address <0) return;
[*]    temp=HEX2BCD(num);
[*]      write_byte(address,temp);
[*]}




代码:

soma 发表于 2024-3-20 15:37:41

手上刚好有片STC12C5A60S2,可以玩下

wan123456 发表于 2024-3-20 16:36:38

感觉有点像论坛里的一个作品…

lezjin 发表于 2024-3-20 17:12:51

谢谢分享

xxxevery 发表于 2024-3-21 16:12:12

有空可以做一下

soma 发表于 2024-3-21 18:07:40


这段关于2月的判断不对吧

yjawei 发表于 2024-3-22 23:52:40

soma 发表于 2024-3-21 18:07
这段关于2月的判断不对吧

芯片里面有万年历,

小涵子爸爸 发表于 2024-4-2 08:31:47

学习一下

dou 发表于 2024-5-9 23:57:42

屏幕有点小啊 谢谢分享

Yim_Hom 发表于 2024-5-11 21:08:01

{:4_250:}
页: [1] 2
查看完整版本: OLED12864+DS3231的万年历制作,带农历,大字体(单片机源码+实物)