51 single chip perpetual calendar

Publisher:温馨小筑Latest update time:2017-01-05 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

I worked on this small project for 5 days and I feel a sense of accomplishment. Thanks to the seniors for their suggestions.


12864 LCD, DS12C887 clock chip, DS18B20 temperature sensor...


#define uchar unsigned char

#define uint unsigned int


uint temp;

float f_temp;


sbit Ds=P2^2;

sbit Dula=P2^6;

sbit Wela=P2^7;


sbit LcdCS=P3^5; //Register selection input determines whether to write data or write command through rs

sbit LcdSID=P3^6; //LCD read/write control Because no data is read from the LCD, rw is always 0

sbit LcdSCLK=P3^4; //LCD enable control Give en a high pulse to send data to the LCD controller

sbit LcdPSB=P3^7; //Serial-parallel control


sbit DSCS=P1^4; //Chip select signal, low level is valid

sbit DSAS=P1^5; //The rising edge of the address select input terminal AS latches the address information appearing on AD0~AD7 into the DS12C887, and the falling edge clears the address information

sbit DSRW=P1^6; //

sbit DSDS=P1^7; //


uchar code table1[]={"CHPAVC 天若海愚"};

uchar code table3[]={"Monday"};

uchar code table4[]={"Tuesday"};

uchar code table5[]={"Wednesday"};

uchar code table6[]={"Thursday"};

uchar code table7[]={"Friday"};

uchar code table8[]={"Saturday"};

uchar code table9[]={"Sunday"};

uchar code table10[]={"°C"};


uchar buff[4];    


char year,month,day,week,miao,fen,shi;

uchar nyrsfm[17]; //In the Write_nyrsfm function, method 2 nyrsfm only needs to be declared as nyrsfm[16]




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

File name: wannianli

Author: Tian Ruo Hai Yu

Version number: V1.0

illustrate :    

Created: September 17, 2013 13:30:38

Modification history: None

Note: The year, month, day, hour and minute data collected from DS12C887 are displayed on the 12864 LCD screen, and the temperature collected by DS18B20 is displayed on the 12864

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


#include

#include

#include

#include


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

Function Name: Delay()

Function: Delay

Input parameters: z

Remark :

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

void Delay(uint z)

{

    uint x,y;

    for(x=z;x>0;x--)

        for(y=110;y>0;y--);

}


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

Function Name: Ds_reset()

Function: DS18B20 reset, initialization function

Entry parameters: None

Remark :

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

void Ds_reset()

{

    uint i;

    Ds=1; //Book P348, timing diagram, first set the data line to high level 1

    _nop_(); //Delay, as short as possible

    Ds=0;

    i=103;

    while(i>0)

        i--; //When the bus stays at a low level for more than 480us, all devices on the bus will be reset.

                //Delay about 680us The bus stays at a low level for more than 480μs, and all devices on the bus will be reset

    _nop_(); //Delay, as short as possible

    

    Ds=1;

    i=5;

    while(i>0)

        i--; //After releasing the bus, if the initialization is successful, a low level 0 is generated within 15~60us, which is returned by DDS18B20.

                //This state can confirm its existence, but cannot wait indefinitely

}


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

Function name: Ds_read_bit()

Function: Read one bit of data

Entry parameters: None

Remark :

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

bit Ds_read_bit()

{

    uint i;

    bit date;

    

    Ds=0; //MCU (microprocessor) pulls the bus low

    _nop_(); //The read time slot starts when the microprocessor pulls the bus down for at least 1us

    Ds=1; //Pull the bus down and then release the bus, so that the slave 18b20 can take over the bus and output valid data

    _nop_();

    _nop_(); // Delay a little and read the data on 18b20, because the data output from ds18b20 is valid within 15us when the falling edge of the read "time gap" appears

    dat=Ds; //The host reads the data output by the slave 18b20. These data are valid within 15us of the falling edge of the read time slot. 

    i=10;

    while(i>0)

        i--; //All read "time intervals" must be 60~120us, here 77us

    return(dat);

}



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

Function name: Ds_read_byte()

Function: Read a byte of data

Entry parameters: None

Remark :

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

uchar Ds_read_byte()

{

    uchar i,j,dat;

    dat=0; //The initial value cannot be forgotten

    for(i=1;i<=8;i++) //This sentence was once written as for(i=0;i<=8;i++), which caused the program to display the wrong result. Details...

    {

        j=Ds_read_bit();

        dat=(j<<7)|(dat>>1); //The lowest bit of the read data is at the front, so there is exactly one byte in dat

    }

    return(dat);

}


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

Function name: Ds_write_byte()

Function: Write a byte function to DS18B20

Entry parameters:    

Remark :

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

void Ds_write_byte(uchar dat)

{

    uchar i;

    uint j;

    bit testb;

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

    {

        testb=dat&0x01;

        dat=dat>>1;

        if(testb)

        {

            Ds=0;

            _nop_();

            _nop_(); //Look at the timing diagram, at least 1us delay is required to generate a write "time gap"  

            Ds=1; //The data line is allowed to be pulled high within 15μs after the start of the write time gap

            j=8;

            while(j>0)

                j--; //All write time gaps must last at least 60us

        }

        else

        {

            Ds=0;

            j=8;

            while(j>0)

                j--; //The host needs to generate a write-0 time gap, and must pull the data line to a low level and maintain it for at least 60μs.

            Ds=1;

            _nop_();

            _nop_();        

        }

    }

}


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

Function name: Ds_change()

Function: 18b20 starts to obtain temperature and convert

Entry parameters:

Remark :

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

void Ds_change()

{

    Ds_reset(); //initialization

    Delay(1);

    Ds_write_byte(0xcc); // Skip ROM. Send temperature conversion command directly to 18b20, suitable for one slave machine

    Ds_write_byte(0x44); //Write temperature conversion instruction

}


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

Function Name: Get_temp()

Function: Read the temperature stored in the register

Entry parameters: None

Remark :

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

uint Get_temp()

{

    uchar a,b;

    Ds_reset();

    Delay(1);

    Ds_write_byte(0xcc); //Write and skip the ROM read instruction

    Ds_write_byte(0xbe); //Read the temporary register. Read the 9-byte temperature data in the internal RAM

    a=Ds_read_byte(); //Read lower 8 bits

    b=Ds_read_byte(); //Read high 8 bits

    temp=b;

    temp<<=8; //Two bytes are combined into one word

    temp=temp|a;

    f_temp=temp*0.0625; //Get the true decimal temperature value. Since DS18B20 can be accurate to 0.0625 degrees, the lowest bit of the read-back data represents 0.0625 degrees.

    temp=f_temp*10+0.5; //Multiplying by 10 does not mean taking only one digit after the decimal point, and adding 0.5 means rounding

    f_temp=f_temp+0.05;

    

    return temp; //temp is an integer

}


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

Function name: init_com()

Function: Serial port initialization

Entry parameters: None

Remark :

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

void init_com()

{

    TMOD=0x20; //Timer 1, mode 2

    PCON=0x00;

    SCON=0x50; //equivalent to REN=1;SM0=0;SM1=1;

    TH1=0xFD;

    TL1=0xFD; //Set baud rate to 9600

    TR1=1; //Start timer 1

}


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

Function name: comm()

Function: Serial port sends data

Entry parameters:    

Remark :

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

void comm(uchar *parr)

{

    do

    {

        SBUF=*parr++;

        while(!TI); //Sending completed, TI is set to 1 by hardware

        TI=0;

    }while(*parr); //Keep looping until the character is '\0'

}


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

Function name: Send_byte()

Function: Send a byte

Input parameter: bbyte

Remark :

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

void Send_byte(uchar bbyte)

{

    uchar i;

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

    {

        LcdSID=bbyte&0x80; //Get the highest bit

        LcdSCLK=1;

        LcdSCLK=0; //At the moment when sclk changes from low level to high level, the LCD controller reads or outputs the data on sid

        bbyte<<=1; //left shift 1 bit

    }

}


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

Function Name: Write_char()

Function: Write data or write command

Entry parameters: start,ddata

Remark :

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

void Write_char(bit start,uchar ddata)

{

    uchar start_data,Hdata,Ldata;

    if(start==0)

    {

        start_data=0xf8; //write instruction

    }

    else

    {

        start_data=0xfa; //write data

    }

    

    Hdata=ddata&0xf0; //Get the upper 4 bits

    Ldata=(ddata<<4)&0xf0; //Get the lower 4 bits

    Send_byte(start_data); //Send start signal

    Delay(5); //Delay is required

    Send_byte(Hdata); //Send high 4 bits

    Delay(1); //Delay is required

    Send_byte(Ldata);

    Delay(1);

}


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

Function Name: Lcd_pos()

Function: Set the display position

Input parameters: X,Y

Remark :

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

void Lcd_pos(uchar X,uchar Y)

{

    uchar pos;

    if(X==0)

    {

        X=0x80;

    }

    else if(X==1)

    {

        X=0x90;

    }

    else if(X==2)

    {

        X=0x88;

    }

    else if(X==3)

    {

        X=0x98;

    }

    pos=X+Y;

    Write_char(0,pos);

}


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

Function name: Lcd_init()

Function: LCD initialization

Entry parameters: None

Remark :

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

void Lcd_init()

{

    Delay(5); //Start waiting, wait for LCD to enter working state

    LcdPSB=0; //Serial port driver

    Write_char(0,0x30); //Basic instruction operation

    Delay(5);

    Write_char(0,0x0c); //display on, off cursor, highlight off

    Delay(5);

    Write_char(0,0x01); //Clear the screen and reset the DDRAM address counter to zero

    Delay(5);

}



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

Function Name: Display_temp()

Function: Display temperature on 12864

Entry parameters:

Note: Keep one decimal place.

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

void Display_temp()

{

    uchar i;

    Lcd_pos(2,4);

    Write_char(1,buff[0]);

    Write_char(1,buff[1]);

    Write_char(1,buff[2]);

    Write_char(1,buff[3]);        


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

    {

        Write_char(1,table10[i]); //Display symbol °C 

        Delay(5);

    }

}


/*********The following is how to operate the DS12C87 clock chip***********/

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

Function Name: Write_ds()

Function: Write 12C8887 function

Entry parameters: add,date

Remark :

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

void Write_ds(uchar add,uchar date)

{

    DSCS=0;

    DSAS=1;

    DSDS=1;

    DSRW=1;

    P0=add;

    DSAS=0; //The falling edge of dsas latches the address information on AD0~~AD7 into DS12C887

    DSRW=0;

    P0=date;

    DSAS=1;

    DSRW=1; //INTER mode, the rising edge of dsrw latches data

    DSCS=1;

}


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

Function Name: Read_ds()

Function: Read 12C8887 function

Entry parameters: add

Remark :

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

uchar Read_ds(uchar add)

{

    uchar ds_date;

    DSAS=1;

    DSDS=1;

    DSRW=1;

    DSCS=0;

    P0=add; //write address first

    DSAS=0;

    DSDS=0;

    P0=0xff;

    ds_date=P0; //Read data again

    DSDS=1;

    DSCS=1;

    DSAS=1;

    return ds_date;

}


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

Function name: Write_nyrsfm()

Function: Display year, month, day, hour and minute on 12864 LCD

Entry parameters:

Note: This cannot be achieved through the functions in /* below

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

void Write_nyrsfm(char year,char month,char day,char shi,char fen)

{

    //method one:

    

    /*uchar i;

    Lcd_pos(1,0);

    

    nyrsfm[0]=0x32;

    nyrsfm[1]=0x30;

    nyrsfm[2]=year/10+0x30;

    nyrsfm[3]=year%10+0x30;

    nyrsfm[4]='-';

    nyrsfm[5]=month/10+0x30;

    nyrsfm[6]=month%10+0x30;

    nyrsfm[7]='-';

    nyrsfm[8]=day/10+0x30;

    nyrsfm[9]=day%10+0x30;

    nyrsfm[10]=' ';

    nyrsfm[11]=shi/10+0x30;

    nyrsfm[12]=shi%10+0x30;    

    nyrsfm[13]=':';

    nyrsfm[14]=fen/10+0x30;

    nyrsfm[15]=fen%10+0x30;

    nyrsfm[16]='\0';

    

    //while(nyrsfm[i]!='\0') //while() loop is not displayed, it is wrong

    //{

    // Write_char(1,nyrsfm[i]);        

    // i++;

    //}

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

    {

        Write_char(1,nyrsfm[i]);

        Delay(5);

    }*/



    //Method Two:

    

    Lcd_pos(1,0);

    

    nyrsfm[0]=0x32;

    Write_char(1,0x32);

    

    nyrsfm[1]=0x30;

    Write_char(1,0x30);

    

    nyrsfm[2]=year/10+0x30;

    Write_char(1,nyrsfm[2]);

    

    nyrsfm[3]=year%10+0x30;

    Write_char(1,nyrsfm[3]);

    

    nyrsfm[4]='-';

    Write_char(1,nyrsfm[4]);

    

    nyrsfm[5]=month/10+0x30;

    Write_char(1,nyrsfm[5]);


    nyrsfm[6]=month%10+0x30;

    Write_char(1,nyrsfm[6]);

    

    nyrsfm[7]='-';

    Write_char(1,nyrsfm[7]);

    

    nyrsfm[8]=day/10+0x30;

    Write_char(1,nyrsfm[8]);

    

    nyrsfm[9]=day%10+0x30;

    Write_char(1,nyrsfm[9]);

    

    nyrsfm[10]=' ';

    Write_char(1,nyrsfm[10]);

    

    nyrsfm[11]=shi/10+0x30;

    Write_char(1,nyrsfm[11]);

    

    nyrsfm[12]=shi%10+0x30;

    Write_char(1,nyrsfm[12]);

    

    nyrsfm[13]=':';

    Write_char(1,nyrsfm[13]);

    

    nyrsfm[14]=fen/10+0x30;

    Write_char(1,nyrsfm[14]);

    

    nyrsfm[15]=fen%10+0x30;

    Write_char(1,nyrsfm[15]);

}


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

Function name: Write_week()

Function: Week display

Entry parameters: xq

Remark :

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

void Write_week(char xq)

{

    uchar i;


    Lcd_pos(2,0);

    switch(xq)

    {

        case 1:

            i=0;

            while(table3[i]!='\0')

            {

                Write_char(1,table3[i]);

                i++;

            }

            break;

        case 2:

            i=0;

            while(table4[i]!='\0')

            {

                Write_char(1,table4[i]);

                i++;

            }

            break;

        case 3:

            i=0;

            while(table5[i]!='\0')

            {

                Write_char(1,table5[i]);

                i++;

            }

            break;

        case 4:

            i=0;

            while(table6[i]!='\0')

            {

                Write_char(1,table6[i]);

                i++;

            }

            break;

        case 5:

            i=0;

            while(table7[i]!='\0')

            {

                Write_char(1,table7[i]);

                i++;

            }

            break;

        case 6:

            i=0;

            while(table8[i]!='\0')

            {

                Write_char(1,table8[i]);

                i++;

            }

            break;

        case 7:

            i=0;

            while(table9[i]!='\0')

            {

                Write_char(1,table9[i]);

                i++;

            }

            break;

    }

}


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

Function name: Set_time()

Function: DS12C887 first power-on initialization time function

Entry parameters: None

Remark :

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

void Set_time()

{

    Write_ds(2,25);

    Write_ds(4,10);

    Write_ds(6,3);

    Write_ds(7,18);

    Write_ds(8,9);

    Write_ds(9,13);

}


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

Function name: init()

Function: Initialization

Entry parameters: None

Remark :

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

void init()

{

    uchar i;

    i=0;

    Wela=0;

    Dula=0;

    EA=1;

    EX1=1;

    IT1=1;


    Set_time(); //Used when powered on for the first time, only needs to be executed once

    Lcd_pos(3,0);    

    while(table1[i]!='\0')

    {

        Write_char(1,table1[i]);

        i++;

    }

}



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

Function name: Main()

Function:    

Entry parameters:

Remark :

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

void Main()

{

    init_com(); //Serial port initialization

    Lcd_init(); //LCD initialization

    init(); //Cannot be placed before the Lcd_init() function, the contents of the init() function can only be displayed after the LCD is initialized

    

    while(1)

    {

        Ds_change(); //Read the temperature stored in the register

        Get_temp(); //Get temperature and convert

        

        sprintf(buff,"%.1f",f_temp); //Format the floating point temperature as a character type and keep one digit. #include is required

        Delay(1000);

        comm(buff); //Serial port sends data and displays it on the serial port debugging assistant. This sentence is mainly added here to test the content of buff.

        Display_temp(); //Display temperature on 12864 LCD

        

        Delay(5);

        year=Read_ds(9); //Read data from DS12C887

        month=Read_ds(8);

        day=Read_ds(7);

        week=Read_ds(6);

        shi=Read_ds(4);

        fen = Read_ds(2);


        Write_nyrsfm(year,month,day,shi,fen); //display on 12864 LCD

        Write_week(week); //Display the week

    }

}


Reference address:51 single chip perpetual calendar

Previous article:[51 MCU Study Notes FIVE]----Independent Buttons
Next article:In-depth analysis of 51 MCU stack

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号