自制电子时钟–总结

源代码https://gitee.com/kiloGrand/electronic-clock

使用到的模块及其功能:

  • DS1302:低功耗实时时钟芯片,它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿等多种功能。
  • LCD1602:用来显示字母、数字、符号等的点阵型液晶模块,能够同时显示16x02即32个字符。
  • 按键k1,k2,k3,k4:
    k1:切换模式,比如工作模式、计时模式、设置模式。
    k2:设置模式: plus;计时模式: 打开计时,暂停计时
    k3:设置模式: shift;计时模式:归零
    k4:闹钟响时,关闭闹钟
  • 蜂鸣器:闹钟铃声,天空之城

主要原理:

    工作模式下,51单片机从DS1302中获取数据,再把数据传递到LCD来显示时间和日期;设置模式下,通过k2和k3来改变数据;计时模式下,通过k2来打开或关闭定时器1,来实现开始/暂停计时,通过k3来计时初始化;闹钟响时,打开定时器1,通过天空之城乐谱来控制蜂鸣器的音调。

DS1302

  • 编码是BCD8421编码,用4位二进制数来表示1位十进制数中的0~9这10个数字

十进制数 8421码
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001

/*BCD8421编码,十进制数据转换成BCD码 */
unsigned char encode_BCD(unsigned char dat)
{unsigned char dat1,dat2;dat1 = dat/10;dat2 = dat%10;dat = dat2 + dat1*16;return dat;
}/*BCD8421解码,BCD码转换成十进制数据   */
unsigned char decode_BCD(unsigned char dat)
{unsigned char dat1,dat2;dat1 = dat/16;dat2 = dat%16;dat = dat2 + dat1*10;return dat;
}

  • 读写数据到DS1302
    DS1302的数据读写是通过I/O串行进行的。当进行一次读写操作时最少得发送两个字节,第一个字节是控制字节,就是一个命令,告诉DS1302是读还是写操作,是对RAM还是对CLOK寄存器操作,以及操作的地址。第二个字节就是要读或写的数据了。

    1. 控制字节
    • 位0就是读写位,当位0为1时,就是告诉DS1302,下面是进行读出操作,而当位0为0时就是写入操作。
    • 位0-位5是要进行操作的DS1302寄存器地址。
      位6就是告诉DS1302,是要对RAM进行操作还是对时间寄存器进行操作,0就是对时间寄存器操作,一般我们都是对时间寄存器进行操作。
    • 位7就是固定的1。
    • 现在就知道为什么控制字80H是写秒寄存器,而81H是读秒寄存器了吧。80H换成二进制就是10000000。而81H的二进制就是10000001,一个是写操作,另一个是读操作嘛!
    1. 读写操作
    • 写:
      在进行操作之前先得将CE(也可说是RST)置高电平,然后单片机将控制字的位0放到I/O上,当I/O的数据稳定后,将SCLK置高电平,DS1302检测到SCLK的上升沿后就将I/O上的数据读取,然后单片机将SCLK置为低电平,再将控制字的位1放到I/O上,如此反复,将一个字节控制字的8个位传给DS1302。
      接下来就是传一个字节的数据给DS1302,在SCLK低电平时单片机将数据放到IO上,当SCLK上升沿时,DS1302读取。当传完数据后,单片机将CE置为低电平,操作结束。
    • 读:
      在进行操作之前先得将CE(也可说是RST)置高电平,然后单片机将控制字的位0放到I/O上,当I/O的数据稳定后,将SCLK置高电平,DS1302检测到SCLK的上升沿后就将I/O上的数据读取,然后单片机将SCLK置为低电平,再将控制字的位1放到I/O上,如此反复,将一个字节控制字的8个位传给DS1302。
      接下来就是从DS1302读数据,在SCLK高电平时DS1302放数据到IO上,将SCLK置为低电平后,产生下降沿电压,单片机就可从IO上读取数据。当传完数据后,单片机将CE置为低电平,操作结束。

/*写入数据到DS1302*/
void write_DS1302_dat(unsigned char addr,unsigned char dat)
{unsigned char i;//初始化TRST = 0;_nop_();     TSCLK = 0;_nop_();TRST = 1; //拉高CE,开始读写数据_nop_();for(i=0;i<8;i++)       //写入地址{TIO = addr & 0x01;  //发送地址的最低位 addr >>= 1;TSCLK = 1;            //产生上升沿电压,写入命令_nop_();TSCLK = 0;_nop_();}for(i=0;i<8;i++)     //写入数据{TIO = dat & 0x01;   //发送数据的最低位dat >>= 1;TSCLK = 1;          //产生上升沿电压,写入数据_nop_();TSCLK = 0;_nop_();}TRST = 0;      //数据传输结束_nop_();
}/*从DS1302读取数据*/
unsigned char read_DS1302_dat(unsigned char addr)
{unsigned char i,dat=0,dat1=0;//初始化TRST = 0;_nop_();  TSCLK = 0;_nop_();TRST = 1; //拉高CE,开始读写数据for(i=0;i<8;i++)       //开始传送八位地址命令{       TIO = addr & 0x01; //发送地址的最低位 addr >>= 1;TSCLK = 1;            //产生上升沿电压,写入命令_nop_();TSCLK = 0;            //DS1302下降沿时,放置数据_nop_();        }for(i=0;i<8;i++)     //读取8位数据{               dat1 = TIO;            //从最低位开始接收dat = (dat>>1) | (dat1<<7);TSCLK = 1;_nop_();TSCLK = 0;            //产生下降沿电压,读取数据_nop_();                   }TRST = 0;_nop_(); //以下为DS1302复位的稳定时间,必须的。TSCLK = 1;_nop_();TIO = 0;_nop_();TIO = 1;_nop_();return dat;
}

LCD1602

  • LCD操作模式
输入 输出 输出
读状态 RS=0,RW=H,EN为高变低脉冲 D0~D7个状态值
读数据 RS=1,RW=1,EN为高变低脉冲
写指令 RS=0,RW=0,D0–D7=数据,EN由高脉冲变为低脉冲 D0–D7状态值
写数据 RS=1, RW=0, D0–D7=数据,EN由高脉冲变为低脉冲 D0–D7状态值
  • 详细说明:
    (1) RS和RW都为0时表示对LCD写指令操作,包括写入LCD的显示模式和设定LCD地址的指令。.显示模式包括清屏、地址归为、显示状态、进入点设定、功能设定、游标显示模式操作;关于地址的操作包括设定CGRAM地址、设定DDRAM地址。
    (2) 当RS=0,RW=1时,表示读LCD状态,此时可以读取LCD忙信号,同时可以读取地址计数器的值。忙信号的状态用来确定LCD内部动作是否完成,若在LCD内部出于忙状态时对LCD进行读写操作将会失败。
    (3) 当RS=1时,若RW=0表示写数据操作,若RW=1表示读数据操作

  • 地址:
    LCD供两行,第一行可立即显示字符的地址为00H—0FH,第二行可立即显示字符的地址为40H—67H。


//判断液晶是否忙,如果忙就等待
void read_busy()
{unsigned char busy;P0 = 0xff;RS = 0;RW = 1;do{EN = 1;busy = P0;               //读状态,RS = 0;RW = 1;EN = 1;EN = 0;}while(busy & 0x80);       //判断状态码最高位,STA7读写使能,1:禁止,0:允许
}//写1字节指令
void write_cmd(unsigned char cmd)      //RS=L,RW=L,E=下降沿脉冲
{read_busy();RS = 0;RW = 0;P0 = cmd;EN = 1;EN = 0;
}//写1字节数据
void write_dat(unsigned char dat)      //RS=H,RW=L,E=下降沿脉冲
{read_busy();RS = 1;RW = 0;P0 = dat;EN = 1;EN = 0;
}

蜂鸣器

核心代码:

void delay_us(unsigned int t)         //us延时 12MHz下
{t/=10;for(t;t;t--);
}void play_tone(unsigned int tone)   //播音调函数,就是方波发生器
{Buzzer=!Buzzer;                delay_us(tone);
}

定时器获取延时时间:

void delay_ms(unsigned int t)         //毫秒延时12MHz下
{unsigned int i=0;while(t--)for(i=0;i<75;i++);
}void time_init( void )
{TMOD|=0x10;                        //使用定时器1TH1=(65536-65000)/256;             //装初值TL1=(65536-65000)%256;EA =  1;                       //开中断,打开定时器开关ET1 = 1;TR1 = 1;
}void timer1_interrupt(unsigned char *song)                 //定时器1 中断
{TH1=(65536-50000)/256;             //装初值TL1=(65536-50000)%256;music_s++;if(music_s>=4*t_tone)                   //一个音节播放的时间,这里可以通过调t_tone前的系数可以改变时长{music_s=0;                      //讲计时器清零if((*tone_p)!=0)           //如果音不是0tone = tones[*tone_p+7*(*(tone_p+1))-1];  //赋值音调else tone = 0;              //关了蜂鸣器t_tone = *(tone_p+2);      //取时间啊tone_p+=3;                  //移动指针if(*tone_p == 8) tone_p = song;      //结束标志delay_ms(30);               //延时一下,不延时特别难听}
}

歌曲谱子数组:

unsigned int tones[]=                //C调音调
{
3816,3401,3030,2865,2551,2272,2024,  //低音
1912,1703,1517,1432,1275,1136,1012,  //中音
965, 851, 758, 715, 605, 538, 466    //高音
};unsigned char code sky[]={            //谱子,天空之城
//格式: 音调, 音度, 拍数
//例: 4,1,1 //音调fa,中音,时长半拍
//0代表空音
0,0,2,
0,0,2,
0,0,2,
6,1,1,
7,1,1,1,2,3,
7,1,1,
1,2,2,
3,2,2,
8       //结束标志
};sbit Buzzer=P1^5;                     //定义buzzer引脚
unsigned char music_s=0, t_tone=0;         //music_s用作定时器计时, t_tone保存音调时长
unsigned int  tone=0;               //tone保存音调,
char *tone_p=sky;                   //指针指向要播放的曲目

51单片机实战之电子时钟相关推荐

  1. 基于51单片机的数字电子时钟

    基于51单片机的数字电子时钟 单片机课程设计要求使用51单片机完成一个电子时钟,要求满足基本功能的同时增添丰富的功能参考了很多大佬的方案代码才勉强完成,工程文件下载点击此链接欢迎交流.如遇下载问题可以 ...

  2. 基于51单片机的LCD1602电子时钟

    摘要: 51系列单片机是各单片机中最为典型和最有代表性的一种.由RAM ,ROM,CPU构成,定时,计数和多种接口于一体的微控制器.本次设计的数字电子时钟采用了STC89C52芯片进行控制,使用DS1 ...

  3. 51单片机LCD1602显示电子时钟 带按键设置和星期显示

    当时看书看到lcd那章,就想利用定时器做一个电子时钟,当时也不知道有时钟模块的,以为都是定时器定时产生的时间,也是一个main文件从头到尾的版本,注释倒不少,不要说什么模块化编程和代码优化,想到什么就 ...

  4. 51驱动DS1302制作电子时钟1602显示

    51驱动DS1302制作电子时钟1602显示 模组选型 模组选型解析 设计思路 产品接线 部分代码解析 总结 原文链接:https://www.yourcee.com/newsinfo/2928557 ...

  5. 基于51单片机1602温度显示时钟

    基于51单片机LCD1602温度显示时钟 要在1602上显示时间和温度先要了解1602是如何显示的.详情可以参考我之前的文章基于51单片机1602显示 :时间显示可以用时钟芯片DS1302,但是此次我 ...

  6. 基于51单片机的简易电子计算器——有温度显示和万年历等额外功能

    基于51单片机的简易电子计算器--有温度显示和万年历等额外功能 设计实际所实现的功能 模式一可显示日期.时钟.温度,模式二可进行计算器的计算,且显示日期温度模式和计算器模式可随意切换,模式三可以滚动显 ...

  7. 基于51单片机的简易电子数字计算器Proteus仿真

    资料编号:089 采用51单片机,使用矩阵键盘,可以计算加减乘除,进行简易计算: 全套资料齐全:具体功能请看下面演示视频 89-基于51单片机的简易电子数字计算器Proteus仿真 单片机最小系统介绍 ...

  8. keil c语言 1602时钟代码,基于单片机的LCD1602电子时钟设计.doc

    基于单片机的LCD1602电子时钟设计 设计任务和目的 1.1.设计任务 (1):用单片机设计基于LCD1602的电子时钟,显示时间和日期: (2):误差精度控制在1s/天: (3):具有时间和日期的 ...

  9. 基于51单片机HX711的电子秤称重计价proteus仿真程序设计

    设计要求 1.利用压力传感器检测重量信号,经放大和A/D转换,送单片机进行处理,并在液晶屏上显示出被称重量值: 2.最小显示单位为1克: 3.量程超过报警值蜂鸣器报警 资料下载地址:基于51单片机HX ...

最新文章

  1. PCA和白化练习之处理图像
  2. android 状态栏、标题栏、屏幕高度
  3. Spark SQL(一)之简介
  4. 深度学习修炼(二)——数据集的加载
  5. jdbc连接云数据库mysql数据库_使用jdbc连接mysql数据库
  6. unity3d android assets,Unity3D之Android同步方法读取streamingAssets(八十八)
  7. 基于JAVA+SpringMVC+Mybatis+MYSQL的医院管理系统
  8. java折行_Java源代码的折行规则
  9. MFC的多国语言界面的实现
  10. winform中notifyIcon的ShowBalloonTip方法的坑
  11. 数字孪生 工业互联网 IIoT 解决方案
  12. 真实渗透改编--综合渗透 sql注入写马+文件上传+udf提权 安鸾靶场SQL注入学习
  13. SpringBoot+Vue打造资产出入库管理系统
  14. 2020年国家扶贫日“三产联动扶贫论坛”在京召开,杭州复杂美科技有限公
  15. python训练自己中文语料库_自然语言处理——NLTK中文语料库语料库
  16. JavaScript实现EAN13条码校验
  17. 动态模态分解 DMD | 做高维时间序列数据短时预测
  18. 1688API详情接口调用示例
  19. d3dcompiler_47.dll缺失怎么修复?D3DCompiler_47.dll修复工具下载
  20. TCP和SCTP的区别

热门文章

  1. Python-字符串
  2. Qt多功能计算器(一)——基本功能
  3. Google着手与 Open AI 合作预防人工智能暴走
  4. 为什么VS2019的解决方案资源管理器中的文件名和文件夹名里的下划线不显示?
  5. ACCV 2020国际细粒度网络图像识别竞赛——正式开赛!
  6. 逻辑与计算机设计基础实验报告,学位论文_逻辑与计算机设计基础课实验报告.doc...
  7. java实现分数四则运算
  8. 天津大学计算机软件学院,2019计算机考研天津大学数据科学与服务工程团队(与软件学院共建)...
  9. 执念斩长河22年寒假出发录
  10. 《见识》----吴军博士,读书笔记