网站导航: 首页 > 设计参考 > 正文 文章搜索
PIC16F877A万年历程序
 
文章编号:
091111213544
文章分类: 单片机 PIC
点 击:
...
关 键 词: PIC16F877A,万年历
文章来源:
网络,作者:Wujieflash
摘 要:

一,原理介绍
说明:
1.单片机还是采用PIC中最经典的PIC16F877A,端口多,功能全,特别是他有8K的ROM,这是我选择的主要原因,因为储存液晶的字库需要很大的空间.
2.液晶显示还是用的KS0108系列,主要是他性价比高,指令简单,特别是公司也在用.
3.时钟/日历芯片用的DALLOS的DS1302芯片,他可以储存从2000-2099年的日历,及实时时钟,可以方便的读写.
4.温度测量还是用的DS18B20,这在我上一实例中已经用过,有兴趣可以查阅.
5.本万年历可以显示实时时钟,精确到秒,年,月,日,星期,阴历,温度,生肖等,显示的信息量大.
6,可以通过按键自由设定时钟及日历,按"设置"键可以在秒,分,时,日,月,星期,年之间来回切换,要设置的单元以闪烁提醒.通过"+"."-"按键可以把要设置的单元设定到预想状态.

二,程序说明:
本程序有许多小的模块,现分列如下:
1.主程序

 
  1. /***************************************************  
  2. * 标题:万年历                                        *  
  3. * 作者:Wujieflash                                  *  
  4. * 日期:2008年1月13日                          *  
  5. * 说明:包含文件  
  6. ***************************************************/  
  7. #include    
  8. #include "ziku.h"   
  9. #include "lcd_init.h"   
  10. #include "ds1302.h"   
  11. #include "ds18b20.h"   
  12. #include "keyscan.h"   
  13. #include "yinli.h"   
  14. //子程序   
  15. //LCD显示空白边框子程序   
  16. void LCDShowTable()   
  17. {   
  18.  uch i;   
  19.  SlectScreen(1);     //写左半屏   
  20.  SetLine(0);         //起使页   
  21.  SetColumn(0);       //起使列   
  22.  for(i=0;i   
  23. //显示固定字符子程序   
  24. void LCDShowGudingWord()   
  25. {   
  26.  Show8X16_2(0,24,s0);   
  27.  Show8X16_2(0,32,s0);   
  28.  Show8X16(2,1,s0);   
  29.  Show8X16(2,9,s0);   
  30.  Show16X16_3(6,40,ri);   
  31.  Show16X32(2,24,ss0);   
  32.  Show16X32(2,40,ss0);   
  33.  Show8X16_2(0,64,s0);   
  34.  Show8X16_2(0,72,s0);   
  35.  Show8X16_2(0,80,maohao);   
  36.  Show8X16_2(0,88,s0);   
  37.  Show8X16_2(0,96,s0);   
  38.  Show8X16_2(0,104,maohao);   
  39.  Show8X16_2(0,112,s0);   
  40.  Show8X16_2(0,119,s0);   
  41.  Show8X16(2,80,s0);   
  42.  Show8X16(2,88,s0);   
  43.  Show16X16_2(4,64,shiyi);   
  44.  Show16X16_2(4,80,yue);   
  45.  Show16X16_2(4,95,chu);   
  46.  Show16X16_2(4,111,yi);   
  47.  Show16X16_3(6,72,sheng);   
  48.  Show16X16_3(6,88,xiao);   
  49.  Show16X16_3(6,104,shu);   
  50.     
  51.  Show16X16_2(0,40,nian);   
  52.  Show16X16(4,2,yue);   
  53.  Show16X16_3(6,8,xing);   
  54.  Show16X16_3(6,24,qi);   
  55.  Show16X16(2,96,danwei1);   
  56.  Show8X16_2(0,8,s2);   
  57.  Show8X16_2(0,16,s0);   
  58. }   
  59. /*----------------------------------------------------------*/  
  60. //TRM1初始化子程序   
  61. void TMR1init()   
  62. {   
  63.  //TRM1 INITIAL   
  64.    T1CON=0X30;       //8分频   
  65.    TMR1IF=0;         //清中断标志   
  66.    TMR1IE=1;         //使能定时器1中断   
  67.    TMR1L=0XDB;       //初始值(定时0.5S)   
  68.    TMR1H=0X0B;   
  69.    TMR1ON=1;         //开定时器1   
  70. }   
  71. //冒号闪烁子程序   
  72. void FlashMaohao()   
  73. {   
  74.  static uch timecount=0;   
  75.  if(TMR1IF==1)   
  76.  {   
  77.   TMR1ON=0;   
  78.   TMR1IF=0;   
  79.   TMR1L=0XDB;     //重新付初值   
  80.      TMR1H=0X0B;   
  81.      flag++;   
  82.      flag=flag%2;    //闪烁标志在0-1间翻转   
  83.      TMR1ON=1;   
  84.   timecount++;   
  85.   if(timecount==120)//1分钟采样一次温度   
  86.   {   
  87.    timecount=0;   
  88.    get_temp();   //温度转换子程序   
  89.   }   
  90.  }   
  91.  if(flag==0)   
  92.  {   
  93.   Show8X16_2(0,80,maohao);   
  94.   Show8X16_2(0,104,maohao);   
  95.  }   
  96.  if(flag==1)   
  97.  {   
  98.   Show8X16_2(0,80,noshu);//清除   
  99.   Show8X16_2(0,104,noshu);   
  100.  }   
  101. }   
  102. //主程序   
  103. void main()   
  104. {   
  105.  TMR1init();             //定时器1初始化   
  106.  keyinit();              //键盘初始化   
  107.  LCDinit();              //LCD操作初始化   
  108.  LCDShowTable();         //显示空白表格   
  109.  LCDShowGudingWord();    //显示固定字符   
  110.  //Set1302(DisCash);     //设置初始时间(默认写入我写程序的时间)   
  111.  get_temp();             //读取温度   
  112.  while(1)   
  113.  {   
  114.   v_Get1302(clock);   //读取时间、日历   
  115.   display();   
  116.   YangToYin(clock[6]/16*10+clock[6]&0x0f,clock[4]/16*10+clock[4]&0x0f,clock[3]/16*10+clock[3]&0x0f);   
  117.   FlashMaohao();      //冒号闪烁   
  118.   KeyScan();         //键盘扫描   
  119.  }   
  120. }  

 2.测温程序:

 
  1. /***************************************************  
  2. * 标题:DS18B20测温                             *  
  3. * 作者:Wujieflash                                   *  
  4. * 日期:2008年1月13日                           *  
  5. * 说明:使用DS18B20芯片测温                *  
  6. ***************************************************/  
  7. # define DQ RC3                                //定义18B20数据端口    
  8. # define DQ_DIR TRISC3                         //定义18B20D口方向寄存器    
  9. # define DQ_HIGH() DQ_DIR =1                   //设置数据口为输入   
  10. # define DQ_LOW() DQ = 0; DQ_DIR = 0           //设置数据口为输出   
  11.  unsigned char  TLV=0 ;                        //采集到的温度高8位   
  12.  unsigned char  THV=0;                         //采集到的温度低8位   
  13.  unsigned char TZ=0;                           //转换后的温度值整数部分   
  14.     
  15.  //------------------------------------------------   
  16. //延时函数   
  17. //系统初始化函数   
  18. void init()   
  19. {   
  20.   ADCON1=0X07;                                //设置A口为普通数字口   
  21.   TRISA=0X00;                                 //设置A口方向为输出   
  22.   //TRISC3=0;                                 //设置D口方向为输出   
  23. }   
  24. //-----------------------------------------------   
  25. //复位DS18B20函数   
  26. reset(void)   
  27. {   
  28.   char presence=1;   
  29.   while(presence)   
  30.   {    
  31.     DQ_LOW() ;                                //主机拉至低电平   
  32.     delay(2,90);                              //延时503us   
  33.     DQ_HIGH();                                //释放总线等电阻拉高总线,并保持15~60us   
  34.     delay(2,8);                               //延时70us   
  35.     if(DQ==1) presence=1;                     //没有接收到应答信号,继续复位   
  36.     else presence=0;                          //接收到应答信号   
  37.     delay(2,70);                              //延时430us   
  38.    }   
  39.   }   
  40. //-----------------------------------------------   
  41. //写18b20写字节函数   
  42. void write_byte(uch val)   
  43. {   
  44.  uch i;   
  45.  uch temp;   
  46.  for(i=8;i>0;i--)   
  47.  {   
  48.    temp=val&0x01;                            //最低位移出   
  49.    DQ_LOW();    
  50.    NOP();   
  51.    NOP();   
  52.    NOP();   
  53.    NOP();   
  54.    NOP();                                    //从高拉至低电平,产生写时间隙   
  55.    if(temp==1)  DQ_HIGH();                   //如果写1,拉高电平   
  56.    delay(2,7);                               //延时63us   
  57.    DQ_HIGH();    
  58.    NOP();   
  59.    NOP();   
  60.    val=val>>1;                               //右移一位   
  61.   }   
  62. }   
  63. //------------------------------------------------   
  64. //18b20读字节函数   
  65. uch read_byte(void)   
  66. {   
  67.  uch i;   
  68.  uch value=0;                                //读出温度   
  69.  static bit j;   
  70.  for(i=8;i>0;i--)   
  71.  {   
  72.    value>>=1;    
  73.    DQ_LOW();   
  74.    NOP();   
  75.    NOP();   
  76.    NOP();   
  77.    NOP();                                   //6us   
  78.    DQ_HIGH();                               //拉至高电平   
  79.    NOP();    
  80.    NOP();    
  81.    NOP();                                //4us   
  82.    j=DQ;   
  83.    if(j) value|=0x80;   
  84.    delay(2,7);                             //63us   
  85.   }   
  86.   return(value);   
  87. }   
  88. //-------------------------------------------------   
  89. //启动温度转换函数   
  90. void get_temp()   
  91. {    
  92. int i;   
  93. DQ_HIGH();   
  94. reset();                                 //复位等待从机应答    
  95. write_byte(0XCC);                        //忽略ROM匹配    
  96. write_byte(0X44);                        //发送温度转化命令     
  97. for(i=10;i>0;i--)   
  98.     {           
  99.         delay(201,132);                       //调用多次延迟函数,确保温度转换完成所需要的时间   
  100.     }   
  101. reset();                                 //再次复位,等待从机应答    
  102. write_byte(0XCC);                        //忽略ROM匹配    
  103. write_byte(0XBE);                        //发送读温度命令    
  104. TLV=read_byte();                         //读出温度低8    
  105. THV=read_byte();                         //读出温度高8位    
  106. DQ_HIGH();                               //释放总线    
  107. TZ=(TLV>>4)|(THV<<4);   
  108. }   

3.日历显示程序

 
  1. /***************************************************  
  2. * 标题:DS1302读写                                *  
  3. * 作者:Wujieflash                                   *  
  4. * 日期:2008年1月14日                           *  
  5. * 说明:日历显示范围:2000年--2099年  *  
  6. ***************************************************/  
  7. #define  RST  RC0   
  8. #define  SCLK RC1    
  9. #define  IO   RC2   
  10. uch flag=0;   
  11. uch second=1,minute=1,hour=1,year=1,month=1,date=1,day=1;   
  12. uch clock[]={0};   
  13. uch DisCash[]={0x00,0x30,0x09,0x16,0x01,0x03,0x09};    
  14. /////往1302写入1Byte数据////////////////////////   
  15. void RTInputByte(uch d)    
  16. {    
  17.     uch i;   
  18.     TRISC=0x00;   
  19.     for(i=8; i>0; i--)   
  20.     {   
  21.       IO = d&0x01;      //取最低位   
  22.       SCLK = 1;         //上升沿发送   
  23.       SCLK = 0;         //恢复   
  24.       d = d >> 1;          
  25.     }    
  26. }   
  27. ///////从1302读取1Byte数据////////////////////////   
  28. uch RTOutputByte(void)    
  29. {    
  30.     uch i,val=0;   
  31.     TRISC2=1;            //设置为输入   
  32.     for(i=8; i>0; i--)   
  33.     {   
  34.       val = val >>1;            
  35.       if(IO)val=val|0x80;// 从最低位开始接收   
  36.       SCLK = 1;          //下降沿接收   
  37.       SCLK = 0;    
  38.     }    
  39.      return(val);    
  40. }   
  41. ///////先写地址,后写命令/数据//////////////////////////   
  42. void W1302(uch ucAddr, uch ucDa)   
  43. {   
  44.     RST = 0;   
  45.     SCLK = 0;   
  46.     RST = 1;                  //打开DS1302   
  47.     RTInputByte(ucAddr);      // /* 地址,命令 */   
  48.     RTInputByte(ucDa);        // /* 写1Byte数据*/   
  49.     SCLK = 1;   
  50.     RST = 0;                  //关闭DS1302   
  51. }   
  52. ///////先写地址,后读命令/数据////////////////////////   
  53. uch R1302(uch ucAddr)   
  54. {   
  55.     uch ucData;   
  56.     RST = 0;   
  57.     SCLK = 0;   
  58.     RST = 1;   
  59.     RTInputByte(ucAddr);            // /* 地址,命令 */   
  60.     ucData = RTOutputByte();        // /* 读1Byte数据 */   
  61.     SCLK = 1;   
  62.     RST = 0;   
  63.     return(ucData);   
  64. }   
  65. /////////向1302写入 秒 分 时 日 月 星期 年 */////////////   
  66. void Set1302(uch *pClock)    
  67. {   
  68.     uch i;   
  69.     uch ucAddr = 0x80;          //起使地址   
  70.     W1302(0x8e,0x00);           ///* 控制命令,WP=0,允许写操作*/   
  71.     for(i =7; i>0; i--)   
  72.     {    
  73.       W1302(ucAddr,*pClock);    ///* 秒 分 时 日 月 星期 年 */    
  74.       pClock++;   
  75.       ucAddr +=2;               //写地址加2   
  76.     }   
  77.      W1302(0x8e,0x80);          // /* 控制命令,WP=1,写保护*/   
  78. }   
  79. ////////从1302读出 秒 分 时 日 月 星期 年 *//////////////////   
  80. void v_Get1302(unsigned char  ucCurtime[])    
  81. {   
  82. unsigned char i;   
  83. unsigned char ucAddr = 0x81;   
  84. for(i=0;i   
  85. /////////与LCD的显示接口//////////////////////   
  86. void display()   
  87. {   
  88.  uch i;   
  89.  for(i=0;i   
 
相关文章:

12 下一页
 
最新开源项目
 
 
  查看更多...  
 
本站相关产品   淘宝网店
 




 
  查看更多...  

 

本站程序由百合电子工作室开发和维护
Copyright @ baihe electric studio
渝ICP备09006681号-4