提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
提示:以下是本篇文章正文内容,下面案例可供参考
DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.0V~5.5V。该芯片采用普通32.768kHz晶振,DS1302 工作时功耗很低,保持数据和时钟信息时功率小于1mW,非常适合用于制作电子钟。
DS1302芯片管脚和实例电路如图:


DS1302共8个引脚,其中VCC供电口共有两个,VCC1为主供电口,VCC2为备用供电口,备用电源口可以保证DS1302在主供电断电情况下依然可以正常计时,使用过程中仅使用VCC2备用电源作为供电,可保证完整功能。
DS1302需要与单片机交互的接口为,SCLK、I/O、RST三个,与单片机的数据交换使用I/O接口,为串行通信模式。SCLK为串行时钟输入引脚,保证数据同步传输。RST为复位口。
DS1302命令字和对应的操纵如下图:

DS1302向单片机返回的时间日期数值采用压缩BCD码,即用16进制数表示10进制数,比如返回55秒对应的值为0x55,在数据解算时需要按照16进制规则计算。
闹钟音乐使用无源蜂鸣器播放,基本原理为通过单片机向无源蜂鸣器输出不同频率的方波信号,无源蜂鸣器则对应播放出不同音调的声音,即播放出不同的音符。通过连续播放不同音符并控制每个音符播放的时间,可以组合成完整的音乐。
单片机输出不同频率的方波使用定时中断实现,首先将每个音符对应的中断计时时间储储存在单片机中,通过在程序中不断改变中断的时间,可以控制单片机输出方波的频率。以此利用无源蜂鸣器播放出音乐。
程序共包括4个文件,分别为main.c、DS1302.h、ds1302.c、music.h三个部分。其中main.c为主程序文件,主要包括lcd1602显示相关函数、可调时钟日期函数、闹钟函数;DS1302.h为ds1302.c的声明文件,声明ds1302.c中的相关函数;ds1302.c中定义了单片机与DS1302芯片通信的主要函数文件,主要包括命令输入,数据读取和输入;music.h定义了音乐播发函数,用于闹钟调用。
以下为示例代码,完整代码免费分享,见文末。
#ifndef __DS1302_H
#define __DS1302_H
void Write_Ds1302(unsigned char temp); //向DS1302写命令函数
void Write_Ds1302_Byte( unsigned char address,unsigned char dat ); //用户输入的时间日期输入DS1302函数
unsigned char Read_Ds1302_Byte( unsigned char address ); //读取DS1302时间日期函数
#endif
代码如下(示例):
#include <reg52.h>
#include <intrins.h>
//定义引脚
sbit SCK=P2^0;//CLK
sbit SDA=P2^1;//DIO
sbit RST = P2^2;//CE
void Write_Ds1302(unsigned char temp)
{
unsigned char i;
for (i=0;i<8;i++)
{
SCK=0; //开传输
SDA=temp&0x01; //与0x01相与,每次只取temp最后一位发送
temp>>=1; //temp右移位
SCK=1; //该位传输结束
}
}
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )
{
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address); //写入对应寄存器输入地址
Write_Ds1302(dat); //向对应寄存器中输入数据
RST=0;
}
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
unsigned char i,temp=0x00;
RST=0; _nop_();
SCK=0; _nop_();
RST=1; _nop_();
Write_Ds1302(address); //写入对应寄存器读取地址
for (i=0;i<8;i++) //串口读取
{
SCK=0;
temp>>=1; //temp右移位
if(SDA) temp|=0x80; //如果IO口给高电平,temp最高位置1,相当于保存IO的高电平数据
//如果IO口给低电平,temp不操作,保持0,相当于保存IO的低电平数据
SCK=1;
}
RST=0; _nop_();
SCK=0; _nop_();
SCK=1; _nop_();
SDA=0; _nop_();
SDA=1; _nop_();
return (temp); //以char类型返回temp的数据
}
#ifndef __music_H
#define __music_H
#include <reg52.h>
#include <stdio.h>
sbit beep = P2^3;
sbit key1=P1^0;
unsigned char timer0h, timer0l, time;
//设置好高低音对应的频率
code unsigned char high_v[] = {
0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC,//低音1234567
0xFC, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE,//中音1234567
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF,//高音1234567
};
code unsigned char low_v[] = {
0x8C, 0x56, 0x22, 0x64, 0x04, 0x90, 0x0C,//低音1234567
0x44, 0xAA, 0x08, 0x32, 0x82, 0xC8, 0x06,//中音1234567
0x22, 0x56, 0x84, 0x9A, 0xC0, 0xE4, 0x02,//高音1234567
};
#include<reg52.h>
#include "ds1302.h"
#include "music.h"
typedef unsigned char u8;
typedef unsigned char u16;
sbit lcdrs=P2^6; //定义LCD寄存器选择位。高电平时选择数据位寄存器,低电平时选择指令寄存器
sbit lcdrw=P2^5; //定义LCD读写信号位。高电平时读操作,低电平时写操作。
sbit lcden=P2^7; //定义LCD使能端
sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
sbit sound=P2^3;
void ds1302_init();
void ds1302_read();
void diplay();
void delay(unsigned int x);
void delay_ms(unsigned int n);
void control();
void time_alter();
void alarm_alter();
void lcdwritecmd (unsigned char cmd); //用来给LCD输入指令
void lcdwritedata(unsigned char dat); //用来给LCD输入要显示的数据
void clear();
void lcdinit();
void showstring(unsigned char b[]);
void delay_ms(unsigned int n);
void alarm_sound();
u8 code read_addr[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d};
u8 code write_addr[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};
u8 code number[] = "0123456789:. ";
unsigned char code low[10] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
unsigned char code high[10] = {0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90};
//01秒02分03时 4日 5月 周6 07年
u8 timer[]={0x00,0x00,0x00,0x04,0x05,0x06,0x07};
//闹钟设置10秒00分00时 音乐2
u8 alarms[]={0x10,0x00,0x00,0x04};
unsigned int choose;

Lcd1602正确显示时间日期,测试CONTROL、K1、K2按钮,所有功能正常。proteus中使用发光二极管D1代表实际开发版上发声元件,当闹钟开始时,蜂鸣器播放选择的音乐,lcd1602显示“alarm!!!”字样,按下CONTROL自动结束闹钟,回到正常显示,同时闹钟不消除,下次同一时间继续响应闹钟。
时间日期显示:

响应闹钟:

将程序下载到开发版,依照上述电路图正确连线,lcd1602正常显示时间日期,闹钟正常响应,蜂鸣器播放设定的音乐。所有现象与proteus仿真一致。

编译过程中,因为在程序中定义了大量的变量,使得变量所需存储空间一度超出了单片机允许的128字节data,查询相关资料后可知,对于那些仅在程序中读取而不需要更改的变量,可以使用code、xdata数据类型,保存在单片机的其他储存空间之中,可以很好地解决变量溢出的问题。
注意:在proteus仿真或者开发板实验的时候,如果遇到按键响应过快的问题(即按下一次按键后,单片机判断按键被按下多次),可以尝试更改代码中按键后的延时时间实现。例如下图画红线位置:

1.DS.uvproj(Keil项目文件,以下为项目下包括文件)
main.c
ds1302.h
ds1302.c
music.h
2.clock.pdsprj(proteus仿真项目文件)
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时