Go Down

Topic: Problem mit mehreren UARTs (Mega <> ATtiny) (Read 5065 times) previous topic - next topic

Doc_Arduino

Hallo,

ich erleide herbe Rückschläge wegen den UARTs.
Beim Aufbau eines generellen Kommunikationstests traf ich auf Probleme.
Manchmal gings und manchmal nicht, je nach Codekonstellation. Und ich wußte nicht genau warum, der Code scheint i.O.

Momentan stelle ich fest, dass es funktioniert, wenn ich einzeln

Mega-UART1 > ... > ATtiny841-UART1 sende und ATtiny841-UART0 > ... > Mega-UART2 sende und an UART0 im Terminal anzeigen lasse.

oder

Mega-UART2 > ... > ATtiny841-UART0 sende und ATtiny841-UART1 > ... > Mega-UART1 sende und an UART0 im Terminal anzeigen lasse.

lasse ich beides im Sekundentakt abwechselnd ablaufen, kommt teilweise verstümmelter Code.
Das seltsame dabei ist, die zugehörige Antwort kommt genau eine Sekunde später und nicht sofort.
Ich weiß nicht warum. Irgendwas kommt sich ins Gehege zwischen den UARTs.

Mache ich das Paket komplett, dann sendet zwar der Mega fleißig, aber der ATtiny sendet nichts mehr zurück.
Ich sehe das auch mittels Logik Analyzer und serial Decoder.

Ich bin ratlos. Es muss doch möglich sein, wechselweise auf beiden Mega UARTs etwas zusenden und im Gegenüber
auf jeweils der anderen UART wieder auszugeben und im Mega dann auch auf der jeweils anderen UART einzulesen und anzeigen.
Die Nachricht sollte doch ohne nennenswerte Verzögerung die Runde machen.

Wenn ich alles einzeln teste funktioniert der Befehlsvergleich im ATtiny und die passende Antwort kommt umgehend, sehe ich im L.A.

Code: [Select]
/* Arduino Mega2560 */
const byte SERIAL_BUFFER_SIZE = 20;     
char serialBuffer_1[SERIAL_BUFFER_SIZE];
char serialBuffer_2[SERIAL_BUFFER_SIZE];

unsigned long last_millis;
bool toggle = true;

void setup()  {
  Serial.begin(250000);
  Serial1.begin(250000);
  Serial2.begin(250000);
}

 
void loop() { 

  handle_Serial_2_to_Serial_0();

  handle_Serial_1_to_Serial_0();

 
  if (millis() - last_millis > 1000) {
    last_millis = millis();

    if (toggle == true) {
      Serial1.println("REQUEST");
    }
    if (toggle == false) { 
      Serial2.println("GOOD");
    }
    toggle = !toggle;
  } 
 
} // loop Ende


// ****** Funktionen ******* //
bool read_Serial_1()
{
  static byte index;

  if (Serial1.available() > 0)  {   
    char c = Serial1.read();
    if (c >= 32 && (index < SERIAL_BUFFER_SIZE - 1))
      {
        serialBuffer_1[index++] = c;
      }
      else if ( (c == '\r' || c == '\n') && index > 0) {
        serialBuffer_1[index] = '\0';
        index = 0;
        return true;
      }
  }
  return false;
}


bool read_Serial_2()
{
  static byte index;

  if (Serial2.available() > 0)  {   
    char c = Serial2.read();
    if (c >= 32 && (index < SERIAL_BUFFER_SIZE - 1))
      {
        serialBuffer_2[index++] = c;
      }
      else if ( (c == '\r' || c == '\n') && index > 0) {
        serialBuffer_2[index] = '\0';
        index = 0;
        return true;
      }
  }
  return false;
}


void handle_Serial_1_to_Serial_0 ()
{
  if( read_Serial_1() == true)  {
    Serial.println(serialBuffer_1);
    memset(serialBuffer_1,'\0',sizeof(serialBuffer_1));  // seriellen Buffer löschen
  }
}


void handle_Serial_2_to_Serial_0 ()
{
  if( read_Serial_2() == true)  {
    Serial.println(serialBuffer_2);
    memset(serialBuffer_2,'\0',sizeof(serialBuffer_2));  // seriellen Buffer löschen
  }
}
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

#1
Feb 21, 2017, 07:43 pm Last Edit: Feb 21, 2017, 07:44 pm by Doc_Arduino
Code: [Select]
/* ATtiny841 */

#define F_CPU 8000000UL  // Systemtakt in Hz

#include <avr/io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <util/atomic.h>    // für cli() und sei() mit SREG Sicherung

/*
  UART Berechnungen des Wertes für das Baudratenregister aus Taktrate und gewünschter Baudrate
*/
#define BAUD 250000UL    // gewünschte Baudrate
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // sauber runden
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // reale Baudrate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
#if ((BAUD_ERROR<995) || (BAUD_ERROR>1005))
  #error Systematischer Fehler der Baudrate greosser 0,5% und damit zu hoch!
#endif

volatile uint32_t millis_count; // ISR Timer 0 Variable
volatile uint32_t second_count; // ISR Timer 0 Variable
uint32_t last_millis;
uint32_t last_second;

const uint8_t SERIAL_BUFFER_SIZE = 20;
char Buffer_Serial_0[SERIAL_BUFFER_SIZE];
char Buffer_Serial_1[SERIAL_BUFFER_SIZE];

/* *** Funktion Deklarationen *** */
/* *** UART 0 *** */
void UART0_Init(); // Pin 8,9, TxD1/RxD1
void UART0_sendChar(unsigned char data);
void UART0_sendString (const char *s);
void UART0_send_uint32(uint32_t zahl);
unsigned char UART0_empfangen();
/* *** UART 1 *** */
void UART1_Init(); // Pin 8,9, TxD1/RxD1
void UART1_sendChar(unsigned char data);
void UART1_sendString (const char *s);
void UART1_send_uint32(uint32_t zahl);
unsigned char UART1_empfangen();
/* *** UARTs read and send *** */
bool read_Serial_0();
bool read_Serial_1();
void handle_Serial_0_to_Serial_1();
void handle_Serial_1_to_Serial_0();

uint32_t millis();
uint32_t second();
ISR(TIMER0_COMPA_vect);
void set_Timer0(); // Timer 0, millis, seconds


int main(void)
{  
// µC Takt langsam justieren zum testen

OSCCAL0 = 40; _delay_ms(100);
OSCCAL0 = 39; _delay_ms(100);
OSCCAL0 = 38; _delay_ms(100);
OSCCAL0 = 37; _delay_ms(100);

UART0_Init();
UART1_Init();
set_Timer0(); // millis, seconds
    
    while (1)
    {  
handle_Serial_0_to_Serial_1();

handle_Serial_1_to_Serial_0();
}
}


/* *** Funktionen *** */

void UART0_Init()
{
UBRR0H = UBRR_VAL >> 8; // Set baud rate
UBRR0L = UBRR_VAL & 0xFF;
UCSR0B = (1<<RXEN0)|(1<<TXEN0); // Enable receiver and transmitter
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00); // Set frame format: 8data, 1stop bit
}


void UART1_Init()
{
UBRR1H = UBRR_VAL >> 8; // Set baud rate
UBRR1L = UBRR_VAL & 0xFF;
UCSR1B = (1<<RXEN1)|(1<<TXEN1); // Enable receiver and transmitter
UCSR1C = (1<<UCSZ11)|(1<<UCSZ10); // Set frame format: 8data, 1stop bit
}


void UART0_sendChar( unsigned char data )
{
while ( !( UCSR0A & (1<<UDRE0)) ) // wait for empty transmit buffer
;
UDR0 = data; // Put data into buffer, sends the data
}


void UART1_sendChar( unsigned char data )
{
while ( !( UCSR1A & (1<<UDRE1)) ) // wait for empty transmit buffer
;
UDR1 = data; // Put data into buffer, sends the data
}


void UART0_sendString (const char *string)
{ // Vergleich auf ASCII Zeichen '\0' (NUL)
while (*string != 0x00) { // "String-Endezeichen" (Null-Terminator)
UART0_sendChar(*string); // vorderstes Zeichen senden
string++;
}
}


void UART1_sendString (const char *string)
{ // Vergleich auf ASCII Zeichen '\0' (NUL)
while (*string != 0x00) { // "String-Endezeichen" (Null-Terminator)
UART1_sendChar(*string); // vorderstes Zeichen senden
string++;
}
}


void UART0_send_uint32(uint32_t zahl)
{ // convert eine long Zahl zu einem String
char string[11];
ultoa(zahl, string, 10); // convert unsigned long to string, radix=10
UART0_sendString(string);
}


void UART1_send_uint32(uint32_t zahl)
{ // convert eine long Zahl zu einem String
char string[11];
ultoa(zahl, string, 10); // convert unsigned long to string, radix=10
UART1_sendString(string);
}


unsigned char UART0_empfangen()
{
while ( !(UCSR0A & (1<<RXC0)) ) // Wait for data to be received
;
return UDR0; // Get and return received data from buffer
}


unsigned char UART1_empfangen()
{
while ( !(UCSR1A & (1<<RXC1)) ) // Wait for data to be received
;
return UDR1; // Get and return received data from buffer
}


void set_Timer0 () // millis, seconds
{
cli(); // Interupts ausschalten
TCNT0 = 0; // Register Reset
TCCR0A = 0;
TCCR0B = 0;
TIMSK0 = 0;
TCCR0A = (1 << WGM01); // CTC Modus
OCR0A = 124; // TOP, (F_CPU/PRESCALER)/1000-1
TIMSK0 |= (1 << OCIE0A); // Interupts einschalten
TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64, Timer starten
sei();
}


bool read_Serial_0()
{
static uint8_t index;

char c = UART0_empfangen();
if (c >= 32 && (index < SERIAL_BUFFER_SIZE - 1))
{
Buffer_Serial_0[index++] = c;
}
else if ( (c == '\r' || c == '\n') && index > 0) {
Buffer_Serial_0[index] = '\0';
index = 0;
return true;
}
return false;
}


bool read_Serial_1()
{
static uint8_t index;

char c = UART1_empfangen();
if (c >= 32 && (index < SERIAL_BUFFER_SIZE - 1))
{
Buffer_Serial_1[index++] = c;
}
else if ( (c == '\r' || c == '\n') && index > 0) {
Buffer_Serial_1[index] = '\0';
index = 0;
return true;
}
return false;
}


void handle_Serial_0_to_Serial_1 ()
{
if( read_Serial_0() == true)  {

if (strncmp(Buffer_Serial_0, "REQUEST", 7) == 0)  {
UART1_sendString("REQUEST UART_0-1"); UART1_sendChar('\n');
UART1_send_uint32( millis() ); UART1_sendChar('\n');
}
else if (strncmp(Buffer_Serial_0, "GOOD", 4) == 0)  {
UART1_sendString("GOOD UART_0-1"); UART1_sendChar('\n');
UART1_send_uint32( millis() ); UART1_sendChar('\n');
}
else {
UART1_sendString("BACK UART1"); UART1_sendChar('\n');
UART1_sendString(Buffer_Serial_0); UART1_sendChar('\n');
UART1_send_uint32( millis() ); UART1_sendChar('\n');
}
memset(Buffer_Serial_0,'\0',sizeof(Buffer_Serial_0));  // seriellen Buffer löschen
}
}


void handle_Serial_1_to_Serial_0 ()
{
if( read_Serial_1() == true)  {

if (strncmp(Buffer_Serial_1, "REQUEST", 7) == 0)  {
UART0_sendString("REQUEST UART_1-0"); UART0_sendChar('\n');
UART0_send_uint32( second() ); UART0_sendChar('\n');
}
else if (strncmp(Buffer_Serial_1, "GOOD", 4) == 0)  {
UART0_sendString("GOOD UART_1-0"); UART0_sendChar('\n');
UART0_send_uint32( second() ); UART0_sendChar('\n');
}
else {
UART0_sendString("BACK UART0"); UART0_sendChar('\n');
UART0_sendString(Buffer_Serial_1); UART0_sendChar('\n');
UART0_send_uint32( second() ); UART0_sendChar('\n');
}
memset(Buffer_Serial_1,'\0',sizeof(Buffer_Serial_1));  // seriellen Buffer löschen
}
}


uint32_t millis()
{
uint32_t value = 0;
ATOMIC_BLOCK (ATOMIC_RESTORESTATE)
{
value = millis_count;
}
return value;
}


uint32_t second()
{
uint32_t value = 0;
ATOMIC_BLOCK (ATOMIC_RESTORESTATE)
{
value = second_count;
}
return value;
}


ISR(TIMER0_COMPA_vect)
{
static uint32_t local_millis = 0;

millis_count++; // Zähler für Millisekunden
local_millis++;

if (local_millis > 999) {
second_count++; // Zähler für Sekunden
local_millis = 0;
}
}



Mega UART1 ist über kreuz mit ATtiny UART1 verbunden.
Mega UART2 ist über kreuz mit ATtiny UART0 verbunden.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

#2
Feb 21, 2017, 08:17 pm Last Edit: Feb 21, 2017, 08:18 pm by Doc_Arduino
Hallo,

noch zwei Bilder vom Mitschnitt.
im ersten zoom in, da sieht man das vom "REQUEST" etwas fehlt. Genau wie im Terminal sichtbar.


Im anderen sieht man die Verzögerung.
Gesendet wird auf dem 2. und 4. Kanal vom Mega aus gesehen.
Deshalb müsste auf dem 3. Kanal umgehend eine Antwort kommen wenn auf dem 2. was gesendet wurde.
Genauso wenn auf dem 4. gesendet wird müßte auf dem 1. umgehen die umgeleitete Antwort kommen.
Sieht alles seltsam aus zeitlich gesehen.

Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Eisebaer

hi,

genau eine sekunde ist schon seltsam, das ist das standard-timeout bei vielen funktionen der serial-library. sehe zwar jetzt  keine in Deinem sketch, aber setz' es doch mal in beiden sketches am anfang für alle benutzten schnittstellen mit settimeout auf 500,
ob sich was ändert...

gruß stefan

Doc_Arduino

#4
Feb 22, 2017, 11:49 am Last Edit: Feb 22, 2017, 11:50 am by Doc_Arduino
Hallo,

du meinst das hier https://www.arduino.cc/en/Serial/setTimeout
war ein Versuch wert, bringt leider keine Abhilfe.
Die zeitliche Verzögerung der Übertragung geht genau mit der eingestellten millis "toggle" Zeit mit.
Was eigentlich nicht sein darf, weil ja ohne Wartezeit jederzeit gelesen werden kann in loop.
Habs nochmal versucht besser darzustellen.


Wenn ich im Mega Sketch eine serielle in toggle auskommentiere, egal welche, dann geht nichts mehr, es kommt nichts zurück.

Irgendwie muss ein Bufferüberlauf stattfinden oder ein Abschluss kommt nicht an oder sowas, habe ich das Gefühl.
Weiß nur nicht wo ich ansetzen soll. Habe den Code schon tausendmal durchgeschaut.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Doc_Arduino

#5
Feb 22, 2017, 01:15 pm Last Edit: Feb 22, 2017, 01:16 pm by Doc_Arduino
Hallo,

wenn ich es wieder einzeln teste, zum Bsp. der Mega sendet nur auf Uart1 und der ATtiny liest nur von Uart1 und sendet damit nur auf Uart0 zurück (kommt im Mega auf Uart2 an), dann klappt alles. Die Antwort erfolgt umgehend sobald das Endezeichen '\r' erkannt wird. Genauso wie ich mir das vorstelle.


Meine Vermutung liegt nachwievor das sich die Buffer gegenseitig ins Gehege kommen. Nur wo und warum das weiß ich nicht.

Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

#6
Feb 22, 2017, 02:23 pm Last Edit: Feb 22, 2017, 02:37 pm by combie
Quote
Meine Vermutung liegt nachwievor das sich die Buffer gegenseitig ins Gehege kommen. Nur wo und warum das weiß ich nicht.
Ich habe mir das mal angesehen.....

Der Mega Code scheint ja zu funktionieren.
Genau habe ich ihn nicht untersucht.....

Beim Tiny Code habe ich ein Problem gefunden.

Deine "Empfangen" Routinen sind blockierend.
Wenn also auf USART0 empfangen werden soll, aber nix kommt, dann geht alles auf USART1 verloren.
Bis auf 1 Byte.

Andersrum natürlich genau so.

Und auch beim senden, wird jeglicher Empfang blockiert.

Kann es das schon sein, was dir einen Streich spielt?

--------
Auch das Timing scheint mir eng zu sein...
Innerhalb von 40µs muss ein Zeichen aus der USART abgeholt worden sein, sonst gehen Bytes/Zeichen verlustig.
Es ist offensichtlich, dass uns die Umstände alleine nicht glücklich oder unglücklich machen.
Es ist die Art unserer Reaktion darauf, die unsere Gefühle bestimmt.

Doc_Arduino

Hallo,

Danke das du dir die Zeit nimmst.

Der Code ist aus den Datenblatt Beispielen. Ich hatte das so verstanden das die whiles immer nur unbedeutend kurz blockieren bis die Übertragungs selbst fertig ist. Wenn nichts da ist, wird es übersprungen.
Du meinst, sobald zum Bsp. UART0_empfangen() aufgerufen wird blockiert der gesamte Code bis wirklich irgendwas reinkommt?

Beim senden UART0_sendChar bin ich mir allerdings sicher das er nicht blockiert. Die while soll doch warten und prüfen ob der UART Buffer leer ist vor Neubefüllung. Da er ja meistens leer sein sollte, dürfte die while doch im Grunde genommen nicht wirklich blockieren.

Was du mit den 40µs meinst verstehe ich nicht. Was muss von wem innerhalb 40µs abgeholt werden?
Die Daten liegen doch solange im Buffer bis sie jemand abholt und bleiben solange unverfälscht bis sie von neuen reinkommenden Daten überschrieben werden. So hatte ich das jedenfalls verstanden.

Allerdings, wenn der Empfang den gesamten ATtiny Code blockiert,dann kann auch kein Buffer abgeholt werden und dann kommt schon der nächste Datenstrom rein. Das könnte die Verstümmelung erklären.

Also heißt das ich muss auf Interrupt Steuerung umbauen und darf keine Flags auswerten?
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

#8
Feb 22, 2017, 04:11 pm Last Edit: Feb 22, 2017, 04:25 pm by combie
Quote
Beim senden UART0_sendChar bin ich mir allerdings sicher das er nicht blockiert.
Doch, tut es.
Zumindest bis zu 40µs.
So lange, bis das vorherige Zeichen im Schieberegister gelandet ist.
(zu den 40µs gleich mehr)

Aber du verwendest ja gar nicht: UART0_sendChar()
Sondern: UART0_sendString().
Und das blockiert bis der ganze String draußen ist(-2 Zeichen).
Bei 10 zu sendenden Zeichen, können auf den beiden seriellen Eingängen zusammen 14 Byte ins Nirvana wandern.
Auch, wenn es bei deiner Anwendung nicht ins Gewicht fällt, solltest du das doch im Hinterkopf behalten.
Denke ich mal....

Quote
Du meinst, sobald zum Bsp. UART0_empfangen() aufgerufen wird blockiert der gesamte Code bis wirklich irgendwas reinkommt?
So sehe ich das in deinem Code.


Quote
Was du mit den 40µs meinst verstehe ich nicht.
1 Byte wird zu 10Bit (8Daten+1start+1stopp)
Bei 250000Baud macht das also 25000Byte Pro Sekunde

1/25000 = 0.00004
40µs Pro Byte
Quote
Was muss von wem innerhalb 40µs abgeholt werden?
Für das "Wem" bist du verantwortlich.

Das "Was":
Da ein Byte selten alleine kommt, muss das jeweils fertig angekommene innerhalb von 40µs abgeholt werden, sonst verschwinden Daten im Nirvana.



Quote
Die Daten liegen doch solange im Buffer bis sie jemand abholt und bleiben solange unverfälscht bis sie von neuen reinkommenden Daten überschrieben werden. So hatte ich das jedenfalls verstanden.
Welcher Buffer?
Der USART Buffer?
Da passt 1 Byte rein.
Darum musst du ja bei 250000Baud schon etwas Gas geben, den rechtzeitig zu leeren.


Quote
Also heißt das ich muss auf Interrupt Steuerung umbauen und darf keine Flags auswerten?
Nunja...
Entweder Interrupts, oder ein rasend schnelles Polling, würde ich mal sagen....
Es ist offensichtlich, dass uns die Umstände alleine nicht glücklich oder unglücklich machen.
Es ist die Art unserer Reaktion darauf, die unsere Gefühle bestimmt.

Doc_Arduino

#9
Feb 22, 2017, 04:30 pm Last Edit: Feb 22, 2017, 04:30 pm by Doc_Arduino
Hallo,

jetzt wird mir einiges klarer.
Das mit dem Buffer ist schnell geklärt. Ich hatte auch beim ATtiny fälschlicherweise die 63Byte Ringbuffer im Hinterkopf wie wir sie beim Arduino haben. Deshalb dachte ich man hätte auch hier alle Zeit der Welt. Aber ist ja nur intern unsichtbar zwischengeschoben.

Das mit dem senden und empfangen meine ich nun auch verstanden zu haben, das dort das Problem liegt, wie du erkannt hast. Weil blockieren darf auch später nichts, auch wenn ich nur eine UART am Ende nutzen werde. Das wäre mir später mörderisch auf die Füße gefallen. Der Code wächst ja noch.

Großes Danke.

Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

combie

Fein!

Hört sich an, als wärst du jetzt auf dem "wahren Pfad".
 :o  :o  :o

Und schön dass ich dir helfen konnte.
Es ist offensichtlich, dass uns die Umstände alleine nicht glücklich oder unglücklich machen.
Es ist die Art unserer Reaktion darauf, die unsere Gefühle bestimmt.

michael_x

Wenn ich recht informiert bin, wird HardwareSerial auf einem Uno jeweils per Interrupt geweckt, wenn der UART sein Sendebyte frei hat und wenn im Empfangsbyte etwas ist, was in den "großen" 64 byte Empfangspuffer geschoben werden kann.

So werden da auch Reaktionszeiten unter 40 µs (250000 Baud) möglich.
Das fehlt bei deiner eigenen Implementation noch.

Quote
Nunja...
Entweder Interrupts, oder ein rasend schnelles Polling, würde ich mal sagen....
Ja nun, wer wollte da widersprechen ;)

Ich frage mich:
- Gibt es kein ordentliches HardwareSerial für attiny841, wo dieses Standard-Problem schon gelöst ist?
- Wer braucht schon 250000 Bd ?

Doc_Arduino

#12
Feb 22, 2017, 06:47 pm Last Edit: Feb 22, 2017, 07:22 pm by Doc_Arduino
Hallo,

250kBaud brauche ich.  :)  

Hardware Serial kann der ATtiny schon. Da nun alles darauf hinausläuft das ich Interrupts verwenden muss, stand die Frage selber umbauen oder was fertiges suchen. Dabei stieß ich auf die uart Lib von Peter Fleury. Die Headerdatei habe ich um den ATtiny841 ergänzt und wollte nun ganz einfach anfangen. Ich scheitere aber schon an der Benutzung der Lib. Im Grunde stehen da nur Macros und Funktionen drin. Kein Konstruktor oder dergleichen. Ich weiß trotz der kompletten Beschreibung nicht wie ich eine UART nun wirklich initialisieren soll und die Baudrate einstellen. Einfachste Dinge und ich raff es nicht. Auch mit Google Hilfe kompilieren die gefundenen Schnipsel nicht.

http://homepage.hispeed.ch/peterfleury/doxygen/avr-gcc-libraries/group__pfleury__uart.html

Code: [Select]
#include <avr/io.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <uart.h>

#define F_CPU 8000000UL  // Systemtakt in Hz

#define UART_BAUD_RATE 9600  

int main(void)
{  
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

    while (1)
    {
    }
}




Quote
Atmel Studio meldet
Fehler        undefined reference to `uart_init(unsigned int)'  
Fehler        recipe for target 'ATtiny841_uart-Lib_001.elf' failed    
Fehler        ld returned 1 exit status    
Die Macros erschlagen mich ehrlich gesagt. Kennt die Lib zufällig jemand von euch?

Edit:
Selbst sowas einfaches wie die RX-Buffergröße zu definieren klappt auch nicht. Default sind 32.
Code: [Select]

#include <avr/io.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <uart.h>

#define F_CPU 8000000UL  // Systemtakt in Hz

#define UART_RX_BUFFER_SIZE 20

int main(void)
{  

    while (1)
    {
    }
}


Atmel Studio meldet:  
Warnung        "UART_RX_BUFFER_SIZE" redefined    
Nachricht        this is the location of the previous definition    

in der uart.h steht das drin
Code: [Select]
#ifndef UART_RX_BUFFER_SIZE
#define UART_RX_BUFFER_SIZE 32
#endif


Momentan verstehe ich mal wieder die Welt nicht.
Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

michael_x

Quote
Hardware Serial kann der ATtiny schon
Wenn er mit 8 oder 16 MHz läuft und Interrupts verwendet, sollte dessen HardwareSerial  auch 250000 Bd können.

Was ist schlecht an diesem HardwareSerial?
Warum nimmst du es nicht?
Muss ich den ganzen Thread nochmal aufmerksam lesen, um das rauszufinden?
Hast schon seit Anfang auf der attiny Seite mit UART Registern rumgefummelt...

Doc_Arduino

Hallo,

mal ganz sachte. Ich habe nie gesagt das Hardware Serial schlecht ist. Ich nutze sie ja auch nur eben ohne Interrupt derzeit.
Ich habe mich mit den ATtiny UARTs beschäftigt, das Datenblatt herangezogen und etwas Internetrecherche.
Ich hatte nicht weiter nachgedacht und Atmel vertraut das die Bsp. perfekt sind.
Nun wie festgestellt, muss ich Interrupts verwenden. Soweit ist alles klar.
An dem Punkt nun dachte ich, entweder schreibste alles nochmal um oder nimmst doch noch eine fremde Lib.
So wie ich dich nun verstehe soll ich meine Funktionen selbst auf Interrupt Nutzung umschreiben.
Eigentlich wollte ich die Lib nutzen.

Tschau
Doc Arduino '\0'

Messschieber auslesen: http://forum.arduino.cc/index.php?topic=273445
EA-DOGM Display - Demos: http://forum.arduino.cc/index.php?topic=378279

Go Up