基于PCF8563的单片机数字时钟

更新时间:2024-07-01 01:23:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

LCD1C21930pU1XTAL1P0.0/AD0P0.1/AD1P0.2/AD2P0.3/AD3P0.4/AD4P0.5/AD5P0.6/AD6P0.7/AD7P2.0/A8P2.1/A9P2.2/A10P2.3/A11P2.4/A12P2.5/A13P2.6/A14P2.7/A15P3.0/RXDP3.1/TXDP3.2/INT0P3.3/INT1P3.4/T0P3.5/T1P3.6/WRP3.7/RD393837363534333221222324252627281011121314151617P02P03P04P05AMPIRE128X64RP1987654321P00P01P02P03P04P05P06P07RP298765432110KP30P31P32P33P34P35P36P37X1C130p12MHz18XTAL29RST1k47u293031PSENALEEA181716151413121110987654321-VoutRSTDB7DB6DB5DB4DB3DB2DB1DB0ER/WRSV0VCCGNDCS2CS1R1C3P20P21RV154K1kP31P17P16P15P14P13P12P11P10P32P34P33P36P37K1K2K3设置键P03加键P04P101P112P123P134P145P156P167P178P1.0/T2P1.1/T2EXP1.2/ECIP1.3/CEX0P1.4/CEX1P1.5/CEX2P1.6/CEX3P1.7/CEX4AT89C51RD2P30P31P32P33P34P35P36P37P1[0..7]RP398765432110KP20P21P22P23P24P25P26P27RP498765432110KP10P11P12P13P14P15P16P17减键P05键盘电路+12VU2P20P2165SCLSDAOSCIOSCO84VDDVSSCLKOUTINT1273CRYSTALX2R24.7kP02321C420pFU3VCCDQGNDDS18B201N41487.0PCF8563D1D21N4148B13VC6温度检测电路47uFC50.1uF

//---库函数声明及相关定义---// #include #include

#define uchar unsigned char #define uint unsigned int sbit SDA=P2^1;//数据 sbit SCL=P2^0;//时钟

#define Databus P1 /*液晶数据总线*/

bit Reverse_Display=0;//是否反相显示(白底黑字/黑底白字) sbit RS=P3^3; /*数据\\指令 选择*/ sbit RW=P3^4; /*读\\写 选择*/ sbit EN=P3^2; /*读\\写使能*/ sbit cs1=P3^6; /*片选1*/ sbit cs2=P3^7; /*片选2*/

uchar g8563_Store[8]; /*时间交换区,全局变量声明*/

uchar code c8563_Store[8]={0x50,0x59,0x23,0x31,0x06,0x12,0x00,0x19}; /*写入时间初值:世纪,09年 7月 星期一 13日 07:59:00*/

sbit DQ=P0^2;//ds18b20与单片机连接口 float f_temp;//浮点型温度值 unsigned int tvalue;//温度值

unsigned char tflag; unsigned int temp=0;

unsigned char SegBuf_DS18B20[4]={0};

sbit menu=P0^3;//菜单 sbit add=P0^4;//加一 sbit dec=P0^5;//减一

uchar second,minute,hour,day,month,year,week,count=0;

/********************************/ /* 定义中文字库 */

/********************************/ uchar code Hzk[]={

0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00,//年//0 0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00, 0x00,0x00,0x00,0x00,0x00,0xFF,0x11,0x11,0x11,0x11,0x11,0xFF,0x00,0x00,0x00,0x00,//月//1 0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x01,0x01,0x21,0x41,0x3F,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,0x00,0x00,//日//2 0x00,0x00,0x00,0x3F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x3F,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xBE,0x2A,0x2A,0x2A,0xEA,0x2A,0x2A,0x2A,0x2A,0x3E,0x00,0x00,0x00,//星//3 0x00,0x48,0x46,0x41,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x49,0x49,0x41,0x40,0x00, //4 //5 //6 //7 //8 //9

0x00,0x04,0xFF,0x54,0x54,0x54,0xFF,0x04,0x00,0xFE,0x22,0x22,0x22,0xFE,0x00,0x00,//

0x42,0x22,0x1B,0x02,0x02,0x0A,0x33,0x62,0x18,0x07,0x02,0x22,0x42,0x3F,0x00,0x00,

0x00,0xFC,0x44,0x44,0x44,0xFC,0x10,0x90,0x10,0x10,0x10,0xFF,0x10,0x10,0x10,0x00,//时0x00,0x07,0x04,0x04,0x04,0x07,0x00,0x00,0x03,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,

0x80,0x40,0x20,0x98,0x87,0x82,0x80,0x80,0x83,0x84,0x98,0x30,0x60,0xC0,0x40,0x00,//分0x00,0x80,0x40,0x20,0x10,0x0F,0x00,0x00,0x20,0x40,0x3F,0x00,0x00,0x00,0x00,0x00,

0x12,0x12,0xD2,0xFE,0x91,0x11,0xC0,0x38,0x10,0x00,0xFF,0x00,0x08,0x10,0x60,0x00,//秒0x04,0x03,0x00,0xFF,0x00,0x83,0x80,0x40,0x40,0x20,0x23,0x10,0x08,0x04,0x03,0x00,

0x00,0x40,0x42,0x42,0x42,0x42,0x42,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x40,0x00,//天0x00,0x80,0x40,0x20,0x10,0x08,0x06,0x01,0x02,0x04,0x08,0x10,0x30,0x60,0x20,0x00,

0x00,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,//一0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x06,0x04,0x00,0x00,0x00,//二//10 0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x18,0x10,0x00, 0x00,0x04,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x04,0x00,0x00,//三//11 0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00, 0x00,0xFE,0x02,0x02,0x02,0xFE,0x02,0x02,0xFE,0x02,0x02,0x02,0x02,0xFE,0x00,0x00,//四//12 0x00,0x7F,0x28,0x24,0x23,0x20,0x20,0x20,0x21,0x22,0x22,0x22,0x22,0x7F,0x00,0x00, 0x00,0x02,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0xC2,0x82,0x02,0x00,0x00,0x00,//五//13 0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x30,0x20,0x00, 0x10,0x10,0x10,0x10,0x10,0x91,0x12,0x1E,0x94,0x10,0x10,0x10,0x10,0x10,0x10,0x00,//六//14 0x00,0x40,0x20,0x10,0x0C,0x03,0x01,0x00,0x00,0x01,0x02,0x0C,0x78,0x30,0x00,0x00, 0x00,0x40,0x42,0x44,0x4C,0x40,0x40,0x7F, 0x40,0x40,0x48,0x44,0xE6,0x40,0x00,0x00, 0x00,0x40,0x44,0x44,0x44,0x44,0x44,0x44, 0x44,0x44,0x44,0x44,0xFF,0x00,0x00,0x00,//当//15 0x08,0x08,0xE8,0x29,0x2A,0x2E,0xE8,0x08, 0x08,0xCC,0x0A,0x0B,0xE8,0x0C,0x08,0x00, 0x00,0x00,0xFF,0x09,0x49,0x89,0x7F,0x00,

0x00,0x0F,0x40,0x80,0x7F,0x00,0x00,0x00,//前//16

0x10,0x22,0x64,0x0C,0x80,0x00,0xFE,0x92, 0x92,0x92,0x92,0x92,0xFF,0x02,0x00,0x00, 0x04,0x04,0xFE,0x01,0x40,0x7E,0x42,0x42,

0x7E,0x42,0x7E,0x42,0x42,0x7E,0x40,0x00,//温//17

0x00,0x00,0xFC,0x24,0x24,0x24,0xFC,0xA5, 0xA6,0xA4,0xFC,0x24,0x34,0x26,0x04,0x00, 0x40,0x20,0x9F,0x80,0x42,0x42,0x26,0x2A,

0x12,0x2A,0x26,0x42,0x40,0xC0,0x40,0x00,//度//18

0x00,0x00,0x00,0x00,0x7F,0x49,0x49,0x49, 0x49,0x49,0x7F,0x00,0x00,0x80,0x00,0x00, 0x01,0x81,0x41,0x21,0x1D,0x21,0x41,0x7F,

0x89,0x89,0x8D,0x89,0x81,0xC1,0x41,0x00,//是//19

0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0x80, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x31,0x7B,0x7B,0x31,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//://20

0x40,0x40,0x42,0xCC,0x00,0x40,0xA0,0x9F, 0x81,0x81,0x81,0x9F,0xA0,0x20,0x20,0x00, 0x00,0x00,0x00,0x7F,0xA0,0x90,0x40,0x43,

0x2C,0x10,0x28,0x26,0x41,0xC0,0x40,0x00,//设//21

0x00,0x10,0x17,0xD5,0x55,0x57,0x55,0x7D, 0x55,0x57,0x55,0xD5,0x17,0x10,0x00,0x00, 0x40,0x40,0x40,0x7F,0x55,0x55,0x55,0x55,

0x55,0x55,0x55,0x7F,0x40,0x60,0x40,0x00,//置//22

0x40,0x42,0x44,0xCC,0x00,0x20,0x22,0x22, 0xE2,0x22,0x22,0x23,0x32,0x20,0x00,0x00, 0x00,0x40,0x20,0x1F,0x20,0x48,0x4C,0x4B,

0x48,0x48,0x4A,0x4C,0x58,0x60,0x20,0x00,//运//23

0x00,0x10,0x88,0xC4,0x23,0x40,0x42,0x42, 0x42,0x42,0x42,0xC2,0x43,0x62,0x40,0x00, 0x02,0x01,0x00,0xFF,0x00,0x00,0x00,0x00,

0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,//行//24

0x00,0xF8,0x08,0x08,0x08,0x08,0x08,0xFF, 0x08,0x08,0x08,0x08,0x08,0xFC,0x08,0x00, 0x00,0x03,0x01,0x01,0x01,0x01,0x01,0xFF,

0x01,0x01,0x01,0x01,0x01,0x03,0x00,0x00,//中//25

0x00,0x06,0x09,0x09,0xE6,0xF0,0x18,0x08, 0x08,0x08,0x18,0x30,0x78,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x07,0x0F,0x18,0x30,

0x20,0x20,0x20,0x10,0x08,0x00,0x00,0x00,//℃//26 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 空格//27 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };

/****************************************/ /* 定义ASCII字库8列*16行 */

/****************************************/ uchar code Ezk[]={

/*此字体下对应的点阵为:宽x高=8x16 --*/

/*-- 宋体12; 此字体下对应的点阵为:宽x高=8x16 --*/ 0x00,0x00,0xF0,0xF8,0x08,0x68,0xF8,0xF0,0x00,0x00,0x07,0x0F,0x0B,0x08,0x0F,0x07, //0

0x00,0x20,0x20,0x30,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0F,0x00,0x00, //1 0x00,0x30,0x38,0x08,0x88,0xF8,0x70,0x00,0x00,0x0C,0x0E,0x0B,0x09,0x08,0x08,0x00, // 2 0x00,0x30,0x38,0x88,0x88,0xF8,0x70,0x00,0x00,0x06,0x0E,0x08,0x08,0x0F,0x07,0x00, //3 0x00,0x00,0xF8,0xF8,0x00,0xE0,0xE0,0x00,0x00,0x03,0x03,0x02,0x02,0x0F,0x0F,0x02,//4 0x00,0xF8,0xF8,0x88,0x88,0x88,0x08,0x00,0x00,0x08,0x08,0x08,0x0C,0x07,0x03,0x00,//5 0x00,0xC0,0xE0,0x78,0x58,0xC8,0x80,0x00,0x00,0x07,0x0F,0x08,0x08,0x0F,0x07,0x00,//6 0x00,0x08,0x08,0x88,0xE8,0x78,0x18,0x00,0x00,0x00,0x0E,0x0F,0x01,0x00,0x00,0x00,//7 0x00,0x70,0xF8,0xC8,0x88,0xF8,0x70,0x00,0x00,0x07,0x0F,0x08,0x09,0x0F,0x07,0x00,//8 0x00,0xF0,0xF8,0x08,0x08,0xF8,0xF0,0x00,0x00,0x00,0x09,0x0D,0x0F,0x03,0x01,0x00,//9 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // - -//10 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x80,0x80,0xE0,0xE0,0x80,0x80,0x00, // -+-//11 0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x00, 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00, // ---//12 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // -.-//13 0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x00 };

/*状态检查,LCD是否忙*/ void CheckState() {

uchar dat; /*状态信息,判断是否忙*/

RS=0; /*数据\\指令选择,D/I(RS)=“L” ,表示 DB7∽DB0 为显示指令数据*/

RW=1; /*R/W=“H” ,E=“H”数据被读到DB7∽DB0*/ do{

Databus=0x00;

EN=1; /*EN下降源*/ _nop_(); /*一个时钟延时*/ dat=Databus; EN=0;

dat=0x80 & dat;/*仅当第7位为0时才可操作(判别busy信号)*/ }while(!(dat==0x00)); }

/*写命令到LCD中*/

SendCommandToLCD(uchar com) {

CheckState();/*状态检查,LCD是否忙*/

RS=0; /*向LCD发送命令。RS=0写指令,RS=1写数据*/ RW=0; /*R/W=“L” ,E=“H→L”数据被写到 IR 或 DR */ Databus=com; /*com :命令*/

EN=1; /*EN下降沿*/ _nop_(); _nop_(); EN=0; }

/*设置页 0xb8是页的首地址*/ void SetLine(uchar page) {

page=0xb8|page; /*1011 1xxx 0<=page<=7 设定页地址--X 0-7,8行为一页64/8=8,共8页*/ SendCommandToLCD(page); }

/*设定显示开始行,0xc0是行的首地址*/ void SetStartLine(uchar startline) { startline=0xc0|startline; /*1100 0000*/

SendCommandToLCD(startline); /*设置从哪行开始:0--63,一般从0 行开始显示*/ }

/*设定列地址--Y 0-63 ,0x40是列的首地址*/ void SetColumn(uchar column) {

column=column &0x3f; /*column最大值为64,越出 0=

/*开关显示,0x3f是开显示,0x3e是关显示*/ void SetOnOff(uchar onoff) {

onoff=0x3e|onoff; /*0011 111x,onoff只能为0或者1*/ SendCommandToLCD(onoff); }

/*写显示数据 */

void WriteByte(uchar dat) {

CheckState();/*状态检查,LCD是否忙*/

RS=1; /*RS=0写指令,RS=1写数据*/

RW=0; /*R/W=“L” ,E=“H→L”数据被写到 IR 或 DR */ if(!Reverse_Display) /*根据Reverse_Display决定是否反相显示*/ Databus=dat; /*dat:显示数据*/ else

Databus=~dat;

EN=1; /*EN下降沿*/ _nop_(); _nop_(); EN=0; }

/*选择屏幕screen: 0-全屏,1-左屏,2-右屏*/ void SelectScreen(uchar screen) { switch(screen) {

case 0: cs1=0;/*全屏*/

_nop_(); _nop_(); _nop_(); cs2=0;

_nop_(); _nop_(); _nop_(); break;

case 1: cs1=0;/*左屏*/

_nop_(); _nop_(); _nop_(); cs2=1;

_nop_(); _nop_(); _nop_(); break;

case 2: cs1=1;/*右屏*/

_nop_(); _nop_(); _nop_(); cs2=0;

_nop_(); _nop_(); _nop_(); break; } }

/*清屏screen: 0-全屏,1-左屏,2-右*/ void ClearScreen(uchar screen) { uchar i,j; SelectScreen(screen); for(i=0;i<8;i++) /*控制页数0-7,共8页*/ { SetLine(i); SetColumn(0); for(j=0;j<64;j++) /*控制列数0-63,共64列*/ { WriteByte(0x00); /*写点内容,列地址自动加1*/ } } }

/*初始化LCD*/ void InitLCD() {

CheckState(); SelectScreen(0);

SetOnOff(0); /*关显示*/ SelectScreen(0);

SetOnOff(1); /*开显示*/ SelectScreen(0);

ClearScreen(0); /*清屏*/ SetStartLine(0);/*开始行:0*/ }

/*--------------------------显示全角汉字-----------------------*/

/*ss选屏参数,pagr选页参数,column选列参数,number选第几汉字输出*/

/*ss=1右屏2左屏,pagr=0,2,4,6第0~3行,column=0~3汉子出现的列,number选第几汉字输出*/

void Display(uchar ss,uchar page,uchar column,uchar number) {

uchar i;

SelectScreen(ss);

column=column&0x3f;

SetLine(page); /*写上半页*/ SetColumn(column); /*控制列*/

for(i=0;i<16;i++) /*控制16列的数据输出*/ {

WriteByte(Hzk[i+32*number]);/*i+32*number汉字的前16个数据输出*/ }

SetLine(page+1); /*写下半页*/ SetColumn(column); /*控制列*/

for(i=0;i<16;i++) /*控制16列的数据输出*/ {

WriteByte(Hzk[i+32*number+16]);/*i+32*number+16汉字的后16个数据输出*/ } }

/*---------------------显示半角汉字和数字和字母----------------------*/

/*选屏参数,pagr选页参数,column选列参数,number选第几汉字输出*/ void Displayen(uchar ss,uchar page,uchar column,uchar number) {

uchar i;

SelectScreen(ss);

column=column&0x3f;

SetLine(page); /*写上半页*/ SetColumn(column);

for(i=0;i<8;i++) {

WriteByte(Ezk[i+16*number]); }

SetLine(page+1); /*写下半页*/ SetColumn(column); for(i=0;i<8;i++) {

WriteByte(Ezk[i+16*number+8]); } }

/******************************************** 内部函数,延时1

********************************************/ void Delay() {

// {P10=1;_nop_();P10=0;} _nop_();

_nop_(); /*根据晶振频率制定延时时间*/ }

/******************************************** 内部函数,I2C开始

********************************************/ void P8563_Start() { EA=0; SDA=1; SCL=1; Delay(); SDA=0; Delay(); SCL=0; }

/******************************************** 内部函数,I2C结束

********************************************/ void P8563_Stop() {

SDA=0; SCL=0; Delay(); SCL=1; Delay(); SDA=1; Delay();

EA=1; }

/********************************************

内部函数,输出ACK ,每个字节传输完成,输出ack=0,结束读书据,ack=1; ********************************************/ void P8563_WriteACK(uchar ack) {

SDA=ack; Delay(); SCL=1; Delay(); SCL=0; }

/******************************************** 内部函数,等待ACK

********************************************/ void P8563_WaitACK() { uchar errtime=20; SDA=1;

Delay(); /*读ACK*/ SCL=1; Delay(); while(SDA) { errtime--;

if(!errtime) P8563_Stop(); }

SCL=0; Delay(); }

/******************************************** 内部函数.输出数据字节 入口:B=数据

********************************************/ void P8563_writebyte(uchar wdata) {

uchar i;

for(i=0;i<8;i++) {

if(wdata&0x80) SDA=1; else SDA=0; wdata<<=1; SCL=1; Delay(); SCL=0;

}

P8563_WaitACK(); //I2C器件或通讯出错,将会退出I2C通讯 }

/******************************************** 内部函数.输入数据 出口:B

********************************************/ uchar P8563_Readbyte() {

uchar i,bytedata; SDA=1;

for(i=0;i<8;i++) {

SCL=1;

bytedata<<=1; bytedata|=SDA; SCL=0; Delay(); }

return(bytedata); }

/******************************************** 输出数据->pcf8563

********************************************/ void P8563_writeData(uchar address,uchar mdata) {

P8563_Start();

P8563_writebyte(0xa2); /*写命令*/ P8563_writebyte(address); /*写地址*/ P8563_writebyte(mdata); /*写数据*/ P8563_Stop(); }

/******************************************** 输入数据<-pcf8563

********************************************/ uchar P8563_ReadData(uchar address) /*单字节*/ { uchar rdata; P8563_Start();

P8563_writebyte(0xa2); /*写命令*/ P8563_writebyte(address); /*写地址*/ P8563_Start();

P8563_writebyte(0xa3); /*读命令*/ rdata=P8563_Readbyte(); P8563_WriteACK(1);

P8563_Stop(); return(rdata); }

void P8563_ReadData1(uchar address,uchar count,uchar * buff) /*多字节*/ { uchar i;

P8563_Start();

P8563_writebyte(0xa2); /*写命令*/ P8563_writebyte(address); /*写地址*/ P8563_Start();

P8563_writebyte(0xa3); /*读命令*/ for(i=0;i

buff[i]=P8563_Readbyte();

if(i

P8563_WriteACK(1); P8563_Stop(); }

/******************************************** 内部函数,读入时间到内部缓冲区

********************************************/ void P8563_Read()

{ uchar time[7],century; P8563_ReadData1(0x02,0x07,time); century=time[5];

g8563_Store[0]=time[0]&0x7f; /*秒*/ g8563_Store[1]=time[1]&0x7f; /*分*/ g8563_Store[2]=time[2]&0x3f; /*小时*/ g8563_Store[3]=time[3]&0x3f; /*日*/ g8563_Store[4]=time[4]&0x07; /*星期*/ g8563_Store[5]=time[5]&0x1f; /*月*/ g8563_Store[6]=time[6]&0xff; /*年*/ g8563_Store[7]=century&0x80; /*取世纪,00为2000,80为1900*/ if(g8563_Store[7]==0x00)g8563_Store[7]=20; if(g8563_Store[7]==0x80)g8563_Store[7]=19; }

/******************************************** 读入时间到内部缓冲区----外部调用

********************************************/ void P8563_gettime() {

P8563_Read();

if(g8563_Store[0]==0)

P8563_Read(); /*如果为秒=0,为防止时间变化,再读一次*/ }

/******************************************** 写时间修改值

********************************************/ void P8563_settime() { P8563_writeData(2,g8563_Store[0]);//秒 P8563_writeData(3,g8563_Store[1]);//分 P8563_writeData(4,g8563_Store[2]);//时 P8563_writeData(5,g8563_Store[3]);//日 P8563_writeData(6,g8563_Store[4]);//星期 if(g8563_Store[7]==0x20)g8563_Store[5]=(g8563_Store[5]&0x3F);//判断世纪 if(g8563_Store[7]==0x19)g8563_Store[5]=(g8563_Store[5]|0x80);//判断世纪 P8563_writeData(7,g8563_Store[5]);//月 P8563_writeData(8,g8563_Store[6]);//年 }

/******************************************** P8563的初始化

********************************************/ void P8563_init() {

uchar i;

if((P8563_ReadData(0xa)&0x3f)!=0x8) /*检查是否第一次启动,是则初始化时间*/ {

for(i=0;i<8;i++) g8563_Store[i]=c8563_Store[i]; /*初始化时间*/ P8563_settime();

P8563_writeData(0x0,0x00);

P8563_writeData(0xa,0x8); /*8:00报警*/ P8563_writeData(0x1,0x12); /*报警有效*/ P8563_writeData(0xd,0xf0); } }

//---BCD转换16函数---// void BCD_16( ) {

uchar i,ucData1,ucData2; for(i=0;i<7;i++) { ucData1=g8563_Store[i]/16; //BCD码转十六进制

ucData2=g8563_Store[i]; g8563_Store[i]=ucData1*10+ucData2; } }

//---DS18B20延时函数---//

void delay_18B20(unsigned int i)//延时1微秒 {

while(i--); }

//---DS18B20复位函数---//

//DS18B20要求数据线拉低500US即可复位。 void ds1820rst() { unsigned char x=0; }

DQ = 1;//DQ复位

delay_18B20(4);//延时 DQ = 0;//DQ拉低

delay_18B20(100);//精确延时大于480us DQ = 1;//拉高

delay_18B20(40);

//---DS18B20读数据函数---// unsigned char ds1820rd() { unsigned char i=0; unsigned char dat = 0; for (i=8;i>0;i--) { DQ = 0; //给脉冲信号 dat>>=1; DQ = 1; //给脉冲信号 if(DQ) dat|=0x80; delay_18B20(10); } return(dat); }

//---DS18B20写数据函数---//

void ds1820wr(unsigned char wdata) { unsigned char i=0;

}

for (i=8; i>0; i--) { DQ = 0; DQ = wdata&0x01; delay_18B20(10); DQ = 1; wdata>>=1; }

//---读取温度值并转换---// read_temp() { unsigned char a,b; ds1820rst();

ds1820wr(0xCC);//跳过ROM _nop_();

//ds1820wr(0x4E);//写EEPROM,发出向内部RAM的3、4 字节写上、下限温度数据命令,紧跟该命令之后,是传送两字节的数据 // ds1820wr(0x00);//Th //ds1820wr(0x00);//Tl ds1820wr(0x7f);//12 bits温度分辨率0x1f, 0x3f, 0x5f ,0x7f温度读数分辨率分别对应0.5, 0.25, 0.125 ,0.0625

//ds1820wr(0xcc); //跳过读EPROM序列

//ds1820wr(0x48); 将RAM 中第3 、4 字节的内容复制到EEPROM 中. ds1820rst();

ds1820wr(0xcc);//*跳过读序列号*/ _nop_();

ds1820wr(0x44);//*启动温度转换*/ ds1820rst();

ds1820wr(0xcc);//*跳过读序列号*/ ds1820wr(0xbe);//*读取温度*/ a=ds1820rd(); b=ds1820rd(); tvalue=b; tvalue<<=8; tvalue=tvalue|a;

if(tvalue<0x0fff)tflag=0; else {tvalue=~tvalue+1; tflag=1; }

f_temp=tvalue*(0.0625); // 温度在寄存器中为12位,分辨率为0.0625

tvalue=f_temp*10+0.5; //乘以10表示小数点后面只取1位,加0.5时四舍五入 return(tvalue);

}

//---填充显示缓冲区函数---// void DisplayBuf_DS18B20(uint n) { SegBuf_DS18B20[3] =n; SegBuf_DS18B20[2] =n/10; SegBuf_DS18B20[1] =n/100; }

if(SegBuf_DS18B20[1]==0)SegBuf_DS18B20[1]=10;//消除前面的0 if(tflag==0)SegBuf_DS18B20[0] =11; //正温度,不显示符号 if(tflag==1)SegBuf_DS18B20[0] =12; //负温度,显示“-”号

void DisplaySecond(uchar x) //写入12864秒 { uchar i,j; i=x/10; j=x; Displayen(1,4,0*8,i); Displayen(1,4,1*8,j); }

void DisplayMinute(uchar x) //写入12864分 { uchar i,j; i=x/10; j=x; Displayen(2,4,4*8,i); Displayen(2,4,5*8,j); }

void DisplayHour(uchar x) //写入12864小时 { uchar i,j; i=x/10; j=x; Displayen(2,4,0*8,i); Displayen(2,4,1*8,j);

}

void DisplayDay(uchar x) //写入12864天 { uchar i,j; i=x/10; j=x; Displayen(1,0,2*8,i); Displayen(1,0,3*8,j); }

void DisplayMonth(uchar x) //写入11864月 { uchar i,j; i=x/10; j=x; Displayen(2,0,6*8,i); Displayen(2,0,7*8,j); }

void DisplayYear(uchar x) //写入12864年 { uchar i,j; i=x/10; j=x; Displayen(2,0,2*8,i);//0 Displayen(2,0,3*8,j);//0 }

void DisplayWeek(uchar x) //写入12864星期 { Display(2,2,2*16,(x+8)); }

void DisplayCentury(uchar x) //写入12864世纪 { uchar i,j; i=x/10; j=x; Displayen(2,0,0*8,i); Displayen(2,0,1*8,j);

}

void displayPCF8563(void) { DisplaySecond(g8563_Store[0]); DisplayMinute(g8563_Store[1]); DisplayHour(g8563_Store[2]); DisplayDay(g8563_Store[3]); DisplayMonth(g8563_Store[5]); DisplayYear(g8563_Store[6]); DisplayWeek(g8563_Store[4]); DisplayCentury(g8563_Store[7]); }

void displayDS18B20(void) { Displayen(1,6,0*8,SegBuf_DS18B20[0]);//+-

Displayen(1,6,1*8,SegBuf_DS18B20[1]);//温度十位 Displayen(1,6,2*8,SegBuf_DS18B20[2]);//温度个位 Displayen(1,6,3*8,13);//小数点 Displayen(1,6,4*8,SegBuf_DS18B20[3]);//小数点1位 Display(1,6,3*16,26);//度 }

void turn_val(uchar newval,uchar flag,uchar newaddr,uchar s1num)

//newval是时间日期值,flag是时间日期增减标识,newaddr是读取数据的地址,s1num是年月日时分秒星期的数字标识 {

uchar ucData1,ucData2,SETCentury; newval=P8563_ReadData(newaddr); switch(newaddr) { case 0x02:newval=(newval&0x7f); /*秒*/ break; case 0x03:newval=(newval&0x7f); /*秒*/ break; case 0x04:newval=(newval&0x3f);/*小时*/ break; case 0x05:newval=(newval&0x3f); /*日*/ break; case 0x06:newval=(newval&0x07); /*星期*/ break;

case 0x07:newval=(newval&0x1f);/*月*/ break;

case 0x08:newval=(newval&0xff);/*年*/ }

ucData1=newval/16; //BCD码转十六进制 ucData2=newval;

newval=ucData1*10+ucData2;

if(flag) //判断是加一还是减一 { newval++; switch(s1num) { case 1: if(newval>99) { SETCentury=P8563_ReadData(0x07); g8563_Store[7]=SETCentury&0x80; /*取世纪,00为2000,80为1900*/ if(g8563_Store[7]==0x00)g8563_Store[7]=19;//2099年变为1900年 if(g8563_Store[7]==0x80)g8563_Store[7]=20;//1999年变为2000年 if(g8563_Store[7]==20)g8563_Store[5]=(g8563_Store[5]&0x3F); if(g8563_Store[7]==19)g8563_Store[5]=(g8563_Store[5]|0x80);

P8563_writeData(7,g8563_Store[5]);//重新写月,从而把世纪状态写回

P8563。

newval=0;

}

DisplayCentury(g8563_Store[7]); DisplayYear(newval); break;

case 2: if(newval>12) newval=1; DisplayMonth(newval); break;

case 3: if(newval>31) newval=1; DisplayDay(newval); break;

case 4: if(newval>6) newval=0; DisplayWeek(newval); break;

case 5: if(newval>23) newval=0; DisplayHour(newval); break;

case 6: if(newval>59) newval=0; DisplayMinute(newval); break; case 7: if(newval>59) newval=0; DisplaySecond(newval); break; default:break; } } else { newval--; switch(s1num) { case 1: if(newval==0xff) {

SETCentury=P8563_ReadData(0x07);//读取月,月的高位1为世纪19**年,0表示20**年 g8563_Store[7]=SETCentury&0x80; /*取世纪,00为2000,80为1900*/ if(g8563_Store[7]==0x00)g8563_Store[7]=19;//2000年变为1999年 if(g8563_Store[7]==0x80)g8563_Store[7]=20;//1999年变为2000年 if(g8563_Store[7]==20)g8563_Store[5]=(g8563_Store[5]&0x3F); if(g8563_Store[7]==19)g8563_Store[5]=(g8563_Store[5]|0x80); P8563_writeData(7,g8563_Store[5]);//重新写月,从而把世纪状态写回P8563。 newval=99; } DisplayCentury(g8563_Store[7]); DisplayYear(newval); break; case 2: if(newval==0) newval=12; DisplayMonth(newval); break; case 3: if(newval==0) newval=31; DisplayDay(newval); break; case 4: if(newval==0xff) newval=6; DisplayWeek(newval); break; case 5: if(newval==0xff) newval=23; DisplayHour(newval); break; case 6: if(newval==0xff) newval=59; DisplayMinute(newval);

}

}

break;

case 7: if(newval==0xff) newval=59; DisplaySecond(newval); break;

default:break;

ucData1=newval/10;//十六进制转BCD码 ucData2=newval; newval=ucData1*16+ucData2; P8563_writeData(newaddr,newval); }

void delayKEY(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); }

//键盘扫描程序 void key_scan(void) { uchar s1num=0; //s1num记录光标的位置的编号 if(menu==0) { delayKEY(5); if(menu==0) { while(!menu); //menum测试到由0到1的变化,也就是按下松开的变化,s1num加1 s1num++; while(1) { if(menu==0) { delayKEY(5); if(menu==0) { while(!menu); s1num++; //menum测试到由0到1的变化,也就是按下松开的变化,s1num再加1 } }

字。 1302

P8563_writeData(0x0,0x20);//停止计时,开始相关设置。 if(s1num==1) {

Display(1,2,0*16,21);//设 Display(1,2,1*16,22);//置 Display(1,2,2*16,0);//年 Display(1,2,3*16,27);//空格

year=P8563_ReadData(0x08); year=year&0xff;//读取年

Reverse_Display=1;

DisplayYear(((year/16)*10+(year)));//设置年的时候反相显示即黑底白Reverse_Display=0;

if(add==0) { delayKEY(3); if(add==0) { while(!add); turn_val(year,1,0x08,1); } } if(dec==0) { delayKEY(3); if(dec==0) { while(!dec); turn_val(year,0,0x08,1);//读取当前年值,根据减小年值,并写入 } } } if(s1num==2)

黑底白字

{

DisplayYear(((year/16)*10+(year))); //年变回白底黑字。 Display(1,2,0*16,21);//设 Display(1,2,1*16,22);//置 Display(1,2,2*16,1);//月 Display(1,2,3*16,27);//空格

month=P8563_ReadData(0x07); month=month&0x1f;//读取月 Reverse_Display=1;

DisplayMonth(((month/16)*10+(month))); //设置月的时候反相显示即Reverse_Display=0; if(add==0) { delayKEY(3); if(add==0) { while(!add); turn_val(month,1,0x07,2); } }

if(dec==0) { delayKEY(3); if(dec==0) { while(!dec); turn_val(month,0,0x07,2); } }

}

if(s1num==3) {

DisplayMonth(((month/16)*10+(month))); //月变回白底黑字。 Display(1,2,0*16,21);//设 Display(1,2,1*16,22);//置 Display(1,2,2*16,2);//日 Display(1,2,3*16,27);//空格

day=P8563_ReadData(0x05); day=day&0x3f;//读取日 Reverse_Display=1;

DisplayDay(((day/16)*10+(day))); //设置日的时候反相显示即黑底白字 Reverse_Display=0;

if(add==0) { delayKEY(3); if(add==0) { while(!add); turn_val(day,1,0x05,3); } }

if(dec==0) { delayKEY(3); if(dec==0) { while(!dec);

底白字

turn_val(day,0,0x05,3); //写入日寄存器

} } }

if(s1num==4) {

DisplayDay(((day/16)*10+(day)));//天变回白底黑字。 Display(1,2,0*16,21);//设 Display(1,2,1*16,22);//置 Display(1,2,2*16,3);//星 Display(1,2,3*16,4);//期

week=P8563_ReadData(0x06); week=week&0x07;//读取星期 Reverse_Display=1;

DisplayWeek(((week/16)*10+(week))); //设置星期的时候反相显示即黑Reverse_Display=0;

if(add==0)

白字

}

{ delayKEY(3); if(add==0) { while(!add); turn_val(week,1,0x06,4); } }

if(dec==0) { delayKEY(3); if(dec==0) { while(!dec); turn_val(week,0,0x06,4); } }

if(s1num==5) {

DisplayWeek(((week/16)*10+(week)));//星期变回白底黑字 Display(1,2,0*16,21);//设 Display(1,2,1*16,22);//置 Display(1,2,2*16,5);//时 Display(1,2,3*16,27);//空格

hour=P8563_ReadData(0x04); hour=hour&0x3f;//读取小时

Reverse_Display=1;

DisplayHour(((hour/16)*10+(hour))); //设置时的时候反相显示即黑底Reverse_Display=0;

if(add==0) { delayKEY(3); if(add==0) { while(!add); turn_val(hour,1,0x04,5); } }

if(dec==0) { delayKEY(3); if(dec==0) { while(!dec); turn_val(hour,0,0x04,5);

黑底白字

} } }

if(s1num==6)//调时间分 {

DisplayHour(((hour/16)*10+(hour))); //小时变回白底黑字 Display(1,2,0*16,21);//设 Display(1,2,1*16,22);//置 Display(1,2,2*16,6);//分 Display(1,2,3*16,27);//空格 minute=P8563_ReadData(0x03); minute=minute&0x7f;//读取分

Reverse_Display=1;

DisplayMinute(((minute/16)*10+(minute))); //设置分的时候反相显示即Reverse_Display=0; if(add==0) { delayKEY(5); if(add==0) { while(!add); turn_val(minute,1,0x03,6);//写入分寄存器 } } if(dec==0) { delayKEY(3); if(dec==0) { while(!dec); turn_val(minute,0,0x03,6);//写入分寄存器 }

黑底白字

} }

if(s1num==7)//调时间秒 {

DisplayMinute(((minute/16)*10+(minute)));//分变回白底黑字 Display(1,2,0*16,21);//设 Display(1,2,1*16,22);//置 Display(1,2,2*16,7);//秒 Display(1,2,3*16,27);//空格 second=P8563_ReadData(0x02);

second=second&0x7f;//读取秒

Reverse_Display=1;

DisplaySecond(((second/16)*10+(second))); //设置秒的时候反相显示即Reverse_Display=0; if(add==0) { delayKEY(3); if(add==0) { while(!add); if(second==0x60) second=0x00; turn_val(second,1,0x02,7); } } if(dec==0) { delayKEY(3); if(dec==0) { while(!dec); turn_val(second,0,0x02,7); } } }

if(s1num==8) {

DisplaySecond(((second/16)*10+(second)));//秒变回白底黑字 Display(1,2,0*16,23);//运

Display(1,2,1*16,24);//行 Display(1,2,2*16,25);//中 Display(1,2,3*16,27);//空格

P8563_writeData(0x0,0x00);//设置结束,开始计时 s1num=0;//s1num清零// break; } } } } }

void Init_DIS() { Displayen(2,0,0*8,2);//2 Displayen(2,0,1*8,0);//0 Displayen(2,0,2*8,0);//0 Displayen(2,0,3*8,0);//0

Display(2,0,2*16,0);//年 Displayen(2,0,6*8,1);//1 Displayen(2,0,7*8,2);//2 Display(1,0,0*16,1);//月 Displayen(1,0,2*8,3);//3 Displayen(1,0,3*8,1);//1 Display(1,0,2*16,2);//日 Display(2,2,0*16,3);//星 Display(2,2,1*16,4);//期 Display(2,2,2*16,8);//天 Displayen(2,4,0*8,2);//2 Displayen(2,4,1*8,3);//3 Display(2,4,1*16,5);//时 Displayen(2,4,4*8,5);//5 Displayen(2,4,5*8,9);//9 Display(2,4,3*16,6);//时 Displayen(1,4,0*8,5);//4 Displayen(1,4,1*8,9);//7 Display(1,4,1*16,7);//时 Display(2,6,0*16,17);//温 Display(2,6,1*16,18);//度

}

Display(2,6,2*16,19);//是 Display(2,6,3*16,20);//: Display(1,2,0*16,23);//运 Display(1,2,1*16,24);//行 Display(1,2,2*16,25);//中

/*主函数*/ void main() { P8563_init();//p8563初始化 InitLCD(); /*初始12864*/ Init_DIS(); while(1) { P8563_gettime(); BCD_16( ); displayPCF8563(); temp=read_temp();//读取温度 DisplayBuf_DS18B20(temp); displayDS18B20( ); key_scan(); } }

本文来源:https://www.bwwdw.com/article/xdy.html

Top