STM8 Microcontrollers – the Final Chapters

Hardware

One Wire – DHT11

Just like DS18B20, DHT11 one wire digital relative humidity and temperature sensor also uses one wire communication method to communicate with its host micro. It uses time-slotting mechanism to transmit-receive relative humidity and temperature data. However, the method of communication is different.

 

Hardware Connection

OW-DHT11

 

Code Example

DHT11.h

#include "STM8S.h"


#define DHT11_port         GPIOD       
#define DHT11_pin          GPIO_PIN_2

#define DHT11_INPUT()     do{GPIO_DeInit(DHT11_port); GPIO_Init(DHT11_port, DHT11_pin, GPIO_MODE_IN_FL_NO_IT);}while(0)
#define DHT11_OUTPUT()    do{GPIO_DeInit(DHT11_port); GPIO_Init(DHT11_port, DHT11_pin, GPIO_MODE_OUT_PP_HIGH_FAST);}while(0)

#define DHT11_IN()         GPIO_ReadInputPin(DHT11_port, DHT11_pin)

#define DHT11_OUT_LOW()   GPIO_WriteLow(DHT11_port, DHT11_pin)
#define DHT11_OUT_HIGH()  GPIO_WriteHigh(DHT11_port, DHT11_pin)


extern unsigned char values[5];


void DHT11_init(void);
unsigned char get_byte(void);
unsigned char get_data(void);

 

DHT11.c

#include "DHT11.h"


void DHT11_init(void)
{
   DHT11_INPUT();
   delay_ms(1000);
}


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

   DHT11_INPUT();

   while(s > 0)
   {
      value <<= 1;

      while(DHT11_IN() == FALSE);
      delay_us(30);

      if(DHT11_IN())
      {
          value |= 1;
      }

      while(DHT11_IN());
      s--;
   }

   return value;
}


unsigned char get_data(void)
{
       bool chk = FALSE;
       unsigned char s = 0x00;
       unsigned char check_sum = 0x00;

       DHT11_OUTPUT();

       DHT11_OUT_HIGH();
       DHT11_OUT_LOW();

       delay_ms(18);

       DHT11_OUT_HIGH();

       delay_us(26);
       DHT11_INPUT();

       chk = DHT11_IN();

       if(chk == TRUE)
       {
              return 1;
       }

       delay_us(80);

       chk = DHT11_IN();

       if(chk == FALSE)
       {
              return 2;
       }

       delay_us(80);

       for(s = 0; s <= 4; s += 1)
       {
              values[s] = get_byte();
       }

       DHT11_OUTPUT();
       DHT11_OUT_HIGH();

       for(s = 0; s < 4; s++)
       {
       check_sum += values[s];
       }

       if(check_sum != values[4])
       {
              return 3;
       }
       else
       {
              return 0;
       }
}

 

main.c

#include "STM8S.h"
#include "lcd.h"
#include "DHT11.h"


unsigned char bl_state;
unsigned char data_value;
unsigned char values[5];

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);
unsigned int make_word(unsigned char HB, unsigned char LB);
void lcd_print(unsigned char x_pos, unsigned char y_pos, unsigned char value);


void main(void)
{     
       unsigned char state = 0x00;

       unsigned int RH = 0x0000;
       unsigned int t = 0x0000;

       clock_setup();
       GPIO_setup();

       DHT11_init();

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

       while(TRUE)
       {
                GPIO_WriteReverse(GPIOD, GPIO_PIN_0);

                state = get_data();

                switch(state)
                {
                           case 1:
                           {
                           }
                           case 2:
                           {
                              LCD_clear_home();
                              LCD_putstr("No Sensor Found!");
                              break;
                           }
                           case 3:
                           {
                              LCD_clear_home();
                              LCD_putstr("Checksum Error!");
                              break;
                           }
                           default:
                           {
                              LCD_goto(0, 0);
                              LCD_putstr("R.H/ %:       ");

                              RH = make_word(values[0], values[1]);
                              lcd_print(14, 0, values[0]);

                              LCD_goto(0, 1);
                              LCD_putstr("Tmp/");
                              LCD_goto(4, 1);
                              LCD_send(0, DAT);
                              LCD_goto(5, 1);
                              LCD_putstr("C:");

                              t = make_word(values[2], values[3]);
                              if((values[2] & 0x80) == 1)
                              {
                                     LCD_goto(13, 1);
                                     LCD_putstr("-");
                              }
                              else
                              {
                                     LCD_goto(13, 1);
                                     LCD_putstr(" ");
                              }

                              lcd_print(14, 1, values[2]);
                              break;
                           }
                }
                delay_ms(1000);
       };
}


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(DHT11_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);
}


unsigned int make_word(unsigned char HB, unsigned char LB)
{
  unsigned int value = 0x0000;

  value = HB;
  value <<= 8;
  value |= LB;

  return value;
}


void lcd_print(unsigned char x_pos, unsigned char y_pos, unsigned char value)
{
       char chr = 0x00;

       chr = ((value / 10) + 0x30);
       LCD_goto(x_pos, y_pos);
       LCD_putchar(chr);

       chr = ((value % 10) + 0x30);
       LCD_goto((x_pos + 1), y_pos);
       LCD_putchar(chr);
}

 

Explanation

Unlike I2C, SMBUS, UART and other communication methods, one wire communication has no fixed communication standard. A perfect example is the difference between the way of communicating with DHT11 and DS18B20.

DHT11 Timing Diagram

Shown above is the timing diagram of DHT11. If you compare the timings for ones and zeroes in both devices you’ll notice that these timings are way different. Same goes for the data, command and control. Here again the datasheet of DHT11 is used to create the library for DHT11 and again the process is just manipulation of a single GPIO pin.

 

 

Demo

DHT11

Continue Reading ...

Related Posts

5 comments

Leave a Reply

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