Forum: Mikrocontroller und Digitale Elektronik Timer-Interrupt beim ATTiny85 (UART)


von Rangi J. (rangi)


Lesenswert?

Hallo,
Ich habe folgende Aufgabe mit meinem ATTiny 85 (wahlweise 25 oder 45) zu 
lösen: Serielle Kommunikation UART mit 57600 8N1 - vollduplex.
Da der Tiny keine Hardware UART bietet und die vorhandene Software UART 
nur halbduplex kann, habe ich selber was implementiert.
- Int0 steht auf fallende Flanke und erkennt das Startbit.
- Timer 0 ist der Rx Timer und generiert alle 17µs einen Interrupt 
(CTC), darin wird die Rx-Leitung gesamplet. Beim 9. mal muss ne 1 
drinstehen, das Stopbit
- Timer 1 ist Tx Timer und macht vom Prinzip her das gleiche, gibt aber 
Start-, Daten- und Stopbit aus.
Zum Tester der Geschichte hab ich einfach ein Echo implemetiert.

Das ganze funktioniert soweit super fuer 1 Byte mit Pause. Der Tiny ist 
auch schnell genug, um die Daten in Echtzeit zubewaeltigen.
Jetzt das Problem, in der Hoffnung, das jemand hier im Forum darauf 
einen guten Tip abgeben könnte.
Sobald ich 2 Byte unmittelbar nacheinnander vom PC sende, beginnt der 
Tiny das 1. Byte wieder raus zu senden, während das 2. Byte gerade am 
Empfangen ist. Dabei "vergisst" der Timer 0 einmal der Interrupt 
auszulösen. Ich habe mir auf einem Portpin das Interruptverhalten 
ausgeben lassen und es sieht so aus als ob einer der Timer-Überläufe 
nicht zum Interrupt führt. Und zwar genau dann, wenn Timer 1 (Tx) 
gestartet wird oder seinen 1. Interrupt hat. Dabei sollten die Timer ja 
nichts miteinander zutun haben.
1
void sio_init(void)
2
{
3
  MCUCR |= ((1<<ISC01)|(0<<ISC00));  /*fallende flanke*/
4
  GIFR |= (1<<INTF0);  GIMSK |= (1<<INT0);  /*Int Enable*/
5
  /* Rx-Timer */
6
  TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(0<<WGM00);
7
  OCR0A = 139;   /*17,361µs = 57600 Baud >> 138,8 * 0,125µs @ 8MHZ*/  
8
  /* Tx-Timer */
9
  TCCR1 = (1<<CTC1)|(1<<PWM1A)|(0<<COM1A1)|(0<<COM1A0)|(0<<CS13)|(0<<CS12)|(0<<CS11)|(0<<CS10);
10
  OCR1C = 139;   /*17,361µs = 57600 Baud >> 138,8 * 0,125µs @ 8MHZ*/  
11
  TIMSK |= (1<<TOIE1)|(1<<OCIE0A);
12
}
13
14
/* Rx - Timer */
15
ISR(TIMER0_COMPA_vect) 
16
{
17
  if(sio_rx_state<8)  /* datenbits 0 bis 7*/
18
  {
19
    sio_rx_state++;
20
    sio_rx_byte>>=1;
21
    if(IO_SIO_RX_GET) sio_rx_byte |= 0x80;
22
  }
23
  else
24
  {
25
    TCCR0B = 0;  /*timer stoppen*/
26
    GIFR|=(1<<INTF0);  GIMSK |= (1<<INT0); /* jetzt wieder flanke zulassen fuers naechste byte*/
27
    if(IO_SIO_RX_GET) /* stop-bit = 1*/
28
    {
29
      sio_in_buffer[sio_in_buffer_ptr_wr++]=sio_rx_byte;
30
      sio_in_buffer_ptr_wr%=SIO_IN_BUFFER_SIZE;
31
    }
32
  }
33
}
34
35
/* Tx Timer*/
36
ISR(TIMER1_OVF_vect)
37
{
38
  if(sio_tx_state==0)   /*StartBit*/
39
  {
40
    if(sio_out_buffer_ptr_rd != sio_out_buffer_ptr_wr) /*es sind noch daten zu senden*/
41
    {
42
      IO_SIO_TX_EN;    /*Startbit*/
43
      sio_tx_byte=sio_out_buffer[sio_out_buffer_ptr_rd++];
44
      sio_out_buffer_ptr_rd%=SIO_OUT_BUFFER_SIZE;
45
      sio_tx_state++;
46
    }
47
    else  /* timer stoppen - nichts zu senden*/
48
    {
49
      TCCR1 &= ~(1<<CS10);
50
    }
51
  }
52
  else if(sio_tx_state<9)  /* 1..8 Datenbits */
53
  {
54
    if(sio_tx_byte & 0x01) IO_SIO_TX_DIS;
55
    else IO_SIO_TX_EN;
56
    sio_tx_byte>>=1;
57
    sio_tx_state++;
58
  }
59
  else if(sio_tx_state<10) /*Stop-Bit*/
60
  {
61
    IO_SIO_TX_DIS;
62
    sio_tx_state++;
63
  }
64
  else   /*Reload oder Stop Tx*/
65
  {
66
    sio_tx_state=0;
67
  }
68
}
69
70
ISR(INT0_vect)   /* StartBit - Fallende Flanke*/
71
{
72
  GIMSK &= ~(1<<INT0);   /*interupt ausschalten und Timer starten nach dem 10. Bit wird der Int wieder eingeschaltet */
73
  TCNT0 = 0;
74
  sio_rx_state=0;
75
  TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(0<<CS01)|(1<<CS00);    /* Timer starten - kein vorteiler */
76
}

Schon mal vielen Danke fuer nützliche Tips

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
Noch kein Account? Hier anmelden.