www.mikrocontroller.net

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


Autor: Rangi Jones (rangi)
Datum:

Bewertung
0 lesenswert
nicht 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.
void sio_init(void)
{
  MCUCR |= ((1<<ISC01)|(0<<ISC00));  /*fallende flanke*/
  GIFR |= (1<<INTF0);  GIMSK |= (1<<INT0);  /*Int Enable*/
  /* Rx-Timer */
  TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(0<<COM0B1)|(0<<COM0B0)|(1<<WGM01)|(0<<WGM00);
  OCR0A = 139;   /*17,361µs = 57600 Baud >> 138,8 * 0,125µs @ 8MHZ*/  
  /* Tx-Timer */
  TCCR1 = (1<<CTC1)|(1<<PWM1A)|(0<<COM1A1)|(0<<COM1A0)|(0<<CS13)|(0<<CS12)|(0<<CS11)|(0<<CS10);
  OCR1C = 139;   /*17,361µs = 57600 Baud >> 138,8 * 0,125µs @ 8MHZ*/  
  TIMSK |= (1<<TOIE1)|(1<<OCIE0A);
}

/* Rx - Timer */
ISR(TIMER0_COMPA_vect) 
{
  if(sio_rx_state<8)  /* datenbits 0 bis 7*/
  {
    sio_rx_state++;
    sio_rx_byte>>=1;
    if(IO_SIO_RX_GET) sio_rx_byte |= 0x80;
  }
  else
  {
    TCCR0B = 0;  /*timer stoppen*/
    GIFR|=(1<<INTF0);  GIMSK |= (1<<INT0); /* jetzt wieder flanke zulassen fuers naechste byte*/
    if(IO_SIO_RX_GET) /* stop-bit = 1*/
    {
      sio_in_buffer[sio_in_buffer_ptr_wr++]=sio_rx_byte;
      sio_in_buffer_ptr_wr%=SIO_IN_BUFFER_SIZE;
    }
  }
}

/* Tx Timer*/
ISR(TIMER1_OVF_vect)
{
  if(sio_tx_state==0)   /*StartBit*/
  {
    if(sio_out_buffer_ptr_rd != sio_out_buffer_ptr_wr) /*es sind noch daten zu senden*/
    {
      IO_SIO_TX_EN;    /*Startbit*/
      sio_tx_byte=sio_out_buffer[sio_out_buffer_ptr_rd++];
      sio_out_buffer_ptr_rd%=SIO_OUT_BUFFER_SIZE;
      sio_tx_state++;
    }
    else  /* timer stoppen - nichts zu senden*/
    {
      TCCR1 &= ~(1<<CS10);
    }
  }
  else if(sio_tx_state<9)  /* 1..8 Datenbits */
  {
    if(sio_tx_byte & 0x01) IO_SIO_TX_DIS;
    else IO_SIO_TX_EN;
    sio_tx_byte>>=1;
    sio_tx_state++;
  }
  else if(sio_tx_state<10) /*Stop-Bit*/
  {
    IO_SIO_TX_DIS;
    sio_tx_state++;
  }
  else   /*Reload oder Stop Tx*/
  {
    sio_tx_state=0;
  }
}

ISR(INT0_vect)   /* StartBit - Fallende Flanke*/
{
  GIMSK &= ~(1<<INT0);   /*interupt ausschalten und Timer starten nach dem 10. Bit wird der Int wieder eingeschaltet */
  TCNT0 = 0;
  sio_rx_state=0;
  TCCR0B = (0<<FOC0A)|(0<<FOC0B)|(0<<WGM02)|(0<<CS02)|(0<<CS01)|(1<<CS00);    /* Timer starten - kein vorteiler */
}

Schon mal vielen Danke fuer nützliche Tips

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.