Ich habe eine Schnittstelle DS1307 RTC
zu PIC32MX795F512L
. Ich benutze I2C1
for DS1307 RTC
und benutze dann, UART2
um den RTC-Wert an das Terminal zu senden. Ich habe den Code geschrieben, weiß aber nicht, warum ich keine Daten erhalte.
In meinem Code verwende ich
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
Diese sind in der Datei plib.h enthalten.
Aktualisierter CODE:
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();
Ich verwende 163 ((33000000/2/100000)-2)
als BRG-Wert für die I2C-Kommunikation. Ich debugge den Code und kann sehen, dass alle Werte in I2C-Registern korrekt sind, aber bei wird res = MasterReadI2C2()
nichts im Register angezeigt , das den empfangenen Wert enthält, und sogar nichts wird in der Variablen I2C2RCV
angezeigt . res
Ich habe auch eine Variable verwendet, n
um zu überprüfen, ob die Werte tatsächlich übertragen werden oder nicht. Also habe ich 0x00
als Wert von n erhalten und laut Dokument bedeutet 0 Übertragung erfolgreich.
Ich weiß nicht, wo ich den Punkt verfehle.
Bit 7 von Register 0 ist das Takthaltebit (CH). Wenn dieses Bit auf 1 gesetzt ist, ist der Oszillator deaktiviert. Wenn auf 0 gelöscht, ist der Oszillator aktiviert
Stellen Sie also beim zweiten Einstellen sicher, dass Bit 7 (CH) 0 ist. UND setzen Sie Bit 7 (CH) jedes Mal auf Null, wenn der IC eingeschaltet wird.
Ich habe diese RTC mit ATMega128 und CodeVisionAVR bearbeitet. Dieser Code funktioniert:
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);
Wenn Sie die älteren PLIB-Bibliotheken von Microchip für I2C verwenden, müssen Sie nach jeder Operation manuell abfragen, ob der Bus im Leerlauf ist. Ein Beispiel ist unten gezeigt:
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();
Die Funktion IdleI2C2() ist einfach die folgende:
while(I2C2CONbits.SEN || I2C2CONbits.PEN || I2C2CONbits.RSEN || I2C2CONbits.RCEN || I2C2CONbits.ACKEN || I2C2STATbits.TRSTAT);
Diese Leitung überprüft einfach alle Bits, die anzeigen, dass das Peripheriegerät beschäftigt ist (z. B. eine aktive Start- oder Stoppbedingung, derzeit Daten austakten usw.
Wenn ich mir Ihren Code ansehe, sehe ich nichts offensichtlich Falsches, aber wenn wir uns das DS1307- Datenblatt auf Seite 13 ansehen, gibt es an, dass Sie zum Lesen von Daten von einem bestimmten Ort die Adresse schreiben, den Ort in den DS1307-Registern, Starten Sie dann eine "Wiederholte Start"-Routine, senden Sie die Adresse erneut und lesen Sie dann die Daten. Sie können einen Multibyte-Burst sequentiell oder ein einzelnes Byte einlesen und dann ein STOP senden und den Prozess an einer anderen Registerstelle erneut starten.
Ich habe kürzlich festgestellt, dass ein Versuch, zwischen einem Master- und einem Slave-PIC zu kommunizieren, erfolglos war, und ich hatte einen DS1307 herumliegen, also habe ich etwas Code gepeitscht. Zum Glück gibt es für i2c.h kein Bit-Banging mehr. Der Code ist für den PIC18F8722 geschrieben, aber Sie sollten feststellen, dass etwas Ähnliches für Sie funktioniert:
#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;
}
Bitte seien Sie nicht zu streng mit dem Code. Ich hoffe das hilft.
Arsenal
Flugzeug
Arsenal
Flugzeug
Arsenal
Flugzeug
Arsenal
Adam Lawrence
Flugzeug