时钟芯片SD2068使用说明及AVR C语言时钟写程序
- 格式:docx
- 大小:28.78 KB
- 文档页数:12
#include "stdio.h"#include "graphics.h"#include "math.h"#include "time.h"#include "dos.h"#define r 200#define pi 3.1415926#define X(a,b,c) x=a*cos(b*c*pi/180-pi/2)+300; /*遇到X(a,b,c) 就用x=a*cos(b*c*pi/180-pi/2)+300 替换*/#define Y(a,b,c) y=a*sin(b*c*pi/180-pi/2)+240; /*遇到Y(a,b,c) 就用y=a*sin(b*c*pi/180-pi/2)+240; 替换*/#define d(a,b,c) X(a,b,c);Y(a,b,c);line(300,240,x,y) /*宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起置换*//*那么就是当执行d(200,12,6)时相当于写了3句话首先X(a,b,c) 也就是X(200,12,6) 这时计算x=200*cos(12*6*pi/180-pi/2)+300也就是计算出了以半径为200,度数为12 步长为6 (实际上就是72度但是这里又减去了pi/2 也就是72-45=27度)的那点的横坐标也就是x的数值然后执行Y(a,b,c)也就是Y(200,12,6)这时计算y=200*sin(12*6*pi/180-pi/2)+240也就是计算出了以半径为200,度数为12 步长为6 (实际上就是72度但是这里又减去了pi/2 也就是72-45=27度)的那点的纵坐标也就是y的数值最后是line(300,240,x,y) 也就是画线这样指针就出来了那么这里第一个参数是设置半径长度第二个参数是设置度数第三个参数是设置步长(度数)*/main(){int x=300,y=240,bx,by,bx1,by1,bx2,by2,bx3,by3,jd,i,j,k,h1,m1,hc=0,l,ax,ay,n,p=0;char b[]={'I',' ',' ',' ',' ','L','o','v','e',' ',' ',' ',' ','Y','o','u'};int driver=VGA,mode=VGAHI; /*定义图形驱动器*/int h,m,s; /*定义时针hour 分针minute 秒针second*/ struct time t[1]; /*定义一个结构体名为time的数组,只有一个成员t[0]*/initgraph(&driver,&mode,""); /*设置图形驱动器*/setbkcolor(0); /*设置背景色为黑色*/for(n=0;n<=27;n++)printf("\n");for(n=0;n<=29;n++)printf(" ");setcolor(14); /*设置前景色为黄色*/circle(x,y,r); /*以300,240,半径为200画大圆*/setcolor(12); /*设置前景色为洋红色*/circle(x,y,190); /* 内部小圆*//*设置填充样式及颜色*/setfillstyle(SOLID_FILL,14); /*实心填充*/floodfill(x,y,12); /* 填充表盘填充色为洋红(12)*/ setfillstyle(SOLID_FILL,13); /*实心填充*/floodfill(1,1,14);setcolor(2); /*设置为绿色*//*画表心*/circle(x,y,2); /*表心小圆*/circle(x,y,5); /*表心大圆*//*眼睛*/ellipse(x-80,y-70,0,360,23,65); /*左外面的椭圆*/ellipse(x+80,y-70,0,360,23,65); /*右外面的椭圆*/ellipse(x-80,y-60,0,180,23,23); /*左里面的椭圆*/setfillstyle(SOLID_FILL,0); /*实型填充填充颜色为黑色*/floodfill(x-80,y-60,2); /*填充颜色绿色*/ellipse(x+80,y-60,0,180,23,23); /*右里面的椭圆*/setfillstyle(SOLID_FILL,0); /*实型填充填充颜色为黑色*/floodfill(x+80,y-70,2); /*填充颜色绿色*//* outtextxy(225,380,"EmBEdDed 06241 ShiwU");outtextxy(245,400,"MaDE In HuaXiA"); *//*六个胡子*/setcolor(5); /* 粉红色*/line(x-120,y+70,x-250,y+90);line(x-120,y+90,x-250,y+110);line(x-120,y+110,x-250,y+130);line(x+120,y+70,x+250,y+90);line(x+120,y+90,x+250,y+110);line(x+120,y+110,x+250,y+130);/*画耳朵*/arc(150,80,0,360,60); /*画圆弧(此处完全可以用圆来代替)*/setfillstyle(SOLID_FILL,14); /*填充色黄色*/floodfill(150,80,5);arc(450,80,0,360,60);setfillstyle(SOLID_FILL,14);floodfill(450,80,5);setcolor(14); /*擦除内部圆弧痕迹*/arc(150,80,0,360,60);arc(450,80,0,360,60);/*画嘴*/setcolor(0);ellipse(x,y+60,160,340,23,23); /*用圆弧画嘴*//*画侧脸*/circle(x+120,y+10,23); /*前景色为0 侧面的圆圈*/setfillstyle( SOLID_FILL,12); /*实型填充颜色为12 淡洋红*/floodfill(x+120,y+10,0); /*以侧面的圆心为中心边缘颜色为0 白色进行对封闭图形的填充*/setcolor(14); /*设置前景色为黄色清除内部圆弧痕迹*/ circle(x+120,y+10,23); /*重新画小圈*/setcolor(0); /*前景色为0 侧面的圆圈*/circle(x-120,y+10,23); /*以下同上*/setfillstyle( SOLID_FILL,12);floodfill(x-120,y+10,0);setcolor(14);circle(x-120,y+10,23);ellipse(x,y+60,0,180,23,23);for(i=0;i<60;i++){if(i%5==0) l=15;else l=5;ax=200*cos(i*6*pi/180)+300;ay=200*sin(i*6*pi/180)+240;bx=(200-l)*cos(i*6*pi/180)+300;by=(200-l)*sin(i*6*pi/180)+240;line(ax,ay,bx,by);}setwritemode(1); /*这句无敌了*/gettime(t); /*得到系统时间给数组t实际上就是给了t[0]*/ h=t[0].ti_hour; /*时针数值给h*/m=t[0].ti_min; /*分针数值给m*/s=t[0].ti_sec;/*秒针数值给s*/setcolor(7); /*设置前景色为7 淡灰色*//*第一个参数是设置半径长度第二个参数是设置起始度数第三个参数是设置步长(度数)*/d(150,h,30); /*以半径为150,h为起始度数,步长为30度,时针总共一圈才走12下*/setcolor(14); /*设置分针颜色1 蓝色*/d(170,m,6); /*以半径170,m为起始度数,步长为6度,分针一圈走60下*/setcolor(4); /*设置秒针颜色4 红色*/d(190,s,6); /*以半径190,s为起始度数,步长为6度,秒针一圈走60下*/while(!kbhit()) /*当不敲击键盘时候一直循环*/{while(t[0].ti_sec==s) /*判断当前系统时间是否与刚才得到的秒时间相等,一定相等,没有刷新系统时间*/gettime(t);setcolor(4);d(190,s,6); /*所以重新刷新系统时间*/s=t[0].ti_sec;setfillstyle(SOLID_FILL,13); /*实心填充*/floodfill(1,380,14);if(p<=15){ setbkcolor(hc); printf("%c",b[p]); }elsesetbkcolor(0);p++;setcolor(4); /*设置秒针颜色为2 绿色*/d(190,s,6);if (t[0].ti_min!=m) /*判断当前系统时间(分)与刚才得到的分是否相等*/{setcolor(14);d(170,m,6);m=t[0].ti_min;d(170,m,6);}if (t[0].ti_hour!=h){setcolor(7);d(150,h,30);h=t[0].ti_hour;d(150,h,30);}setcolor(hc++);if(hc==12)hc=0;ellipse(300,300,160,340,23,23);/*眼睛*/ellipse(220,170,0,360,23,65); ellipse(380,170,0,360,23,65); ellipse(220,180,0,180,23,23); ellipse(380,180,0,180,23,23);arc(150,80,20,250,59);arc(450,80,-70,165,59);}getch();}。
51-数字时钟-89C52-单片机C语言程序数字时钟89C52 单片机C语言程序STC89C52|/************** 【数字时钟】****************//****【功能】1、时间显示2、秒表3、闹钟4、日期显示都可以设置****/#include /*包含器件配置文件*/#define uchar unsigned char /*宏定义字符型数据整型数据*/ #define uint unsigned intuchar code H[] = {0x0f, 0x07, 0x0b, 0x0d, 0x0e}; /*按键【P3】端口断码用于按键*/ char Code[10] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d,0x7d, 0x07, 0x7f, 0x6f}; /*显示【0 1 2 3 4 5 6 7 8 9】数字的数码管的段码*/ uchar code C[] = {0x0, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F};/*列扫描控制LED1位2位3位4位5位6位7位8位*/uchar MON[]={0,31,28,31,30,31,30,31,31,30,31,30,31};uchar A;uchar BIN=0; /* 【BIN】作为倒计时开始的标志*/uchar hour = 0; /* 定义[时][分][秒] */uchar min = 0;uchar sec = 0;uint shi=12;uint fen=30;uchar Mmin=0;uchar Msec=30;uchar M0=0;uchar m=0;uchar year=9;uchar month=7;uchar month2;uchar day=19;uchar set1 = 1; /* set1=1 是调节时分秒set1=2时时调节年月日set=3时事调节闹钟*/uchar set2 = 1; /* set2=1时是调节【时】位set2=2时事调节【分】位*/uint x = 0; /* x 每【0.01s】自加一*/void Delay(uint k);void Timer0() /*定时器T0 5mS初始化*/{TMOD = 0x01; /*设置*定时器0**计数方式一* (每12个时钟脉冲计数一次)或IT0=1 第二种计数方式*/TH0 = (65536 - 10000) / 256; /*给定计时器高位赋予初值=15536/256*/TL0 = (65536 - 10000) % 256; /*给定计时器低位赋予初值=15536%256 */ET0 = 1; /*打开定时器外部终断0允许ET1是中断器1的开关*/ EA = 1; /*打开总中断允许*/TR0 = 1;}void T0_srv(void) interrupt 1 /*5mS定时中断服务函数秒分时的值*/{TH0 = (65536 - 10000) / 256; /*给定计时器高位赋予初值=15536/256*/TL0 = (65536 - 10000) % 256; /*给定计时器低位赋予初值=15536%256 */x++;if(x==100){sec++;x=0; /*没每一秒【sec】加一*/if(sec==60){min++;sec=0;if(min==60) /*每一分钟【min】加一*/ {min = 0;hour++;if(hour==24){hour = 0; /*每一小时【hour】加一*/ day++;if(year%4==0) /*是否闰年的判断*/ MON[2]=29;else MON[2]=28;if(day==MON[month]){day=0;month++;}}}}}if(BIN==1)if(Mmin!=0||Msec!=0){M0 = 100-x;if(M0==100){ if(Mmin>0){Msec--;if(Msec==0){Msec=60;Mmin-- ;}if(Msec==0) {Mmin=0;Msec=0;M0=0;} }if(Mmin==0){if(Msec!=0)Msec--;if(Msec==0){Msec=0;M0=0;}}}}if(Mmin==0&&Msec==0){M0=0;}} /*秒表分秒M0的赋值*/}void Scan_key() /*按键扫描函数【Scan_key()】*/ {P3=H[0];if(P3!=H[0])Delay(1);if(P3==H[4]){set1++;if(set1>4) set1 = 1;er1: if(P3==H[4]) goto er1; /*按下键后未释放,在此等候*/ }Delay(1);if(P3==H[3]){set2++;if(set2>3) set2 = 1;er2: if(P3==H[3]) goto er2; /*按下键后未释放,在此等候*/ }Delay(1);if(P3==H[1]){BIN++;if(BIN>1) BIN=0;er3: if(P3==H[1]) goto er3; /*按下键后未释放,在此等候*/ }}}void Time_show() /*时间的显示变量为【时】【分】【秒】*/ { P0 = Code[hour/10]; /*第一位数字显示【时】的【十】位*/ P2 = C[1];Delay(1);P0 = Code[hour%10]; /*第二位数字显示【时】的【个】位*/P2 = C[2];Delay(1);if(x/50==0)P0 = 0x40; /*第三位符号【-】的显示*/elseP0 = 0x00;P2 = C[3];Delay(1);P0 = Code[min/10]; /*第四位的数字的显示【分】的【十】位*/ P2 = C[4];Delay(1);P0 = Code[min%10]; /*第五位的数字显示【分】的【个】位*/ P2 = C[5];Delay(1);Delay(1);if(x/50==0)P0 = 0x40; /*第六位符号【-】的显示*/elseP0 = 0x00;P2 = C[6];Delay(1);P0 = Code[sec/10]; /*第七位数字的显示【秒】的【十】位显示*/P2 = C[7];Delay(1);P0 = Code[sec%10]; /*第八位数字的显示【秒】的【个】位显示*/ P2 = C[8];Delay(1);}void Year_show(){P0 = Code[year/10]; /*第一位数字显示【年】的【十】位*/P2 = C[1];Delay(1);P0 = Code[year%10]; /*第二位数字显示【年】的【个】位*/P2 = C[2];Delay(1);P0 = 0x40; /*第三位符号【-】的显示*/P2 = C[3];Delay(1);P0 = Code[month/10]; /*第四位的数字的显示【月】的【十】位*/P2 = C[4];Delay(1);P0 = Code[month%10]; /*第五位的数字显示【月】的【个】位*/P2 = C[5];Delay(1);Delay(1);P0 = 0x40; /*第六位符号【-】的显示*/P2 = C[6];Delay(1);P0 = Code[day/10]; /*第七位数字的显示【天】的【十】位显示*/P2 = C[7];Delay(1);P0 = Code[day%10]; /*第八位数字的显示【天】的【个】位显示*/ P2 = C[8];Delay(1);}void Clock_show(){P0 = Code[shi/10]; /*第一位数字显示【时】的【十】位*/P2 = C[4];P0 = Code[shi%10]; /*第二位数字显示【时】的【个】位*/P2 = C[5];Delay(1);P0 = 0x40; /*第三位符号【-】的显示*/P2 = C[6];Delay(1);P0 = Code[fen/10]; /*第四位的数字的显示【分】的【十】位*/ P2 = C[7];Delay(1);P0 = Code[fen%10]; /*第五位的数字显示【分】的【个】位*/P2 = C[8];Delay(1);}void Miao_show() /*时间的显示变量为【时】【分】【秒】*/ { P0 = Code[Mmin/10]; /*第一位数字显示【时】的【十】位*/P2 = C[1];Delay(1);P0 = Code[Mmin%10]; /*第二位数字显示【时】的【个】位*/ P2 = C[2];Delay(1);P0 = 0x40; /*第三位符号【-】的显示*/P2 = C[3];Delay(1);P0 = Code[Msec/10]; /*第四位的数字的显示【分】的【十】位*/ P2 = C[4];Delay(1);P0 = Code[Msec%10]; /*第五位的数字显示【分】的【个】位*/ P2 = C[5];Delay(1);P0 = 0x40; /*第六位符号【-】的显示*/P2 = C[6];Delay(1);P0 = Code[M0/10]; /*第七位数字的显示【秒】的【十】位显示*/P2 = C[7];Delay(1);P0 = Code[M0%10]; /*第八位数字的显示【秒】的【个】位显示*/ P2 = C[8];Delay(1);}void Time_set() /*调整时间的函数time_set() */{Scan_key();if(set1==1){if(set2==1) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) hour++; /*按一下第三行的键hour 就加一*/Delay(1);if(hour>24) hour=0;while(P3==H[2]); /*按键未释放,在此等候*/}if(set2==2) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) min++; /*按一下第三行的键hour 就加一*/Delay(1);if(min>60){ min=0; hour++;}while(P3==H[2]); /*按键未释放,在此等候*/}}}void Year_set() /*调整时间的函数time_set() */{Scan_key();if(set1==2){if(set2==1) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) year++; /*按一下第三行的键hour 就加一*/ Delay(1);if(year>100) year=0;while(P3==H[2]);}if(set2==2) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) month++; /*按一下第三行的键hour 就加一*/ Delay(1);if(month>12){ month=0; year++;}while(P3==H[2]);}if(set2==3){if(P3==H[2]) day++; /*按一下第三行的键hour 就加一*/ Delay(1);if(day>MON[month]){ day=0; month++;}while(P3==H[2]); /*按键未释放,在此等候*/}}}Clock_set(){Scan_key();if(set1==3){if(set2==1) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) shi++; /*按一下第三行的键hour 就加一*/ Delay(1);if(shi>24) shi=0;while(P3==H[2]); /*按键未释放,在此等候*/}if(set2==2) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) fen++; /*按一下第三行的键hour 就加一*/ Delay(1);if(fen>60){ fen=0; shi++;}while(P3==H[2]); /*按键未释放,在此等候*/}}}void Miao_set() /*调整时间的函数time_set() */{Scan_key();if(set1==4){if(set2==1) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) Mmin++; /*按一下第三行的键hour 就加一*/Delay(1);if(Mmin>24) Mmin=0;while(P3==H[2]); /*按键未释放,在此等候*/}if(set2==2) /*当set1=1 set2=1时位时的设置*/{if(P3==H[2]) Msec++; /*按一下第三行的键hour 就加一*/ Delay(1);。
c语言课程设计钟表一、教学目标本节课的学习目标为:知识目标:使学生掌握C语言中指针、函数、结构体等基本概念;理解并掌握钟表的运行原理及其在C语言中的实现方式。
技能目标:培养学生具备运用C语言进行钟表程序设计的能力;提高学生的编程思维和问题解决能力。
情感态度价值观目标:激发学生对计算机科学的兴趣,培养学生的创新精神和团队合作意识。
二、教学内容本节课的教学内容主要包括:1.C语言基础知识:指针、函数、结构体等基本概念。
2.钟表运行原理:时钟、分针、秒针的运动规律及其表示方法。
3.钟表程序设计:利用C语言实现钟表的运行,包括时钟、分针、秒针的动态显示。
三、教学方法本节课采用以下教学方法:1.讲授法:讲解C语言基础知识,引导学生理解并掌握基本概念。
2.案例分析法:分析钟表运行原理,让学生通过实际案例理解并掌握钟表的实现方法。
3.实验法:学生动手编写钟表程序,培养学生的实际编程能力和问题解决能力。
四、教学资源本节课所需教学资源包括:1.教材:《C语言程序设计》等相关教材,用于引导学生学习基础知识。
2.多媒体资料:钟表运行原理PPT、编程实例等,用于辅助讲解和展示。
3.实验设备:计算机、编程环境等,用于学生动手实践。
4.在线资源:相关编程教程、讨论区等,用于学生课后自学和交流。
五、教学评估本节课的评估方式包括:1.平时表现:评估学生在课堂上的参与程度、提问回答等情况,占总评的30%。
2.作业:评估学生完成的编程练习质量和进度,占总评的40%。
3.考试:进行一次钟表程序设计考试,评估学生的综合编程能力,占总评的30%。
评估方式应客观、公正,全面反映学生的学习成果。
教师应及时给予反馈,指导学生改进学习方法和策略。
六、教学安排本节课的教学安排如下:1.进度:按照教材和教学大纲,合理安排每个阶段的教学内容,确保在有限的时间内完成教学任务。
2.时间:根据学生的作息时间,选择合适的时间段进行授课,保证学生的学习效果。
3.地点:选择安静、设施齐全的教室作为教学地点,创造良好的学习环境。
Fax:86-0731-******* Mail:dsc52@ Web: 源点教育项目报告一、功能要求:(1)、电路图对学员要求是一样,完整电路图请见原理图。
(2)、由图1所示:正常显示(上电显示)如下:星期时分两红灯亮秒闪(3)、●按下key1第一次,显示如下:年月{阳历}日{阳历}两红灯亮两灯亮●再按下key1,则回到正常显示,依次类推。
(4)、在任何显示状态下,按下key1超过2秒,则进入设置状态,同时显示“时、分、秒”闪烁。
此时按下key2,“秒”闪,进入设置状态。
再按下key2,“分”闪,进入设置状态。
再按下key2,“时”闪,进入设置状态。
再按下key2,显示“星期、月{阳历}、日{阳历}”,同时“日{阳历}”闪,进入设置状态。
再按下key2,“月{阳历}”闪,进入设置状态。
再按下key2,“星期”闪,进入设置状态。
再按下key2,显示“年(四个数码管显示)”,同时“年”闪,进入设置状态。
再按下key2,则回到“秒”重复设计置。
注:进入设置状态时,key3作减键,key4作加键,并且key3,key4具有连动功能(如果key3或者key4按下持续1秒后,以0.5秒时间连减或者连加)(5)、在(2)的任何状态下,按下key5,则回正常显示。
(6)、在正常显示状态下:按下key5超过2秒,则进入闹钟设置状态。
Fax:86-0731-******* Mail:dsc52@ Web: 再按key5则回正常显示。
三、扩展功能要求。
(1)、按下key6,把闹钟时间存于AT24C16里。
(2)、由图1所示:正常显示(上电显示)如下:星期时分两红灯亮秒闪(3)、●按下key1第一次,显示如下:年月{阳历}日{阳历}两红灯亮两灯亮●按下key1第二次,显示如下:年月{阴历}日{阴历}两红灯闪两灯闪●再按下key1,则回到正常显示,依次类推。
(4)、在任何显示状态下,按下key1超过2秒,则进入设置状态,同时显示“时、分、秒”闪烁。
湖南人文科技学院课程设计报告课程名称:单片机原理及应用课程设计设计题目:电子时钟的设计系别:通信与控制工程系专业:通信工程班级:09级通信二班学生姓名: 袁琦黄文付学号: 09416230 09416227起止日期: 2011年12月20日~2011年12月30日指导教师:王善伟姚毅谢四莲教研室主任:刘建闽.指导教师评语:指导教师签名:年月日成绩评定项目权重成绩袁琦黄文付1、设计过程中出勤、学习态度等方面0.22、课程设计质量与答辩0.53、设计报告书写及图纸规范程度0.3总成绩教研室审核意见:教研室主任签字:年月日教学系审核意见:.摘要时钟是人类日常生活必不可少的工具,本设计从日常生活中常见的事物入手,通过对电子时钟的设计,让我们认识到单片机已经深入到我们生活的每个领域,该设计不仅可以锻炼我们的动手能力,而且可以加深我们对单片机的认识和激发我们对未知科学领域的探索。
本文利用单片机实现数字时钟计时功能的主要内容。
它体积小,成本低、功能强、使用方便、可靠性高等一系列优点,广泛应用于智能产业和工业自动化上。
本次设计采用独立式按键进行时间调整,其中STC89C52是核心元件,同时采用数码管LED动态显示“时”,“分”,“秒”的现代计时装置。
与传统机械表相比,它具有走时精确,显示直观等特点。
它的计时周期为24小时,显满刻度为“23时59分59秒”,另外利用DS1302具有校时功能,断电后有记忆功能,恢复供电时可实现计时同步等特点。
该系统同时具有硬件设计简单、工作稳定性高、价格低廉等优点。
关键词:STC89C52 ;LED数码管;8255芯片;DS1302芯片;目录设计要求 (1)1.方案论证与对比 (1)1.1方案一 (1)1.2方案二 (2)1.3方案对比 (3)2.系统硬件电路的设计 (3)2.1单片机的选择及引脚功能介绍 (3)2.2 8255A芯片的结构及引脚功能介绍 (5)2.3 DS1302芯片的结构及引脚功能介绍 (8)2.4显示电路设计 (9)2.5电源电路设计 (10)2.6键盘动态扫描电路设计 (10)3.控制系统的软件设计 (12)3.1主程序流程图 (12)3.2显示子程序 (13)3.3闹钟时间设定功能程序 (14)3.4键盘扫描程序 (15)4.系统功能调试与整体指标 (16)4.1硬件调试与分析 (16)4.2软件调试与分析 (16)4.3性能分析 (16)5.详细仪器清单 (17)6.总结与思考及致谢 (18)参考文献 (19)附录一:程序(方案一) (21)附录二:程序(方案二) (36)电子时钟的设计设计要求利用单片机作为控制核心,完成一个时钟计时器。
SD2068低功耗、两线接口、数字时钟调整功能、多种中断/报警系统、12字节用户RAM,并具备多种抗干扰措施下为SD2068 AVR 单片机时钟C程序:#include <iom64v.h>#include <macros.h>#define uchar unsigned char#define uint unsigned int#define ulong unsigned long//数据sda的位设置#define sda_in DDRC &= ~(1 << PC1) //数据设置输入#define sda_out DDRC |= (1 << PC1) //数据设置输出#define sda_setb PORTC |= (1 << PC1) //数据拉高#define sda_clr PORTC &= ~(1 << PC1) //数据拉低#define sda_r PINC & (1 << PC1) //数据读取//时钟scl的位设置#define scl_in DDRC &= ~(1 << PC0) //时钟设置输入#define scl_out DDRC |= (1 << PC0) //时钟设置输出#define scl_setb PORTC |= (1 << PC0) //时钟拉高#define scl_clr PORTC &= ~(1 << PC0) //时钟拉低#define scl_r PINC & (1 << PC0) //时钟读取//===============#define true 1#define false 0//===============uchar date[7]; //日期数组/*date[6]=year,date[5]=month,date[4]=day,date[3]=week,date[2]=hour,date[1]=minute,date[0]=second*/uchar bat1,bat2,temp; //电池电量和温度uint bat; //电池电量值uchar data1[8]; //EEPROM数据//=================================================================== =/*延时子程序*/void delay_ms(uint time) //11.0592M,time=1表示延时1ms {uint i;for(;time>0;time--)for(i=0;i<1571;i++);asm("nop");asm("nop");asm("nop");}void delay_1us(void) //11.0592M, 1us延时函数{asm("nop");}void delay_us(uint time) //11.0592M, Nus延时函数{uint i;for (i=0;i<time;i++)asm("nop");}//=================================================================== ==/********开启SD30系列的I2C总线********/uchar I2CStart(void){sda_out;scl_out;delay_1us();sda_setb;scl_setb;delay_us(5);sda_in;delay_us(5);if(!sda_r)return false; //SDA线为低电平则总线忙,退出sda_out;delay_1us();sda_clr;delay_us(10);sda_in;delay_us(10);while(sda_r)return false; //SDA线为高电平则总线出错,退出scl_clr;delay_us(5);return true;}//********关闭SD30系列的I2C总线****// void I2CStop(void){scl_out;sda_out;delay_1us();sda_clr;delay_1us();scl_clr;delay_us(5);scl_setb;delay_us(2);sda_setb;}//*********发送 ACK****//void I2CAck(void){scl_out;sda_out;delay_1us();sda_clr;delay_1us();scl_clr;delay_us(5);scl_setb;delay_us(5);scl_clr;}/*********发送NO ACK*********/void I2CNoAck(void){scl_out;sda_out;delay_1us();sda_setb;delay_1us();scl_clr;delay_us(5);scl_setb;delay_us(5);scl_clr;}//*********读取ACK信号*********uchar I2CWaitAck(void) //返回为:1=有ACK,0=无ACK{uchar errtime=255;scl_out;sda_in;delay_1us();scl_clr;delay_us(5);scl_setb;delay_1us();sda_in;delay_1us();while(sda_r){errtime--;delay_1us();if(!errtime){delay_us(10);scl_clr;return false;}}scl_clr;return true;}/************MCU向SD30系列发送一个字节*************/void I2CSendByte(uchar demand) //数据从高位到低位{uchar bd=8;sda_out;scl_out;while(bd--){scl_clr;delay_1us;if(demand&0x80){sda_setb;}else{sda_clr;}demand<<=1;delay_us(3);scl_setb;delay_us(3);}scl_clr;}/*********MCU从SD30系列读入一字节*********/uchar I2CReceiveByte(void) //数据从高位到低位//{uchar bl=8;uchar ddata=0;scl_out;delay_1us();delay_1us();sda_in; //端口切换为输入状态!!sda_setb; //有的单片机需要加这句,如果不需要可以删掉delay_1us();while(bl--){ddata<<=1; //数据从高位开始读取delay_1us();scl_clr;delay_us(5); //从高位开始ddata|=SDA;ddata<<=1scl_setb;delay_us(5);if(sda_r){ddata|=0x01;}}scl_clr;return ddata;}/******读SD30系列实时数据寄存器******/char I2CReadDate(void){uchar n;if(!I2CStart())return false;I2CSendByte(0x65);if(!I2CWaitAck()){I2CStop(); return false;}for(n=0;n<7;n++){date[n]=I2CReceiveByte();if (n!=6) //最后一个数据不应答{I2CAck();}}I2CNoAck();I2CStop();}/******写SD30系列实时数据寄存器******/char I2CWriteDate(void) // 设置时间:2013年2月2日 07:59:55 星期一。
写时间操作要求一次对实时时间寄存器(00H~06H)依次写入,{ // 不可以单独对7个时间数据中的某一位进行写操作 , 否则可能会引起时间数据的错误进位.// 所以要修改其中某一个数据 , 应一次性写入全部 7 个实时时钟数据.WriteTimeOn(); // 使能,开锁if(!I2CStart())return false;I2CSendByte(0x64);if(!I2CWaitAck()){I2CStop(); return false;}I2CSendByte(0x00); //设置写起始地址I2CWaitAck();I2CSendByte(0x55); //secondI2CWaitAck();I2CSendByte(0x59); //minuteI2CWaitAck();I2CSendByte(0x07|0x80); //hour ,二十四小时制I2CWaitAck();I2CSendByte(0x01); //weekI2CWaitAck();I2CSendByte(0x02); //dayI2CWaitAck();I2CSendByte(0x02); //monthI2CWaitAck();I2CSendByte(0x13); //yearI2CWaitAck();I2CStop();WriteTimeOff(); //使能,关锁}/******写SD30系列单字节程序******/void WriteOneByte(uchar add, uchar date){WriteTimeOn();I2CStart();I2CSendByte(0x64);I2CWaitAck();I2CSendByte(add); //设置写地址I2CWaitAck();I2CSendByte(date); //写数据I2CWaitAck();I2CStop();WriteTimeOff();}/******读SD30系列单字节程序******/uchar ReadOneByte(uchar add){uchar buf;I2CStart();I2CSendByte(0x64);I2CWaitAck();I2CSendByte(add); //设置要读的地址I2CWaitAck();I2CStart();I2CSendByte(0x65); //写数据I2CWaitAck();buf=I2CReceiveByte(); //读数据I2CNoAck();I2CStop();return buf;}/******设置SD30系列报警中断演示程序******/void WriteALARM(void) //设置报警时间:2012年2月14日8:00{WriteOneByte(0x09,0x08); //8时WriteOneByte(0x0b,0x14); //14日WriteOneByte(0x0c,0x14); //02月WriteOneByte(0x0d,0x14); //12年WriteOneByte(0x0e,0x74); //设置报警允许(使能年、月、日、小时报警)WriteOneByte(0x10,0x92); //设置INT中断选通(INTS1,INTS0),及报警中断总允许位(INTAE)}/******关闭SD30XX报警中断程序******/void ClrALARM(void) //关闭报警中断{WriteOneByte(0x10,0x90);}/******设置SD30XX倒计时中断******/void SetDjs(void) //设置倒计时中断{WriteOneByte(0x10,0x0f); //先清倒计时中断总允许位(INTDE)WriteOneByte(0x10,0xf4); //设置周期性中断(IM=1)INT中断选通(INTS1,INTS0),配置倒计时中断总允许位(INTDE)WriteOneByte(0x11,0x30); //选择定时器频率源(TDS1、TDS0)为1/60HZWriteOneByte(0x13,5); //倒计时初值寄存器,设置24位倒计时计数初值(5min)WriteOneByte(0x14,0); //倒计时初值寄存器,设置24位倒计时计数初值(5min)WriteOneByte(0x15,0); //倒计时初值寄存器,设置24位倒计时计数初值(5min)}/******关闭SD30XX倒计时中断程序******/void ClrDjs(void){WriteOneByte(0x10,0xf0);}/******设置SD30XX频率中断******/void SetFrq(void){WriteOneByte(0x10,0xa1); //选通频率中断(INTS1,INTS0),设置频率中断总允许位(INTFE)WriteOneByte(0x11,0x09); //设置2Hz频率中断}/******关闭SD30XX频率中断******/void ClrFrq(void){WriteOneByte(0x10,0xa0);}/******尾缀B、C型第一页,F型写EEPROM程序(连续写)******/void WriteEE(uchar sramadd,uchar sramdata){uchar n;I2CStart();I2CSendByte(0xa0); //发送EEPROM写寄存器命令I2CWaitAck();I2CSendByte(sramadd); //发送访问地址I2CWaitAck();for(n=0;n<8;n++){I2CSendByte(sramdata); //发送数据,数据写入寄存器单元(地址自动加1)。