PIC16F877A万年历程序.docx

上传人:b****8 文档编号:10829431 上传时间:2023-02-23 格式:DOCX 页数:29 大小:113.57KB
下载 相关 举报
PIC16F877A万年历程序.docx_第1页
第1页 / 共29页
PIC16F877A万年历程序.docx_第2页
第2页 / 共29页
PIC16F877A万年历程序.docx_第3页
第3页 / 共29页
PIC16F877A万年历程序.docx_第4页
第4页 / 共29页
PIC16F877A万年历程序.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

PIC16F877A万年历程序.docx

《PIC16F877A万年历程序.docx》由会员分享,可在线阅读,更多相关《PIC16F877A万年历程序.docx(29页珍藏版)》请在冰豆网上搜索。

PIC16F877A万年历程序.docx

PIC16F877A万年历程序

PIC16F877A万年历程序

时间:

2009-03-05 来源:

 作者:

Wujieflash 点击:

1581 字体大小:

【大中小】

   为了把KS0108系列的液晶吃透,特别制作了这款万年历,感觉效果还是不错的.希望大家分享我的喜悦,毕竟有了更多志同道合的朋友支持,我才能更进一步提高.

一,原理介绍

说明:

1.单片机还是采用PIC中最经典的PIC16F877A,端口多,功能全,特别是他有8K的ROM,这是我选择的主要原因,因为储存液晶的字库需要很大的空间.

2.液晶显示还是用的KS0108系列,主要是他性价比高,指令简单,特别是公司也在用.

3.时钟/日历芯片用的DALLOS的DS1302芯片,他可以储存从2000-2099年的日历,及实时时钟,可以方便的读写.

4.温度测量还是用的DS18B20,这在我上一实例中已经用过,有兴趣可以查阅.

5.本万年历可以显示实时时钟,精确到秒,年,月,日,星期,阴历,温度,生肖等,显示的信息量大.

6,可以通过按键自由设定时钟及日历,按"设置"键可以在秒,分,时,日,月,星期,年之间来回切换,要设置的单元以闪烁提醒.通过"+"."-"按键可以把要设置的单元设定到预想状态.

 

二,程序说明:

本程序有许多小的模块,现分列如下:

1.主程序

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

*标题:

万年历                                       *

*作者:

Wujieflash                                 *

*日期:

2008年1月13日                         *

*说明:

包含文件

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

#include

#include"ziku.h"

#include"lcd_init.h"

#include"ds1302.h"

#include"ds18b20.h"

#include"keyscan.h"

#include"yinli.h"

//子程序

//LCD显示空白边框子程序

voidLCDShowTable()

{

 uchi;

 SlectScreen

(1);    //写左半屏

 SetLine(0);        //起使页

 SetColumn(0);      //起使列

 for(i=0;i

//显示固定字符子程序

voidLCDShowGudingWord()

{

 Show8X16_2(0,24,s0);

 Show8X16_2(0,32,s0);

 Show8X16(2,1,s0);

 Show8X16(2,9,s0);

 Show16X16_3(6,40,ri);

 Show16X32(2,24,ss0);

 Show16X32(2,40,ss0);

 Show8X16_2(0,64,s0);

 Show8X16_2(0,72,s0);

 Show8X16_2(0,80,maohao);

 Show8X16_2(0,88,s0);

 Show8X16_2(0,96,s0);

 Show8X16_2(0,104,maohao);

 Show8X16_2(0,112,s0);

 Show8X16_2(0,119,s0);

 Show8X16(2,80,s0);

 Show8X16(2,88,s0);

 Show16X16_2(4,64,shiyi);

 Show16X16_2(4,80,yue);

 Show16X16_2(4,95,chu);

 Show16X16_2(4,111,yi);

 Show16X16_3(6,72,sheng);

 Show16X16_3(6,88,xiao);

 Show16X16_3(6,104,shu);

 

 Show16X16_2(0,40,nian);

 Show16X16(4,2,yue);

 Show16X16_3(6,8,xing);

 Show16X16_3(6,24,qi);

 Show16X16(2,96,danwei1);

 Show8X16_2(0,8,s2);

 Show8X16_2(0,16,s0);

}

/*----------------------------------------------------------*/

//TRM1初始化子程序

voidTMR1init()

{

 //TRM1INITIAL

  T1CON=0X30;      //8分频

  TMR1IF=0;        //清中断标志

  TMR1IE=1;        //使能定时器1中断

  TMR1L=0XDB;      //初始值(定时0.5S)

  TMR1H=0X0B;

  TMR1ON=1;        //开定时器1

}

//冒号闪烁子程序

voidFlashMaohao()

{

 staticuchtimecount=0;

 if(TMR1IF==1)

 {

 TMR1ON=0;

 TMR1IF=0;

 TMR1L=0XDB;    //重新付初值

    TMR1H=0X0B;

    flag++;

    flag=flag%2;   //闪烁标志在0-1间翻转

    TMR1ON=1;

 timecount++;

 if(timecount==120)//1分钟采样一次温度

 {

  timecount=0;

  get_temp();  //温度转换子程序

 }

 }

 if(flag==0)

 {

 Show8X16_2(0,80,maohao);

 Show8X16_2(0,104,maohao);

 }

 if(flag==1)

 {

 Show8X16_2(0,80,noshu);//清除

 Show8X16_2(0,104,noshu);

 }

}

//主程序

voidmain()

{

 TMR1init();            //定时器1初始化

 keyinit();             //键盘初始化

 LCDinit();             //LCD操作初始化

 LCDShowTable();        //显示空白表格

 LCDShowGudingWord();   //显示固定字符

 //Set1302(DisCash);    //设置初始时间(默认写入我写程序的时间)

 get_temp();            //读取温度

 while

(1)

 {

 v_Get1302(clock);  //读取时间、日历

 display();

 YangToYin(clock[6]/16*10+clock[6]&0x0f,clock[4]/16*10+clock[4]&0x0f,clock[3]/16*10+clock[3]&0x0f);

 FlashMaohao();     //冒号闪烁

 KeyScan();        //键盘扫描

 }

}

2.测温程序:

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

*标题:

DS18B20测温                            *

*作者:

Wujieflash                                  *

*日期:

2008年1月13日                          *

*说明:

使用DS18B20芯片测温               *

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

#defineDQRC3                               //定义18B20数据端口

#defineDQ_DIRTRISC3                        //定义18B20D口方向寄存器

#defineDQ_HIGH()DQ_DIR=1                  //设置数据口为输入

#defineDQ_LOW()DQ=0;DQ_DIR=0          //设置数据口为输出

 unsignedchar TLV=0;                       //采集到的温度高8位

 unsignedchar THV=0;                        //采集到的温度低8位

 unsignedcharTZ=0;                          //转换后的温度值整数部分

 

 //------------------------------------------------

//延时函数

//系统初始化函数

voidinit()

{

 ADCON1=0X07;                               //设置A口为普通数字口

 TRISA=0X00;                                //设置A口方向为输出

 //TRISC3=0;                                //设置D口方向为输出

}

//-----------------------------------------------

//复位DS18B20函数

reset(void)

{

 charpresence=1;

 while(presence)

 {

   DQ_LOW();                               //主机拉至低电平

   delay(2,90);                             //延时503us

   DQ_HIGH();                               //释放总线等电阻拉高总线,并保持15~60us

   delay(2,8);                              //延时70us

   if(DQ==1)presence=1;                    //没有接收到应答信号,继续复位

   elsepresence=0;                         //接收到应答信号

   delay(2,70);                             //延时430us

  }

 }

//-----------------------------------------------

//写18b20写字节函数

voidwrite_byte(uchval)

{

 uchi;

 uchtemp;

 for(i=8;i>0;i--)

 {

  temp=val&0x01;                           //最低位移出

  DQ_LOW();

  NOP();

  NOP();

  NOP();

  NOP();

  NOP();                                   //从高拉至低电平,产生写时间隙

  if(temp==1) DQ_HIGH();                  //如果写1,拉高电平

  delay(2,7);                              //延时63us

  DQ_HIGH();

  NOP();

  NOP();

  val=val>>1;                              //右移一位

 }

}

//------------------------------------------------

//18b20读字节函数

uchread_byte(void)

{

 uchi;

 uchvalue=0;                               //读出温度

 staticbitj;

 for(i=8;i>0;i--)

 {

  value>>=1;

  DQ_LOW();

  NOP();

  NOP();

  NOP();

  NOP();                                  //6us

  DQ_HIGH();                              //拉至高电平

  NOP();

  NOP();

  NOP();                               //4us

  j=DQ;

  if(j)value|=0x80;

  delay(2,7);                            //63us

 }

 return(value);

}

//-------------------------------------------------

//启动温度转换函数

voidget_temp()

{

inti;

DQ_HIGH();

reset();                                //复位等待从机应答

write_byte(0XCC);                       //忽略ROM匹配

write_byte(0X44);                       //发送温度转化命令 

for(i=10;i>0;i--)

   {        

       delay(201,132);                      //调用多次延迟函数,确保温度转换完成所需要的时间

   }

reset();                                //再次复位,等待从机应答

write_byte(0XCC);                       //忽略ROM匹配

write_byte(0XBE);                       //发送读温度命令

TLV=read_byte();                        //读出温度低8

THV=read_byte();                        //读出温度高8位

DQ_HIGH();                              //释放总线

TZ=(TLV>>4)|(THV<<4);

}

3.日历显示程序

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

*标题:

DS1302读写                               *

*作者:

Wujieflash                                  *

*日期:

2008年1月14日                          *

*说明:

日历显示范围:

2000年--2099年 *

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

#define RST RC0

#define SCLKRC1

#define IO  RC2

uchflag=0;

uchsecond=1,minute=1,hour=1,year=1,month=1,date=1,day=1;

uchclock[]={0};

uchDisCash[]={0x00,0x30,0x09,0x16,0x01,0x03,0x09};

/////往1302写入1Byte数据////////////////////////

voidRTInputByte(uchd)

{

   uchi;

   TRISC=0x00;

   for(i=8;i>0;i--)

   {

     IO=d&0x01;     //取最低位

     SCLK=1;        //上升沿发送

     SCLK=0;        //恢复

     d=d>>1;      

   }

}

///////从1302读取1Byte数据////////////////////////

uchRTOutputByte(void)

{

   uchi,val=0;

   TRISC2=1;           //设置为输入

   for(i=8;i>0;i--)

   {

     val=val>>1;        

     if(IO)val=val|0x80;//从最低位开始接收

     SCLK=1;         //下降沿接收

     SCLK=0;

   }

    return(val);

}

///////先写地址,后写命令/数据//////////////////////////

voidW1302(uchucAddr,uchucDa)

{

   RST=0;

   SCLK=0;

   RST=1;                 //打开DS1302

   RTInputByte(ucAddr);     ///*地址,命令*/

   RTInputByte(ucDa);       ///*写1Byte数据*/

   SCLK=1;

   RST=0;                 //关闭DS1302

}

///////先写地址,后读命令/数据////////////////////////

uchR1302(uchucAddr)

{

   uchucData;

   RST=0;

   SCLK=0;

   RST=1;

   RTInputByte(ucAddr);           ///*地址,命令*/

   ucData=RTOutputByte();       ///*读1Byte数据*/

   SCLK=1;

   RST=0;

   return(ucData);

}

/////////向1302写入秒分时日月星期年*/////////////

voidSet1302(uch*pClock)

{

   uchi;

   uchucAddr=0x80;         //起使地址

   W1302(0x8e,0x00);          ///*控制命令,WP=0,允许写操作*/

   for(i=7;i>0;i--)

   {

     W1302(ucAddr,*pClock);   ///*秒分时日月星期年*/

     pClock++;

     ucAddr+=2;              //写地址加2

   }

    W1302(0x8e,0x80);         ///*控制命令,WP=1,写保护*/

}

////////从1302读出秒分时日月星期年*//////////////////

voidv_Get1302(unsignedchar ucCurtime[])

{

unsignedchari;

unsignedcharucAddr=0x81;

for(i=0;i

/////////与LCD的显示接口//////////////////////

voiddisplay()

{

 uchi;

 for(i=0;i

4.按键扫描与服务程序

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

*标题:

按键扫描和服务                            *

*作者:

Wujieflash                                    *        

*日期:

2008年1月17日                            *

*说明:

当按键按下,选中的单元就会闪烁*

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

uchk=0;

//键盘初始化子程序

voidkeyinit()

{

 TRISD0=1;

 TRISD0=1;

 TRISD0=1;

}

/*----------------------------------------------------------*/

//键盘扫描子程序

voidKeyScan()

{

 intd;

 if(RD0==0) //设置键按下

 {

 k++;   //选定入口值

 k=k%8;

 }

 while

(1)

 {

 if(RD0==1)break;//等待按键松开

 }

 switch(k)//键盘服务入口

 {

 case1:

//设置秒

 {

  d=R1302(0x81);//读取秒

  d=d/16*10+d%16;//转换为16进制

  second=flag;  //设置秒的闪烁标志

  minute=1;     //其余变量不闪烁

  hour=1;

  year=1;

  month=1;

  date=1;

  day=1;

  if(second==0) //闪烁

  {

   Show8X16_2(0,111,noshu);

   Show8X16_2(0,119,noshu);

  }

  if(RD1==0)    //秒数值加1

  {

   d++;

   if(d>0x3b)d=0;//大于59就为0

   d=d/10*16+d%10;

   W1302(0x80,d);//写入DS1302

   while

(1)

   {

    if(RD1==1)break;//等待键松开

   }

  }

  if(R

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 金融投资

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1