Hallo,

Probleem 2 (eerst is gelukt bedankt voor de hulp)

 
  
idata unsigned char waardenPoort0 [32]; 
main() 
{ //...... 

  while(1){ 
  verzendPoort0(ch); 
  
                ch++; 
     if (ch>'9') 
     ch='0'; 
  } 
} 

void verzendPoort0 (char ch) { 
   waardenPoort0[tellerInstoppenPoort0]=ch; 
   tellerInstoppenPoort0++; 
   tellerTotaalPoort0++; 
    
   if (tellerInstoppenPoort0 == 32){            tellerInstoppenPoort0 = 0; 
   } 
    
   TI_0=1; 
} 

void interruptPort0() interrupt 4 { 
  if (RI_0) {                
    //...    
    RI_0 = 0;    
  } 
    
  if (TI_0) {             
    TI_0=0; 

     if (tellerTotaalPoort0) {             
     SBUF0 = waardenPoort0 [tellerVerstuurPoort0]; 
     tellerVerstuurPoort0++;             
     tellerTotaalPoort0--; 

       if (tellerVerstuurPoort0 == 32){    
       tellerVerstuurPoort0 = 0; 
       } 
     } 
  } 
}  
 

Het werkt allemaal wel maar het probleem is dat we alle cijfers door elkaar verkrijgen en niet 0 1 2 3 4 5 6 7 8 9 0 1 ...
Dit komt omdat we telkens in de functie VerstuurPoort0 die interrupt setten. Terwijl dit enkel voor de eerste keer zou mogen.
Dus nu is de vraag. Hoe zorg je er voor dat "TI_0=1" enkel maar de eerste keer gedaan wordt en niet elke keer zodat je telkens die interrup routine oproept.
Van die tellers moet je je niet aantrekken dat is enkel om alles bij te houden
Tis veel, hopelijk kan je er aan uit.

alvast bedankt

In mijn UART lib houd ik een bit bij of het ding 'idle' is (nl. als er een TI IRQ voorbij komt en de output queue is leeg). Als bij een 'putchar' die flag aangeeft dat het ding idle is, kun je die IRQ laten triggeren. Uiteraard even je interrupts uit zetten voor de check op die flag om te voorkomen dat-ie onder je handen veranderd wordt. Je zou dan zo her en der kunnen blijven hangen tot het volgende character in de queue gemikt wordt...

Kijken of je queue leeg is buiten je ISR heeft niet zoveel zin; het ding kan nog staan te TXen (laatste char), er komt dus nog een IRQ voorbij, terwijl je queue al leeg is.

Overigens...
Je hebt je array in idata staan. Nou is idata al erg schaars op z'n beest. Om er nou nog 32 bytes vanaf te snoepen... Je gaat ergens klem lopen met je stack op die manier. Als je mazzel hebt, zeurt die compiler erover, maar daar zou ik niet op vertrouwen.

Je geeft bij die ISR geen register bank op. Doet de compiler dat zelf? Of frut die alles nou in XRAM? (da's niet handig voor de performance).

Dus als ik het goed begrijp moet ik kijken in mijn ISR ofdat de queue (=buffer) leeg is en als TI IRQ hoog is.
Als dit dan zo is zet ik een bit hoog. Dat zou dan zo iets moeten zijn


int idle;
void interruptPort0() interrupt 4 { 
//....
 if (TI_0) {             
   TI_0=0;
 
   if ( (buffer==0) && (TI IRQ)) {
     idle = 1;
   }
  }
}

Maar hoe zorg ik er dan voor dat 'TI_0 = 1' maar 1 keer geset wordt in de functie verzendPoort0() die ik oneindig keer op roep.

Of heb ik het verkeerd voor??

Volgens mij heb je het redelijk gesnapt. Maar niet helemaal ;).
Die check op TI binnen de binnenste if is zinloos. Die is echt wel 0 daar, want dat zet je vlak er boven. En je komt daar alleen als-ie op dat moment al geset was...

In je verzendPoort0() (brrrr.... Nederlandstalige function names...) kun je toch gewoon checken of het spul idle was? Of mis ik wat?

Overigens... Die 'idle' bit is binnen deze lib wel een global. Houdt er ook rekening mee dat die in de ISR gebruikt wordt, en dat je je compiler dat dus moet vertellen (kijk eens naar het gebruik van 'volatile' binnen C).

Sorry maar je moet toch kijken het TI was die geset werdt, het kan toch ook zijn dat RI geset werdt dus moet je dat tocht bekijken

En dan gewoon in verzendPoort0() nog:


if (idle == 1){
//....
}

k ga sebiet eens testen 

sorry typ foutje: tocht moest toch

Op 15 februari 2007 15:07:44 schreef Strootje:
Sorry maar je moet toch kijken het TI was die geset werdt, het kan toch ook zijn dat RI geset werdt dus moet je dat tocht bekijken

Yep. En dat doe je hier:

if (TI_0)

Vervolgens clear je die hier:

TI_0=0

En dan check je die hier in pseudo-code nog eens:

(buffer==0) && (TI IRQ))

Dat gaat 'm dus niet worden.

En dan gewoon in verzendPoort0() nog:


if (idle == 1){
//....
}

k ga sebiet eens testen

Zoiets ja...

der zit ene fout in je verzendroutine.

je moet daar wachten tot TI terug nul geworden is !

nu overschrijf je telkens de data in dat register.

zet data in SCON
zet TI=1
wacht op TI=0 ( pas dan is de data weg ! )

do opnieuw ...

Niet mee eens, f_e.

Het concept is dat de ISR de enige is die daadwerkelijk wat verstuurt, door wat in SBUF te frutten.

De eerst volgende keer dat dat stukje ISR een schop krijgt, is als TI voorbij komt. Dat impliceert dat het ding inderdaad 'weg' is.

Voor het eerste character wordt (wat lomp) een IRQ geforceerd, indien het ding 'idle' was (anders gaat eea. inderdaad fout).

Door een 'idle' flag te gebruiken, kun je die status bijhouden.

Tenslotte... SCON is als ik het mij goed herinner een bit-mapped register waar je wat zaken mbt. die UART kunt lezen / schrijven.

Overigens...
De methode die jij beschrijft werkt prima voor non-interrupt UART gebruik:
clear TI
frut data in SBUF
wacht tot TI gezet wordt
repeat.

Marco69, heb het deze net getest en het werkt.

Bedankt

Mooi zo.
En eh... google er ook eens wat op. Ik heb dit ook niet zelf verzonnen, maar gewoon bij elkaar gejat.

(en ja, het heeft zo zijn technische als organisatorische redenen waarom een hapklare library niet de oplossing was...)

Op 15 februari 2007 17:53:32 schreef Marco69:
Niet mee eens, f_e.

Overigens...
De methode die jij beschrijft werkt prima voor non-interrupt UART gebruik:
clear TI
frut data in SBUF
wacht tot TI gezet wordt
repeat.

inderdaad. verdikke waar zat ik met mijn gedachten. moest sbuf zijn. scon is controle register.

ik schrijf mijn input code meestal interrupt driven. mijn output code is niet interrupt driven.

en alst rap moet gaan pak ik een uart die een TX fifo heeft . while txfull =0 : duw data ...