Hallo Community, wie ist es eurer Meinung nach am einfachsten einen Clock für den SMBUS zu generieren hab schon über ein Timer Interrupt hinbekommen jedoch als Dauerschleife. Gibt es eine Möglichkeit den Interrupt zu stoppen sodass ich nur den Clock 9 mal erzeuge mit eine Frequenz von 100kHz. hier ist die Funktion zum Timer Initialisieren: #include "TimerInit.h" void Timer0 (void) { TCCR0B |= (1<<CS00); /* Precaler auf 1 (µC-Frequenz) */ TIMSK0 |= (1<<TOIE0); /* Overflow Interrupt erlauben */ TCNT0 = 240; /* Timer mit 240 vorgeladen */ _asm_ volatile ("sei"); /* Interrupt global aktivieren */ } hier die Interrupt Routine: #include "TimerInit.h" #include <avr/io.h> ISR (TIMER0_OVF_vect) { TCNT0 = 240; /* Timer mit 240 vorgeladen */ PORTD ^= (1 << PD7); } und main: #include <avr/io.h> /*Ende Include*/ int main( void ) { unsigned int i; DDRD = ( 1 << PD7 ); /* PORTD PIN7 als Ausgang definiert (SMB Clock) */ Timer0();/* Funktion Timer aufrufen */ ; while( 1 ) { /* Endlosschleife */ } return 0; } oder ist es doch besser mit der bib. delay.h zu arbeiten und einfach entsprechend dem SMB-Protokoll die Ports zuschalten? P.S der Controller ist ein Mega88 8Mhz interner Clock.
hat keiner ne Idee? über den SMBus soll ein Laderegler eingestellt werden. Wäre die Bibliothek delay.h genau genug um das richtige Timing hinzubekommen?
hat keine bisher was mit SMBUS gemacht oder warum gibt es gar keine Kommentare? Ja ich weiß es ist sehr ähnlich zum I2C-Bus... Wie würdet ihr es in C gestalten über delay.h oder doch timer intterrupt? Über Anregungen / Infos würde ich mich freuen :-)
Für SMBus und IIC habe ich schon diverses gebaut, aber ich habe mir noch nie so viel Gedanken über die Erzeugung der CLK gemacht ;-) Falls es noch frei ist, kannst du ja das TWI/IIC Modul deines ATmega88 die ganze Arbeit verrichten lassen. Dann passt auch das Timing exakt. Ansonsten ist ein IIC-Master auch schnell programmiert, indem man die SDA und SCL-Pins "von Hand" toggelt. Um das Timing etwas zu bremsen setze ich dabei üblicherweise eine Schleife über ein paar NOPs ein. (Ich schätze mal, _delay_us macht das selbe, oder?) Damit triffst du zwar nicht exakt die 100kHz, aber der Bus funktioniert auch problemlos, wenn du ihn etwas langsamer. (Nur zu schnell könnte schlecht sein...)
Achim S. schrieb: > Für SMBus und IIC habe ich schon diverses gebaut, aber ich habe > mir noch > nie so viel Gedanken über die Erzeugung der CLK gemacht ;-) > > Falls es noch frei ist, kannst du ja das TWI/IIC Modul deines ATmega88 > die ganze Arbeit verrichten lassen. Dann passt auch das Timing exakt. nee, ist nicht frei muss auf software i2c ausweichen > > Ansonsten ist ein IIC-Master auch schnell programmiert, indem man die > SDA und SCL-Pins "von Hand" toggelt. Um das Timing etwas zu bremsen > setze ich dabei üblicherweise eine Schleife über ein paar NOPs ein. (Ich > schätze mal, _delay_us macht das selbe, oder?) hast du mal in Beispiel in C hab schon über Timer interrupts versucht aber bekomme keine Start Bedingung hin die ja da heißt CLK high SDA Low oder? erst dann kommen die Daten bzw. muss ich erst die sende Adresse schicken? > > Damit triffst du zwar nicht exakt die 100kHz, aber der Bus funktioniert > auch problemlos, wenn du ihn etwas langsamer. (Nur zu schnell könnte > schlecht sein...)
Radjesch schrieb: > hast du mal in Beispiel in C Ich hätte zwar erwartet, dass das Netz voll mit Beispielen für IIC ist, aber bitteschön: hier die Erzeugung der Startcon:
1 | clr_sda(); //erzeuge Startcondition |
2 | shortpause(IIC_PAUSE); |
3 | clr_scl(); |
4 | shortpause(IIC_PAUSE); |
Nicht zu kompliziert. shortpause() ist wie gesagt eine Schleife über ein NOP und damit wohl ziemlich ähnlich zu _delay_us(). Müsste man viel länger warten, würde sich der Einsatz eines Timerinterrupts lohnen. Aber bei 5µs zwischen zwei Flanken... Danach kommt die Übermittlung der Device-Adresse an und das Prüfen des Acknowledge:
1 | write8bitiic(devadr); //Übertrage Device-Adresse |
2 | if (!check_ack()) {return 0;}; //frage Acknowledge ab. |
Wenn in check_ack() kein Acknowledge erkannt wird, wird eine Stopcon angelegt, damit der Bus wieder für die nächste Startcon vorbereitet ist. Ansonsten gibt check_ack einfach einen CLK-Puls aus, um das Acknowledge-bit weiterzuschalten. Ganz zum Schluss überprüft die aufrufende Routine am Rückgabewert, ob die gewünschte Anzahl von Bytes geschrieben wurde. die Routine zum Rausschieben der Adresse (und später der Daten) ist auch nicht zu kompliziert:
1 | void write8bitiic(uint8_t data) //Rotiere Daten bitweise nach SDA. Hänge jeweils einen SCL-Puls an |
2 | {
|
3 | |
4 | for (int8_t i = 7;i>=0;i--) { |
5 | if (data & (1 << 7)) set_sda(); else clr_sda(); |
6 | data = data << 1; |
7 | shortpause(IIC_PAUSE); |
8 | set_scl(); |
9 | shortpause(IIC_PAUSE); |
10 | clr_scl(); |
11 | }
|
12 | }
|
Wie man die folgenden Acknowledges abfragt und wie am Ende die Stopcon erzeugt wird, überlasse ich deiner Kreativität ;-)
Achim S. schrieb: > Radjesch schrieb: >> hast du mal in Beispiel in C > > Ich hätte zwar erwartet, dass das Netz voll mit Beispielen für IIC ist, > aber bitteschön: hier die Erzeugung der Startcon: > clr_sda(); //erzeuge Startcondition > shortpause(IIC_PAUSE); > clr_scl(); > shortpause(IIC_PAUSE); > > Nicht zu kompliziert. > > shortpause() ist wie gesagt eine Schleife über ein NOP und damit wohl > ziemlich ähnlich zu _delay_us(). Müsste man viel länger warten, würde > sich der Einsatz eines Timerinterrupts lohnen. Aber bei 5µs zwischen > zwei Flanken... > > Danach kommt die Übermittlung der Device-Adresse an und das Prüfen des > Acknowledge: > write8bitiic(devadr); //Übertrage Device-Adresse > if (!check_ack()) {return 0;}; //frage Acknowledge ab. > > Wenn in check_ack() kein Acknowledge erkannt wird, wird eine Stopcon > angelegt, damit der Bus wieder für die nächste Startcon vorbereitet ist. > was steht in der Funktion check_ack()? > Ansonsten gibt check_ack einfach einen CLK-Puls aus, um das > Acknowledge-bit weiterzuschalten. Ganz zum Schluss überprüft die > aufrufende Routine am Rückgabewert, ob die gewünschte Anzahl von Bytes > geschrieben wurde. > > die Routine zum Rausschieben der Adresse (und später der Daten) ist auch > nicht zu kompliziert:void write8bitiic(uint8_t data) //Rotiere Daten > bitweise nach SDA. Hänge jeweils einen SCL-Puls an > { > > for (int8_t i = 7;i>=0;i--) { > if (data & (1 << 7)) set_sda(); else clr_sda(); > data = data << 1; > shortpause(IIC_PAUSE); > set_scl(); > shortpause(IIC_PAUSE); > clr_scl(); > } > } > die Schleife ist mit noch nciht ganz klar: du toggelst die Datenleitung 8 mal auf high bei der steigenden Flanke vom Clock? > Wie man die folgenden Acknowledges abfragt und wie am Ende die Stopcon > erzeugt wird, überlasse ich deiner Kreativität ;-) hast du vllt. ein Beispiel Quellcode denn ich müsste mir das ganze im gesamten mal anschauen und dann mit dem Oszi mal nachmessen und vergleichen. Vielen Dank vorab!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.