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

7 comments

  • Hello,
    How can i change the font size so i can support for example [92][12] ? Saw some libraries on the net but i am not sure if they are compatible with this code… or am i doing something wrong ? I tried manipulating the current one with some cycles within ” OLED_print_char ” also chaning 0x06 to 0x0C with a font library also tried creating fonts but i did not get the expected result. Can you give me some advice please ?
    Thank you for your time!

    • The coordinates of the OLED displays are mapped as multiples of 8-bits or 8 dots in both x and y directions. So just by changing x-coordinate values won’t result in larger fonts…. You must also take care of the y-coordinate too…. Take the example of the bitmap function:

      void OLED_draw_bitmap(unsigned char xb, unsigned char yb, unsigned char xe, unsigned char ye, unsigned char *bmp_img)
      {
      unsigned int s = 0x0000;
      unsigned char x_pos = 0x00;
      unsigned char y_pos = 0x00;

      for(y_pos = yb; y_pos <= ye; y_pos++)
      {
      OLED_gotoxy(xb, y_pos);
      for(x_pos = xb; x_pos < xe; x_pos++)
      {
      OLED_write(bmp_img[s], DAT);
      s++;
      }
      }
      }

      It takes care of the y-coordinate part once the x-coordinate points are filled up….

  • Hi great tutorial!
    Can you post code for interfacing external eeprom using i2c for stm8s003f3??

  • Pingback: .NET i jiné ...

  • Pingback: STM8 Microcontrollers – gStore

  • Outstanding bro. Carry on. Wish your good luck.

Leave a Reply

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