郭天祥的10天学会51单片机_第十一节
参考第十节的课件DS12887
RTC就是Real Time Clock实时时钟
DS12887芯片是保持时间的,即当前设定一个时间,然后断电,而该芯片的时间还在走
DS12887-5指的是5伏,DS12887-33指的是3.3伏
OSC是时钟振荡器(给时钟提供频率),下面是电源控制及掉电自动保护,往下是总线接口
DIVID BY 8是八分频
MOT是总线类型选择,本节让MOT接地或不接,即用于Intel模式
NC就是Not Connect不连接
AD0到AD7接单片机的P0口
TX-1C型单片机实验板原理图上的24C02(图中标错了,标成24C00)是EEPROM
AS就是Address strobe(地址闸门),接P1^5口,高电平写地址,低电平锁存数据
DS就是Data strobe(数据闸门),连到P1^7口,高电平写数据
R/W连到P1^6口
便找个口,这里用P1^4口,操作时拉低,不操作时拉高
IRQ(Interrupt Reques)是中断,接P3^2口(只能接单片机的外部中断1口P3^3口和外部中断0口P3^2口),用于定时闹钟后,当中断发生时IRQ由高电平变成低电平,送到单片机,让单片机控制蜂鸣器响
RESET接VCC(高电平1)
SQW是方波输出,见DS12887的P20表3,这里没用到所以不接
一般时钟是32.768KHZ石英晶体
见DS12CR887-DS12R887_cn的PDF的P14表2A,时分秒的地址,Second Alarm是秒定时器,例如Second,秒的地址是00H,可以从00H读出秒的值,只使用BIT0到BIT5;0A到0D是四个定时器;读的时候先赋地址再赋数据
写程序的时候要考虑时间,见DS12887的P4时间表,指令时间宽度都是纳秒,而一个机器周期至少是毫秒,肯定保证机器时间内指令能完成,所以纳秒可以不用管
见DS12887的P17给B寄存器设置为26开启闹钟
蜂鸣器是P2^3口
见DS12CR887-DS12R887_cn的PDF的P18,如果不读取C寄存器就会让IRQ变低后一直保持低电平,只触发一次中断,而不能触发下一次中断
延时消抖的时间1毫秒是消抖不了的,可以设置成5毫秒
TX-1C型单片机实验板原理图上的PL2303是下载口
点击Options for Target按钮,在Output菜单页面上,将Browse Information 点上钩,作用是要看函数的定义或引用可以用鼠标右键选择最后两项
标记,鼠标右键选择Toggle Bookmark,然后按F2即可选择标记所在的行
添加头文件,写完头文件,保存完头文件,再添加时,保存类型选择ALL Files,出现的对话框中的Type选择Text Document File,再确定
以后可以把每个模块都写成头文件,在源文件中添加即可
学完单片机要多练,单片机熟练后可以学嵌入式ARM7,然后ARM9,多锻炼多实践
我犯的错误:外部中断0接3^2口,外部中断1接3^3口,把时钟芯片的IRQ接单片机的3^2口
Shizhong.c:
#include<reg52.h>
#include<define.h>
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void didi()
{
beep=0;
delay(50);
beep=1;
delay(100);
beep=0;
delay(50);
beep=1;
}
void write_com(uchar com)
{
rs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(uchar date)
{
rs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
{
uchar num;
EA=1;
EX0=1; //开外部中断0,使用内部中断时还需要启动内部中断,而外部的时钟芯片自己一直自动提供频率,不需要再启动外部中断
IT0=1; //外部中断0,下降沿触发方式
dula=0;
wela=0;
lcden=0;//先关闭外部中断,为时钟芯片的定时中断做准备
//set_time();//设置时钟芯片初始时间,这里如果设置,每次开启单片机就会重新设置时钟芯片的时间,如果不设置,时钟芯片会在关闭期间还在走,每次开启单片机时就会输出新时间,即上次关闭的时间加上再次开启之间的时间
set_alarm(14,13,10);
write_ds(0x0B,0x26);//向B寄存器里写26,开启闹钟
read_ds(0x0c);//读一下C寄存器,见DS12CR887-DS12R887_cn的PDF的P18,读一下C
//寄存器为了清除上次IRQ的状态;因为见DS12CR887-DS12R887_cn的PDF的P17的闹钟中断使能AIE,AIE置1时,寄存器C的闹钟中断标志AF位驱动产生IRQ信号,见DS12CR887-DS12R887_cn的PDF的P18,当AF=AIE=1时,IRQF为1,让IRQ变低,这样IRQ就不能产生下降沿进入中断,所以要读一下C寄存器清除IRQ低电平状态
// fen=59;
// miao=53;
// shi=23;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<15;num++)
{
write_date(table[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<12;num++)
{
write_date(table1[num]);
delay(5);
}
}
void write_sfm(uchar add,uchar date)
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void keyscan()
{
rd=0;
if(flag1==1)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!s2);
flag1=0;
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!s3);
flag1=0;
}
}
}
if(s1==0)
{
delay(5);
if(s1==0)
{ s1num++;
flag=1;
flag1=0;
while(!s1);
if(s1num==1)
{
TR0=0;
write_com(0x80+0x40+10);
write_com(0x0f);
}
}
if(s1num==2)
{
write_com(0x80+0x40+7);
}
if(s1num==3)
{
write_com(0x80+0x40+4);
}
if(s1num==4)
{
s1num=0;
write_com(0x0c);
flag=0;
write_ds(0,miao);
write_ds(2,fen);
write_ds(4,shi);
}
}
if(s1num!=0)
{
if(s2==0)
{
delay(1);
if(s2==0)
{
while(!s2);
if(s1num==1)
{
miao++;
if(miao==60)
miao=0;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(s1num==2)
{
fen++;
if(fen==60)
fen=0;
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(s1num==3)
{
shi++;
if(shi==24)
shi=0;
write_sfm(4,shi);
write_com(0x80+0x40+4);
}
}
}
if(s3==0)
{
delay(1);
if(s3==0)
{
while(!s3);
if(s1num==1)
{
/* if(miao==0)
{
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}*/
miao--;
if(miao==-1)
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(s1num==2)
{
fen--;
if(fen==-1)
fen=59;
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(s1num==3)
{
shi--;
if(shi==-1)
shi=23;
write_sfm(4,shi);
write_com(0x80+0x40+4);
}
}
}
}
}
void write_ds(uchar add,uchar date)
{
dscs=0;//片选置低电平使用时钟芯片
dsas=1;//准备给地址
dsds=1; //准备给数据
dsrw=1;//读
P0=add;//给地址
dsas=0;//锁存地址
dsrw=0;//写
P0=date;//写数据
dsrw=1;
dsas=1;
dscs=1;
}
uchar read_ds(uchar add)
{
uchar ds_date;
dsas=1;//准备给地址
dsds=1; //准备给数据
dsrw=1;//读
dscs=0;
P0=add;//读入地址
dsas=0;//锁存地址
dsds=0;
P0=0xff;
ds_date=P0;//数据准备好
dsds=1;//读入数据
dsas=1;
dscs=1;
return ds_date;
}
void set_time()
{
write_ds(4,10);
write_ds(2,32);
write_ds(0,12);
}
void set_alarm(uchar ashi,uchar afen,uchar amiao)
{
write_ds(1,amiao);
write_ds(3,afen);
write_ds(5,ashi);
}
void main()
{
init();
while(1)
{
keyscan();
if(flag1==1)
didi();
if(flag==0)
{
miao=read_ds(0);
fen=read_ds(2);
shi=read_ds(4);
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
}
}
}
void exter() interrupt 0
{ uchar c;
flag1=1;
c=read_ds(0x0c);// 读一下C寄存器,清除上次IRQ的状态
}
Define.h:
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;
sbit wela=P2^7;
sbit rs=P3^5;
sbit lcden=P3^4;
sbit s1=P3^0;
sbit s2=P3^1;
sbit s3=P3^2;
sbit rd=P3^7;
sbit beep=P2^3;
sbit dscs=P1^4;
sbit dsas=P1^5;
sbit dsrw=P1^6;
sbit dsds=P1^7;
sbit dsirq=P3^3;
uchar count,s1num,flag,flag1;
char miao,shi,fen;
uchar code table[]=" 2007-7-30 MON";
uchar code table1[]=" : : ";
void write_ds(uchar,uchar);
void set_alarm(uchar,uchar,uchar);
uchar read_ds(uchar);
void set_time();
我的程序:
我犯的错误:为了防止串口下载程序时不能使用第一行键,我把s3定义成P3^3口后,又把dsirq定义成P3^3口,造成冲突
Shizhong.c:
#include<define.h>
void delay(uint z)
{
uchar x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com)
{
rs=0;
lcden=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_date(uchar date)
{
rs=1;
lcden=0;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_ds(uchar add,uchar date)
{
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add;
dsas=0;
dsrw=0;
P0=date;
dsas=1;
dsrw=1;
dscs=1;
}
uchar read_ds(uchar add)
{
uchar date;
dsas=1;
dsds=1;
dsrw=1;
dscs=0;
P0=add;
dsas=0;
dsds=0;
P0=0xff;
date=P0;
dsds=1;
dscs=1;
dsas=1;
return date;
}
void set_time()
{
write_ds(4,15);
write_ds(2,30);
write_ds(0,45);
write_ds(7,14);
write_ds(8,2);
write_ds(9,11);
write_ds(6,2);
}
void set_alarm(uchar ashi,uchar afen,uchar amiao)
{
write_ds(5,ashi);
write_ds(3,afen);
write_ds(1,amiao);
}
void init()
{
uchar num;
dula=0;
wela=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_com(0x80);
for(num=0;num<15;num++)
{
write_date(table1[num]);
delay(5);
}
write_com(0x80+0x40);
for(num=0;num<12;num++)
{
write_date(table2[num]);
delay(5);
}
EA=1;
EX0=1;
IT0=1;
lcden=0;
set_alarm(15,31,10);
write_ds(0x0B,0x26);
read_ds(0x0C);
set_time();
}
void wrtie_sfm(uchar add,uchar sfm)
{
uchar shi,ge;
shi=sfm/10;
ge=sfm%10;
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void keyscane()
{
rd=0;
if(flag1==1)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!s2);
flag1=0;
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!s3);
flag1=0;
}
}
}
if(s1==0)
{
delay(5);
if(s1==0)
{
flag1=0;
flag=1;
while(!s1);
num1++;
if(num1==1)
{
write_com(0x80+0x40+10);
write_com(0x0f);
}
if(num1==2)
{
write_com(0x80+0x40+7);
}
if(num1==3)
{
write_com(0x80+0x40+4);
}
if(num1==4)
{
write_com(0x0c);
num1=0;
flag=0;
write_ds(0,miao);
write_ds(2,fen);
write_ds(4,shi);
}
}
}
if(num1!=0)
{
if(s2==0)
{
delay(5);
if(s2==0)
{
while(!s2);
if(num1==1)
{
miao++;
if(miao==60)
miao=0;
wrtie_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(num1==2)
{
fen++;
if(fen==60)
fen=0;
wrtie_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(num1==3)
{
shi++;
if(shi==24)
shi=0;
wrtie_sfm(4,shi);
write_com(0x80+0x40+4);
}
}
}
if(s3==0)
{
delay(5);
if(s3==0)
{
while(!s3);
if(num1==1)
{
miao--;
if(miao==-1)
miao=59;
wrtie_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(num1==2)
{
fen--;
if(fen==-1)
fen=59;
wrtie_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(num1==3)
{
shi--;
if(shi==-1)
shi=23;
wrtie_sfm(4,shi);
write_com(0x80+0x40+4);
}
}
}
}
}
void didi()
{
beep=0;
delay(500);
beep=1;
delay(500);
beep=0;
delay(500);
beep=1;
}
void write_yrn(uchar add,uchar date)
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void write_xq(uchar date)
{
if(date==1)
{
write_com(0x80+12);
write_date('M');
write_date('O');
write_date('N');
}
if(date==2)
{
write_com(0x80+12);
write_date('T');
write_date('U');
write_date('E');
}
if(date==3)
{
write_com(0x80+12);
write_date('W');
write_date('E');
write_date('N');
}
if(date==4)
{
write_com(0x80+12);
write_date('T');
write_date('H');
write_date('I');
}
if(date==5)
{
write_com(0x80+12);
write_date('F');
write_date('I');
write_date('V');
}
if(date==6)
{
write_com(0x80+12);
write_date('S');
write_date('A');
write_date('T');
}
if(date==7)
{
write_com(0x80+12);
write_date('S');
write_date('U');
write_date('N');
}
}
void main()
{
init();
while(1)
{
keyscane();
if(flag1==1)
{
flag1=0;
didi();
}
if(flag==0)
{
miao=read_ds(0);
fen=read_ds(2);
shi=read_ds(4);
day=read_ds(6);
date=read_ds(7);
month=read_ds(8);
year=read_ds(9);
xq=read_ds(6);
wrtie_sfm(10,miao);
wrtie_sfm(7,fen);
wrtie_sfm(4,shi);
write_yrn(9,date);
write_yrn(6,month);
write_yrn(3,year);
write_com(0x80+1);
write_date(0x30+2);
write_date(0x30+0);
write_xq(xq);
}
}
}
void exter0() interrupt 0
{
read_ds(0x0C);
flag1=1;
}
Define.h:
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6;
sbit wela=P2^7;
sbit rs=P3^5;
sbit lcden=P3^4;
sbit rd=P3^7;
sbit s1=P3^0;
sbit s2=P3^1;
sbit s3=P3^2;
sbit dsas=P1^5;
sbit dsds=P1^7;
sbit dsrw=P1^6;
sbit dscs=P1^4;
sbit dsirq=P3^3;
sbit beep=P2^3;
uchar aa,num1,num2,num3,flag,flag1;
char miao,fen,shi,day,date,month,year,xq;
uchar code table1[]=" 2011-02-14 MON";
uchar code table2[]=" : : ";
void write_ds(uchar,uchar);
uchar write_rd(uchar);
void set_time();
void set_alarm(uchar,uchar,uchar);
void didi();
void write_yri(uchar,uchar);
void write_xq(uchar);
我调了很多次调不出时钟的闹钟功能,我就先看看能不能接收到时钟的闹钟数值,在set_alarm()中添加didi(),现象是闹钟响,说明进入到了时钟的闹钟数值设置中,在didi()中又进入flag=1,让时钟静止,现象是时钟没有静止,说明时钟设置好闹钟后到设定时间没有进入闹钟响声程序,
郭天祥的10天学会51单片机_第十一节相关推荐
- 郭天祥的10天学会51单片机_第七节
串行通信:从D0位一位一位发发到D7位 十个位为一帧如:0101000100,表示一个字符 起始位低电平有效,停止位高电平有效,单片机是异步通信 宽带网线是八根线,组成两队差分信号,分别是TXD1(发 ...
- 郭天祥的10天学会51单片机_第十三节
AD软件: AD软件可以编译C语言和VHDL语言等:AD软件的工具栏上面可以输入网络地址进行浏览网页:AD软件可以布差分信号,即可以两条线可以一起布 按住Shift键和左键可以向左移动,按住Shift ...
- 郭天祥的10天学会51单片机_第三节
单片机管脚,P3口有两个功能,上电默认情况下就使用P3口的普通IO口,当对单片机内部的某些寄存器设置时就启用P3口的第二个功能 P3^4和 P3^5可以作为计时器或定时器使用,给这两个口输入方波,进行 ...
- 10.4.4 51单片机控制系统8个LED“跑马灯”实验
10.4.4 51单片机控制系统8个LED"跑马灯"实验 仿真+代码 方法一 利用数组 #include"reg52.h"#define u8 unsigned ...
- 51单片机学习笔记(郭天祥版)(1)——单片机基础和点亮LED灯
关于单片机型号的介绍: STC89C52RC40C-PDIP 0721CV4336..... STC:STC公司 89:89系列 C:COMS 52(还有51,54,55,58,516,):2表示存储 ...
- 红外测距模块 51单片机_[51单片机] HC-SR04超声波测距仪
1.HC-SR04超声波模块工作原理 (1)采用IO口触发测距,给至少10us高电平脉冲: (2)模块自动发送八个40khz方波,并自主检测是否有电波返回: (3)当有信号返回时,通过IO口输出一个高 ...
- 2440 8字数码管 显示0到10 c语言,51单片机对8位数码管依次显示0-7的设计
共阳极数组0~9:display[]={0xC0,0xF9,0xA4,0xB0,0x91,0xA2,0x82,0xF8,0x80,0x90} 共阳极数组A~F:display[]={0x88,0x83 ...
- 单片机c语言二进制转10进制,51单片机用C语言怎么样把八位二进制转换成十进制...
满意答案 sunzhaoming 2013.07.06 采纳率:41% 等级:12 已帮助:8866人 //******************************************* ...
- 51单片机_动态数码管显示
动态数码管显示(延时函数) 编程原理 利用延迟函数,每秒钟数码管加1显示,一直加到250.延时函数精度不高,最好使用定时器中断. 数码管动态显示原理 动态数码管显示有段选和位选.段选是单个数码管显示的 ...
- 51单片机_点亮第一个LED灯_0x01
/*点亮第一个led灯sbit 变量名=地址值; */#include <reg52.h>sbit led=P2^0; //即定义led为P2口的第0位,以便进行位操作.(sbit是定义特 ...
最新文章
- 【转】Usage of sendBroadcast()
- 解决IE无法查看源文件问题
- 每日一皮:死循环的深刻理解...
- 第13章 集成学习和随机森林
- 不服来战!这才是产品汪与程序猿撕逼的正确方式
- 嵌入式笔录(6)单管收音机电路分析
- docker中创建Jmeter及在外部使用JMeter-Server控制
- python桌面开发吐血_Python3环境(Windows10)单独配置Spyder——记录我的吐血之路...
- linux 超时 tcp,Linux中TCP设置syn超时时间
- 【程序员感悟系列】 由一点业务说开去
- Intel 64/x86_64/IA-32/x86处理器 - SIMD指令集 - SSE扩展(7) - 混洗指令 解组合指令
- 最小二乘法和极大似然估计
- Mysql,phpmyadmin密码忘了怎么办
- 数据库学习笔记3-隔离级别 Read Uncommitted
- C语言system函数使用
- 博途plc连接电脑_PLC编程中如何连接电脑将程序写入PLC
- 540s inter 固件_Intel SSD Firmware Update Tool(英特尔ssd固件更新工具)下载 v2.1.6官方版...
- RabbitMQ系列8 TTL 死信队列 延迟队列
- Detours学习之三:使用Detours
- 物联网-移远M26模块初识及资料分享