Gast
#40523
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