Du, ich muß eine Stunde weg. ich meld' mich
Druckbare Version
Du, ich muß eine Stunde weg. ich meld' mich
*grüberl*
Sag mal, steht das noch so drin ? (in der timer-isr)
if (bRxFlag & RX_M_RECEIVE)
{
if (bRxCount & 0x080)
das ist katastophal falsch muß heißen :
if (bRxCount & 0x08)
EDIT: Seh grad, du hast jetzt if (rxcount == 9) das ist aber auch eines zu viel, wir haben ja nur 8 datenbits
Hab jetzt ein bischen rumgespielt mit der if-Abfrage
wenn du if(bRxCount & 0x08) machst passts mit der Bit-Kopie inner while() und die y kommen bzw. ab und zu auch mal ein þ.
Wenn du z.b. if(bRxCount & 0x09) oder 0x07 machst dann ist Bit-Kopie nicht mehr ok und y kommen immer noch..... :-s
Morgen, da sind wir wieder !
ist klar, das ist der Unterschied "&" und "==". EgalZitat:
Zitat von schamp
Ein neues Spiel, ein neues Glück:
Wir machen die Counterei zu Fuß, vergleichen dann mit dem Timer-ISR Ergebnis und erhoffen Weisheiten.
Dazu senden wir immer nur das Zeichen 0x55, das ergibt mit start und stop genau das Muster 0 10101010 1, dadurch kriegen wir die Bitwechsel auch ohne Time genau mit. die erste Flanke zum Startbit kriegt ja der INT0, der setzt RX_M_RECEIVE, und dann geht's los
(dabei läuft die Timer0-ISR ganz normal, nur
RX_M_DATA setzt er NICHT und
RX_M_RECEIVE löscht er NICHT, das machen wir jetzt extra)
send_one_byte(bRxCount + 0x30);Code:unsigned char bOld = 0; // wegen den Flanken
unsigned char bCnt = 0; // vergleichszähler
// in der INT0 ISR zusätzlich
bOld = 0;
bCnt = 0;
// in der while(1) -schleife
if (bRXFlag & RX_M_RECEIVE)
{
if ( ( PIND & (1<<PD2)) ^ bOld & (1<<PD2)) // any Flanke ?
{
if (bCnt & 0x08)
{
bRXFlag &= ~RX_M_RECEIVE;
bRXFlag |= RX_M_DATA;
}
else
{
bOld = PIND;
bCnt++;
bRxByte >>= 1;
}
}
if ( PIND & (1<<PD2))
{
PORTD |=(1<<PD4);
bRxByte |=0x80;
}
else
{
PORTD &= ~(1<<PD4);
}
}
if (bRXFlag & RX_M_DATA)
{
bRxFlag &= ~RX_M_DATA;
send_one_byte(bRxCount + 0x30);
}
Wir senden den Byte-Zähler, den die Timer0-ISR zu diesem Zeitpunkt gerade hat. Der sollte ja eigentlich auch ca 8 oder 9 sein. Ist er weiter weg, können wir abschätzen, wo die Differenz liegt
( + 0x30) --> damit das ein druckbares zeichen wird und wir es lesen können.
0x30 ---> "0"
wie gesagt, kann nur funzen, wenn 0x55 = "U" geschickt wird, wegen des Bit musters
Verständlich ?
Aber wie is das dann mit RxByte in der Timer-ISR ?
Wird das dann net überschrieben, wenn du auch RxByte in while setzt ?
Versteh den Ablauf nicht mehr so ganz...
EDIT: 8en kommen wenn die Timer-ISR so aussieht
nya wenn ich so ziemlich alles auskommentier auf Tastendruck immer u0Code:if (bRxFlag & RX_M_RECEIVE) // receive ?
{
if (bRxCount & 0x08) // is this the stop-Bit (9th)
{
bRxFlag &= ~RX_M_RECEIVE; // receiving sequence done
bRxFlag |= RX_M_DATA; // signal data
GICR |= 1<<INT0; // re-enable int0 for next
}
else
{
bRxByte >>= 1; // Shift right data
bRxCount++;
/* if(PIND&(1<<PD2)) //set bit or leave it
{
bRxByte |=0x80;
bRxCount++;
} */
}
}
RxByte: was die TimerISR reinschreibt, wissen wir eh schon (y) daher ausgeliehen für die while-routine
Ich wollte wissen, wenn wir durch ein Spezialzeichen extra die Bits zählen, und nach der 8. Flanke den (parallel)Zähler der TimerISR anschauen, wieweit denn die Timer-Isr gekommen wäre (in der selben Zeit)
Übrigens: Großes (shift) "U" ist gefragt (0x55)
Wenn dir bei der beschriebenen Methode "u0" rauskommt, ("u" ist das Echo, und "0" der iSR-Counter zum selben Zeitpunkt) heißt das ja, daß die Timer-ISR nichteinmal zu zählen begonnen hat, obwohl das Byte schon aus war.
Das müssen wir sicherstellen. Bitte stell den ganzen Code rein.
Code while()
Receive-Routine inner Timer-ISR:Code:while(1)
{
if (bRxFlag & RX_M_RECEIVE)
{
if ( ( PIND & (1<<PD2)) ^ (bOld & (1<<PD2))) // any Flanke ?
{
if (bCnt & 0x08)
{
bRxFlag &= ~RX_M_RECEIVE;
bRxFlag |= RX_M_DATA;
}
else
{
bOld = PIND;
bCnt++;
bRxByte >>= 1;
}
}
if ( PIND & (1<<PD2))
{
PORTD |=(1<<PD4);
bRxByte |=0x80;
}
else
{
PORTD &= ~(1<<PD4);
}
}
if (bRxFlag & RX_M_DATA)
{
bRxFlag &= ~RX_M_DATA;
send_one_byte(bRxCount + 0x30);
}
}
und INT0Code:if (bRxFlag & RX_M_RECEIVE) // receive ?
{
if (bRxCount & 0x08) // is this the stop-Bit (9th)
{
//bRxFlag &= ~RX_M_RECEIVE; // receiving sequence done
//bRxFlag |= RX_M_DATA; // signal data
GICR |= 1<<INT0; // re-enable int0 for next
}
else
{
bRxByte >>= 1; // Shift right data
bRxCount++;
/* if(PIND&(1<<PD2)) //set bit or leave it
{
bRxByte |=0x80;
bRxCount++;
} */
}
}
so wie ichs jetzt hab kommen nur U's (UUUUUUUU usw.)Code:if(!(bRxFlag & RX_M_RECEIVE))
{
GICR = 0; // Disable external interrupt
// bTxFlag &= ~TX_M_SEND; // Deactivate Transmit-Mode
TCNT0 = INT0_PRELOAD; // Set timer reload-value (to 1.5 bit len). 29 = time delay that
// have already been used in this
// interrupt plus the time
// that will be used by the time
// delay between timer interrupt request
// and the actual sampling of the first
// data bit.
TIFR |= (1<<TOV0); // clear T/C0 overflow flag
TIMSK |= (1<<TOIE0); // enable T/C0 overflow interrupt
bRxCount = 0; // Clear Receive Counter
bOld = 0;
bCnt = 0;
bRxFlag |= RX_M_RECEIVE; // Activate Receive-Mode
}
das muß aus der ISR noch raus
bRxByte >>= 1; // Shift right data
In der Main-Routine, sicherheitshalber
if ( PIND & (1<<PD2))
{
PORTD |=(1<<PD4);
bRxByte |=0x80;
}
else
{
PORTD &= ~(1<<PD4);
bRxByte &=~0x80;
}
bleibt bei UUUUUUUU....
D.h bei der Methode wird offenbar RX_M_DATA garnicht gesetzt, sonst müßte er nach jedem "U" ja irgendwas ausgeben.
Da müssen wir kontrollieren, ob die while routine überhaupt die Flanken erkennt
(es ist nur ein "}" anders)Code:while(1)
{
if (bRxFlag & RX_M_RECEIVE)
{
if ( ( PIND & (1<<PD2)) ^ (bOld & (1<<PD2))) // any Flanke ?
{
if (bCnt & 0x08)
{
bRxFlag &= ~RX_M_RECEIVE;
bRxFlag |= RX_M_DATA;
}
else
{
bOld = PIND;
bCnt++;
bRxByte >>= 1;
}
if ( PIND & (1<<PD2))
{
PORTD |=(1<<PD4);
bRxByte |=0x80;
}
else
{
PORTD &= ~(1<<PD4);
bRxByte &= ~0x80;
}
}
}
if (bRxFlag & RX_M_DATA)
{
bRxFlag &= ~RX_M_DATA;
send_one_byte(bRxCount + 0x30);
}
}
in diesem Falle dürft jetzt GARKEIN echo kommen
tuts aber, wieder die UUUUUUUUUU (also halt nur die Bit-Kopie, so wie vorher) :(Zitat:
Zitat von PicNick
andere Tasten nur irgendein Müll
(Müll ist klar, das geht nur mit 0x55)
Ja, aber wenn er RX_M_DATA auslöst,
send_one_byte(bRxCount + 0x30);
kann doch kein "U" sein ?
Hopperla, da pfuscht uns die INT0 rein.
Lösch' das RX_M_RECEIVE erst zusammen mit dem RX_M_DATA , aber VOR dem Send_one...
if (bRxFlag & RX_M_DATA)
{
bRxFlag &= ~RX_M_DATA;
bRxFlag &= ~RX_M_RECEIVE;
send_one_byte(bRxCount + 0x30);
}
U's kommn immer noch :shock:
Noch ne Frage, bei 8 Datenbit 10101010 müßtn das net 0xAA sein?
Nein, LSB is first, er fängt beim kleinsten Bit an, also gew. rechts nach links
Was mich jetzt wundert, wieso send-One_byte scheinbar nix schickt, zwischen den U's
Stimmt auch wieder.. :-kZitat:
Zitat von PicNick
Aber eigentlich sollte doch das RX_M_DATA gesetzt werden oder nicht ?!?!
Ja, eben. das kann er doch nur versäumen, wenn er keine 8 Flanken erkennen kann ? Das kann er aber, sonst tät er ja nicht richtig kopieren (echo)
Da spuckt uns wer in die Suppe
Andere Strategie:
Du nimmst mal ganz normal die HW-UART zum senden und empfangen.
Den RxPin verbinden wir aber mit INT0 als Spion und der startet auch den Timer, der nix tut, außer bit zählen
Wenn beim empfangenen Byte das UDR signal gibt, müßte dieser Zähler ja unabhängig bis etwa 8 kommen. tut er das nicht, isser zu schnell oder langsam.
HW Uart stimmt no was net ganz.. Hab ich noch was vergessen zu initialisieren ??
Würd das dann mit unserem SW Uart kombinieren, so wie du meintest
INT0 mit dranhängen und in der Timer-ISR nur Bits mitzählen
Code:__task void main()
{
hw_uart_init(11); // 19200 @3.686 MHz
while(1);
}
void hw_uart_init(unsigned char baudrate)
{
UBRRL = baudrate;
UCSRB |= (1<<RXEN) | (1<<TXEN) | (1<<RXCIE);
}
void transmit_byte(unsigned char data)
{
UDR = data;
}
#pragma vector=USART_RXC_vect
__interrupt void UART_RX_interrupt(void)
{
unsigned char data;
data = UDR; //receive data
transmit_byte(data); // echo data
}
Morgen, in voller Frische ?
UBRRL = LOW(baudrate);
UBRRH = HIGH(baudrate);
Mag er net.
Kann ich doch auch so schreiben:
UBRRL = 0x0B;
UBRRH = 0x00;
Geht imma no net
So gesehen hast du recht.
Ich kann aber eigentlich keinen Fehler sehen.
Sei () hast du ja drinnen ?
siehst du da irgndwo einen Fehler ? :-sCode:__task void main()
{
init_hw_uart(); // 19200 @3.686 MHz
__enable_interrupt();
while(1);
}
void init_hw_uart()
{
// Set Baudrate
UBRRH = 0x00;
UBRRL = 0x0B;
// Enable receiver and transmitter
UCSRB |= (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
// Set frame format: 8data bit , 1 Stop Bit
UCSRC |= (1<<UCSZ1)|(1<<UCSZ0);
}
void transmit_byte(unsigned char data)
{
// Put data into buffer, sends the data
UDR = data;
}
#pragma vector=USART_RXC_vect
__interrupt void UART_RX_interrupt(void)
{
DDRB |= (1<<PB0); // Status LED initialization
PORTB ^= (1<<PORTB0); // toggle status LED
unsigned char data;
data = UDR; //receive data
transmit_byte(data); // echo data
}
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
Geht jetzt.... ](*,)
ok dann ma sw-uart mit reinbasteln
Sollt eigentlich funzen (HW UART geht noch *gg*). Stell den Code schon ma online..
Muss nur noch die zusätzlichen Leitungen verbinden.
Der RxCounter-Stand vom Software UART wird wieder mit send_one_byte() ans Terminal geschickt.
So wars auch gedacht ?!
Schau ich mir gleich an.
Wir können für diesen Versuch auch mit der HW-Uart senden, es ist im Grunde egal.
Wenn das Echo mal prinzipiell getestet ist und funzt,
hw_transmit_byte(data); // echo data
reicht aber dann
hw_transmit_byte(bRxCount + 0x30); // return actual rxcounter
bin ich neugierig
HW-UART funzt, aber anscheinend wird nie RX_M_DATA gesetzt (siehe while-Schleife)
Denn im Terminal zeigts kein Counterstand an...
Habs jetzt so:
Mal schauen, ob INT0 überhaupt anspringt.
In der Hw Receive-ISR den Flag RX_M_RECEIVE prüfen
Isser gesetzt, ist INT0 offenbar angesprungen
wenn nicht, müssen wir klären, warum das so ist.
( mach einfach statt "send-one-byte( '0') oder ('1') )
Ist der Flag da, aber rxCount bleibt null, kommt die Timer-ISR nicht dran
(irgendein enable fehlt ?)
Schaust du mal ?
Sag ma sperren sich die Interrupts nicht gegenseitig ??
Meine damit INT0 und den USART_RXC...
Hab Status LED in INT0 und des springt net an...
Außerdem is ja INT0 PD2 und RXD ist PD0
Na ich hoff doch, du hast PD2 und PD0 verbunden ?
RX Pin aufm Board mit PD2 sollt ja auch gehn..
klaro, INT0 (PD2) muß mithören können
Das gibsch nich.. jetzt hab ich nochmal "umgepfrimelt" von PD0 auf PD2 anstatt glei von RX auf PD2
Und INT0 springt net an...
HW Uart geht *krise* :cry:
Also RX_M_RECEIVE wird in der INT0 definitiv nicht gesetzt, habs jetzt in der HW-UART ISR abgefragt..
keine Zeichen am Terminal
Wenn INT0 anspringt, setzt er auch _M_receive, da kommt er nicht vorbei.
Vielleicht ist da auch ein Gedankenfehler drin und INT0 wird irgendwie erst NACH der Uart ausgeführt.
Setz vielleicht in der HW-UART-ISR einen anderen Flag (RX_M_MUHKUH), frag den in der Mainroutine ab und schau, ob JETZT Receive gesetzt ist
Erstma so halbe Entwarnung.. wenn ich die Status LED jetzt in der INT0 drinne hab leuchtets, also schon ma gut.
Wenn ich se stattdessen jetzt inne Receive Routine in der Timer ISR reintu leuchtets net.
Anscheinend lösch ma irgndwo ausversehen RX_M_RECEIVE... ?!
while(1)
{
if(bRxFlag & RX_M_DATA)
{
bRxFlag &= ~RX_M_DATA;
//bRxFlag &= ~RX_M_RECEIVE;
hw_transmit_byte(bRxCount + 0x30);
}
}
So auskommentiert: //bRxFlag &= ~RX_M_RECEIVE; gehts..
Counter ist immer 0 im Terminal
Das wirklich sehr komische ist... RX_M_DATA wird vorher nie gesetzt.....
Count müßte daher eigentlich auf jedenfall > 0 sein (bzw. solltns eigentlich 8 sein...) bevor in der while-Schleife hw_transmit_byte(bRxCount + 0x30);
ausgeführt wird.
wenn int0 _M_receive setzt, kann die Timer routine was tun.
wenn sie zählt, könnte sie M_data setzen und ggf. wieder INT0 enablen.
der wiederum würde den count zurücksetzen, und nur _data bliebe über
Nimm aus der Timer routine mal alles raus, außer zählen
if (bRxCount & 0x08) // is this the stop-Bit (9th)
{
bRxFlag &= ~RX_M_RECEIVE; // receiving sequence done
bRxFlag |= RX_M_DATA; // signal data
GICR |= 1<<INT0; // re-enable int0 for next
}
Alles sehr sehr komisch....
Wenn ich alles aus der Timer-ISR rausschmeiss ausser dem bRxCount
Also so:
while-Schleife:Code:#pragma vector=TIMER0_OVF_vect
__interrupt void tim0_ovf(void)
{
TCNT0 = T0_PRELOAD; // Refresh preload
// ==========================================================================
// receive
// ==========================================================================
if (bRxFlag & RX_M_RECEIVE) // receive ?
{
DDRB |= (1<<PB2); // Status LED initialization
PORTB ^= (1<<PORTB2); // toggle status LED
/* if (bRxCount & 0x08) // is this the stop-Bit (9th)
{
bRxFlag &= ~RX_M_RECEIVE; // receiving sequence done
bRxFlag |= RX_M_DATA; // signal data
GICR |= 1<<INT0; // re-enable int0 for next
}
else */
// {
// bRxByte >>= 1; // Shift right data
bRxCount++;
bRxFlag |= RX_M_MUHKUH;
/* if(PIND&(1<<PD2)) //set bit or leave it
{
bRxByte |=0x80;
bRxCount++;
} */
// }
}
}
wird kein INT0 ausgelöst. d.h. nur HW-Uart Echo, kein bRxCounter Stand.Code:while(1)
{
if(bRxFlag & RX_M_MUHKUH)
{
//bRxFlag &= ~RX_M_DATA;
bRxFlag &= ~RX_M_RECEIVE;
bRxFlag &= ~RX_M_MUHKUH;
hw_transmit_byte(bRxCount + 0x30);
}
}
Kommentiere ich aber bRxFlag &= ~RX_M_RECEIVE; und bRxFlag &= ~RX_M_MUHKUH; aus, wird INT0 ständig ausgelöst (ein Tastendruck reicht...)
Was dann gesendet wird:
!+5?IS]gq{…™£*·ÁËÕßéóýCMWaku‰“§±»ÅÏÙãí÷
)3=GQ[eoyƒ—¡«µ¿ÉÓÝçñû#-7AKU_is}‡‘›¥¯¹Ã
also nur Müll halt...