- Get link
- X
- Other Apps
- Get link
- X
- Other Apps
Digital clock " DS1307 RTC" with PIC16F877A microcontroller and I2C:
#include "config.h" // Include configuration header file specific to the project
#define _XTAL_FREQ 4000000 // Define the crystal frequency for delay calculation
#define RS PORTBbits.RB0 // Define LCD RS pin
#define RW PORTBbits.RB1 // Define LCD RW pin
#define EN PORTBbits.RB2 // Define LCD EN pin
#define delay for(i=0;i<1000;i++) // Define delay macro
#define ds_adress 0xD0 // Define DS1307 I2C address
#define second 0x00 // Define DS1307 register addresses
#define minute 0x01
#define hour 0x02
#define day 0x03
#define date 0x04
#define month 0x05
#define year 0x06
#define control_reg 0x07
void ds_write(char _second, char _minute, char _hour, char _day, char _date, char _month, char _year);
void ds_read(char slave_adress, char register_adress);
void bcd_to_ascii(unsigned char value);
char decimal_to_bcd(unsigned char value);
void lcd_data(unsigned char data);
void lcd_comand(unsigned char cmd);
void lcd_string(const unsigned char *str, unsigned char num);
void lcd_init();
unsigned char __sec, __min, __hr, __day, __date, __month, __yr, __con; // Declare variables to store time and control data
void main(void) {
TRISC = 0xFF; // Configure PORTC as input
SSPADD = 9; // Set I2C clock frequency
SSPCON = 0x28; // Configure I2C master mode
TRISD = 0X00; // Configure PORTD as output
PORTD = 0X00; // Initialize PORTD
TRISB = 0X00; // Configure PORTB as output
PORTB = 0X00; // Initialize PORTB
lcd_init(); // Initialize LCD
lcd_comand(0x80); // Set cursor position for clock display
lcd_string("clock:", 6); // Display "clock:" on LCD
lcd_comand(0xC0); // Set cursor position for date display
lcd_string("DATE:", 5); // Display "DATE:" on LCD
ds_write(3, 2, 1, 1, 5, 4, 20); // Write initial time and date to DS1307
__delay_ms(300); // Delay for stability
while (1) {
__delay_ms(20); // Delay for stability
ds_read(ds_adress, 0); // Read time and date from DS1307
}
}
char decimal_to_bcd(unsigned char value) {
unsigned char msb, lsb, hex; // Declare variables for storing BCD value
msb = value / 10; // Get the most significant digit
lsb = value % 10; // Get the least significant digit
hex = ((msb << 4) + lsb); // Convert to BCD format
return hex; // Return BCD value
}
void bcd_to_ascii(unsigned char value) {
unsigned char bcd; // Declare variable for storing BCD value
bcd = value;
bcd = bcd & 0xf0; // Extract most significant digit
bcd = bcd >> 4; // Shift to right
bcd = bcd | 0x30; // Convert to ASCII
lcd_data(bcd); // Display most significant digit
bcd = value;
bcd = bcd & 0x0f; // Extract least significant digit
bcd = bcd | 0x30; // Convert to ASCII
lcd_data(bcd); // Display least significant digit
}
void lcd_data(unsigned char data) {
PORTD = data; // Write data to PORTD
RS = 1; // Set RS pin high for data
RW = 0; // Set RW pin low for write
EN = 1; // Set EN pin high to enable
delay; // Delay for stability
EN = 0; // Set EN pin low to disable
}
void lcd_comand(unsigned char cmd) {
PORTD = cmd; // Write command to PORTD
RS = 0; // Set RS pin low for command
RW = 0; // Set RW pin low for write
EN = 1; // Set EN pin high to enable
delay; // Delay for stability
EN = 0; // Set EN pin low to disable
}
void lcd_string(const unsigned char *str, unsigned char num) {
unsigned char i; // Declare loop variable
for (i = 0; i < num; i++) { // Loop through each character in the string
lcd_data(str[i]); // Display each character on LCD
}
}
void lcd_init() {
lcd_comand(0x38); // Initialize LCD in 2 lines, 5x7 matrix
lcd_comand(0x0C); // Display on, cursor off
lcd_comand(0x06); // Entry mode: auto-increment cursor
}
void ds_write(char _second, char _minute, char _hour, char _day, char _date, char _month, char _year) {
SSPCON2bits.SEN = 1; // Start condition
while (SSPCON2bits.SEN); // Wait for start condition to complete
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
SSPBUF = ds_adress; // Send DS1307 address with write bit
while (!PIR1bits.SSPIF); // Wait for transmission to complete
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
if (SSPCON2bits.ACKSTAT) { // Check for ACK
SSPCON2bits.PEN = 1; // End condition
while (SSPCON2bits.PEN); // Wait for end condition
return; // Return if ACK not received
}
SSPBUF = second; // Send address of second register
while (!PIR1bits.SSPIF); // Wait for transmission to complete
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
if (SSPCON2bits.ACKSTAT) { // Check for ACK
SSPCON2bits.PEN = 1; // End condition
while (SSPCON2bits.PEN); // Wait for end condition
return; // Return if ACK not received
}
// Write time and date values to DS1307 registers similar to the above approach
SSPBUF = 0x00; // Dummy write to end transmission
while (!PIR1bits.SSPIF); // Wait for transmission to complete
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
SSPCON2bits.PEN = 1; // End condition
while (SSPCON2bits.PEN); // Wait for end condition
}
void ds_read(char slave_adress, char register_adress) {
// Start condition
SSPCON2bits.SEN = 1;
while (SSPCON2bits.SEN); // Wait for start condition to complete
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
// Send slave address with write bit
SSPBUF = slave_adress;
while (!PIR1bits.SSPIF); // Wait for transmission to complete
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
// Check for ACK
if (SSPCON2bits.ACKSTAT) {
SSPCON2bits.PEN = 1; // End condition
while (SSPCON2bits.PEN); // Wait for end condition
return; // Return if ACK not received
}
// Send repeated start condition
SSPCON2bits.RSEN = 1;
while (SSPCON2bits.RSEN); // Wait for repeated start condition to complete
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
// Send register address
SSPBUF = register_adress;
while (!PIR1bits.SSPIF); // Wait for transmission to complete
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
// Check for ACK
if (SSPCON2bits.ACKSTAT) {
SSPCON2bits.PEN = 1; // End condition
while (SSPCON2bits.PEN); // Wait for end condition
return; // Return if ACK not received
}
// Send repeated start condition
SSPCON2bits.RSEN = 1;
while (SSPCON2bits.RSEN); // Wait for repeated start condition to complete
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
// Send slave address with read bit
SSPBUF = (slave_adress + 1);
while (!PIR1bits.SSPIF); // Wait for transmission to complete
PIR1bits.SSPIF = 0; // Clear SSP interrupt flag
// Check for ACK
if (SSPCON2bits.ACKSTAT) {
SSPCON2bits.PEN = 1; // End condition
while (SSPCON2bits.PEN); // Wait for end condition
return; // Return if ACK not received
}
// Enable receive mode
SSPCON2bits.RCEN = 1;
while (!SSPSTATbits.BF); // Wait for data to be received
__sec = SSPBUF; // Store seconds value
// Send ACK
SSPCON2bits.ACKDT = 0;
SSPCON2bits.ACKEN = 1;
while (SSPCON2bits.ACKEN); // Wait for ACK to be sent
// Receive minute value
SSPCON2bits.RCEN = 1;
while (!SSPSTATbits.BF); // Wait for data to be received
__min = SSPBUF; // Store minutes value
// Send ACK
SSPCON2bits.ACKDT = 0;
SSPCON2bits.ACKEN = 1;
while (SSPCON2bits.ACKEN); // Wait for ACK to be sent
// Similar process for hour, day, date, month, year, and control registers
// Send NACK
SSPCON2bits.ACKDT = 1;
SSPCON2bits.ACKEN = 1;
while (SSPCON2bits.ACKEN); // Wait for NACK to be sent
// End condition
SSPCON2bits.PEN = 1;
while (SSPCON2bits.PEN); // Wait for end condition to complete
// Display time on LCD
lcd_comand(0x88); // Set LCD cursor position
bcd_to_ascii(__hr); // Display hour
lcd_data(":"); // Display colon
bcd_to_ascii(__min); // Display minute
lcd_data(":"); // Display colon
bcd_to_ascii(__sec); // Display second
// Display date on LCD
lcd_comand(0xC7); // Set LCD cursor position
bcd_to_ascii(__date); // Display date
lcd_data("/"); // Display slash
bcd_to_ascii(__month); // Display month
lcd_data("/"); // Display slash
bcd_to_ascii(__yr); // Display year
}
Comments
Post a Comment