STM8 Microcontrollers – the Final Chapters

Hardware

One Wire (OW) – DS18B20

One Wire (OW) communication is not as much as popular as I2C, SPI or serial communication. However, there are a number of devices that use one-wire communication method. DS18B20 digital temperature sensor from Dallas is one such example. For OW communication, we do not need any special hardware. Only GPIO bit-banging is all that is needed. Additionally, we can use a timer if we do not want to use software-based delays.

 

Hardware Connection

OW-DS18B20

 

 

 

Code Example

one_wire.h

#include "STM8S.h"


#define DS18B20_port      GPIOD       
#define DS18B20_pin       GPIO_PIN_2

#define DS18B20_INPUT()   do{GPIO_DeInit(DS18B20_port); GPIO_Init(DS18B20_port, DS18B20_pin, GPIO_MODE_IN_FL_NO_IT);}while(0)
 
#define DS18B20_OUTPUT()  do{GPIO_DeInit(DS18B20_port); GPIO_Init(DS18B20_port, DS18B20_pin, GPIO_MODE_OUT_PP_HIGH_FAST);}while(0)

#define DS18B20_IN()      GPIO_ReadInputPin(DS18B20_port, DS18B20_pin)

#define DS18B20_OUT_LOW() GPIO_WriteLow(DS18B20_port, DS18B20_pin)
#define DS18B20_OUT_HIGH() GPIO_WriteHigh(DS18B20_port, DS18B20_pin)     


bool onewire_reset(void);
void onewire_write_bit(bool bit_value);
bool onewire_read_bit(void);
void onewire_write(unsigned char value);   
unsigned char onewire_read(void);

 

one_wire.c

#include "one_wire.h"


bool onewire_reset(void
{                                        
        bool res = FALSE;

        DS18B20_OUTPUT();                
        DS18B20_OUT_LOW();
        delay_us(480);       
        DS18B20_OUT_HIGH();
        delay_us(60);       

        DS18B20_INPUT();
        res = DS18B20_IN();
        delay_us(480);      

        return res;
}


void onewire_write_bit(bool bit_value)
{
       DS18B20_OUTPUT();
       DS18B20_OUT_LOW();

       if(bit_value)
       {    
              delay_us(104);
              DS18B20_OUT_HIGH();  
       }             
}    


bool onewire_read_bit(void)       
{    
       DS18B20_OUTPUT();
       DS18B20_OUT_LOW(); 
       DS18B20_OUT_HIGH(); 
       delay_us(15);     
       DS18B20_INPUT();

       return(DS18B20_IN());   
}


void onewire_write(unsigned char value)
{                   
        unsigned char s = 0;

        DS18B20_OUTPUT();

        while(s < 8)   
        {                             
                if((value & (1 << s)))
                {
                       DS18B20_OUT_LOW();
                       delay_cycles(1);  
                       DS18B20_OUT_HIGH(); 
                       delay_us(60);  
                }      

                else
                {
                      DS18B20_OUT_LOW();          
                       delay_us(60);          
                       DS18B20_OUT_HIGH();  
                       delay_cycles(1); 
                }
                s++;
        }
}                                     


unsigned char onewire_read(void)
{
        unsigned char s = 0x00;
        unsigned char value = 0x00;

        while(s < 8)
        {
                DS18B20_OUTPUT();

                DS18B20_OUT_LOW();
                delay_cycles(1);                 
                DS18B20_OUT_HIGH(); 

                DS18B20_INPUT();
                if(DS18B20_IN()) 
                {                                     
                    value |=  (1 << s);                        
                }       

                delay_us(60);     
                s++;
        }    

        return value;
}   

 

DS18B20.h

#include "STM8S.h"
#include "one_wire.h" 


#define convert_T          0x44
#define read_scratchpad   0xBE           
#define write_scratchpad  0x4E
#define copy_scratchpad   0x48  
#define recall_E2          0xB8
#define read_power_supply 0xB4   
#define skip_ROM           0xCC

#define resolution         12


void DS18B20_init(void);
float DS18B20_get_temperature(void);

DS18B20.c

#include "DS18B20.h"


void DS18B20_init(void)                            
{                                      
       onewire_reset();
       delay_ms(100);
}             


float DS18B20_get_temperature(void)
{                                              
       unsigned char msb = 0x00;
       unsigned char lsb = 0x00;
       register float temp = 0.0; 

       onewire_reset();    
       onewire_write(skip_ROM);       
       onewire_write(convert_T);

       switch(resolution)  
       {                                                 
              case 12:
              {                                              
                     delay_ms(750);
                     break;
              }               
              case 11:                                    
              {             
                     delay_ms(375);
                     break;
              }          
              case 10:                            
              {                                
                     delay_ms(188);  
                     break;
              }                                       
              case 9:                                  
              {                                               
                     delay_ms(94);                
                     break;                           
              }                       
       }                 

       onewire_reset();

       onewire_write(skip_ROM);                
       onewire_write(read_scratchpad);

       lsb = onewire_read();
       msb = onewire_read();

       temp = msb;                          
       temp *= 256.0;
       temp += lsb;


       switch(resolution)  
       {                                 
              case 12:           
              {                                               
                     temp *= 0.0625;                
                     break;                           
              }            
              case 11:
              {             
                     temp *= 0.125;     
                     break;
              }               
              case 10:
              {           
                     temp *= 0.25;      
                     break;
              } 
              case 9:                                
              {                                
                     temp *= 0.5;       
                     break;     
              }                         
       } 

       delay_ms(40);      

       return (temp);      
}

 

main.c

#include "STM8S.h"
#include "DS18B20.h"
#include "lcd.h"


unsigned char bl_state;
unsigned char data_value;

const unsigned char symbol[8] =
{
   0x00, 0x06, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00
};


void clock_setup(void);
void GPIO_setup(void);
void lcd_symbol(void);
void print_C(unsigned char x_pos, unsigned char y_pos, signed int value);
void print_I(unsigned char x_pos, unsigned char y_pos, signed long value);
void print_D(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char points);
void print_F(unsigned char x_pos, unsigned char y_pos, float value, unsigned char points);


void main(void)
{            
       float temp = 0.0;

       clock_setup();
       GPIO_setup();

       DS18B20_init();

       LCD_init(); 
       LCD_clear_home();
       lcd_symbol();

       LCD_goto(0, 0);
       LCD_putstr("STM8 DS18B20 Ex.");

       LCD_goto(0, 1);
    LCD_putstr("T/ C");
    LCD_goto(2, 1);
    LCD_send(0, DAT);

       while(TRUE)
       {
              temp = DS18B20_get_temperature();
              print_F(9, 1, temp, 3);
              delay_ms(600);
       };
}


void clock_setup(void)
{
       CLK_DeInit();

       CLK_HSECmd(DISABLE);
       CLK_LSICmd(DISABLE);
       CLK_HSICmd(ENABLE);
       while(CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == FALSE);

       CLK_ClockSwitchCmd(ENABLE);
       CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
                                                                            CLK_SYSCLKConfig(CLK_PRESCALER_CPUDIV1);

       CLK_ClockSwitchConfig(CLK_SWITCHMODE_AUTO,
                             CLK_SOURCE_HSI,
                            DISABLE,
                            CLK_CURRENTCLOCKSTATE_ENABLE);

       CLK_PeripheralClockConfig(CLK_PERIPHERAL_I2C, ENABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_SPI, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_ADC, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_AWU, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_UART1, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER1, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER2, DISABLE);
       CLK_PeripheralClockConfig(CLK_PERIPHERAL_TIMER4, DISABLE);
}


void GPIO_setup(void)
{
    GPIO_DeInit(DS18B20_port);
}


void lcd_symbol(void
{
   unsigned char s = 0; 

   LCD_send(0x40, CMD);

   for(s = 0; s < 8; s++)
   {
        LCD_send(symbol[s], DAT);
   }

   LCD_send(0x80, CMD);
}


void print_C(unsigned char x_pos, unsigned char y_pos, signed int value)
{
     unsigned char ch[5] = {0x20, 0x20, 0x20, 0x20, '\0'};

     if(value < 0x00)
     {
        ch[0] = 0x2D;
        value = -value;
     }
     else
     {
        ch[0] = 0x20;
     }

     if((value > 99) && (value <= 999))
     {
         ch[1] = ((value / 100) + 0x30);
         ch[2] = (((value % 100) / 10) + 0x30);
         ch[3] = ((value % 10) + 0x30);
     }
     else if((value > 9) && (value <= 99))
     {
         ch[1] = (((value % 100) / 10) + 0x30);
         ch[2] = ((value % 10) + 0x30);
         ch[3] = 0x20;
     }
     else if((value >= 0) && (value <= 9))
     {
         ch[1] = ((value % 10) + 0x30);
         ch[2] = 0x20;
         ch[3] = 0x20;
     }

        LCD_goto(x_pos, y_pos);
     LCD_putstr(ch);
}


void print_I(unsigned char x_pos, unsigned char y_pos, signed long value)
{
    unsigned char ch[7] = {0x20, 0x20, 0x20, 0x20, 0x20, 0x20, '\0'};

    if(value < 0)
    {
        ch[0] = 0x2D;
        value = -value;
    }
    else
    {
        ch[0] = 0x20;
    }

    if(value > 9999)
    {
        ch[1] = ((value / 10000) + 0x30);
        ch[2] = (((value % 10000)/ 1000) + 0x30);
        ch[3] = (((value % 1000) / 100) + 0x30);
        ch[4] = (((value % 100) / 10) + 0x30);
        ch[5] = ((value % 10) + 0x30);
    }

    else if((value > 999) && (value <= 9999))
    {
        ch[1] = (((value % 10000)/ 1000) + 0x30);
        ch[2] = (((value % 1000) / 100) + 0x30);
        ch[3] = (((value % 100) / 10) + 0x30);
        ch[4] = ((value % 10) + 0x30);
        ch[5] = 0x20;
    }
    else if((value > 99) && (value <= 999))
    {
        ch[1] = (((value % 1000) / 100) + 0x30);
        ch[2] = (((value % 100) / 10) + 0x30);
        ch[3] = ((value % 10) + 0x30);
        ch[4] = 0x20;
        ch[5] = 0x20;
    }
    else if((value > 9) && (value <= 99))
    {
        ch[1] = (((value % 100) / 10) + 0x30);
        ch[2] = ((value % 10) + 0x30);
        ch[3] = 0x20;
        ch[4] = 0x20;
        ch[5] = 0x20;
    }
    else
    {
        ch[1] = ((value % 10) + 0x30);
        ch[2] = 0x20;
        ch[3] = 0x20;
        ch[4] = 0x20;
        ch[5] = 0x20;
    }

    LCD_goto(x_pos, y_pos);
    LCD_putstr(ch);
}


void print_D(unsigned char x_pos, unsigned char y_pos, signed int value, unsigned char points)
{
    char ch[5] = {0x2E, 0x20, 0x20, '\0'};

    ch[1] = ((value / 100) + 0x30);

    if(points > 1)
    {
        ch[2] = (((value / 10) % 10) + 0x30);

              if(points > 1)
              {
                     ch[3] = ((value % 10) + 0x30);
              }
    }

    LCD_goto(x_pos, y_pos);
    LCD_putstr(ch);
}


void print_F(unsigned char x_pos, unsigned char y_pos, float value, unsigned char points)
{
    signed long tmp = 0x0000;

    tmp = value;
    print_I(x_pos, y_pos, tmp);
    tmp = ((value - tmp) * 1000);

    if(tmp < 0)
    {
       tmp = -tmp;
    }

    if(value < 0)
    {
        value = -value;
              LCD_goto(x_pos, y_pos);
        LCD_putchar(0x2D);
    }
    else
    {
        LCD_goto(x_pos, y_pos);
        LCD_putchar(0x20);
    }

    if((value >= 10000) && (value < 100000))
    {
        print_D((x_pos + 6), y_pos, tmp, points);
    }
    else if((value >= 1000) && (value < 10000))
    {
        print_D((x_pos + 5), y_pos, tmp, points);
    }
    else if((value >= 100) && (value < 1000))
    {
        print_D((x_pos + 4), y_pos, tmp, points);
    }
    else if((value >= 10) && (value < 100))
    {
        print_D((x_pos + 3), y_pos, tmp, points);
    }
    else if(value < 10)
    {
        print_D((x_pos + 2), y_pos, tmp, points);
    }
}

 

Explanation

One wire communication is detailed in these application notes from Maxim:

https://www.maximintegrated.com/en/app-notes/index.mvp/id/126

https://www.maximintegrated.com/en/app-notes/index.mvp/id/162

These notes are all that are needed for implementing the one wire communication interface for DS18B20. Please go through these notes. The codes are self-explanatory and are implemented from the code examples in these app notes.

 

 

Demo

DS18B20

Continue Reading ...

Related Posts

2 comments

Leave a Reply

Your email address will not be published. Required fields are marked *