找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5444|回复: 4
打印 上一主题 下一主题
收起左侧

求助!电子钟

[复制链接]
跳转到指定楼层
楼主
ID:17087 发表于 2009-12-10 15:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
 求助!~本人是阿蔡~据以下程序做了一个电子钟,但最后有点小问题,1602显示不正确~秒走起来时每隔一个就显示一个问号~其余年月日,时间等也是如此~请问有谁遇到类似问题?怎样解决啊~?原理图及PCB见附件

 

#include "regx51.h"

#include "string.h"

#include "intrins.h"

#define uchar unsigned char

#define uint unsigned int

typedef unsigned char byte;

typedef unsigned int  word;


//*********** 1602引脚定义引脚

#define LCM_RS   P2_0    // 数据/命令选择信号

#define LCM_RW   P2_1    // 读/写选择信号

#define LCM_E    P2_2    // 使能信号


//*********** DS1302 时间显示定义部分

sbit T_CLK=P1^0;         //串行时钟输入

sbit T_IO =P1^1;         //串行数据端口

sbit T_RST=P1^2;         //复位端口


//*********** 18B20温度显示定义部分

sbit DQ=P3^3; //18B20 接P33口

sbit ACC0=ACC^0;

sbit ACC7=ACC^7;


#define LCM_Data P0      //显示数据端口

#define Busy     0x80    //用于检测LCM状态字中的Busy标识


uchar id,timecount;      //全局变量

bit  flag,sflag;         //flag是时钟冒号闪烁标志,sflag是温度负号显示标志

bit  sec,min,hour,year,mon,day,weekk; //闪烁标志位

//*********************函数申明

void   Disp_line1(void);             // 显示屏幕第一行

void   Disp_line2(void);             // 显示屏幕第二行

void   id_case1_key();               // id为1时的下一级选择

void   Set(uchar,uchar);             // 根据选择调整相应项目

void   RTInputByte(uchar);           /* 输入 1Byte */

uchar  RTOutputByte(void);           /* 输出 1Byte */

void   W1302(uchar, uchar);          // 向DS1302写入一个字节

uchar  R1302(uchar);                 // 从DS1302读出一个字节

void   Set1302(uchar * );            // 设置时间

//******* 1602LCD驱动 **********************************************************

void   WriteDataLCM(uchar WDLCM);           //写数据

void   WriteCommandLCM(uchar WCLCM,BuysC);  //写指令

uchar  ReadStatusLCM(void);                 //读状态

void   LCMInit(void);                       //LCM初始化

void   DisplayOneChar(uchar X, uchar Y, uchar DData);        //按指定位置显示一个字符

void   DisplayListChar(uchar X, uchar Y, uchar code *DData); //按指定位置显示一串字符

void   Delay5Ms(void);   //5ms延时

void   Delay400Ms(void); //400ms延时

       Read_Temperature(char,char);//温度显示

void   mychar(void);          //显示自定义字符

void   adjust_res(char res);  //res 分别等于 0x1f, 0x3f, 0x5f 温度读数分辨率分别对应

                              //              0.5, 0.25, 0.125  

//初始化后设置为:07年07月04日 星期3 12点00分00秒

//      12:00:00 XX. C

//      07/07/04 Week.3

unsigned char inittime[7]={0x00,0x00,0x12,0x04,0x07,0x03,0x07};

//                          秒  分钟 小时  日   月  星期  年 

uchar code week[]={"Week."};//星期显示

 

 

 

 //主函数

void main(void)

  Delay400Ms();  //启动等待,等LCM讲入工作状态

  LCMInit();     //LCM初始化

  Delay5Ms();    //延时片刻(可不要)

  mychar();      //显示自定义字符


  TMOD=0x01;     //选择定时模式

  TH0=(65535-50000)/256;//取定时初值

  TL0=(65535-50000)%256;

  EA=1;             //开中断

  TR0=1;

  ET0=1; 

  W1302(0x90,0xa5); //打开充电二级管  一个二级管串联一个2K电阻

  W1302(0x8e,0x80); //写保护,禁止写操作

  adjust_res(0x5f); //调整18B20的分辨率 0x1f:0.5; 0x3f:0.25; 0x5f:0.125


  while(1)

    {             

     if ((P1_4|P1_5)==0)   // 初始化 同时按下P1_4、P1_5

      {

         Delay5Ms();       // 适当延时,消除抖动

         if ((P1_4|P1_5)==0) Set1302(inittime); // 显示初始值

      }

     if (P1_6==0)                               // 设置和选择项目键

      {

         Delay5Ms();                            // 适当延时,消除抖动

         if(P1_6==0){id++;if(id>7) id=0;}       // 7个可调节项目循环调节

         while(P1_6==0);   

      }

     switch(id) // 跳转到对应的项目进行设置

      {

         case 0:

                sec=0;

                Disp_line1(); Disp_line2();

                break;

         case 1: //调节年

                year=1;//设置年闪烁标志位

                Disp_line1(); Disp_line2();                  

                id_case1_key();

                break;

         case 2: //调节月

                year=0;mon=1;//设置月闪烁标志位

                Disp_line1(); Disp_line2();                

                id_case1_key();

                break;

         case 3: //调节日

                mon=0;day=1;//设置日闪烁标志位

                Disp_line1(); Disp_line2();

                id_case1_key();

                break;            

         case 4: //调节星期

                day=0;weekk=1;//设置星期闪烁标志位

                Disp_line1(); Disp_line2();        

                id_case1_key();

                break;

         case 5: //调节小时

                weekk=0;hour=1;//设置小时闪烁标志位

                Disp_line1(); Disp_line2();

                id_case1_key();     

                break;      

         case 6: //调节分钟

                hour=0;min=1;//设置分钟闪烁标志位

                Disp_line1(); Disp_line2();

                id_case1_key();

                break;

         case 7: //调节秒

                min=0;sec=1;//设置秒钟闪烁标志位

                Disp_line1(); Disp_line2();            

                id_case1_key();

                break;      

      }

    }

}

//================================== 定时中断

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

// 函 数 名:void t0()

// 功    能:时间工作时,冒号闪烁

 //T0中断入口,方式1

 

void t0(void) interrupt 1 using 0

{

  TH0=(65535-50000)/256; //取50ms定时初值

  TL0=(65535-50000)%256; 

  timecount++;

  if(timecount>9)

   {

    timecount=0;    //计时到,从先开始

    flag=~flag;     //标志位取反         

   } 

}

//==================================== 项目设置

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

 函 数 名:void id_case1_key()

 功    能:项目设置加减控制

 说    明:P1.5和P1.4 <==> +和-

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

//id为1时的下一级选择

void id_case1_key()

{

   if (P1_5==0)     //P1_5有按下,则数值增加(+)

      {

       Delay5Ms(); //适当延时,消除抖动

       if(P1_5==0) Set(id,0);  //根据选择调整相应项目

       if(id!=7)  while(P1_5==0);   

      }

   if (P1_4==0)    //P1_4有按下,则数值减少(-)

      {

       Delay5Ms(); //适当延时,消除抖动

       if(P1_4==0) Set(id,1);     //根据选择调整相应项目    

       if(id!=7) while(P1_4==0);   

      }

}

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

 函 数 名:void Set()

 功    能:项目设置

 说    明:sel_1=0时,数值加;sel_1=1时,数值减

 入口参数:sel和sel_1

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

//根据选择调整相应项目并写入DS1302

void Set(uchar sel,uchar sel_1)

{

  signed char address,item;

  signed char max,mini;

  //偶数指令是写,奇数指令是读

  //最大值与最小值限定

  if(sel==7)  {address=0x80; max=00;mini=0;}    //秒

  if(sel==6)  {address=0x82; max=59;mini=0;}    //分钟

  if(sel==5)  {address=0x84; max=23;mini=0;}    //小时

  if(sel==3)  {address=0x86; max=31;mini=1;}    //日

  if(sel==2)  {address=0x88; max=12;mini=1;}    //月

  if(sel==1)  {address=0x8c; max=99;mini=0;}    //年

  if(sel==4)  {address=0x8a; max=07;mini=1;}    //星期

  //先从1302中读出数据,把数据转换成十进制进行加减设置;后从先转换回来写入1302中

  item=R1302(address+1)/16*10+R1302(address+1)%16;//从1302中读出1字节,再转换成十进制

  if (sel_1==0) item++;  else item--; //sel_1=0则加,sel_1=1则减

  if(item>max) item=mini;   //大于最大值,则赋最小值(循环)

  if(item<mini) item=max;   //小于最小值,则赋最大值(循环)

          

  W1302(0x8e,0x00);   //允许写操作

  W1302(address,item/10*16+item%10);//把调节好的十进制数据转换成十六进制后写入1302中

  W1302(0x8e,0x80);   //写保护,禁止写操作 

}

//=======================================================================================

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

 函 数 名:void Disp_line1()

 功    能:显示时间和温度 (XX:XX:XX XX.X C)

 说    明:第一行显示数据处理

 入口参数:无

 返 回 值:无 

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

//屏幕显示第一行: 时间和温度显示

void Disp_line1(void)

  Read_Temperature(10,0); //温度显示

  //冒号闪烁    

  if(flag==0)

    {DisplayOneChar(3,0,0x3a); DisplayOneChar(6,0,0x3a);}

  else

    {DisplayOneChar(3,0,0x20); DisplayOneChar(6,0,0x20);}

  if(sec==1)  //秒闪烁标志位

    {

     if(flag==1)

       {   

        DisplayOneChar(7,0,R1302(0x81)/16+0x30); //显示秒十位

        DisplayOneChar(8,0,R1302(0x81)%16+0x30); //显示秒个位     

       }

     else

       {

        DisplayOneChar(7,0,0x20); //显示秒十位

        DisplayOneChar(8,0,0x20); //显示秒个位

       }

    }

  else

    {

     DisplayOneChar(7,0,R1302(0x81)/16+0x30); //显示秒十位

     DisplayOneChar(8,0,R1302(0x81)%16+0x30); //显示秒个位       

    }   

  

  if(min==1)  //分钟闪烁标志位

    {

     if(flag==1)

       {   

        DisplayOneChar(4,0,R1302(0x83)/16+0x30); //显示分钟十位

        DisplayOneChar(5,0,R1302(0x83)%16+0x30); //显示分钟个位      

       }

     else

       {

        DisplayOneChar(4,0,0x20); //显示分钟十位

        DisplayOneChar(5,0,0x20); //显示分钟个位  

       }

    }

  else

    {

     DisplayOneChar(4,0,R1302(0x83)/16+0x30); //显示分钟十位

     DisplayOneChar(5,0,R1302(0x83)%16+0x30); //显示分钟个位       

    }

  if(hour==1)  //小时闪烁标志位

    {

     if(flag==1)

       {   

        DisplayOneChar(1,0,R1302(0x85)/16+0x30);//显示小时十位

        DisplayOneChar(2,0,R1302(0x85)%16+0x30);//显示小时个位

       }

     else

       {

        DisplayOneChar(1,0,0x20); //显示小时十位

        DisplayOneChar(2,0,0x20); //显示小时个位  

       }

    }

  else

   {

    DisplayOneChar(1,0,R1302(0x85)/16+0x30);//显示小时十位

    DisplayOneChar(2,0,R1302(0x85)%16+0x30);//显示小时个位

   }

}

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

 函 数 名:void Disp_line2()

 功    能:显示日期和星期 (XX/XX/XX Week.X)

 说    明:第二行显示数据处理

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

// 屏幕显示第二行  日期和星期  

void Disp_line2(void)

{

  DisplayOneChar(3,1,0x2f);  //显示固定字符

  DisplayOneChar(6,1,0x2f);

  DisplayListChar(10,1,week);

   

  if(year==1)  //年闪烁标志位

    {

     if(flag==1)

       {   

        DisplayOneChar(1,1,R1302(0x8d)/16+0x30);//显示年十位

        DisplayOneChar(2,1,R1302(0x8d)%16+0x30);//显示年个位

       }

     else

       {

        DisplayOneChar(1,1,0x20); //显示年十位

        DisplayOneChar(2,1,0x20); //显示年个位  

       }

    }

  else

    {

      DisplayOneChar(1,1,R1302(0x8d)/16+0x30);//显示年十位

      DisplayOneChar(2,1,R1302(0x8d)%16+0x30);//显示年个位

    }

    

  if(mon==1)  //月闪烁标志位

    {

     if(flag==1)

       {   

        DisplayOneChar(4,1,R1302(0x89)/16+0x30);//显示月十位

        DisplayOneChar(5,1,R1302(0x89)%16+0x30);//显示月个位

       }

     else

       {

        DisplayOneChar(4,1,0x20); //显示月十位

        DisplayOneChar(5,1,0x20); //显示月个位  

       }

    }

  else

    {

      DisplayOneChar(4,1,R1302(0x89)/16+0x30);//显示月十位

      DisplayOneChar(5,1,R1302(0x89)%16+0x30);//显示月个位

    }  

  if(day==1)  //日闪烁标志位

    {

     if(flag==1)

       {   

         DisplayOneChar(7,1,R1302(0x87)/16+0x30);//显示日十位

         DisplayOneChar(8,1,R1302(0x87)%16+0x30);//显示日个位

       }

     else

       {

        DisplayOneChar(7,1,0x20); //显示日十位

        DisplayOneChar(8,1,0x20); //显示日个位  

       }

    }

  else

    {

      DisplayOneChar(7,1,R1302(0x87)/16+0x30);//显示日十位

      DisplayOneChar(8,1,R1302(0x87)%16+0x30);//显示日个位

    }

   if(weekk==1)  //星期闪烁标志位

    {

     if(flag==1)

       {   

         DisplayOneChar(15,1,R1302(0x8b)%16+0x30);//显示星期

       }

     else

       {

        DisplayOneChar(15,1,0x20); //显示星期         

       }

    }

  else

    {

      DisplayOneChar(15,1,R1302(0x8b)%16+0x30);//显示星期

    }    

}

 


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:17087 发表于 2009-12-10 15:44 | 只看该作者

//================================ LCM1602控制部分 =======================================

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

 函 数 名:void WriteDataLCM()

 功    能:向LCM1602中写入数据

 说    明:将形参WDLCM中的数据写入LCM中

 入口参数:WDLCM

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

//写数据

void WriteDataLCM(uchar WDLCM)

{

  ReadStatusLCM(); //检测忙

  LCM_Data = WDLCM;//写入数据到LCM

  LCM_RS = 1;

  LCM_RW = 0;

  LCM_E = 0; //若晶振速度太高可以在这后加小的延时

  LCM_E = 0; //延时

  LCM_E = 1;

}

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

 函 数 名:void WriteCommandLCM()

 功    能:向LCM1602中写入指令

 说    明:向LCM中写入指令;如果BuysC=0时,忽略忙检测,如果BuysC=1时,不忽略忙检测

 入口参数:WCLCM,BuysC

 返 回 值:无 

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

//写指令

void WriteCommandLCM(uchar WCLCM,BuysC) //BuysC为0时忽略忙检测

{

  if (BuysC) ReadStatusLCM(); //根据需要检测忙

  LCM_Data = WCLCM;   //写入指令

  LCM_RS = 0;

  LCM_RW = 0;

  LCM_E = 0;

  LCM_E = 0;

  LCM_E = 1;

}

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

 函 数 名:uchar ReadStatusLCM()

 功    能:读状态

 说    明:判断LCM的工作状态;也可以不用此函数,用一段延时程序代替

 入口参数:无

 返 回 值:LCM_Data 

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

//读状态

uchar ReadStatusLCM(void)

{

  LCM_Data = 0xFF; //LCM数据口先置1

  LCM_RS = 0;

  LCM_RW = 1;

  LCM_E = 0;

  LCM_E = 0;

  LCM_E = 1;

  while (LCM_Data & Busy); //检测忙信号.如果忙,则不执行

  return(LCM_Data);//不忙返回读取数据

}

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

 函 数 名:void LCMInit()

 功    能:初始化LCM1602

 说    明:LCM在工作前先要对显示屏初始化,否则模块无法正常工作

 入口参数:无

 返 回 值:五 

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

//LCM初始化

void LCMInit(void)

{

  LCM_Data = 0;

  WriteCommandLCM(0x38,0); // 三次显示模式设置,不检测忙信号

  Delay5Ms();

  WriteCommandLCM(0x38,0); // 0x38指令表示:8位数据显示模式,俩行多显示

  Delay5Ms();

  WriteCommandLCM(0x38,0);

  Delay5Ms();

  WriteCommandLCM(0x38,1); // 显示模式设置,开始要求每次检测忙信号

  WriteCommandLCM(0x08,1); // 关闭显示

  WriteCommandLCM(0x01,1); // 显示清屏

  WriteCommandLCM(0x06,1); // 显示光标移动设置

  WriteCommandLCM(0x0C,1); // 显示开及光标设置

}

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

 函 数 名:void DisplayOneChar()

 功    能:按指定坐标中写入数据

 说    明:X-横坐标,Y-纵坐标

 入口参数:X,Y,DData

 返 回 值: 

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

//按指定位置显示一个字符

void DisplayOneChar(uchar X, uchar Y, uchar DData)

{

  Y &= 0x01;

  X &= 0x0F;              //限制X不能大于15,Y不能大于1

  if (Y) X |= 0x40;       //当要显示第二行时地址码+0x40;

  X |= 0x80;              //算出指令码

  WriteCommandLCM(X, 0);  //这里不检测忙信号,发送地址码

  WriteDataLCM(DData);

}

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

 函 数 名:void DisplayListChar()

 功    能:向指定坐标中写入字符串

 说    明:X-横坐标,Y-纵坐标

 入口参数:X,Y,*DData

 返 回 值: 

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

//按指定位置显示一串字符  ***原来的遇到空格0x20就不显示***

void DisplayListChar(uchar X, uchar Y, uchar code *DData)

{

  uchar ListLength,j;

  ListLength = strlen(DData);//strlen:读取字符串的长度

  Y &= 0x1;

  X &= 0xF; //限制X不能大于15,Y不能大于1

      if (X <= 0xF) //X坐标应小于0xF

        {

      for(j=0;j<ListLength;j++)

        {

             DisplayOneChar(X, Y, DData[j]); //显示单个字符

             X++;//横坐标加1,纵坐标不变

            }

        }

}

//=================================== 自定义字符 ==========================================

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

 函 数 名:void mychar()

 功    能:自定义字符--CGRAM

 说    明:LCM1602字符库中没有温度符号,自定义温度符号

 入口参数:无

 返 回 值:无

 定义形式:1602中定义CGRAM的形式如下:

 ---------------------------------------------------------------------------

 |          CGRAM地址设置              |        自定义的代码               |

 | DB7 DB6 | DB5 DB4 DB3 | DB2 DB1 DB0 | DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0   |

 |  0   1  |  0   0   0  |  X   X   X  |  0   0   0   0   *   0   0   0    |

 |  0   1  |  0   0   1  |  X   X   X  |  0   0   0   0   *   0   0   1    |

 |   ...   |     ...     |     ...     |       ...               ...       |

 |  0   1  |  1   1   0  |  X   X   X  |  0   0   0   0   *   1   1   0    |

 |  0   1  |  1   1   1  |  X   X   X  |  0   0   0   0   *   1   1   1    |

 ---------------------------------------------------------------------------

  1. 1602共能定义8个5x8字符;

  2. CGRAM地址设置: X X X--DB2 DB1 DB0对应写入地址,1~8行;

  DB5 DB4 DB3对应自定义字符代码;DB7 DB6为指令码,不可变.

  3. 自定义的代码: 高4位DB7 DB6 DB5 DB4为0000时它的低3位DB2 DB1 DB0对应于第1-8个,DB3为无关项。

  4. 自定义的代码的DB2 DB1 DB0对应于CGRAM地址的DB5 DB4 DB3。

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

void mychar()

{

//---------自定义字符代码--01H-------------------

  WriteCommandLCM(0x48,0); //第1行  

  WriteDataLCM(0x02);//              

  WriteCommandLCM(0x49,0); //第2行  

  WriteDataLCM(0x05);//               

  WriteCommandLCM(0x4a,0); //第3行    1------**--

  WriteDataLCM(0x05);//               2----**--**

  WriteCommandLCM(0x4b,0); //第4行    3----**--**

  WriteDataLCM(0x02);//               4------**--

  WriteCommandLCM(0x4c,0); //第5行    5----------

  WriteDataLCM(0x00);//               6----------

  WriteCommandLCM(0x4d,0); //第6行    7----------

  WriteDataLCM(0x00);//               8----------

  WriteCommandLCM(0x4e,0); //第7行  

  WriteDataLCM(0x00);//

  WriteCommandLCM(0x4f,0); //第8行  

  WriteDataLCM(0x00);//

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

}

//======================================= 延时函数部分 ====================================

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

 函 数 名:void Delay5Ms()

 功    能:5ms延时

 说    明:软件消除按键抖动和适当的延时

 入口参数:无

 返 回 值:无 

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

//5ms延时

void Delay5Ms(void)

{

  uint TempCyc = 5552; //放入延时数据

  while(TempCyc--);

}

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

 函 数 名:void Delay400Ms()

 功    能:400ms延时

 说    明:

 入口参数:无

 返 回 值:无 

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

//400ms延时

void Delay400Ms(void)

{

  uchar TempCycA = 5;

  uint TempCycB;

  while(TempCycA--)

   {

     TempCycB=7269;

     while(TempCycB--);

   };

}

 

[此贴子已经被作者于2009-12-10 15:45:26编辑过]
回复

使用道具 举报

板凳
ID:17087 发表于 2009-12-10 15:44 | 只看该作者

//================================== 时钟芯片控制部分 ======================================

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

 函 数 名:RTInputByte()

 功    能:实时时钟写入一字节

 说    明:往DS1302写入1Byte数据 (内部函数)

 入口参数:d 写入的数据

 返 回 值:无 

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

void RTInputByte(uchar d)

{

    uchar i;

    ACC = d;

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

    {

        T_IO = ACC0;           /*相当于汇编中的 RRC */

        T_CLK = 1;

        T_CLK = 0;

        ACC = ACC >> 1;

    }

}

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

 函 数 名:RTOutputByte()

 功    能:实时时钟读取一字节

 说    明:从DS1302读取1Byte数据 (内部函数)

 入口参数:无 

 返 回 值:ACC

 设    计:zhaojun              日    期:2007-06-29

 修    改:                     日    期:

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

uchar RTOutputByte(void)

{

    uchar i;

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

    {

        ACC = ACC >>1;    /*相当于汇编中的 RRC */

        ACC7 = T_IO;

        T_CLK = 1;

        T_CLK = 0;

    }

    return(ACC); //返回读取值

}

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

 函 数 名:W1302()

 功    能:往DS1302写入数据

 说    明:先写地址,后写命令/数据 (内部函数)

 调    用:RTInputByte() , RTOutputByte()

 入口参数:ucAddr: DS1302地址, ucData: 要写的数据

 返 回 值:无

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

void W1302(uchar ucAddr, uchar ucDa)

{

    T_RST = 0;

    T_CLK = 0;

    T_RST = 1;

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

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

    T_CLK = 1;

    T_RST = 0;

}

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

 函 数 名:R1302()

 功    能:读取DS1302某地址的数据

 说    明:先写地址,后读命令/数据 (内部函数)

 调    用:RTInputByte() , RTOutputByte()

 入口参数:ucAddr: DS1302地址

 返 回 值:ucData :读取的数据

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

uchar R1302(uchar ucAddr)

{

    uchar ucData;

    T_RST = 0;

    T_CLK = 0;

    T_RST = 1;

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

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

    T_CLK = 1;

    T_RST = 0;

    return(ucData);

}

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

 函 数 名:Set1302()

 功    能:设置初始时间

 说    明:先写地址,后读命令/数据(寄存器多字节方式)

 调    用:W1302()

 入口参数:pClock: 设置时钟数据地址 格式为: 秒 分 时 日 月 星期 年

                               7Byte (BCD码)1B 1B 1B 1B 1B  1B  1B

 返 回 值:无

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

void Set1302(uchar *pClock)

{

    uchar i;

    uchar ucAddr = 0x80;

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

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

    {

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

        pClock++;

        ucAddr +=2;

    }

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

}

//================================= 温度显示控制部分 ===============================================

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

 函 数 名:void delay()

 功    能:DS18B20延时

 说    明:DS18B20时序延时

 入口参数:useconds

 返 回 值:无 

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

//*********** 18B20驱动 **************************

//延时

void delay(word useconds)

{

  for(;useconds>0;useconds--);

}

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

 函 数 名:byte ow_reset()

 功    能:DS18B20复位

 说    明:DS18B20使用时先要复位

 入口参数:无

 返 回 值:presence 

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

//复位

byte ow_reset(void)

{

  byte presence;

  DQ = 0;           //拉低总线

  delay(29);        // 保持 480us

  DQ = 1;           // 释放总线

  delay(3);         // 等待回复

  presence = DQ;    // 读取信号

  delay(25);        // 等待结束信号

  return(presence); // 返回   0:正常 1:不存在

}    

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

 函 数 名:byte read_byte()

 功    能:从 1-wire 总线上读取一个字节

 说    明:读总线上的数据有严格的时序

 入口参数:

 返 回 值:value 

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

byte read_byte(void)

{

  byte i;

  byte value = 0;

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

  {

    value>>=1;

    DQ = 0;

    DQ = 1;

    delay(1); 

    if(DQ)value|=0x80;

    delay(6);

  }

  return(value);

}

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

 函 数 名:void write_byte()

 功    能:向 1-WIRE 总线上写一个字节

 说    明:写总线上的数据有严格的时序

 入口参数:val

 返 回 值:无 

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

void write_byte(char val)

{

  byte i;

  for (i=8; i>0; i--) // 一次写一位

  {

    DQ = 0;          //

    DQ = val&0x01;

    delay(5);        //

    DQ = 1;

    val=val/2;

  }

  delay(5);

}

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

 函 数 名:Read_Temperature()

 功    能:读取和显示温度

 说    明:

 入口参数:xx,yy

 返 回 值:无 

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

Read_Temperature(char xx,char yy)

{

  uchar i,tl_temp;

  uint  x;

  uchar ct[8];

  union   //共用体

  {

    byte c[2];

    int x;

  }temp;   

 

  ow_reset();             // DS18B20复位

  write_byte(0xCC);       // Skip ROM

  write_byte(0x44);       // 转换温度

  ow_reset();

  write_byte(0xCC);       // Skip ROM

  write_byte(0xbe);       // 读取寄存器

  temp.c[1]=read_byte();  // 读出温度低8位

  temp.c[0]=read_byte();  // 读出温度高8位

  // 零下温度判断

  sflag=0; //温度零下标志 0:零上,1:零下

  if((temp.c[0]&0xf8)!=0x00)

   {

    sflag=1;                        // 零下标志位置1

    temp.c[1]=~temp.c[1];           // 低8位取反

    temp.c[0]=~temp.c[0];           // 高8位取反

    tl_temp=temp.c[1]+1;            // 低8位加1

    temp.c[1]=tl_temp;              // 计算后重新存入数组

    if(tl_temp>255) temp.c[0]++;    // 如果低8位大于255,向高8位进1

  } 

  x=((temp.c[0]&0x07)*256+temp.c[1])*.625;

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

       {

         ct=0;

       }

  i=0;

  while(x/10)

   {

    ct=x%10;

    x=x/10;

    i++;

   }

  ct=x;

  if(sflag==1) DisplayOneChar(xx-1,yy,0x2d);

  else         DisplayOneChar(xx-1,yy,0x20);

  DisplayOneChar(xx,  yy,ct[2]+0x30);        // 显示温度十位数

  DisplayOneChar(xx+1,yy,ct[1]+0x30);        // 显示温度个位数

  DisplayOneChar(xx+2,yy,0x2e);              // 显示小数点

  DisplayOneChar(xx+3,yy,ct[0]+0x30);        // 显示温度小数位

  DisplayOneChar(xx+4,yy,0x01);              // 显示自定义字符

  DisplayOneChar(xx+5,yy,0x43);              // 显示字符"C"

}

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

 函 数 名:void adjust_res()

 功    能:温度分辨率调整

 说    明:此函数可以对温度的显示进行精度调节.

 入口参数:res

 返 回 值:无 

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

void adjust_res(char res)  // res 分别等于 0x1f, 0x3f, 0x5f 温度读数分辨率分别对应

                           //               0.5, 0.25, 0.125  

{

  ow_reset();             // 复位

  write_byte(0xcc);       // 跳过Rom

  write_byte(0x4e);       // 写暂存器

  write_byte(0x02);       // 写TH

  write_byte(0x01);       // 写TL

  write_byte(res);        // 温度转换分辨率设置

  ow_reset();             // 复位

  write_byte(0xcc);       // 跳过Rom

  write_byte(0x48);       // 把暂存器内容写到EPRam中

}

//==========================程序结束======================================================

[此贴子已经被作者于2009-12-10 15:47:04编辑过]
回复

使用道具 举报

地板
ID:17087 发表于 2009-12-11 20:52 | 只看该作者

咋没人鸟一下呢?~~

回复

使用道具 举报

5#
ID:20595 发表于 2009-12-29 21:52 | 只看该作者
我鸟你一下,可惜我看不懂
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表