Fontes de consulta:
- Datasheet: capítulo 19
- Philips: - I2C manual - NXP
- Microchip: I2C master mode
- I2C INFO: I2C Info – I2C Bus, Interface and Protocol
RTC - Real Time Clock
Exemplo: DS1307
Código de exemplo em linguagem C para uso do RCT DS1307 com PIC18F4550
/*
* File: I2C - Atv01 - Exemplo.c
* Author: Pilger
*
* Created on 25 de Novembro de 2017, 13:58
*
* Exemplo de ligação I2C com RTC DS1307
* Caledário e horário no LCD
* Start em 23/12/2014 as 23h 59min 45s
* Ver mudança em caledário e tempo
*/
#define _XTAL_FREQ 48000000
#include <xc.h>
#include <stdio.h>
#include "C:\h\config_PIC18F4550.h"
#include "c:\h\biblioteca_lcd_2x162_48M_XC.h"
//protóptipo de funções
// I2C
void i2c_init();
void i2c_start(void);
void i2c_restart(void);
void i2c_stop(void);
void i2c_wait(void);
void i2c_send(unsigned char dat);
unsigned char i2c_read(void);
// funções criadas
unsigned char rtc1307_read(unsigned char address); //RTC DS1307 Read Function
void delay_ms(int i);
void atrasos(unsigned char segundos);
// variáveis globais
unsigned char sec,min,hour,day,date,month,year;
void main()
{
unsigned char buffer[16];
// defionição direção pinos
TRISB = 0x0F;
TRISC = 0xFF;
TRISD = 0x00;
// inicia LCD
lcd_inicia(0x28, 0x0f, 0x06); // incializa o LCD com 4 linhas
lcd_LD_cursor(0); // Desliga o cursortar instrução
lcd_limpa_tela();
lcd_posicao(1, 1);
imprime_string_lcd("RTC DS1307 ");
atrasos(2); // atraso de 2s
lcd_limpa_tela();
i2c_init(); //To Generate the Clock of 100Khz
// escreve data e hora inicial no DS1307
// exemplo usado data 31/dez/2014 numero gravado: dia 4 (quarta) 31/12/14
// exemplo usado tempo: 23h 59min e 45 seg
// exemplo p/ mostrar a virada de hora, dia e mês e ano
i2c_start();
i2c_send(0xD0);
i2c_send(0x00);
i2c_send(0x45|0x80); //CH = 1 Stop oscillator
i2c_send(0x59); //Minute
i2c_send(0x23); //Hour
i2c_send(0x04); //4 - quarta
i2c_send(0x31); //31 data
i2c_send(0x12); //12 Dez
i2c_send(0x14); //2014
i2c_stop(); //Stop the I2C Protocol
//Have to start the Clock again
i2c_start();
i2c_send(0xD0);
i2c_send(0x00);
i2c_send(0x45); //start Clock and set the second hand to Zero
i2c_stop();
while(1)
{
sec = rtc1307_read(0x00);
min = rtc1307_read(0x01);
hour = rtc1307_read(0x02);
day = rtc1307_read (0x03);
date = rtc1307_read(0x04);
month = rtc1307_read(0x05);
year = rtc1307_read(0x06);
// imprime dia, data, mês e ano
lcd_posicao(1, 1);
switch (day){
case 1: sprintf(buffer, " SUN %02x/%02x/20%02x ", date,month,year);
break;
case 2: sprintf(buffer, " MON %02x/%02x/20%02x ", date,month,year);
break;
case 3: sprintf(buffer, " TUE %02x/%02x/20%02x ", date,month,year);
break;
case 4: sprintf(buffer, " WED %02x/%02x/20%02x ", date,month,year);
break;
case 5: sprintf(buffer, " THU %02x/%02x/20%02x ", date,month,year);
break;
case 6: sprintf(buffer, " FRI %02x/%02x/20%02x ", date,month,year);
break;
case 7: sprintf(buffer, " SAT %02x/%02x/20%02x ", date,month,year);
break;
}
imprime_buffer_lcd(buffer, 16);
// imprime hora
lcd_posicao(2, 1);
sprintf(buffer, " Hora: %02x:%02x.%02x ", hour,min,sec);
imprime_buffer_lcd(buffer, 16);
atrasos(1); // atraso de 1s
}
}
// função que gera atraso em mlisegundos
void delay_ms(int i){
for ( int x = 0; x < i; x++ ) {
__delay_ms(1);
}
}
void atrasos(unsigned char segundos) { // função de atraso em segundo
delay_ms (1000*segundos);
}
void i2c_init()
{
TRISBbits.TRISB0 = 1; // SDA IN
TRISBbits.TRISB1 = 1; // SCL IN
SSPCON1=0b00101000; //Master mode
/* <7> Sem colisão - WCOL=0
* <6> sem Overflow na recepção SSPOV=0
* <5> Habilita porta serial e ativa pinos SDA E SCL - SSPEN=1
* <4> não usado em modo mestre =0
* <3:0> ativa modo mestre - SSPM3:SSPM0 --> 1000 - I2C Master Mode */
SSPADD = 119;
/* Clock = Fosc/4*(SSPADD+1)
* para 100KHz:
* SSPADD = [48M / 100K)/4]-1 = 119 */
SSPSTAT = 0b10000000;
/* <7> SMP=1 Slew rate control disabled for Standard Speed mode (100 kHz and 1 MHz) - controle de inclinação desativado = 1
* <6> CKE=0 -Disable SMBus specific inputs - níveis de entrada conforme especificação i2c = 0
* <5> D//A= 0 - Master Reservado
* <4> P=0 Stop bit was not detected last
* <3> S=0 Start bit was not detected last
* <2> R//W= 0 Master: Transmit is not in progress
* <1> UA=0 Address does not need to be updated
* <0> BF=0 SSPBUF is empty */
}
void i2c_start(void)
{
SSPCON2bits.SEN = 1;
/* SSPCON2 <0> SEN: Start Condition Enable/Stretch Enable bit(2)
* 1 = Initiate Start condition on SDA and SCL pins. Automatically cleared by hardware.
* 0 = Start condition Idle */
while (SSPCON2bits.SEN == 1)
continue; // Aguarda o bit voltar a 0 automaticamente por hardware
}
void i2c_restart(void)
{
SSPCON2bits.RSEN = 1;
/* SSPCON2 <1> RSEN: Repeated Start Condition Enable bit(2)
* 1 = Initiate Repeated Start condition on SDA and SCL pins. Automatically cleared by hardware.
* 0 = Repeated Start condition Idle */
while (SSPCON2bits.RSEN == 1)
continue; // Aguarda o bit voltar a 0 automaticamente por hardware
}
void i2c_stop(void)
{
SSPCON2bits.PEN=1;
/* SSPCON2 <2> PEN: Stop Condition Enable bit(2)
* 1 = Initiate Stop condition on SDA and SCL pins. Automatically cleared by hardware.
* 0 = Stop condition Idle */
while(SSPCON2bits.PEN==1)
continue; // Aguarda o bit voltar a 0 automaticamente por hardware
}
void i2c_wait(void)
{
while( SSPSTATbits.R_W == 1)
continue;
if(SSPCON2bits.ACKSTAT == 1)
{
i2c_stop();
}
//If ACKSTAT bit is 0 Acknowledgment Received Successfully
//Otherwise Not
}
void i2c_send(unsigned char dat)
{
SSPBUF = dat; /* Move data to SSPBUF */
while(SSPSTATbits.BF); /* wait till complete data is sent from buffer */
i2c_wait(); /* wait for any pending transfer */
}
unsigned char i2c_read(void)
{
unsigned char temp;
SSPCON2bits.RCEN = 1; /* Enable data reception */
while(SSPSTATbits.BF == 0) /* wait for buffer full */
continue;
temp = SSPBUF; /* Read serial buffer and store in temp register */
i2c_wait(); /* wait to check any pending transfer */
SSPCON2bits.ACKDT=1; //send not acknowledge
SSPCON2bits.ACKEN=1;
while(SSPCON2bits.ACKEN == 1)
continue;
i2c_stop();
return temp; /* Return the read data from bus */
}
unsigned char rtc1307_read(unsigned char address)
{
unsigned char temp;
i2c_start();
i2c_send(0xD0);
i2c_send(address);
i2c_restart();
i2c_send(0xD1);
temp = i2c_read();
//i2c_stop(); this line is Removed Because it is already included in i2c_read function
return temp;
}
Nenhum comentário:
Postar um comentário