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 ********************************/