PIC18F4550 LCD2004 DS1307 RTC, cảm biến DHT22 trên CCS C

1
1035

Chuẩn bị linh kiện:

  • PIC18F4550
  • DS1307 RTC
  • DHT22 (AM2302 – RHT03)
  • Màn hình 20×4 LCD
  • Pin 3V
  • Thạch anh 32.768KHz
  • Điện trở 2 x 10K
  • Điện trở 4.7K
  • Chiết áp/ biến trở 10K
  • 2 nút nhấn
  • Nguồn +5V
  • Board cắm
  • Dây cắm board

Code trên CCS

// PIC18F4550 with DS1307 and DHT22 (AM2302-RHT03) CCS C code
 
//LCD module connections
#define LCD_RS_PIN PIN_D0
#define LCD_RW_PIN PIN_D1
#define LCD_ENABLE_PIN PIN_D2
#define LCD_DATA4 PIN_D3
#define LCD_DATA5 PIN_D4
#define LCD_DATA6 PIN_D5
#define LCD_DATA7 PIN_D6
//End LCD module connections
 
#include <18F4550.h>
#fuses NOMCLR INTRC_IO
#use delay(clock = 8000000)
#include <lcd.c>
#use fast_io(B)
#use I2C(master, I2C1, FAST=100000)
#define DHT22_PIN PIN_B4                // Connection pin between DHT22 and mcu
 
short button_state, Time_out;
char time[] = "TIME:      :  :  ";
char calendar[] = "  /  /20  ";
unsigned int8 second, second10, minute, minute10,
               hour, hour10, date, date10, month, month10,
               year, year10, day, i, j ;
char message1[] = "Temperature: 00.0 C ";
char message2[] = "Humidity   : 00.0 % ";
unsigned int8 T_byte1, T_byte2, RH_byte1, RH_byte2, CheckSum, time_read ;
unsigned int16 Temp, RH;
void ds1307_display(){
  second10  =  (second & 0x70) >> 4;
  second = second & 0x0F;
  minute10  =  (minute & 0x70) >> 4;
  minute = minute & 0x0F;
  hour10  =  (hour & 0x30) >> 4;
  hour = hour & 0x0F;
  date10  =  (date & 0x30) >> 4;
  date = date & 0x0F;
  month10  =  (month & 0x10) >> 4;
  month = month & 0x0F;
  year10  =  (year & 0xF0) >> 4;
  year = year & 0x0F;
  time[16]  = second  + 48;
  time[15]  = second10  + 48;
  time[13]  = minute  + 48;
  time[12]  = minute10  + 48;
  time[10]  = hour  + 48;
  time[9]  = hour10  + 48;
  calendar[9]  = year  + 48;
  calendar[8]  = year10  + 48;
  calendar[4]  = month + 48;
  calendar[3]  = month10 + 48;
  calendar[1]  = date + 48;
  calendar[0]  = date10 + 48;
  lcd_gotoxy(1, 1);                              // Go to column 1 row 1
  printf(lcd_putc, time);                        // Display time
  lcd_gotoxy(1, 2);                              // Go to column 1 row 2
  switch(day){
    case 1: lcd_putc("DATE:Sun"); break;
    case 2: lcd_putc("DATE:Mon"); break;
    case 3: lcd_putc("DATE:Tue"); break;
    case 4: lcd_putc("DATE:Wed"); break;
    case 5: lcd_putc("DATE:Thu"); break;
    case 6: lcd_putc("DATE:Fri"); break;
    case 7: lcd_putc("DATE:Sat"); break;}
  lcd_gotoxy(10, 2);                             // Go to column 10 row 2
  printf(lcd_putc, calendar);                    // Display calendar
}
void ds1307_write(unsigned int8 address, data_){
  i2c_start();                                   // Start I2C
  i2c_write(0xD0);                               // DS1307 address
  i2c_write(address);                            // Send register address
  i2c_write(data_);                              // Write data to the selected register
  i2c_stop();                                    // Stop I2C
}
void ds1307_read(){
   i2c_start();                                  // Start I2C
   i2c_write(0xD0);                              // DS1307 address
   i2c_write(0);                                 // Send register address
   i2c_start();                                  // Restart I2C
   i2c_write(0xD1);                              // Initialize data read
   second =i2c_read(1);                          // Read seconds from register 0
   minute =i2c_read(1);                          // Read minuts from register 1
   hour = i2c_read(1);                           // Read hour from register 2
   day = i2c_read(1);                            // Read day from register 3
   date = i2c_read(1);                           // Read date from register 4
   month = i2c_read(1);                          // Read month from register 5
   year = i2c_read(0);                           // Read year from register 6
   i2c_stop();                                   // Stop I2C
}
int8 edit(int8 parameter, int8 xx, int8 yy){
  while(TRUE){
    if(input(PIN_B2)) button_state = 0;
    while(!input(PIN_B3)){
      parameter++;
      if(i == 1 && parameter > 23)
        parameter = 0;
      if(i == 2 && parameter > 59)
        parameter = 0;
      if(i == 3 && parameter > 31)
        parameter = 1;
      if(i == 4 && parameter > 12)
        parameter = 1;
      if(i == 5 && parameter > 99)
        parameter = 0;
      lcd_gotoxy(xx, yy);
      printf(lcd_putc,"%02u", parameter);
      delay_ms(200);}
    lcd_gotoxy(xx, yy);
    lcd_putc("  ");
    j = 0;
    while((input(PIN_B2) || button_state) && input(PIN_B3) && j < 5){
      j++;
     delay_ms(50);}
    lcd_gotoxy(xx, yy);
    printf(lcd_putc,"%02u", parameter);
    j = 0;
    while((input(PIN_B2) || button_state) && input(PIN_B3) && j < 5){
      j++;
      delay_ms(50);}
    if(!input(PIN_B2) && !button_state){
      button_state = 1; return parameter;}
  } 
}
void start_signal(){
  output_drive(DHT22_PIN);              // Configure connection pin as output
  output_low(DHT22_PIN);                // Connection pin output low
  delay_ms(25);
  output_high(DHT22_PIN);               // Connection pin output high
  delay_us(30);
  output_float(DHT22_PIN);              // Configure connection pin as input
}
short check_response(){
  delay_us(40);
  if(!input(DHT22_PIN)){                // Read and test if connection pin is low
    delay_us(80);
    if(input(DHT22_PIN)){               // Read and test if connection pin is high
      delay_us(50);
      return 1;
    }
  }
}
unsigned int8 Read_Data(){
  unsigned int8 i, k, _data = 0;        // k is used to count 1 bit reading duration
  if(Time_out)
    break;
  for(i = 0; i < 8; i++){
    k = 0;
    while(!input(DHT22_PIN)){                    // Wait until pin goes high
      k++;
      if (k > 100) {Time_out = 1; break;}
      delay_us(1);}
    delay_us(30);
    if(!input(DHT22_PIN))
      bit_clear(_data, (7 - i));                 // Clear bit (7 - i)
    else{
      bit_set(_data, (7 - i));                   // Set bit (7 - i)
      while(input(DHT22_PIN)){                   // Wait until pin goes low
      k++;
      if (k > 100) {Time_out = 1; break;}
      delay_us(1);}
    }
  }
  return _data;
}
void main(){
  setup_oscillator(OSC_8MHZ);                    // Set internal oscillator to 8MHz
  setup_adc_ports(NO_ANALOGS);                   // Configure all AN pins as digital
  port_b_pullups(TRUE);                          // Enable PORTB pull-ups
  output_b(0);
  set_tris_b(0x0F);                        // Configure RB0,RB1,RB2 & RB3 as inputs
  lcd_init();                                    // Initialize LCD module
  lcd_putc('\f');                                // LCD clear
  while(TRUE){
    Time_out = 0;
    if(input(PIN_B2)) button_state = 0;
    if(!input(PIN_B2) && (!button_state)){
      button_state = 1;
      // Convert BCD to decimal
      minute = minute + minute10 * 10;
      hour = hour + hour10 * 10;
      date = date + date10 * 10;
      month = month + month10 * 10;
      year = year + year10 * 10;
      // End conversion
      i=1;
      hour = edit(hour, 10, 1);
      i=2;
      minute = edit(minute, 13, 1);
      while(TRUE){
        if(input(PIN_B2)) 
          button_state = 0;
        while(!input(PIN_B3)){
          day++;
          if(day > 7)
            day = 1;
          lcd_gotoxy(6, 2);                      // Go to column 6 row 2
          switch(day){
            case 1: lcd_putc("Sun"); break;
            case 2: lcd_putc("Mon"); break;
            case 3: lcd_putc("Tue"); break;
            case 4: lcd_putc("Wed"); break;
            case 5: lcd_putc("Thu"); break;
            case 6: lcd_putc("Fri"); break;
            case 7: lcd_putc("Sat"); break;}
          delay_ms(200);
        }
        lcd_gotoxy(6, 2);
        lcd_putc("   ");
        j = 0;
        while((input(PIN_B2)||button_state) && input(PIN_B3) && j < 5){
          j++;
          delay_ms(50);}
        lcd_gotoxy(6, 2);
        switch(day){
          case 1: lcd_putc("Sun"); break;
          case 2: lcd_putc("Mon"); break;
          case 3: lcd_putc("Tue"); break;
          case 4: lcd_putc("Wed"); break;
          case 5: lcd_putc("Thu"); break;
          case 6: lcd_putc("Fri"); break;
          case 7: lcd_putc("Sat"); break;}
        if(!input(PIN_B2) && (!button_state)){
          button_state = 1;
          break;}
        j = 0;
        while((input(PIN_B2)||button_state) && input(PIN_B3) && j < 5){
          j++;
          delay_ms(50);}
      }
      i=3;
      date = edit(date, 10, 2); 
      i=4;
      month = edit(month, 13, 2);
      i=5;
      year = edit(year, 18, 2);
      // Convert decimal to BCD
      minute = ((minute/10) << 4) + (minute % 10);
      hour = ((hour/10) << 4) + (hour % 10);
      date = ((date/10) << 4) + (date % 10);
      month = ((month/10) << 4) + (month % 10);
      year = ((year/10) << 4) + (year % 10);
      // End conversion
      ds1307_write(1, minute);
      ds1307_write(2, hour);
      ds1307_write(3, day);
      ds1307_write(4, date);
      ds1307_write(5, month);
      ds1307_write(6, year);
      ds1307_write(0, 0);
    }
    
    ds1307_read();                               // Read data from DS1307 RTCC
    ds1307_display();                            // Diaplay time and calendar
    if(((second10 * 10+second)>time_read)||((second10 * 10+second)==0 && time_read)){
      time_read = second10 * 10 + second;
      Start_signal();
      if(check_response()){                      // If there is response from sensor
        RH_byte1 = Read_Data();                  // read RH byte1
        RH_byte2 = Read_Data();                  // read RH byte2
        T_byte1 = Read_Data();                   // read T byte1
        T_byte2 = Read_Data();                   // read T byte2
        Checksum = Read_Data();                  // read checksum
        if(Time_out){                            // If reading takes long time
          lcd_gotoxy(21, 1);                     // Go to column 1 row 3
          lcd_putc("     Time Out!      ");
          lcd_gotoxy(21, 2);                     // Go to column 1 row 4
          lcd_putc("                    ");      // Clear 4th row
        }
        else{
          if(CheckSum == ((RH_Byte1 + RH_Byte2 + T_Byte1 + T_Byte2) & 0xFF)){
            RH = RH_byte1;
            RH = (RH << 8) | RH_byte2;
            Temp = T_byte1;
            Temp = (Temp << 8) | T_byte2;
            if(Temp > 0X8000){
              message1[12] = '-';
              Temp = Temp & 0X7FFF; }
            else
              message1[12] = ' ';
            message1[13]  = (Temp / 100) % 10  + 48;
            message1[14]  = (Temp / 10) % 10  + 48;
            message1[16] = Temp % 10  + 48;
            message2[13]  = (RH / 100) % 10 + 48;
            message2[14]  = (RH / 10) % 10 + 48;
            message2[16] = RH % 10 + 48;
            message1[17] = 223;                    // Degree symbol 
            lcd_gotoxy(21, 1);                     // Go to column 1 row 1
            printf(lcd_putc, message1);            // Display message1
            lcd_gotoxy(21, 2);                     // Go to column 1 row 2
            printf(lcd_putc, message2);            // Display message2
          }
          else{
            lcd_gotoxy(21, 1);                     // Go to column 1 row 3
            lcd_putc("  Checksum Error!   ");
            lcd_gotoxy(21, 1);                     // Go to column 1 row 4
            lcd_putc("                    ");      // Clear 4th row
          }
        }
      }
      else {
        lcd_gotoxy(21, 1);                         // Go to column 3 row 3
        lcd_putc("    No response     ");
        lcd_gotoxy(21, 2);                         // Go to column 1 row 4
        lcd_putc("  from the sensor   ");
      }
    }  
    delay_ms(50);
  }
}

Theo: https://simple-circuit.com/

1 COMMENT

LEAVE A REPLY

Please enter your comment!
Please enter your name here