Archiv verlassen und diese Seite im Standarddesign anzeigen : Rtc ds3231
simonelein
09.08.2012, 12:11
Hallo ich bin absoluter programmier anfänger und wollte nun mir auf LCD die Uhrzeit anzeigen lassen.I2C Bus.
Ich benutze einen atmega1284 und das RTC DS3231.
ich habe mein LCD an den Ports PC4-PC7 und den RTC SCL an PC0(SCL) und SDA an PC1(SDA)
allerdings weiß ich gar nicht wie ich überhaupt anfangen soll.
ICh habe mir jetzt schon seit tagen durch viele code beispiele gelesen, aber ich verstehe es einfach nicht.
LG
Simone
021aet04
10.08.2012, 08:25
Wilkommen im Forum,
hast du schon einfache Ein/Ausgabe versucht? Ich würde als Anfänger mit der einfachen Ein/Ausgabe beginnen (wie die Meisten die anfangen), Signale verknüpfen,....
Erst wenn du weißt wie es geht würde ich mich an einen Bus wagen.
Wenn du externe ICs verwendest brauchst du immer die Datenblätter. Dort steht die Ansteuerung drinnen, was es zu beachten gibt,...
Nach diesem kann man ein Programm erstellen. Wenn du irgendwo Probleme hast kannst du den Code posten und es wird dir geholfen.
MfG Hannes
simonelein
13.08.2012, 13:36
Hallo
also ich habe jetzt den code von Peter Fleury angewendet "I2C Master Interface" und mit einerm oszilloskop an PC1 geptüft ob daten gesendet werden.
Das klappt auch, aber ich kann leider keine daten an PD6 (INT/SQW) empfangen/messen.
ich versuche mal den code hier zu posten.
Vielleicht sieht ja einer von euch den Fehler, ich finde ihn leider nicht.
* TWI_Test.c
#define F_CPU 20000000UL
/* I2C clock in Hz */
#define SCL_CLOCK 100000L
#include <avr/io.h>
#include <util/twi.h>
/************************************************** ***********************
Initialization of the I2C bus interface. Need to be called only once
************************************************** ***********************/
void i2c_init(void)
{
/* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
TWSR = 0; /* no prescaler */
TWBR = ((F_CPU/SCL_CLOCK)-16)/2; /* must be > 10 for stable operation */
}/* i2c_init */
/************************************************** ***********************
Issues a start condition and sends address and transfer direction.
return 0 = device accessible, 1= failed to access device
************************************************** ***********************/
unsigned char i2c_start(unsigned char address)
{
uint8_t twst;
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) return 1;
// send device address
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
// wail until transmission completed and ACK/NACK has been received
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1;
return 0;
}/* i2c_start */
/************************************************** ***********************
Issues a start condition and sends address and transfer direction.
If device is busy, use ack polling to wait until device is ready
Input: address and transfer direction of I2C device
************************************************** ***********************/
void i2c_start_wait(unsigned char address)
{
uint8_t twst;
while ( 1 )
{
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
// wait until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst != TW_START) && (twst != TW_REP_START)) continue;
// send device address
TWDR = address;
TWCR = (1<<TWINT) | (1<<TWEN);
// wail until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits.
twst = TW_STATUS & 0xF8;
if ( (twst == TW_MT_SLA_NACK )||(twst ==TW_MR_DATA_NACK) )
{
/* device busy, send stop condition to terminate write operation */
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
// wait until stop condition is executed and bus released
while(TWCR & (1<<TWSTO));
continue;
}
//if( twst != TW_MT_SLA_ACK) return 1;
break;
}
}/* i2c_start_wait */
/************************************************** ***********************
Terminates the data transfer and releases the I2C bus
************************************************** ***********************/
void i2c_stop(void)
{
/* send stop condition */
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
// wait until stop condition is executed and bus released
while(TWCR & (1<<TWSTO));
}/* i2c_stop */
/************************************************** ***********************
Send one byte to I2C device
Input: byte to be transfered
Return: 0 write successful
1 write failed
************************************************** ***********************/
unsigned char i2c_write( unsigned char data )
{
uint8_t twst;
// send data to the previously addressed device
TWDR = data;
TWCR = (1<<TWINT) | (1<<TWEN);
// wait until transmission completed
while(!(TWCR & (1<<TWINT)));
// check value of TWI Status Register. Mask prescaler bits
twst = TW_STATUS & 0xF8;
if( twst != TW_MT_DATA_ACK) return 1;
return 0;
}/* i2c_write */
int main(void)
{ DDRC = (1<<PC0)|(1<<PC1);
PORTC = (1<<PC0)|(1<<PC1);
DDRD= (1<<PD6);
PORTD=(1<<PD6);
i2c_init();
// write 0x75 to EEPROM address 5 (Byte Write)
//i2c_start_wait(0xAA); // set device address and write mode
i2c_start(0x68);
i2c_write(0x0E); // write address = 5
i2c_write(0b00000000); // write value 0x75 to EEPROM
i2c_stop();
i2c_start(0x68);
i2c_write(0x0F); // write address = 5
i2c_write(0b00000100); // write value 0x75 to EEPROM
i2c_stop();
//TODO:: Please write your application code
while(1)
{
}
}
021aet04
14.08.2012, 07:22
Du solltest die Code Tags verwenden, damit du den Code direkt in den Post integrierst. Wenn du auf Antorten gehst und dann auf Erweitert siehst du ein Raute Symbol. Damit kannst du den Code integrieren.
Jetzt zu deinem Problem. Du solltest dich in die Bustopologie genau einlesen. Ich weiß zwar nicht wie du es angeschlossen hast, bei einem I2C hast du aber 2Leitungen (eigentlich min. 4 da du noch VCC und GND brauchst). Die anderen Leitungen sind der Takt und die Daten. Der Takt wird mit SCL (Serial Clock) und die Daten werden mit SDA (Serial Data) bezeichnet.
Da du TWSR, TBSR,... Register verwendest, verwendest du Hardware I2C. Das bedeutet das du SCL des IC (dein RTC, könnte aber auch ein anderer sein) mit SCL von deinem µC (PC0). Das gleiche ist mit PC1 (das wäre SDA). Der Bus ist bidirektional. Es geht vom µC die Daten an den I2C-Teilnehmer über die SDA Leitung, aber auch vom I2C Teilnehmer zum µC. Der Clock wird immer vom Master erzeugt. Ich schreibe absichtlich nicht µC, da man den auch als Slave konfigurieren kann.
Es gibt auch einen TWI-Interrupt, falls du die Übertragung Interrupt gesteuert haben willst.
MfG Hannes
simonelein
15.08.2012, 10:21
Hallo Hannes.
Danke für deine Antwort.
Ich habe nun einen anderen code verwendet (Peter fleury) da er für mich einfacher zu verstehen war. Unten ein kleiner auzug davon. Es klappt auch alles, habe es mit einem osziloskop nach geprüft. Nun wollte ich aber den INT/SQW am ausgang aktivieren (auskommentierter Teil) leider funktioniert das nicht.
Was mache ich falsch?
HIer ein auszug aus dem Datenblatt des DS3231
Alarm1 can be set by writing to register 07h- to 0Ah. The alarm can be programmed to activate the INT/SQW output on an alarm match condition.
Bit 7 of each of the time of day alarm registers are make bits.
int main(void)
{ DDRC = (1<<PC0)|(1<<PC1);
PORTC = (1<<PC0)|(1<<PC1);
DDRD= (1<<PD6);
PORTD=(1<<PD6);
i2c_init();
//i2c_start(0xD0);
//i2c_write(0x07);
//i2c_write(0x80);
//i2c_write(0x80);
//i2c_write(0x80);
//i2c_write(0x80);
//i2c_stop();
//
//i2c_start(0xD0);
//i2c_write(0x0E);
//i2c_write(0x05);
//i2c_stop();
while(1)
{
_delay_ms(1);
i2c_start(0xD1);
i2c_write(0x00); // write address = 5
i2c_stop();
_delay_ms(100);
i2c_start(0xD0);
i2c_write(0x0B);
i2c_write(0x05);
i2c_stop();
}
}
LG simone
Hallo,
funktioniert dein LCD schon? Wenn nicht würde ich erst mal daran gehen, um die Funktionsweise des Controllers besser zu verstehen. Und wenn das LCD läuft kann man seinen Code auch leichter debuggen, da man Statuswerte einfach anzeigen kann.
Wie ist denn die Verdrahtung deines I2C-Busses? Hast du die Pull-Up-Widerstände richtig platziert? Vielleicht wäre es sinnvoll mal einen Schaltplan deiner Schaltung zu zeigen, damit wir hier eventuell Fehler erkennen können.
Viele Grüße
Andreas
simonelein
15.08.2012, 12:46
Hallo Andreas,
um mein LCD kümmere ich mich erst später wollte erst mal mein bauteil richtig ansteuern können.
Der schaltplan ist im anhang. Da sind aber die 2 pull up widerstände noch nicht mit eingezeichnet, da ich sie nachträglich eingelötet habe.
Zum debuggen brächte ich einen JATG, den ich aber leider nicht habe.
LG
Hallo,
Zum debuggen brächte ich einen JATG, den ich aber leider nicht habe.
Genau deshalb solltest du das LCD erst mal zum laufen bekommen. Wenn du dann mit den Ports des Controllers einigermassen vertraut bist würde ich erst mal testen, ob die ganzen Pins richtig geschaltet werden. Beim I2C ist das etwas tricky, da der Pin entweder als Eingang verwendet wird, oder als Ausgang um die Leitung auf Low zu ziehen. Das würde ich als nächstes mithilfe eines Meßgerätes und des LCD überprüfen. Mit dem Meßgerät messen, ob der Controller die Leitung korrekt auf Low zieht und dann auf dem LCD ausgeben, wie der Status der Leitung ist und diese dann mal mit einer Brücke auf Low ziehen.
Wenn alle IOs funktionieren und das Problem immer noch besteht kann man sich mal den Code anschauen. Aber da er ja kopiert ist sollte dieser funktionieren, zumindest wenn er durch das kopieren nicht verändert wurde.
Viele Grüße
Andreas
simonelein
15.08.2012, 13:49
hallo andreas,
mit einem messgerät (oszilloskop) habe ich es schon überprüft. Wie gesagt das klappt alles. Nur den alarm kann ich nicht aktivieren.
die 0x80 ist ein Datenbyte was in die RTC geschrieben werden soll. 0x80 bedeutet in binär 10000000. also eine 1 an die stelle wo die Alarmbits stehen.
Datenblatt RTC Seite 11. Register adresse 0x07 bis 0x0A. Da sollen mit der 0x80 die bits A1M1 bis A1M4 gesetzt werden.
..und genau das funktioniert nicht. Das lässt sich ja ebenfalls mit dem oszilloskop nach messen.
LG
simonelein
15.08.2012, 14:59
hab meinen Fehler soeben selber gefunden.
Trotzdem vielen Dank :) an alle
021aet04
15.08.2012, 18:27
Was war der Fehler? Vielleicht hilft es anderen, die auch ein Problem damit haben.
PS: Wie ich schon oben geschrieben habe solltest du deinen Code mit den Code Tags einfügen.
Das sieht dann so aus:
Da steht dein Code.
Das kannst du entweder mit dem Raute (#) Symbol oder mit [ c o d e ] (Anfang) und [ / c o d e ] (Ende) machen (du musst alles ohne Leerzeichen schreiben).
MfG Hannes
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.