Jednoduchý teploměr s čidlem DS1820 a LCD displejem. Program je opět odladěn v C51v6.20. Čidlo komunikuje po sběrnicí OneWire. Samotná implementace SW pro tuto sběrnici je značně zjednodušena. Vřele nedoporučuji připojit čidlo na větší vzdálenost. Autoři sice použili procesor 80C751, ale nic nebrání implementaci do libovolného klonu x51.


/*==========================================================================*\

File:       PRO.C

Purpose:    Interface an HD4470 LCD driver with a DS1820 thermometer via
            an 8051 microprocessor.

Language: C

Compiled in uVision (part of the Kyle Development environment)

Written By:
    Ian Downard and Chess Combites    28 Nov 1999


\*===========================================================================*/

#include<reg51.h>#define uchar unsigned char
#define uint unsigned


/* ROM COMANDS */
#define READ_ROM             0x33
#define MATCH_ROM            0x55
#define SKIP_ROM             0xCC
#define SEARCH_ROM           0xF0
#define ALARM_SEARCH         0xEC
 
/* MEMORY FUNCTIONS */
#define WRITE_SCRATCHPAD     0x4E
#define READ_SCRATCHPAD      0xBE
#define COPY_SCRATCHPAD      0x48
#define CONVERT_T            0x44
#define RECALL_E2            0xB8
#define READ_POWER_SUPPLY    0xB4

/* LCD Commands*/
#define DISPLAY_ON 0xC                  /* display on, cursor on, no blink */
#define RETURN_HOME 0x2                 /* to first position on display */
#define FUNCTION_SET 0X30               /* 8 bit interface, 5x7 dots, 2 lines */
#define ENTRY_MODE1 0X6                  /* entry mode: incrmnt +1, dsp shift */
#define ENTRY_MODE2 0X6                  /* set display to shift after each data write */
#define CLEAR_DISPLAY 0x1
#define DISPLAY_OFF 0x8

/* Characters */
#define _SPACE_  0x20
#define _DEC_    0x2E
#define _DEG_    0xDF
#define _NEG_    0xB0
#define _C_      0x43
#define _0_      0x30
#define _1_      0x31
#define _2_      0x32
#define _3_      0x33
#define _4_      0x34
#define _5_      0x35
#define _6_      0x36
#define _7_      0x37
#define _8_      0x38
#define _9_      0x39


char command(char comm, char second);
void c_write(char out);
char c_read(void);
char reset();
void initialize(void);
void msec(int Delay);
void lcd_cmdwr(uchar dbyte);
void lcd_dwr(uchar dbyte);

/* global variables */
sbit rw = 0xB5;
sbit rs = 0xB6;
sbit ena = 0xB7;
sbit IO = P0^1;

char SCRATCHPAD[9];
char E2[2];
char POWER_STATUS;
 
//char * T_LSB = SCRATCHPAD[0];
//char *T_MSB = SCRATCHPAD[1];
//char *TH = SCRATCHPAD[2];
//char *TL = SCRATCHPAD[3];
//char *R1 = SCRATCHPAD[4];
//char *R2 = SCRATCHPAD[5];
//char *COUNT_REMAIN = SCRATCHPAD[6];
//char *COUNT_PER_C = SCRATCHPAD[7];
//char *CRC = SCRATCHPAD[8];

//char *ETH = E2[0];
//char *ETL = &E2[1];



void main(void){
     char num[10];
     char i = 0;
     char sign,
          hunds,
          newhunds,
          tens,
          newtens,
          ones,
          newones,
          halfs,
          newhalfs;

     num[0] = _0_;
     num[1] = _1_;
     num[2] = _2_;
     num[3] = _3_;
     num[4] = _4_;
     num[5] = _5_;
     num[6] = _6_;
     num[7] = _7_;
     num[8] = _8_;
     num[9] = _9_;
/* initalize display */
    initialize();

    /* loop of read and display */
    while(1){

        /* take measurment*/
        i = command( SKIP_ROM, i);
        i = command( CONVERT_T, i);

        while(!IO);

        i = command( SKIP_ROM, i);
        i = command( READ_SCRATCHPAD, 1);


        if( SCRATCHPAD[0] & 0x01)
             newhalfs = _5_;
        else
             newhalfs = _0_;

        if( SCRATCHPAD[1] & 0x01)   /* 1st bit of 2nd byte is the signed bit */
             sign = _NEG_;
        else
             sign = _SPACE_;
        SCRATCHPAD[0] = SCRATCHPAD[0] >> 1;

        SCRATCHPAD[0] = (SCRATCHPAD[0] & 0x7F) | (SCRATCHPAD[1]);

        if(sign == _NEG_)
             SCRATCHPAD[0] = ~SCRATCHPAD[0] +1;

        newhunds = SCRATCHPAD[0] / 100;
        SCRATCHPAD[0] = SCRATCHPAD[0] - (newhunds * 100);
        newtens  = SCRATCHPAD[0] / 10;
        SCRATCHPAD[0] = SCRATCHPAD[0] - (newtens * 10);
        newones = SCRATCHPAD[0];

        /* This keeps erronious characters from being displayed */
        if((newhunds > 9) || (newhunds < 0) || (newtens > 9) || (newtens < 0) ||
             (newones > 9) || (newones < 0));
        else{
       
                newhunds = num[newhunds];
                newtens = num[newtens];
                newones = num[newones];

       
       
                if (newhunds!=hunds || newtens!=tens || newones!=ones || newhalfs!=halfs)
                {
                     hunds = newhunds; tens = newtens; ones = newones; halfs = newhalfs;
                     /* prepare LCD */
                     lcd_cmdwr(CLEAR_DISPLAY);        
                     lcd_cmdwr(RETURN_HOME);

                     /* write to LCD */
                     lcd_dwr(sign);
                     lcd_dwr(hunds);
                     lcd_dwr(tens);
                     lcd_dwr(ones);
                     lcd_dwr(_DEC_);
                     lcd_dwr(halfs);
                     lcd_dwr(_DEG_);
                     lcd_dwr(_C_);
                }
        }
    }
}

void initialize(void)
{
    msec(15);                           /* set up LCD modes */
    rs = 0;
    rw=0;
    msec(1);
    P1=0;

    lcd_cmdwr(FUNCTION_SET);
    lcd_cmdwr(FUNCTION_SET);
    lcd_cmdwr(FUNCTION_SET);
    lcd_cmdwr(CLEAR_DISPLAY);
    lcd_cmdwr(DISPLAY_OFF);
    lcd_cmdwr(DISPLAY_ON);
    lcd_cmdwr(CLEAR_DISPLAY);
    lcd_cmdwr(ENTRY_MODE1);
    lcd_cmdwr(CLEAR_DISPLAY);
}

void lcd_dwr(uchar dbyte)
{
    rs=1;
    msec(1);
    ena=1;
    msec(2);
    P1=dbyte;
    msec(2);
    ena = 0;
    msec(5);
}

void lcd_cmdwr(uchar dbyte)
{
    rs=0;
    msec(1);
    ena=1;
    msec(2);
    P1=dbyte;
    msec(2);
    ena = 0;
    msec(5);
}

void msec(int Delay)
{
    int i, j;
    for(j=0; j<Delay; j++)
    {
        for (i=0; i<500; i++);
    }
}

char command(char comm, char second){
     char retvalue=0;//OK
     char i;

     switch(comm){
          case READ_ROM:     //not currently needed
               while(reset());
               c_write(READ_ROM);
               break;
          case MATCH_ROM:    // not currently needed
               while(reset());
               c_write(MATCH_ROM);
               break;
          case SKIP_ROM:
               while(reset());
               c_write(SKIP_ROM);
               break;
          case SEARCH_ROM:   //not currently neaded
               while(reset());
               c_write(SEARCH_ROM);
               break;
          case ALARM_SEARCH: // not currently needed
               while(reset());
               c_write(ALARM_SEARCH);
               break;
          case WRITE_SCRATCHPAD:
               // second is number of bytes to write
               second++;
               c_write(WRITE_SCRATCHPAD);
               for(i=2; i<= second; i++)
                    c_write(SCRATCHPAD[i]);
               //while(reset());                  
               break;
          case READ_SCRATCHPAD:
               // second is number of bytes to read
               c_write(READ_SCRATCHPAD);
               for(i=0; i <= second; i++){
                    SCRATCHPAD[i] = c_read();
               }
               //while(reset());
               break;
          case COPY_SCRATCHPAD:
               c_write(COPY_SCRATCHPAD);
               i=10;
               while(i--);  /* wait */
               //while(reset());
               break;
          case CONVERT_T:
               c_write(CONVERT_T);
               i = 10;
               while(i--);   /* wait*/
               //while(!IO);
               //while(reset());
               break;
          case RECALL_E2:
               c_write(RECALL_E2);
               i=10;
               while(i--)
               retvalue = (0x01 | IO);
               //while(reset());
               break;
          case READ_POWER_SUPPLY:
               c_write(READ_POWER_SUPPLY);
               i=10;
               while(i--);
               POWER_STATUS= (0x01 | IO);
               break;
     }
     return retvalue;
}


void c_write(char out){
     char i,j;

     for (j=0; j<=7;j++){

          IO = 0;             //set low
          if(out &  0x01){      /* write '1' */
               i = 3;
               while(i--);      /* 10us delay */

               IO = 1;        //set high
               i=20;
               while(i--);      /* 60us delay */
          }
          else {
               i=20;
               while(i--);      /* 60us delay */                    

               IO = 1;        //set high
               i=3;
               while(i--);      /* 10us delay */
          }
          out = out >> 1;
     }
}

char c_read(void){
     char i,j;
     char t = 0;

     //out 0 or input without pullup
     for(i=0; i<=7; i++){

          IO = 0;         // set output 0;
          j=1;
          while(j--);     /* 2us delay */
   
          IO = 1;          //set to input
          j=3;
          while(j--);     /* 10us deloay */
         
          t>>=1;          /*next bit */

          if(IO == 1)
               t |= 0x80;
          else
               t &= 0x7f;
          j=60;
          while(j--);     /* 60us delay */
     }
     return t;
}

char reset(){
     unsigned char i;
     unsigned char status;
     
     i = 255;              /* reset send */
     IO = 0;
     while(i--);

     IO = 1;               /* ready read */
 
     i=20;
     while(i--);

     i=255;                /* wait for presence pulse */
     while(i--);
     
      /* read presence pulse */
     if (IO)
        status = 0;
     else
        status = 1;

     i=255;                /*wait for idle */
     while(i--);
     
     return status;
}

Modifikováno z původního SW, jehož autory jsou Ian Downard a Chess Combites

00.19.zip