Wecker: PIC16F887, DS3231, PCF8574T, I2C, LCD2004, Eeprom

Bitte nutzt dieses Forum um eure eigenen Projekte vorzustellen oder um selbst entwickelten Code zur Verfügung zu stellen.

Wecker: PIC16F887, DS3231, PCF8574T, I2C, LCD2004, Eeprom

#1

Ungelesener Beitrag Dmitrij88 » 2. Jan 2021, 14:01

Bild

main_DS3231_PCF8574.c

Code: Alles auswählen

/*
 * File:   main_DS3231_PCF8574.c
 * Author: Dmitrij Bobow
 *
 * Created on 4. April 2020, 19:43
 *
 * Der Code von DS3231 und PCF8574 ist nicht von mir, es wurde von https://simple-circuit.com/ genommen.
 * Ich habe zusätlich Wecker funktion gemacht. Bei DS3231 und PCF8574 den Code umgeändert und durch I2C Leitung zusammen verbunden.
 * I2C Verbindung mit DS3231 und PCF8574T läuft durch eine Leitung. Zu der Schaltung wurde Piezo und Transistor genommen.
 * 
 * PIC16F887(Vielleicht kann man auch mit anderem PIC16 verwendet werden, manche PIC sind ähnlich, ausprobieren...)
 * _XTAL_FREQ 8000000
 * MPLAB X IDE v5.25, XC8
 * FOSC = INTRC_NOCLKOUT
 *
 * D1 verbinden:
 * mit 10 kOhm Resistor siehe Foto, Taste mit drei Leitungen
 * 
 * D2 verbinden:
 * Mit Transistor PNP 2N3906(oder ähnlich). Wichtig! Basis mit 10 kOhm Resistor,
 * dann zu D2. Piezo: Transistor mit Collektor. Weitere Verbindungen,
 * siehe Bild.
 *  
 * Restliche Verbindungen:
 * Siehe Bilder
 */


#include <xc.h>
#include <stdint.h>
#include "config.h"
#include "I2C_LCD.h"       // include I2C LCD driver source file
#include "I2C_DS3231.h"
 
// button definitions
#define button1      RB0   // button B1 is connected to RB0 pin
#define button2      RB1   // button B2 is connected to RB1 pin

// variables declaration
uint16_t i, second, minute, hour, m_day, month, year;
uint16_t w_minute, w_hour;

unsigned char w_aus_ein;
 
// void ADC_Initialize();
// unsigned int ADC_Read(unsigned char channel);
unsigned char eeprom_read(unsigned char address);
void eeprom_write(unsigned char address, unsigned char value);

 
// a small function for button1 (B1) debounce
__bit debounce ()
{
  uint8_t count = 0;
  for(i = 0; i < 6; i++) {
    if (button1 == 0)
      count++;
    __delay_ms(10);
  }
  if(count > 2)  return 1;
  else           return 0;
}
 
/********************** RTC chip functions *********************/
// convert BCD to decimal function
uint8_t bcd_to_decimal(uint16_t number) {
  return((number >> 4) * 10 + (number & 0x0F));
}
 
// convert decimal to BCD function
uint8_t decimal_to_bcd(uint16_t number) {
  return(((number / 10) << 4) + (number % 10));
}
 
// display time and date function
void RTC_display()
{
  static char Time[] = "ZEIT: 00:00:00";
  static char Date[] = "DATE: 00/00/2000";
  static char weck[] = "WECK: 00:00";
 
  // convert data from BCD format to decimal format
  second = bcd_to_decimal(second);
  minute = bcd_to_decimal(minute);
  hour   = bcd_to_decimal(hour);
  m_day  = bcd_to_decimal(m_day);
  month  = bcd_to_decimal(month);
  year   = bcd_to_decimal(year);
  // end conversion
 
    // update wick
  weck[6]  = w_hour   / 10 + '0';
  weck[7]  = w_hour   % 10 + '0';
  weck[9]  = w_minute / 10 + '0';
  weck[10] = w_minute % 10 + '0';
  
  // update time
  Time[6]  = hour   / 10 + '0';
  Time[7]  = hour   % 10 + '0';
  Time[9]  = minute / 10 + '0';
  Time[10] = minute % 10 + '0';
  Time[12] = second / 10 + '0';
  Time[13] = second % 10 + '0';

  // update date
  Date[6]  = m_day  / 10 + '0';
  Date[7]  = m_day  % 10 + '0';
  Date[9]  = month  / 10 + '0';
  Date[10] = month  % 10 + '0';
  Date[14] = year   / 10 + '0';
  Date[15] = year   % 10 + '0';
 
  LCD_Goto(1, 1);    // go to column 1, row 1
  LCD_Print(Time);   // print time
  
  LCD_Goto(1, 2);    // go to column 1, row 2
  LCD_Print(Date);   // print date
  
  LCD_Goto(1, 3);    // go to column 1, row 2
  LCD_Print(weck);   // print date
  
  if(w_aus_ein == 1)
  {
      LCD_Goto(18, 3);    // go to column 1, row 2
      LCD_Print((unsigned char *)"EIN");   // print date
  }
  else
  {
      LCD_Goto(18, 3);    // go to column 1, row 2
      LCD_Print((unsigned char *)"AUS");      
  }
  
  LCD_Goto(1, 4);    // go to column 1, row 4
  if(hour > 15 && hour < 22) LCD_Print((unsigned char*)"Guten Abend!        ");   // print
  if(hour==22 || hour==23 || hour==0 || hour==1 || hour==2 || hour==3) 
  {
      LCD_Print((unsigned char*)"Gute Nacht!         ");
  }
  if(hour > 3 && hour < 11)  LCD_Print((unsigned char*)"Guten Morgen!       ");
  if(hour > 10 && hour < 16) LCD_Print((unsigned char*)"Guten Tag!          ");
  
  if((hour == w_hour) && (minute == w_minute) && (w_aus_ein == 1))
  {
      PORTDbits.RD2 = 0;
      __delay_ms(300);
      PORTDbits.RD2 = 1;
      __delay_ms(300);
      
      PORTDbits.RD2 = 0;
      __delay_ms(250);
      PORTDbits.RD2 = 1;
      __delay_ms(250);
      
      PORTDbits.RD2 = 0;
      __delay_ms(200);
      PORTDbits.RD2 = 1;
      __delay_ms(200);
      
      PORTDbits.RD2 = 0;
      __delay_ms(150);
      PORTDbits.RD2 = 1;
      __delay_ms(150);
      
      PORTDbits.RD2 = 0;
      __delay_ms(100);
      PORTDbits.RD2 = 1;
      __delay_ms(100); 
  }
  else
  {
      PORTDbits.RD2 = 1;
  }
}
 
// make editing parameter blinks function
void blink()
{
  uint8_t j = 0;
  while(j < 100 && button1 && button2) {
    j++;
    __delay_ms(5);
  }
}
 
// Edit time and date function
uint8_t edit(uint8_t x, uint8_t y, uint16_t parameter)
{
  //while(debounce());  // call debounce function (wait for B1 to be released)
 
  while(1) {
 
    while(!button2)    // if button B2 is pressed
    {
      parameter++;
      if(i == 0 && parameter > 23)   // if hours > 23 ==> hours = 0
        parameter = 0;
      if(i == 1 && parameter > 59)   // if minutes > 59 ==> minutes = 0
        parameter = 0;
      if(i == 2 && parameter > 31)   // if date > 31 ==> date = 1
        parameter = 1;
      if(i == 3 && parameter > 12)   // if month > 12 ==> month = 1
        parameter = 1;
      if(i == 4 && parameter > 99)   // if year > 99 ==> year = 0
        parameter = 0;
      if(i == 5 && parameter > 23)
          parameter = 0;
      if(i == 6 && parameter > 59)
          parameter = 0;
 
      LCD_Goto(x, y);
      LCD_PutC(parameter / 10 + '0');
      LCD_PutC(parameter % 10 + '0');
      __delay_ms(200);
 
    }
 
    LCD_Goto(x, y);
    LCD_Print((unsigned char*)"  ");  // print 2 spaces
    blink();
 
    LCD_Goto(x, y);
    LCD_PutC(parameter / 10 + '0');
    LCD_PutC(parameter % 10 + '0');
    blink();
 
    if(!button1)     // if button B1 is pressed
    //if(debounce())   // call debounce function (make sure if B1 is pressed)
    {  
      __delay_ms(1000);
      i++;   // increment 'i' for the next parameter
      return parameter;     // return parameter value and exit
    }
 
  }
  return 0;
}
/********************** end RTC chip functions *****************/
 
/*************************** main function *********************/
void main(void)
{
  OSCCON = 0X70;        // set internal oscillator to 8MHz
  ANSELH = 0;           // configure all PORTB pins as digital
  // enable RB0 and RB1 internal pull ups
  nRBPU  = 0;      // clear RBPU bit (OPTION_REG.7)
  WPUB   = 0x03;   // WPUB register = 0b00000011
  
  //if(w_hour == hour) PORTBbits.RB2 = 1;
  TRISDbits.TRISD2 = 0;
  PORTDbits.RD2 = 1;
 
  TRISDbits.TRISD1 = 1; // als input definieren
  PORTDbits.RD1 = 1;
  
 
  __delay_ms(1000);
 
  I2C_Init(100000);   // initialize I2C bus with clock frequency of 100kHz
  LCD_Begin(0x4E);        // initialize LCD module
 
  while(1) {
      
       // ADC_Initialize();
       
       if(PORTDbits.RD1 == 0)
       {
            __delay_ms(1000);
           w_aus_ein = 0;
           eeprom_write(2,w_aus_ein);
       }
 
    if(!button1)     // if button B1 is pressed
    //if(debounce())   // call debounce function (make sure if B1 is pressed)
    {
        __delay_ms(1000);
      i = 0;
      hour   = edit(7,  1, hour);
      minute = edit(10, 1, minute);
      m_day  = edit(7,  2, m_day);
      month  = edit(10, 2, month);
      year   = edit(15, 2, year);
      
      //weck
      w_hour   = edit(7,  3, w_hour);
      w_minute = edit(10, 3, w_minute);
      
       w_aus_ein = 1;
      //eeprom write anfang
       eeprom_write(0, w_hour);
       eeprom_write(1, w_minute);
       eeprom_write(2, w_aus_ein);
      //eeprom write ende
       
 
      //while(debounce());  // call debounce function (wait for button B1 to be released)
 
      // convert decimal to BCD
      
      minute = decimal_to_bcd(minute);
      hour   = decimal_to_bcd(hour);
      m_day  = decimal_to_bcd(m_day);
      month  = decimal_to_bcd(month);
      year   = decimal_to_bcd(year);
      // end conversion
 
      // Write data to DS3231 RTC
      I2C_DS3231_Start();         // start I2C
      I2C_DS3231_Write(0xD0);     // RTC chip address
      I2C_DS3231_Write(0);        // send register address
      I2C_DS3231_Write(0);        // reset seconds and start oscillator
      I2C_DS3231_Write(minute);   // write minute value to RTC chip
      I2C_DS3231_Write(hour);     // write hour value to RTC chip
      I2C_DS3231_Write(1);        // write day value (not used)
      I2C_DS3231_Write(m_day);    // write date value to RTC chip
      I2C_DS3231_Write(month);    // write month value to RTC chip
      I2C_DS3231_Write(year);     // write year value to RTC chip
      I2C_DS3231_Stop();          // stop I2C
 
      __delay_ms(200);
 
    }
 
    // read current time and date from the RTC chip
    I2C_DS3231_Start();           // start I2C
    I2C_DS3231_Write(0xD0);       // RTC chip address
    I2C_DS3231_Write(0);          // send register address
    I2C_DS3231_Repeated_Start();  // restart I2C
    I2C_DS3231_Write(0xD1);       // initialize data read
    second = I2C_DS3231_Read(1);  // read seconds from register 0
    minute = I2C_DS3231_Read(1);  // read minutes from register 1
    hour   = I2C_DS3231_Read(1);  // read hour from register 2
    I2C_DS3231_Read(1);           // read day from register 3 (not used)
    m_day  = I2C_DS3231_Read(1);  // read date from register 4
    month  = I2C_DS3231_Read(1);  // read month from register 5
    year   = I2C_DS3231_Read(0);  // read year from register 6
    I2C_DS3231_Stop();            // stop I2C
 
    RTC_display();    // print time & date
 
    __delay_ms(50);   // wait 50 ms
    
  // eeprom read    
  w_hour = eeprom_read(0);
  w_minute = eeprom_read(1);
  w_aus_ein = eeprom_read(2);
  // eeprom read 
    
  }
 
}
/*
// ADC FUnctions
void ADC_Initialize()
{
  ADCON0 = 0b01000001; //ADC ON and Fosc/16 is selected
  ADCON1 = 0b11000000; // Internal reference voltage is selected
}
 
unsigned int ADC_Read(unsigned char channel)
{
  ADCON0 &= 0b11000101; //Clearing the Channel Selection Bits
  ADCON0 |= (unsigned int)channel<<3; //Setting the required Bits
  __delay_ms(2); //Acquisition time to charge hold capacitor
  GO_nDONE = 1; //Initializes A/D Conversion
  while(GO_nDONE); //Wait for A/D Conversion to complete
  return ((unsigned int)(ADRESH<<8)+ADRESL); //Returns Result
}
// End of ADC Functions
*/
/*************************** end main function ********************************/
Dateianhänge
DS3231_PCF8574_I2C_LCD_2004_wecker_eeprom.X.rar
(1.21 MiB) 12-mal heruntergeladen

Re: Wecker: PIC16F887, DS3231, PCF8574T, I2C, LCD2004, Eeprom

#2

Ungelesener Beitrag Dmitrij88 » 2. Jan 2021, 14:36

Über die Rechte:
Der Code von DS3231 und PCF8574 ist nicht von mir, und die Bilder im Ordner DS3231_PCF8574_I2C_LCD_2004_wecker_eeprom.X sind auch nicht von mir, es wurde von https://simple-circuit.com/ genommen.

Das Bild, was Sie im ersten Beitrag sehen, ist von mir.
Ich habe zusätlich Wecker funktion gemacht. Bei DS3231 und PCF8574 den Code umgeändert und durch I2C Leitung zusammen verbunden.
I2C Verbindung mit DS3231 und PCF8574T läuft durch eine Leitung. Zu der Schaltung wurde Piezo und Transistor genommen.

Antworten
  • Vergleichbare Themen
    Antworten
    Zugriffe
    Letzter Beitrag

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast