Estoy interactuando DS1307 RTC
con PIC32MX795F512L
. Estoy usando I2C1
for DS1307 RTC
y luego usando UART2
para enviar el valor RTC a la terminal. He escrito el código pero no sé por qué no obtengo datos.
En mi código estoy usando
OpenI2C2 to open the i2c channel.
StartI2C2() to start the communication
StopI2C2() to stop the communication
MasterWriteI2C() to write the data
MasterReadI2C() to read the data
Estos están incluidos en el archivo plib.h.
CÓDIGO actualizado:
OpenI2C2(I2C_EN, 163); // I2C channel Configuration
StartI2C2();
IdleI2C2();
n = MasterWriteI2C2(0xD0); //device address
IdleI2C2();
MasterWriteI2C2(0x07);
IdleI2C2();
MasterWriteI2C2(0x00);
IdleI2C2();
StopI2C2();
StartI2C2();
IdleI2C2();
MasterWriteI2C2(0xD0);
IdleI2C2();
MasterWriteI2C2(0x01);
IdleI2C2();
MasterWriteI2C2(0b00010011);
IdleI2C2();
StopI2C2();
StartI2C2();
IdleI2C2();
MasterWriteI2C2(0xD0);
IdleI2C2();
MasterWriteI2C2(0x01);
IdleI2C2();
StopI2C2();
StartI2C2();
IdleI2C2();
MasterWriteI2C2(0xD1);
IdleI2C2();
**res = MasterReadI2C2();**
IdleI2C2();
NotAckI2C2();
IdleI2C2();
StopI2C2();
Estoy usando 163 ((33000000/2/100000)-2)
como valor BRG para la comunicación I2C. Estoy depurando el código y puedo ver que todos los valores en los registros I2C son correctos, pero en res = MasterReadI2C2()
, no aparece nada en I2C2RCV
el registro que contiene el valor recibido e incluso no aparece nada en la res
variable. También usé una variable n
para verificar si los valores realmente se transmiten o no. Entonces recibí 0x00
como el valor de n y según el documento, 0 significa transmisión exitosa.
No sé dónde me estoy perdiendo el punto.
El bit 7 del registro 0 es el bit de parada de reloj (CH). Cuando este bit se establece en 1, el oscilador se desactiva. Cuando se borra a 0, el oscilador está habilitado
Entonces, cuando configure el segundo, asegúrese de que el bit 7 (CH) sea 0. Y configure el bit 7 (CH) en cero cada vez que se encienda el IC.
Trabajé este RTC con ATMega128 y CodeVisionAVR Este código funciona:
rtc_init(0,1,0); // output pin for debugging
delay_ms(10);
i2c_start();
i2c_write(0xD0);
i2c_write(0x00);
i2c_write( (data_rtc[10]-48)*16 + (data_rtc[11]-48)); //second
i2c_stop();
delay_ms(10);
i2c_start();
i2c_write(0xD0);
i2c_write(0x01);
i2c_write( (data_rtc[8]-48)*16 + (data_rtc[9]-48)); // minutes
i2c_stop();
delay_ms(10);
i2c_start();
i2c_write(0xD0);
i2c_write(0x02);
i2c_write( (data_rtc[6]-48)*16 + (data_rtc[7]-48)); // hour
i2c_stop();
delay_ms(10);
i2c_start();
i2c_write(0xD0);
i2c_write(0x04);
i2c_write( (data_rtc[4]-48)*16 + (data_rtc[5]-48)); // day
i2c_stop();
delay_ms(10);
i2c_start();
i2c_write(0xD0);
i2c_write(0x05);
i2c_write( (data_rtc[2]-48)*16 + (data_rtc[3]-48)); // month
i2c_stop();
delay_ms(10);
i2c_start();
i2c_write(0xD0);
i2c_write(0x06);
i2c_write( (data_rtc[0]-48)*16 + (data_rtc[1]-48)); // year
i2c_stop();
delay_ms(10);
rtc_init(0,1,0);
Con las bibliotecas heredadas PLIB de Microchip para I2C, debe sondear manualmente el bus para que esté inactivo después de cada operación. A continuación se muestra un ejemplo:
StartI2C2(); // Send the Start Bit
IdleI2C2(); // Wait to complete
MasterWriteI2C2(0xE0); // Send slave address with write bit
IdleI2C2(); // Wait to complete
MasterWriteI2C2(addr);
IdleI2C2(); // Wait to complete
StopI2C2(); // Send Stop bit
IdleI2C2();
StartI2C2(); // Send the Start Bit
IdleI2C2(); // Wait to complete
MasterWriteI2C2(0xE1); // Send slave address with read bit
IdleI2C2(); // Wait to complete
val = MasterReadI2C2();
IdleI2C2();
NotAckI2C2(); // Master Aknodledge End of transfer
StopI2C2(); // Send Stop bit
IdleI2C2();
La función IdleI2C2() es simplemente la siguiente:
while(I2C2CONbits.SEN || I2C2CONbits.PEN || I2C2CONbits.RSEN || I2C2CONbits.RCEN || I2C2CONbits.ACKEN || I2C2STATbits.TRSTAT);
Esta línea simplemente verifica cualquier bit que signifique que el periférico está ocupado (como una condición activa de inicio o parada, datos de salida actuales, etc.).
Al mirar su código, no veo nada claramente incorrecto, pero si miramos la hoja de datos de DS1307 , página 13, especifica que para hacer una lectura de datos desde una ubicación específica, escriba la dirección, la ubicación en los registros de DS1307, luego inicie una rutina de "Inicio repetido", envíe la dirección nuevamente y luego lea los datos. Puede leer una ráfaga multibyte, secuencialmente, o un solo byte y luego enviar un STOP y comenzar el proceso nuevamente en una ubicación de registro diferente.
Recientemente encontré un intento fallido de comunicación entre un PIC maestro y un esclavo, y tenía un DS1307 por ahí, así que preparé un código. Afortunadamente, para i2c.h, no más golpes de bits. El código está escrito para PIC18F8722, pero debería encontrar que algo similar funcionará para usted:
#include <pic18f8722.h>
#include <i2c.h>
#include <spi.h>
#include <delays.h>
#include "LCD.h"
#include "SerComm.h"
#pragma config OSC = HSPLL
#pragma config WDT = OFF
#pragma config FCMEN = OFF
#define newline 0x0A
#define carriageReturn 0x0D
void initialize(void);
unsigned char x;
unsigned char seconds = 0x00;
unsigned char minutes = 0x36;
unsigned char hours = 0x48;
unsigned char days = 0x03;
unsigned char date = 0x17;
unsigned char month = 0x08;
unsigned char year = 0x15;
unsigned char hyear, lyear, hmonth, lmonth, hdate, ldate, hdays, ldays, hhours, lhours, hminutes, lminutes, hseconds, lseconds;
unsigned char time[7];
void main(void)
{
lcdInit();
initialize();
CloseI2C2();
OpenI2C2(MASTER, SLEW_OFF);
IdleI2C2();
StartI2C2();
WriteI2C2(0xD0);
WriteI2C2(0x00);
WriteI2C2(seconds);
WriteI2C2(minutes);
WriteI2C2(hours);
WriteI2C2(days);
WriteI2C2(date);
WriteI2C2(month);
WriteI2C2(year);
StopI2C2();
while(1)
{
IdleI2C2();
StartI2C2();
WriteI2C2(0xD0);
WriteI2C2(0x00);
RestartI2C2();
WriteI2C2(0xD1);
for(x = 0; x < 6; x++)
{
time[x] = ReadI2C2();
AckI2C2();
}
time[6] = ReadI2C2();
NotAckI2C2();
StopI2C2();
hyear = ((time[6] & 0xF0) >> 4) + 0x30;
lyear = (time[6] & 0x0F) + 0x30;
hmonth = ((time[5] & 0xF0) >> 4) + 0x30;
lmonth = (time[5] & 0x0F) + 0x30;
hdate = ((time[4] & 0xF0) >> 4) + 0x30;
ldate = (time[4] & 0x0F) + 0x30;
hdays = ((time[3] & 0xF0) >> 4) + 0x30;
ldays = (time[3] & 0x0F) + 0x30;
hhours = ((time[2] & 0x10) >> 4) + 0x30;
lhours = (time[2] & 0x0F) + 0x30;
hminutes = ((time[1] & 0xF0) >> 4) + 0x30;
lminutes = (time[1] & 0x0F) + 0x30;
hseconds = ((time[0] & 0xF0) >> 4) + 0x30;
lseconds = (time[0] & 0x0F) + 0x30;
lcdGoTo(0x00);
lcdWriteString("Time: ");
lcdChar(hhours);
lcdChar(lhours);
lcdChar(':');
lcdChar(hminutes);
lcdChar(lminutes);
lcdChar(':');
lcdChar(hseconds);
lcdChar(lseconds);
SerTx(hhours);
SerTx(lhours);
SerTx(':');
SerTx(hminutes);
SerTx(lminutes);
SerTx(':');
SerTx(hseconds);
SerTx(lseconds);
SerTx(newline);
SerTx(carriageReturn);
}
}
void initialize(void)
{
TRISAbits.RA2=0; // Chip select pin for the SPI port expander;
TRISDbits.RD5 = 1; //Set the ports of the I2C bus;
TRISDbits.RD6 = 0;
SSP2STAT = 0x80; //Disable the slew rate control;
SSP2CON1 = 0x28; //Enable the Serial Port, Set the mode to: Master Mode, clock = Fosc/(4*(SSP1ADD + 1);
SSP2CON2 = 0x00; //No bits to set here;
SSP2ADD = 0x59; //Set to 100 kHz at 40 MHz clock;
TXSTA1 = 0x24; //Set serial communication to High Speed, TX enabled, 8 bit mode;
RCSTA1 = 0x90; //Enable the serial port, Enable the Receiver;
BAUDCON1 = 0x00; //;
SPBRG1 = 42; //57600 kBaud;
}
Por favor, no seas demasiado duro con el código. Espero que esto ayude.
Arsenal
Aeronave
Arsenal
Aeronave
Arsenal
Aeronave
Arsenal
adam lorenzo
Aeronave