Hi! Ich habe ein Problem mit meinem Programm, kann aber den Fehler nicht wirklich finden! #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> #define F_CPU 3686400 /* Hz */ #define UART_BAUD_RATE 9600 /* 9600 baud */ #define UART_BAUD_SELECT (F_CPU/(UART_BAUD_RATE*16l)-1) #define max_data_len 9 unsigned char volatile receive_state; unsigned char volatile packet_length; unsigned char volatile data[max_data_len]; unsigned char volatile data_length; const unsigned char msg_status_response[9] = {0X68,0x39,0x00,0x09,0x00,0x3F,0x00,0x01,0x01}; const unsigned char msg_announce[3] = {0xFF,0x02,0x01}; const unsigned char msg_poll_response[3] = {0xFF,0x02,0x00}; //XXX: use enum instead #define state_sender_id 1 #define state_get_length 2 #define state_dest_id 3 #define state_get_data 4 #define state_packet_done 5 SIGNAL(SIG_UART0_RECV) // signal handler for receive complete interrupt { unsigned char byte; byte = inp(UDR0); //read byte for UART data buffer if (receive_state == state_get_length){ packet_length = byte; receive_state = state_dest_id; }else if (receive_state == state_dest_id){ //waiting for "CD-Changer" packet_length--; if (byte == 0x18){ receive_state = state_get_data; data_length = 0; } }else if (receive_state == state_get_data){ if (--packet_length > 0){ data[(int)data_length++] = byte; }else{ //we get checksum //checksum is egal receive_state = state_packet_done; } }else { //standard: wait for sender_id=="Radio" receive_state = state_sender_id; //sischer is sischer if (byte == 0x68) receive_state = state_get_length; } } unsigned char ibus_send_byte(unsigned char byte) { unsigned char j,parity; parity=1; for (j=7;j>0;j--) parity += byte>>j & 0x01; while (bit_is_clear(UCSR0A,UDRE)) ; //wait until ready if (parity & 0x01) //Set Parity sbi(UCSR0B,TXB8);// else cbi(UCSR0B,TXB8); outp(byte,UDR0); while (bit_is_clear(UCSR0A,RXC)); j = inp(UDR0); //get rec. byte if (j != byte) return 0; //contention in parity bit is egal //sei(); return 1; } unsigned char __ibus_send(unsigned const char *buf, unsigned char size){ unsigned char i,checksum=0^0x18; if (!ibus_send_byte(0x18)){ return 0;} outp(1<<PC2,PORTC); if (!ibus_send_byte(size+1)){ return 0;} checksum ^= size+1; for (i=0;i<size;i++){ checksum ^= buf[i]; if (!ibus_send_byte(buf[i])) return 0; } if (!ibus_send_byte(checksum)) return 0; return 1; } void ibus_send(unsigned const char *buf, unsigned char size){ cli(); while(!(__ibus_send(buf,size))); } void uart_init(void) /* initialize uart */ { /* enable RxD/TxD and ints */ outp((1<<RXCIE)|(1<<TXCIE)|(1<<RXEN)|(1<<TXEN)|(1<<CHR9),UCSR0B); /* set baud rate */ outp(UART_BAUD_SELECT, UBRR0); } int main(void) { uart_init(); outp(0xff,DDRC); sei(); /* enable interrupts */ receive_state=state_sender_id; //XXX: wait? ibus_send(msg_announce,3); //announce for (;;) { /* loop forever */ if (receive_state == state_packet_done){ if (data[0]==0x01){ //poll -> respond. ibus_send(msg_poll_response,3); receive_state=state_sender_id; } if (data[0] == 0x38) if ((data[1]==0)||(data[1]==3)){ //req stat||play ibus_send(msg_status_response,9); receive_state=state_sender_id; } } } } Das Problem tritt in der Funktion ibus_send_byte auf! Wenn ich hier das unten auskommentierte sei() reinschreibe und die Interrupts wieder aktiviere, dann sendet er ständig das gleihe Byte über den UART. Wenn ich sei() auskommentiere, dann sendet er das Paket so, wie ich will. Allerdings kann ich dann natürlich nichts empfangen, weil der Interrupt für die Empfangsroutine ja nicht ausgelöst wird! Wenn ich sei(); drinlasse und : while (bit_is_clear(UCSR0A,RXC)); j = inp(UDR0); //get rec. byte if (j != byte) return 0; auskommentiere,dann funktioniert es auch. Ich finde den Fehler einfach nicht, da ich nicht weiss, wo da noch ein Interrupt ausgelöst werden könnte, der mir dazwischenfunkt. Laufen tut das ganze auf nem Atmega 161! Danke Tobias Michaels
Nun, Du hast TXCIE gesetzt, aber wo ist der Interrupthandler für TXCIE? Übrigens ist es sinnvoller, statt TXCIE lieber UDRIE zu benutzen: Du kannst ja das nächste Zeichen bereits in den Puffer schieben, während das aktuelle Zeichen gerade das Sende-Schieberegister verläßt. Damit ist ein nahtloser Übergang zwischen zwei Zeichen ohne zusätzliche Pause gewährleistet. inp()/outp() sind »deprecated«, stattdessen bitte auf direkte Portzuweisung umstellen. Namen, die mit einem Unterstrich beginnen (__ibus_send()) sind für die ``Implementation'' reserviert (also für Compiler und Bibliothek), daher besser grundsätzlich nicht benutzen, damit es nicht zu Kollisionen mit der Bibliothek kommt.
Ich habe das Programm komplett umstrukturiert und es läuft jetzt, wie es soll, danke an alle die sich Gedanken drüber gemacht haben! Tobi
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.