Dubbel UART - hur utforma program? (AVR)

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Dubbel UART - hur utforma program? (AVR)

Inlägg av jesse »

Jag har hittills jobbat med enbart en UART-kanal med ATMega644.

Nu har jag ett nytt projekt med en ATMEGA644A som har två UART-kanaler (UART0 / UART1) och jag ska modifiera mina egna källfiler uart.c och uart.h för att kunna använda båda kanaler samtidigt. (I framtida projekt kanske jag vill använda tre eller fyra UART-kanaler).

Nu är frågan vad som är smartast/enklast/effektivast?

Göra dubbla uppsättningar funktioner av allting eller att försöka använda gemensamma funktioner men bara ändra en variabel 0 eller 1 beroende på vilken kanal jag vill använda?

Mina UART-rutiner bygger på interrupt och har buffert både för att ta emot och sända tecken. Jag har ett antal globala variabler som hör till:

Kod: Markera allt

volatile int8_t uartInputBuffer[UART_INPUT_BUFFER_LEN];
volatile int8_t uartInbufpos; //  läser in data hit
volatile int8_t uartInbufRead; // läser av data här/ 
volatile uint8_t uaflag;		// flaggar olika tillstånd i inbuffer
volatile uint8_t uartLinesWaiting; // antal väntande rader som ska läsas in.

volatile uint8_t uartSendBuffer[UART_SEND_BUFFER_LEN];
volatile uint16_t uartSendbufWrite=0; //  lägger in data här
volatile uint16_t uartSendbufRead=0; // skickar ut data här
volatile uint8_t ICR_flag_set = 0; // intern flagga
(Dessa måste vara 'volatile' eftersom de används i interruptrutinerna).

I C++ hade det varit självklart att man bara hade skapar två objekt - en för varje kanal, så hade det varit klart. Men i C är det ju inte lika smidigt. Jag kan ju t.ex. göra en struct av alla variabler ovan och sedan göra en array med två likadana struct-element i. Då skulle det kanske kunna se ut så här?:

Kod: Markera allt

struct uartstr {
    uint8_t uartSendBuffer[UART_SEND_BUFFER_LEN];
    uint16_t uartSendbufWrite=0; //  lägger in data här
    uint16_t uartSendbufRead=0; // skickar ut data här
    uint8_t ICR_flag_set = 0; // intern flagga
}

struct uartstr uart[1]; // skapar en array med två poster [0] och [1]
Så kan man sedan använda uart[0].uartSendBuffer[n] och uart[1].uartSendBuffer[n] men det känns intuitivt som om det kommer att öka på programomfånget rejält (hantera ytterligare ett index på alla variabler tar säkert många extra instruktioner för varje liten operation)...

Kanske man kunde göra någon egen variant av 'objektorientering' med hjälp av pekare... man sätter en 'startpekare' som pekar på vilken UART man vill arbeta med, sedan adderas bara konstanter till denna pekare för att hitta rätt variabler (eller blir det lika klumpigt som varianten med index?)

Utan någon form av 'indexering' av de två UART-kanalerna blir jag ju tvungen att göra dubbla funktioner för de två kanalerna , med exakt samma kod i, förutom att man skriver UART1 istället för UART0 etc. och att man döper dem till putChar0() respektive putChar1()...

Jag hoppas det går att förstå vad jag upplever är problemet här... :roll:
Hur skulle du ha gjort?
Användarvisningsbild
Icecap
Inlägg: 26652
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Dubbel UART - hur utforma program? (AVR)

Inlägg av Icecap »

Jag är inte helt säker på vad problemet består i, sedan har jag också programmerat ett antal år med 2-3 UART aktiva samtidig.

Jag har frångått att använda putchar() sedan länge, det är en rimlig enkel metod - fram till man har fler kanaler som du har upptäckt.

Istället skriver jag ut i minnet (sprintf()) och kallar en "Send på UART 0/1"-funktion som då antingen sänder direkt om det inte är upptagit på UART'en, annars läggs det i en sänd-buffer.

Första gången 2 aktiva UART kom upp använde jag faktisk putchar() och hade då en rutin som valde vilken UART data skulle sändas på, denna kallade jag då innan utskrift. Jag har även testat att ett visst tecken skulle "flippa switchen" till endera kanal men detta fungerar inte helt bra tycker jag, det är tydligare (för mig) att skriva ut till en buffer som jag sedan skickar till endera kanal.

Att börja med funktionspekare och skit kommer knappast att ge mindre program men däremot lär det bli mer besvärligt och otydligt.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Dubbel UART - hur utforma program? (AVR)

Inlägg av jesse »

Ursäkta, jag var otydlig: putChar() är alltså min egen funktion i uart.c som lägger ett tecken på sändbufferten (om den inte är tom - då skickas tecknet direkt). Jag använder inga standardfunktioner alls (standardfunktionen heter putchar() ). Så alla varaibler jag har ovan, med buffertar, buffertpekare och flaggor är det som ligger i bakgrunden och sköter om skickandet och mottagandet till och från buffrarna. Jag måste ju ha en uppsättning inbuffert+utbuffert+pekare för varje kanal.

Mitt dilemma är : ska jag göra separata funktioner för varje uart-kanal, eller finns det något smidigt sätt att välja kanal med ett index och sedan anropa samma funktioner och på så vis spara program-minne?

Nu varkar du ju köra den färdiga funktionerna, och de är väl faktiskt gjorda just så att de kan hantera olika kanaler med samma funktion?

Jag har två vägar att gå:

Kod: Markera allt

// (A)

uint8_t kanal; // global variabel - kanalväljare : 0 eller 1

main{
    kanal = 0;
    putChar('A');
    uartPrint(" Kanal noll"); // en av mina funktioner i uart.c
    kanal = 1;
    putChar('B');
    uartPrint(" Kanal ett");
}
eller

Kod: Markera allt

main{
    putChar0('A');
    uartPrint0(" Kanal noll"); // en av mina funktioner i uart.c
    putChar1('A');
    uartPrint1(" Kanal ett");
}
Användarvisningsbild
Icecap
Inlägg: 26652
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Dubbel UART - hur utforma program? (AVR)

Inlägg av Icecap »

"Nu verkar du ju köra de färdiga funktioner"
Och där har du så fel du kan! Jag använder INGEN sådana, helt enkelt för att det blir de problem du beskriver här.

Jag känner mycket väl till putchar() sedan mycket länga - och jag har alltså kommit fram till att det är fel väg att gå för mig!

Ska jag skriva till en kanal kan det bli så enkelt som:
sprintf(Buffer, "bla bla bla %s", Some_String); // Här formateras utskriften, kan bli ganska avancerat
Send2PC(Buffer);

Till andra kanalen blir det:
sprintf(Buffer, "bla bla bla %s", Some_String); // Här formateras utskriften, kan bli ganska avancerat
Send2GSM(Buffer);

osv.
Användarvisningsbild
AndLi
Inlägg: 18288
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Dubbel UART - hur utforma program? (AVR)

Inlägg av AndLi »

Jag skulle inte haft en global variabel, som styr var datan ska, känns som att det är uppgjort för att man ska försöka vara effektiv och glömmer sätta kanal vid.
Skulle lagt till det som argument i funktionsanropet, putchar(COM1,'a'); alt putBuf(COM1,buf,bufLen); typ och inte tänkt så mycket på utnyttjandet, det finns ju en atmega1284 när 644 tar slut...

Dubbla funktioner med nästan samma funktion känns fel, rättar man en bug i den ena ska man komma ihåg att göra samma sak nån annan stans, förutom att de tar dubbla utrymmet..
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Dubbel UART - hur utforma program? (AVR)

Inlägg av jesse »

det finns ju en atmega1284 när 644 tar slut...
kanske inte om man redan har 20 exemplar fastlödda...

>Dubbla funktioner med nästan samma funktion känns fel, rättar man en bug i den ena ska man komma ihåg att göra samma sak nån annan stans, förutom att de tar dubbla utrymmet..

Precis så tänker jag också, och fyrdubbla utrymmet om det ska hanteras fyra UART-kanaler. Men då uppstår ju problemet att samma funktioner måste kunna hantera flera olika kanaler, flera uppsättning buffrar etc.... (nu menar jag inte formatering av text, int to ascii etc. vilket givetvis görs först. Jag menar "kärnfunktionerna": ISR-interrupten som tar hand om inkommande tecken eller skickar nytt tecken när förra var klart, och de rutiner som läser ur eller fyller på sänd- och mottagarbuffrarna.)
Jonas L
Inlägg: 432
Blev medlem: 14 juli 2009, 14:28:41
Ort: Karlshamn

Re: Dubbel UART - hur utforma program? (AVR)

Inlägg av Jonas L »

En rutin som hanterar flera är bättre om man inte har extremt ont om tid, och en array med structar är väl metoden jag skulle ha använt om jag inte körde C++ (vilket jag skulle gjort i de flesta fall).

Nu kanske jag svär i kyrkan, men om du verkligen vill göra två nästan identiska funktioner ska du kanske titta på preprocessorn och få den att generera två lika kodavsnitt, med UART0 ersatt av UART1 i den ena.
Användarvisningsbild
Icecap
Inlägg: 26652
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Dubbel UART - hur utforma program? (AVR)

Inlägg av Icecap »

På det sätt jag beskriver är det enda som ska dubblas den bit som tar från buffern till TX på hhv. UART1 och UART2.

Sedan kan man kapa av en hel del vid att t.ex. inte använda printf() alls eller hitta en minnessnål version, det ville ge ganska mycket mer plats.
Skriv svar