#include <p18f4550.h>
#include <delays.h>
#include <sw_uart.h>
#include <i2c.h>
// Pragma, internal register configuration
#pragma config FOSC = INTOSCIO_EC //Internal oscillator, port function on RA6, EC used by USB
#pragma config WDT = OFF // watch dog disabled
#pragma config IESO = OFF //Oscillator Switchover mode disabled
//#pragma config PWRT = OFF //PWRT disabled
#pragma config BORV = 2 // output voltage test 2V
#pragma config PBADEN=OFF //PORTB<4:0> pins are configured as digital I/O on Reset
#pragma config STVREN=OFF //Stack full/underflow will not cause Reset
#pragma config LVP=OFF //Single-Supply ICSP disabled
#pragma config XINST=OFF //Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
// definitions
#define PCF8583_WRITE_ADDRESS 0xA0
#define PCF8583_READ_ADDRESS 0xA1
// Register addresses
#define PCF8583_CTRL_STATUS_REG 0x00
#define PCF8583_100S_REG 0x01
#define PCF8583_SECONDS_REG 0x02
#define PCF8583_MINUTES_REG 0x03
#define PCF8583_HOURS_REG 0x04
#define PCF8583_DATE_REG 0x05
#define PCF8583_MONTHS_REG 0x06
#define PCF8583_TIMER_REG 0x07
#define PCF8583_ALARM_CONTROL_REG 0x08
#define PCF8583_ALARM_100S_REG 0x09
#define PCF8583_ALARM_SECS_REG 0x0A
#define PCF8583_ALARM_MINS_REG 0x0B
#define PCF8583_ALARM_HOURS_REG 0x0C
#define PCF8583_ALARM_DATE_REG 0x0D
#define PCF8583_ALARM_MONTHS_REG 0x0E
#define PCF8583_ALARM_TIMER_REG 0x0F
// Use the first NVRAM address for the year byte.
#define PCF8583_YEAR_REG 0x10
// Commands for the Control/Status register.
#define PCF8583_START_COUNTING 0x00
#define PCF8583_STOP_COUNTING 0x80
// Variables
unsigned char seconds=0x00,minutes=0x00,hours=0x00,day=0x00,month=0x00,year=0x00;
/** L O C A L F U N C T I O N S *******************************************/
void init_UART(void)
{
TXSTAbits.TX9=0;
TXSTAbits.TXEN=1;
TXSTAbits.SYNC=0;
TXSTAbits.BRGH=1;
TXSTAbits.TX9D=0;
RCSTAbits.SPEN=1;
BAUDCONbits.BRG16=0;
SPBRG=25; // 9600KBaud
}
// Read time and date information from RTC( PCF8583 )
void Read_Time(void)
{
// read seconds
StartI2C();
while(SSPCON2bits.SEN);
WriteI2C(PCF8583_WRITE_ADDRESS); // Address and Write Flag
WriteI2C(PCF8583_SECONDS_REG); // Start from seconds memory location
RestartI2C(); // At this moment master transmitter becomes master receiver
while(SSPCON2bits.RSEN); // and PCF8583 slave receiver becomes slave transmitter
WriteI2C(PCF8583_READ_ADDRESS); // Address and Read Flag
seconds=ReadI2C(); // read seconds reg
NotAckI2C();
StopI2C();
while(SSPCON2bits.PEN);
// read minutes
StartI2C();
while(SSPCON2bits.SEN);
WriteI2C(PCF8583_WRITE_ADDRESS); // Address and Write Flag
WriteI2C(PCF8583_MINUTES_REG); // Start from minutes memory location
RestartI2C(); // At this moment master transmitter becomes master receiver
while(SSPCON2bits.RSEN); // and PCF8583 slave receiver becomes slave transmitter
WriteI2C(PCF8583_READ_ADDRESS); // Address and Read Flag
minutes=ReadI2C(); // read minutes reg
NotAckI2C();
StopI2C();
while(SSPCON2bits.PEN);
// read hours
StartI2C();
while(SSPCON2bits.SEN);
WriteI2C(PCF8583_WRITE_ADDRESS); // Address and Write Flag
WriteI2C(PCF8583_HOURS_REG); // Start from hours memory location
RestartI2C(); // At this moment master transmitter becomes master receiver
while(SSPCON2bits.RSEN); // and PCF8583 slave receiver becomes slave transmitter
WriteI2C(PCF8583_READ_ADDRESS); // Address and Read Flag
hours=ReadI2C(); // read hours reg
NotAckI2C();
StopI2C();
while(SSPCON2bits.PEN);
// read day
StartI2C();
while(SSPCON2bits.SEN);
WriteI2C(PCF8583_WRITE_ADDRESS); // Address and Write Flag
WriteI2C(PCF8583_DATE_REG); // Start from year/date memory location
RestartI2C(); // At this moment master transmitter becomes master receiver
while(SSPCON2bits.RSEN); // and PCF8583 slave receiver becomes slave transmitter
WriteI2C(PCF8583_READ_ADDRESS); // Address and Read Flag
day=ReadI2C(); // read year/date reg
NotAckI2C();
StopI2C();
while(SSPCON2bits.PEN);
// read month
StartI2C();
while(SSPCON2bits.SEN);
WriteI2C(PCF8583_WRITE_ADDRESS); // Address and Write Flag
WriteI2C(PCF8583_MONTHS_REG); // Start from weekday/month memory location
RestartI2C(); // At this moment master transmitter becomes master receiver
while(SSPCON2bits.RSEN); // and PCF8583 slave receiver becomes slave transmitter
WriteI2C(PCF8583_READ_ADDRESS); // Address and Read Flag
month=ReadI2C(); // read weekday/month reg
NotAckI2C();
StopI2C();
while(SSPCON2bits.PEN);
}
// Formats date and time
void Transform_Time()
{
seconds = ((seconds & 0xF0) >> 4)*10 + (seconds & 0x0F); // Transform seconds
minutes = ((minutes & 0xF0) >> 4)*10 + (minutes & 0x0F); // Transform months
hours = (((hours & 0xF0) >> 4)*10 + (hours & 0x0F)) & 0x3F; // Transform hours
// year = (day & 0xC0) >> 6; // Transform year
day = (((day & 0x30) >> 4)*10 + (day & 0x0F)) & 0x3F; // Transform day
month = (((month & 0x10) >> 4)*10 + (month & 0x0F)) & 0x3F; // Transform month
}
// This function converts an 8 bit binary value
// to an 8 bit BCD value.
// The input range must be from 0 to 99
unsigned char bin2bcd(unsigned x)
{
unsigned char y;
y=(x / 10) << 4;
y= y | (x % 10);
return(y);
}
// This function converts an 8 bit BCD value to
// an 8 bit binary value.
// The input range must be from 00 to 99.
unsigned bcd2bin(unsigned char x)
{
return (x & 0x0F) + (x >> 4)*10;
}
void print_date_time(char t)
{
int k,n,j,m,c;
unsigned char data;
unsigned char string[5];
data=t;
n=data;
j=0;
while(n!=0)
{
c=n%10;
n=n/10;
string[j]=c+48;
j++;
}
m=j-1;
while(m>=0)
{
WriteUSART(string[m]);
while(!TXSTAbits.TRMT);
m--;
}
}
///////////////////functia main///////////////////////////////////////////
void main(void)
{
//Outputs:
TRISCbits.TRISC6=0; // UART__TX
//Inputs:
TRISBbits.TRISB0=1; // I2C_SDA
TRISBbits.TRISB1=1; // I2C_SCL
TRISCbits.TRISC7=1; // UART__RX
// Oscillator frequency
OSCCON=0b01100110; // 4MHz
// the configuration of the functions of port pins
ADCON1=0b00001111; // digital port configured
// Initializations
init_UART();
TXREG=12; // new page
// I2C settings
SSPSTAT=0x80; // SLEW RATE CONTROL DISABLED FOR std mode (100khz)
SSPCON1=0x28; // i2c master mode, serial synch enable
SSPCON2=0x00;
SSPADD=0x09; // for 100Khz
// Set time and date
StartI2C();
while(SSPCON2bits.SEN);
WriteI2C(PCF8583_WRITE_ADDRESS); // Address and Write Flag
WriteI2C(PCF8583_CTRL_STATUS_REG); // start from address 0 (control/status reg)
WriteI2C(PCF8583_STOP_COUNTING); // write 0x80 to control/status reg (stop counting)
WriteI2C(0x00); // write 0 to 100's memory location
WriteI2C(0x00); // write 0 to seconds memory location
WriteI2C(0x02); // write 0x18 to minutes memory location
WriteI2C(0x10); // write 0x09 to hours memory location
WriteI2C(0x06); // write 0x18 to year/date memory location
WriteI2C(0x02); // write 0x09 to weekday/month memory location
StopI2C();
while(SSPCON2bits.PEN);
StartI2C();
while(SSPCON2bits.SEN);
WriteI2C(PCF8583_WRITE_ADDRESS); // Address and Write Flag
WriteI2C(PCF8583_CTRL_STATUS_REG); // Start from address 0
WriteI2C(PCF8583_START_COUNTING); // write 0x00 to control/status reg (enable counting)
StopI2C();
while(SSPCON2bits.PEN);
while(1)
{
// Read the date and time from the PCF8583 and dispaly it once per second
Delay10KTCYx(100);
Read_Time();
Transform_Time();
print_date_time(hours);
TXREG=58; // :
print_date_time(minutes);
TXREG=58; // :
print_date_time(seconds);
TXREG=32; // space
TXREG=32; //space
print_date_time(day);
TXREG=47; // /
print_date_time(month);
TXREG=10; // new line
TXREG=13; //carriage return
}
} // main