新手作业——1602+DS3231+STC89C53简单时钟+第一次制作PCB。。。。
学51也好几个月了。。。。。做了不少时钟。。。。。。。但都是洞洞板或者用别人现成的板子。。。。。。。刚好手电有人做1602,想开板,偶也来尝试一下。。。。。。。。。。
第一次做PCB,不敢弄太复杂的,软件还没熟悉呢。。。。。1602最适合练手了。。。。。。
貌似大家都是用DS1302做时钟,不过时间不准太头痛了。。。。。。。。我费了九牛二虎之力才把其中几个DS1302时钟调的误差很小(几天1秒吧),但是在太折腾了。。。。还是一步到位用DS3231 RTC吧。。。。。如果要求不高,还省了DS18B20,直接用DS3231内置温度传感器了(虽然官方指标±3°,但作为日常参考温度,也够用了)。。。。。
单片机——最通用的AT89S52或者STC89C52。。。。。。。。。。。。
5V MINIUSB口供电(可选5mm圆孔插头)。。。。。。。。。。。。。
大概流程图如下,没几个零件,感觉超级简单。。。。。。。。。。。。
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_611580YNUL5W.jpg
(原文件名:1602+DS3231SCH.jpg)
不过学化学的我,电子基础约等于0,虽然很简单的东西,等真正要画图的时候晕了。。。。。。。。。。
貌似很多人还在用Protell99,我也跟风学这个。。。。。。。但这个系统的操作,简直就是WIN32年代的东西。。。。。忍受不了。。。
改换门庭,一次到位,学AD9。。。。。。。。这下倒好,自己给自己找麻烦。。。。。。软件实在太专业了,不知从哪儿入手。。。。。。
在最后拼着一股牛劲,以很不成熟的方式,连流程图都没对应好,拼着出来一个单面PCB。。。。。。。。。部分电容电阻直插贴片兼容。。。
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_611581QYSYBZ.jpg
(原文件名:1602+DS3231.jpg)
不管了,打样去。。。。。。。等啊等啊。。。。。。。N天后拿到了我的第一块板子。。。。。。。
嘿嘿,貌似还能用。。。。。。。虽然有几个小错误。。。。。。。。(5mm圆孔插头的过孔小了,不知道厂家的问题还是我的问题,我PCB图上过孔貌似很大的。。。。。只能剪剪脚再安装5mm电源座了,不过MINIUSB的很好,没事就用这个吧)。。。。。。另外另外,就是几个电容,应该转个90度,这样就更方便了。。。。。。。
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_611596K2MCCI.jpg
(原文件名:N70_2456.jpg)
板子都到了,开干,焊上需要的零件。。。。。。差不多成型了。。。。。。。
正反面的样子,哈哈,还好还好。。。。。。。。。
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_611597T14VA4.JPG
(原文件名:N20_0012.JPG)
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_611598LN0H9F.jpg
(原文件名:N70_2461.jpg)
焊接完毕。。。。。。。剩下就是程序了。。。。。。。。。
1602的简单,但DS3231 I2C的方式还没学过。。。。。。。虽然有官方例程,但貌似有点乱。。。。。。。
开始听WANG1JIN的I2C课程,讲24C08的。。。。。貌似不难,照抄到我的DS3231上。。。。
但结果是杯具的。。。。。。。读出一堆问号或者I5。。。。。
找网上例程,用51的很少,基本都是用AVR的。。。。。。移植。。。。。。。还是杯具。。。。。
莫非硬件?该死。。。。。。硬件全是有问题。。。。。本来左上4脚(也就是13脚该接地的),怎么把左下4脚接地了。。。。
妈妈咪呀,当时没找到DS3231的封装,自己做的,真出问题了。。。。。。把RST接地了,GND悬空,DS3231能干活吗。。。。。真实。。。
做个小手术。。。。。。4脚悬空,13脚接地。。。。。但还是杯具。。。。。。。。。。。。。。结果一样。。。。。。。
担心IC被我整坏了,换一个,继续杯具。。。。。。。。
SCL SDA上拉10K,莫非太小,换4.7K。。。。。杯具。。。。。
不用DS1302,用个DS3231,自寻烦恼啊。。。。。。。。。。。
百度啊百度。。。。。。网上终于有个51的例程照抄还是杯具的。。。。。。
手上没有示波器,没有逻辑分析仪,看不到I2C的时序。。。。。。。。苦恼。。。。。。
延时已经改了又改。。。。。。偶然想起读取温度寄存器不能连续,读取时间跟读取温度寄存器过程延时时间长一点试试。。。。。
两次读取过程加了个400ms延时。。。。。。。。。晕,居然通了。。。。。。。。。。。。。
难看DS3231读取间隔要延时这么长,不会吧。。。。。。。。。。。。。。再试不同的延时方式。。。。。。。
再也没有成功。。。。。。。。。。。。。。。。。。。。。。。。
板子没做ISP下载,用AT89S52,AT89C52做的测试,每次插拔芯片,辛苦死了。。。。。。。
干脆在IC座引脚上焊两根线,用STC的在线烧录做测试,省得每次插拔芯片。。。。。。。。。
结果。。。。。。。。。。。。。。。换上一片STC89C53,居然读出时间了。。。。。。。每次读取延时怎么弄都成。。。。。。。
I2C时序稍微调整一下也没事。。。。。。。。。。。。。。。。。。。
我的天哪。。。。。。。。。。。别把我当作STC枪手啊。。。。。。。。这是我的实际经历。。。。。。。
I2C总线我接的P17 P16,为啥这样。。。。。。。。。。等高手的解答。。。。。。。。。。。。
终于调通了。。。。。。上个图先。。。。。。。。。。。。。。。。。
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_611599FFJVEI.jpg
(原文件名:N70_2466.jpg)
简单的菜单。。。。。。。
http://cache.amobbs.com/bbs_upload782111/files_35/ourdev_611600WRT0XG.jpg
(原文件名:N70_2463.jpg)
完善程序。。。。。。。按键。。。。两个独立闹钟。。。。,自动星期。。。。。。菜单返回。。。。。。。
音乐铃声还在杯具中。。。。。先预听吧。。。。。。
板上预留DS18B20接口(用延长线,离开发热的PCB,保证温度准确),加上DS18B20程序,但实际还没写完,需要用上的时候再加个显示小程序就行了,读取,判断都加上了。。。。
没有DS18B20用内置温度传感器,如果检测到有DS18B20,用18B20的数据。。。。。。。
差不多先这个样了。。。。。。。程序先放上来,请大家多多指点。。。。。。。
点击此处下载 ourdev_611582CDT6LL.rar(文件大小:133K) (原文件名:程序.rar)
不是科班出生。。。。。玩个小东西。。。。。真累啊。。。。。。。。
趴下休息ING。。。。。。。。。。。。。。。。。。。 很好新手做到这么好 呵呵,支持!这种精神很好 楼主那个电池什么型号?有资料吗? 呵呵,厉害啊,不过开板太烧钱了,所以我现在还没有开过板,不过,最近准备DIY PCB。用过硫酸体系的腐蚀法。 回复【3楼】bbssr
楼主那个电池什么型号?有资料吗?
-----------------------------------------------------------------------
带焊脚的CR1220,淘宝很好找,不需要资料。。。。。。 回复【4楼】kerrwang1982
呵呵,厉害啊,不过开板太烧钱了,所以我现在还没有开过板,不过,最近准备diy pcb。用过硫酸体系的腐蚀法。
-----------------------------------------------------------------------
呵呵,找个便宜一点的厂家,其实开板很便宜的。。。。。。我这次做了20片,平均到每片5块不到吧。。。。。 mark 话说去年申请了2片DS3231,却说搬了次家,就不翼而飞了,郁闷ing! 楼主的PCB比我画得好,大面积敷铜是怎么做到的,我学的PROTEL 2.X好像没有这个功能。 MARK.楼主,难道大面积铺铜不多花钱吗?我做的第一个PCB都没敢铺一点痛, 回复【9楼】pxlpxlpxl
楼主的pcb比我画得好,大面积敷铜是怎么做到的,我学的protel 2.x好像没有这个功能。
-----------------------------------------------------------------------
我后来用的AD9,PROTELL不知道怎么弄 了哈。。。。。 新手能做到如此也不错了,学电子就得实际动手,否则神马都是浮云! 回复【10楼】muzheyun
mark.楼主,难道大面积铺铜不多花钱吗?我做的第一个pcb都没敢铺一点痛,
-----------------------------------------------------------------------
呵呵,做PCB价格只跟尺寸,层数有关吧。。。。至于你铺多少铜,我想厂家不会在意的。。。。。。。。。 早知道我就全都铺上了。 竟然搜到你的帖子了,顶一下! 回复【楼主位】soso_lxy
-----------------------------------------------------------------------
强! 顶~ 这新手。。。。。PCB作得比我好~~~~ 哈哈 楼主能不能加上个电波种接收模块,这样就省的对时了。 回复【楼主位】soso_lxy
-----------------------------------------------------------------------
能否提供:1602、5V、 MINIUSB口供电 的封装?
我的Q:448254938 1602能显示 " ° "符号。 楼主也是学化学的啊,同行啊 楼主的这个程序已经超过8K了,AT89S52能烧进去?我用STC89c52试了一下,装不下 我调DS3231,如同楼主刚开始一样,各种悲剧,从MSP430单片机,换成STC89C52,都不行。
郁闷了好长时间。
程序怎么看都是对的。
电路没毛病,
后来,在程序没改的情况下,用手把电源线多插拔了几次,居然好使了,不知道什么原因。 mark Mark下,下不了代码,标记一下。 mark 不错 楼主很强啊! 楼主,PCB花了how much??? 近来想自己搞块板板的,but看到那价格,就有点怕... 那排针很强大!!!! mark下 23楼长了一个大猪头,楼主明明写着1602+DS3231+STC89C53,你偏偏要用s52. 哪个厂家制的板,我也想去做几块 我头一次听说,官方的例程有点乱的。。嘿嘿 很给力,哈哈 经过鉴定 发现lz是有钱淫 楼主的话里面全是泡泡 记号下 不错~
咋这么多句号呀。。。。。。。。。。。。。。。。。。。。。。。。。。。 楼主你那个PCB打样得多少钱呀? 楼主看天祥的教程吧?有个地方我怀疑你被误导了,我一直在怀疑这个问题,今天在你的程序里看见了这个,所以特的验证了一下:
void delay()
{
;;
}
你的这个函数里的 ;; 是不起作用的,编译的时候会被自动忽略
口说无凭,看看这个函数的反汇编代码(KEIL 0级优化)吧
RSEG?PR?delay?MAIN
delay:
USING 0
; SOURCE LINE # 11
; {
; SOURCE LINE # 12
; ;;
; }
; SOURCE LINE # 14
?C0004:
RET
; END OF delay
END
汇编代码里的 ; 号就是注释,END是伪指令,类似注释的东西,告诉编译器函数块到这里就结束了
这下明白了吧?整个函数只执行一条指令, RET,就是return
如果你还不相信,你可以反汇编调试一下,看到底执行了哪几句,我这里顺便贴上来
代码就这点
void delay()
{
;;
}
void main()
{
delay();
while(1);
}
反汇编调试, 我在执行了的语句后加标号,(1) 表示第1个执行的指令,(2)表示第2个...
; .\main.SRC generated from: main.c
; COMPILER INVOKED BY:
; D:\Program Files\Keil\C51\BIN\C51.EXE main.c OMF2 OPTIMIZE(0,SPEED) BROWSE INCDIR(..\..\INC;..\..\8051codelib\INC) DEBUG SRC(.\main.SRC)
NAME MAIN
?PR?delay?MAIN SEGMENT CODE
?PR?main?MAIN SEGMENT CODE
EXTRN CODE (?C_STARTUP)
PUBLIC main
PUBLIC delay
; void delay()
RSEG?PR?delay?MAIN
delay:
USING 0
; SOURCE LINE # 1
; {
; SOURCE LINE # 2
; ;;
; }
; SOURCE LINE # 4
?C0001:
RET
; END OF delay
;
; void main()
RSEG?PR?main?MAIN
main:
USING 0
; SOURCE LINE # 6
; {
; SOURCE LINE # 7
; delay();
; SOURCE LINE # 8
LCALL delay ;--------------------------------------------------------------------(1)
?C0002:
; while(1);
; SOURCE LINE # 9
SJMP ?C0002 ;--------------------------------------------------------------------(3, 4, ...,死循环)
?C0003:
; }
; SOURCE LINE # 10
?C0004:
RET ;--------------------------------------------------------------------(2)
; END OF main
END
要说这个函数真的有延时,那也对,
因为调用函数基本上都有执行LCALL(函数调用的指令)和RET(返回指令,就相当于return;),这里就有几个机器周期了(对51的汇编不熟,具体多少时间我也不清楚)
感谢楼主开源~以后在论坛里多多交流~./emotion/em012.gif 另外再给楼主个建议
按键扫描最好不要软件Delay,用状态机
我也是菜鸟,前段时间里看见论坛里有人讨论这个问题,所以特地去了解了一下,原理还是挺简单的
楼主可以去看 马潮 编的书
http://ishare.iask.sina.com.cn/f/8882764.html
印象中貌似是第9章吧。。。(AVR我也没学过。。。看他的程序的构思就行了,很简单的) 回复【楼主位】soso_lxy
-----------------------------------------------------------------------
呵呵。。我以前先用面包板弄下,再pcb. 做个记号,楼主继续努力 牛B啊! PCB画得这么好还是第一次呢,LZ太谦了 本帖最后由 youjianbaba 于 2012-4-2 21:43 编辑
楼主,我做了一块与你一样的板子,用的相同器件,单只截取你的3231部分,但无法读取时间?
#include <STC89.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
/********1602定义***********************/
#define LCD_DB P0
sbit LCD_RS=P2^1;//0为指令,1为写数据
sbit LCD_RW=P2^2;//0可写入,1为读
sbit LCD_E=P2^5;//1允许
/*******ds3231相关定义*********/
/**************************** defines *******************************/
sbit SCL = P1^7; /* I2C pin definitions */
sbit SDA = P1^6;
sbit int0 = P3^2;
sbit rest = P3^6;
#define ADDRTW0xD0 //器件写地址
#define ADDRTD0xD1 //器件读地址
//#define DS3231_WriteAddress 0xD0 //器件写地址
//#define DS3231_ReadAddress0xD1 //器件读地址
#define DS3231_SEC 0x00 //秒
#define DS3231_MIN 0x01 //分
#define DS3231_HOUR 0x02 //时
#define DS3231_DAY 0x03 //星期
#define DS3231_DATE 0x04 //日
#define DS3231_MONTH 0x05 //月
#define DS3231_YEAR 0x06 //年
//闹铃1
#define DS3231_Al1SEC 0x07 //秒
#define DS3231_AL1MIN 0x08 //分
#define DS3231_AL1HOUR 0x09 //时
#define DS3231_AL1DAY 0x0A //星期/日
//闹铃2
#define DS3231_AL2MIN 0x0b //分
#define DS3231_AL2HOUR 0x0c //时
#define DS3231_AL2DAY 0x0d //星期/日
#define DS3231_CONTROL 0x0e //控制寄存器
#define DS3231_STATUS 0x0f //状态寄存器
#define BSY 2 //忙
#define OSF 7 //振荡器停止标志
#define DS3231_XTAL 0x10 //晶体老化寄存器
#define DS3231_TEMP_H 0x11 //温度寄存器高字节(8位)
#define DS3231_TEMP_L 0x12 //温度寄存器低字节(高2位)
//extern xdata uchar sec, min, hour, day, date, month, year,Dtemp;
//extern xdata uchar al1_min,al1_hour,al1_day,al2_min,al2_hour,al2_day;
uchar year,month,date,day,hour,min,sec,Dtemp=0;
uchar al1_min,al1_hour,al1_day,al2_min,al2_hour,al2_day;
/*********************** Function Prototypes **************************/
uchar BCD2HEX(uchar val);
uchar B_BCD(uchar val);
void delayus(uchar i);
void Start();
void Stop();
void I2CACK(bit a);
void SendByte(uchar Dat);
uchar ReceiveByte(uchar b);
uchar I2CWrite(uchar addr,uchar bytedata);
uchar I2CRead();
uchar I2CReadAdd(uchar addr);
void read_temp();
void init_alrm();
void Readtime();
void ReadAlarm();
void SetTime(uchar yea,uchar mon,uchar da,uchar hou,uchar min,uchar sec);
void InitDS3231();
bit runnian();
void autoweek();
bit ack;
uchar qushi;
/*******按键定义******/
sbit KEY= P3^2;
void InitTimer0(void);
//要在哪行那位显示啥就修改a和b
uchar idata c[]="ABCDEFGHIJKLMNOP";//显示字符串,一行最多16个字母
uchar idata d[]="0123456789abcdef";
uchar idata num="0123456789";//数字表
uchar a="2000-00-00 Day 0";//显示字符串,一行最多16个字母
uchar b="00-00-0000C ";
//////////"0123456789123456";
/******定义函数****************/
#define Busy 0x80 //DB7为1时表示忙,为0时表示闲
#define SomeNOP(); { _nop_(); }//空函数,用于微小延时,包含在intrins.h
void LCD_init(void);//初始化函数
void WaitForEnable( void );
void LCD_write_command(uchar dat,uchar AttribC);//写指令函数
void LCD_write_data(uchar dat);//写数据函数
void LCD_disp_addw(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X(0-16),y(1-2)
void LCD_disp_lin(uchar x,uchar y,uchar dat[],uchar s);
void Delay5Ms(void);//延时函数
//********************************
//*******初始化函数***************
void LCD_init(void)
{
LCD_write_command(0x38,0);//设置8位格式,2行,5x7
Delay5Ms();
LCD_write_command(0x38,0);//设置8位格式,2行,5x7
Delay5Ms();
LCD_write_command(0x38,0);//设置8位格式,2行,5x7
Delay5Ms();
LCD_write_command(0x38,1);//设置8位格式,2行,5x7
LCD_write_command(0x08,1);// 显示关闭
LCD_write_command(0x01,1);//清除屏幕显示
LCD_write_command(0x06,1);//设定输入方式,增量不移位
LCD_write_command(0x0c,1);//整体显示,无光标,闪烁,0x0c
Delay5Ms();
}
/*=======================================================
正常读写操作之前必须检测LCD控制器状态: CS=1 RS=0 RW=1
DB7: 0 LCD控制器空闲; 1 LCD控制器忙---忙信号检测函数
========================================================*/
void WaitForEnable( void )//测忙函数
{
LCD_DB=0xff;
LCD_RS=0;
LCD_RW=1;
SomeNOP();
LCD_E=1;
SomeNOP();
SomeNOP();
while(LCD_DB&Busy);
LCD_E=0;
}
//********************************
//********写指令函数************
void LCD_write_command(uchar dat,uchar AttribC)
{
if (AttribC) WaitForEnable(); // 检测忙信号
LCD_DB=dat;
LCD_RS=0;//指令
LCD_RW=0;//写入
LCD_E=1;//允许
SomeNOP();
LCD_E=0;
Delay5Ms();
}
//*******************************
//********写数据函数*************
void LCD_write_data(uchar dat)
{
LCD_DB=dat;
LCD_RS=1;//数据
LCD_RW=0;//写入
LCD_E=1;//允许
SomeNOP();
LCD_E=0;
Delay5Ms();
}
//********************************
//**指定显示位置******************
void LCD_disp_addw(uchar x,uchar y,uchar dat)
{
uchar address;
if(y==1)
address=0x80+x;//第一行
if(y==2)
address=0xc0+x;//第二行
LCD_write_command(address,0);
LCD_write_data(dat);
}
//********************************
//*******显示多个字符函数或向任意行的任意位置写任意个字符,但位置不能超过16个*********
//x表示开始位置,第一位为1;y表示行数;dat[]是要显示的内容;s表示内容的长度,最大16
void LCD_disp_lin(uchar x,uchar y,uchar dat[],uchar s)
{
uchar ss;
if(s>16||x>16)return;//各种情况下保证不超过16位
x=x-1;//为了符合自然习惯,在调用本函数是1代表末一行的第一位
if(s+x>16)return;//各种情况下保证不超过16位
for(ss=0;ss<s;ss++)
{
LCD_disp_addw(x++,y,dat);//指向每个字符,一个一个的写,x轴自动加1,y表示行
}
}
// 短延时
void Delay5Ms(void)
{uchar w,i,j;
for(w=5;w>0;w--)
for(i=2;i>0;i--)
for(j=255;j>0;j--);
}
/************************************************************/
/**********开始3231***********/
uchar BCD2HEX(uchar val) //BCD转换为Byte
{
uchar i;
i= val&0x0f;
val >>= 4;
val &= 0x0f;
val *= 10;
i += val;
return i;
}
uchar B_BCD(uchar val)//B码转换为BCD码
{
uchar i,j,k;
i=val/10;
j=val%10;
k=j+(i<<4);
return k;
}
void delayus(uchar i)
{
while(--i) ;
}
/************************START***************************/
void Start()
{
SDA=1; //发送起始条件的数据信号
delayus(1);
SCL=1;
delayus(5); //起始条件建立时间大于4.7us,延时
SDA=0; //发送起始信号
delayus(5); // 起始条件锁定时间大于4μs
SCL=0; //钳住I2C总线,准备发送或接收数据
delayus(2);
}
/********************************************************/
/************************STOP****************************/
void Stop()
{
SDA=0; //发送结束条件的数据信号
delayus(1); //发送结束条件的时钟信号
SCL=1; //结束条件建立时间大于4us
delayus(5);
SDA=1; //发送I2C总线结束信号
delayus(4);
}
/********************************************************/
/*******************************************************************
字节数据发送函数
函数原型: void SendByte(uchar Dat);
功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0)
ack=1 发送数据正常,
ack=0 被控器无应答或损坏。
********************************************************************/
void SendByte(uchar Dat)
{
uchar BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
{
if((Dat<<BitCnt)&0x80)
SDA=1; //判断发送位
else
SDA=0;
delayus(1);
SCL=1; //置时钟线为高,通知被控器开始接收数据位
delayus(5); //保证时钟高电平周期大于4μs
SCL=0;
}
delayus(2);
SDA=1; //8位发送完后释放数据线,准备接收应答位
delayus(2);
SCL=1;
delayus(3);
if(SDA==1)
ack=0;
else
ack=1; //判断是否接收到应答信号
SCL=0;
delayus(2);
}
/********************************************************/
/*******************************************************************
字节数据接收函数
函数原型: uchar RcvByte();
功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数应答从机。
********************************************************************/
uchar RcvByte()
{
uchar retc;
uchar BitCnt;
retc=0;
SDA=1; //置数据线为输入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{
delayus(1);
SCL=0; //置时钟线为低,准备接收数据位
delayus(5); //时钟低电平周期大于4.7μs
SCL=1; //置时钟线为高使数据线上数据有效
delayus(3);
retc=retc<<1;
if(SDA==1)
retc=retc+1; //读数据位,接收的数据位放入retc中
delayus(2);
}
SCL=0;
delayus(2);
return(retc);
}
/********************************************************************
应答子函数
函数原型: void I2CACK(bit a);
功能: 主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
********************************************************************/
void I2CACK(bit a)
{
if(a==0)
SDA=0; //在此发出应答或非应答信号
else
SDA=1;
delayus(3);
SCL=1;
delayus(5); //时钟低电平周期大于4μs
SCL=0; //清时钟线,钳住I2C总线以便继续接收
delayus(2);
}
/****************************************************/
/***********将一个字节写入DS3231指定的地址***********/
uchar I2CWrite(uchar addr,uchar bytedata)
{
Start();
SendByte(ADDRTW);
if (ack == 0)
return 0;
SendByte(addr);
if (ack == 0)
return 0;
SendByte(bytedata);
if (ack == 0)
return 0;
Stop();
delayus(10);
return 1;
}
/****************************************************/
/************从DS3231当前地址读一个字节************/
uchar I2CRead()
{
uchar read_data;
Start();
SendByte(ADDRTD);
if(ack==0)
{
LCD_disp_addw(11,1,'t');/////
return(0);
}
read_data = RcvByte();
I2CACK(1);
Stop();
return read_data;
}
/****************************************************/
/************从DS3231指定地址读一个字节************/
uchar I2CReadAdd(uchar addr)
{
Start();
SendByte(ADDRTD);
if(ack==0)
{
LCD_disp_addw(12,1,'x');/////老是这里通不过 return(0);
}
SendByte(addr);
if(ack==0)
{
LCD_disp_addw(13,1,'y');
return(0);
}
return(I2CRead());
}
/***************************************************/
/*********************读取时间**********************/
void Readtime()
{
uchar temp;
temp=I2CReadAdd(DS3231_SEC);//秒
sec=BCD2HEX(temp);
temp=I2CReadAdd(DS3231_MIN);//分
min=BCD2HEX(temp);
temp=I2CReadAdd(DS3231_HOUR);//时
//temp&=0x3F;
hour=BCD2HEX(temp);
day=I2CReadAdd(DS3231_DAY);//星期
temp=I2CReadAdd(DS3231_DATE);//日
date=BCD2HEX(temp);
temp=I2CReadAdd(DS3231_MONTH); //月
month=BCD2HEX(temp);
temp=I2CReadAdd(DS3231_YEAR);//年
year=BCD2HEX(temp);
Dtemp=I2CReadAdd(DS3231_TEMP_H);//温度
}
/***************************************************/
/*******************读取闹铃时间********************/
void ReadAlarm()
{
uchar temp;
temp=I2CReadAdd(DS3231_AL1MIN);//分
al1_min=BCD2HEX(temp);
temp=I2CReadAdd(DS3231_AL1HOUR);//时
al1_hour=BCD2HEX(temp);
temp=I2CReadAdd(DS3231_AL1DAY);//星期or日
al1_day=BCD2HEX(temp);
temp=I2CReadAdd(DS3231_AL2MIN);//分
al2_min=BCD2HEX(temp);
temp=I2CReadAdd(DS3231_AL2HOUR);//时
al2_hour=BCD2HEX(temp);
temp=I2CReadAdd(DS3231_AL2DAY);//星期or日
al2_day=BCD2HEX(temp);
}
bit runnian()//闰年判断
{
if((year%4==0&&year%100!=0)||(year%100==0&&year%400==0))
{
return 1;
}
else
{
return 0;
}
}
void autoweek()
{
Readtime();
if( month == 1 || month == 2 )
{
month += 12;
if( year> 0 )
year--;
else
year = 4;
}
day = (1+(( date + 2*month + 3*(month+1)/5 + year + year/4 ) %7));
I2CWrite(DS3231_DAY,day);
}
void InitDS3231()
{
SCL=1;
delayus(5);
SDA=1;
delayus(5);
I2CWrite(DS3231_AL1DAY,0x81); //A1M4置位,时分秒匹配时闹钟响应
I2CWrite(DS3231_AL2DAY,0x81); //A2M4置位,时分匹配时闹钟响应
I2CWrite(DS3231_CONTROL,0x04); //中断允许,闹钟1和2关闭
I2CWrite(DS3231_STATUS,0x00); //32KHZ输出禁止,闹钟标志位清零
//SetTime(11,1,14,8,10,0);
}
/**********3231函数结束******/
void TimeDisplay(uchar Dhour,uchar Dmin,uchar Dsec)
{
b=num; // 时十位
b=num; // 时个位
b=num; // 分十位
b=num; // 分个位
b=num; // 秒十位
b=num; // 秒个位
}
//uchar a[]="2000-00-00 Day 0";//显示字符串,一行最多16个字母
//uchar b[]="00-00-0000C ";
////////////"0123456789123456";
void DateDisplay(uchar Dyear,uchar Dmonth,uchar Dday)
{
a=num; // 年十位
a=num; // 年个位
a=num; // 月十位
a=num; // 月个位
a=num; // 天十位
a=num; // 天个位
}
/*******定时器0*****/
void InitTimer0(void)//定时器0开,模式1,时长50ms
{
EA = 1;
TMOD = 0x01;
ET0 = 1;
TH0 = 0x3C;
TL0 = 0xB0;
TR0 = 1;
}
void Timer0Interrupt(void) interrupt 1
{
qushi=qushi+1;
if(qushi==8)//ds3231取时间隔400ms
{
qushi=0;
Readtime();//显示时间
Delay5Ms();
Delay5Ms();
Delay5Ms();
DateDisplay(year,month,date);
TimeDisplay(hour,min,sec);
//字符串显示
//函数原型void LCD_disp_lin(uchar x,uchar y,uchar dat[],uchar s)
//x表示开始位置,第一位为1;y表示行数;dat[]是要显示的内容;s表示内容的长度,最大16
LCD_disp_lin(1,1,a,16);//从指定显示位置显示多个字符,这里指第1行第1位开始
LCD_disp_lin(1,2,b,16);//从指定显示位置显示多个字符,这里指第2行第1位开始
Delay5Ms();
}
//在任意行的任意位置单个字母显示,原始函数,直接调用LCD_disp_addw,可以不用啦
//LCD_disp_addw(0,1,'V');//从指定显示位置显示一个字符,这里指第1行第1位,每行最多16个字符
//LCD_disp_addw(0,2,'Q');//从指定显示位置显示一个字符,这里指第2行第1位
TR0 = 0;//重新装定定时器0
TH0 = 0x3C;
TL0 = 0xB0;
TR0 = 1;
}
//*********主函数*****************
void main(void)
{
LCD_init();//初始化
LCD_disp_lin(1,1,c,16);//从指定显示位置显示多个字符,这里指第1行第1位开始
LCD_disp_lin(1,2,d,16);//从指定显示位置显示多个字符,这里指第2行第1位开始
Delay5Ms();
Delay5Ms();
Delay5Ms();
rest=0;
InitDS3231(); //初始化DS3231
autoweek(); //开机自动星期转换
Delay5Ms();
Delay5Ms();
Delay5Ms();
qushi=0;
InitTimer0();//定时器0开,模式1,时长50ms
while(1);
}
楼主强! 学化学的也来抢我们饭碗了,呵呵 {:biggrin:}多谢分享 mige062 发表于 2011-4-3 15:05
我调DS3231,如同楼主刚开始一样,各种悲剧,从MSP430单片机,换成STC89C52,都不行。
郁闷了好长时间。
程 ...
用ATMEGA16没搞定,结果用AT89S52一调就通了。郁闷了半天。 wb5846410 发表于 2011-7-31 06:40
23楼长了一个大猪头,楼主明明写着1602+DS3231+STC89C53,你偏偏要用s52.
楼主,开始用的S52,后天因为没有预留ISP,所以改用STC,这样不用来回插拔了。 youjianbaba 发表于 2012-4-2 21:40
楼主,我做了一块与你一样的板子,用的相同器件,单只截取你的3231部分,但无法读取时间?
#include
#incl ...
换程序吧,我没用楼主的,
http://www.amobbs.com/forum.php?mod=viewthread&tid=5531595&pid=7171389&page=1&extra=#pid7171389
这个链接二楼的,用S52一调就通了。 下载楼主的程序参考下,我用STC单片机控制。。。 这个必须顶!楼主好样的,话说,我也是业余做做【表情】 能否发个PCB,偷个懒{:smile:} 支持lz的开源 我仿制了一个两个,一个用了stc89c52,一个用了stc12c5a60s2 stc12c5a60s2 不成功,stc89c52能运行,但是年月日字符是乱码,不知错在那 lz 我仿制为何有乱码
页:
[1]