Kan iemand aangeven wat de maximale overbrugbare afstanden zijn tussen een CPU en een MAX232 bij verschillende baudrate's ?

Korte beschrijving:

Ik heb hier een tester liggen waarmee 96 I/O kanalen worden getest op een eindproduct voordat het wordt uitgeleverd aan onze klant. De tester stuurt een bitpatroon naar de DUT (Device Under Test) en op een schakelflankje wordt deze data door geklokt naar een uitgang.

De boel is opgebouwd rondom een AT89C5131 kan solo draaien met een wat beperkte output op een 4 x 20 LCD schempje maar als de problemen wat groter worden kan een meer uitgebreide beschrijving van de problemen op een terminal zichtbaar gemaakt worden.

Echter de communicatie tussen de PC en mijn print gaat boven de 4800 baud het bos in. en voor de hoeveelheid tekst die geproduceerd wordt zou ik graag naar 9600 of zelfs 19200 baud willen.

Aanvankelijk werd het kristal als boosdoener aangewezen meting met een frequentie meter gaf 12001100 Mhz aan (de processor rekent uit aan de hand van de opgegeven kristal frequentie hoe hij aan de juiste baudrate kan komen) maar uit wat proefjes blijkt dat er behoorlijk veel tolerantie mag zitten in het kristal voordat 4800Baud ook niet meer werkt (opgegeven waarden tussen de 11,9 Mhz en de 12.1 Mhz werkte 4800 baud nog prima).

Het enigste dat overblijft (voor mij dan) is dat de afstand tussen de CPU en MAX232 te groot is geworden, nagemeten blijkt dat iets meer te zijn dan 20cm (bedenk dat de hele print 40 x 26 cm is en in totaal ca 350 componenten bevat).

Zijn er wat vuistregels voor spoorlengte versus baudrate ? en valt er nog wat te ritselen om dit probleem te verkleinen ? (PI filtertje ?)

Sander.

IK kan niet duidelijk uit je omschrijving afleiden of je al geprobeerd hebt om de baudrate in de Atmel aan te passen...

Ik denk dat je met een 12Mhz kristal niet zoveel meer keus hebt dan 4800Baud (en 28800 met een beetje geluk). 11.0592 is een iets betere keus kun je tot 115K. Timer 2 gebruiken als baudrate generator.

http://www.keil.com/products/c51/baudrate.asp

Bij 4800 baud werkt het allemaal nog prima zij het dat het vullen van een terminal venster (in de fout afhandeling) te lang duurt.

Bij 9600 baud krijg ik in het allerbeste geval alleen wat rommel op het scherm.

Dat zeg ik ;-). Kijk voor de aardigheid eens in de baudrate calculator. 9600 is ook niet mogelijk met Timer 1 en 12Mhz.

[Bericht gewijzigd door bprosman op (25%)]

inderdaad : kristal aanpassen !

Als vuistregel kun je nemen, dat een afwijking van de gewenste baudrate met meer als 3% leidt tot fouten in de data-overdracht.

Okee het kwartje is gevallen 12Mhz ligt te ongelukkig, De timer dan zo instellen dat het binnen de toleranties ligt lukt dan gewoon niet meer.

Maar nu wordt kip en het ei, met 11.0592 loopt de USB niet meer.

Terug naar 12Mhz en overschakelen naar Timer2.

[Bericht gewijzigd door Silkroad op (17%)]

Okee,

Kristal is nu weer 12Mhz --> USB programmeer poort werkt weer.

Timer2 aangeslingerd met Rcap2h = &HFF en Rcap2l = &HD9 voila nu loopt het seriele kanaal op 9600 Baud.

De AT89C5131 processor kan slechts uit de voeten met een beperkte range kristallen 3, 6, 8, 12, 16, 18, 20, 24, 32 en 40 Mhz. Met tussen liggende waarden kan de PLL van de USB die op 48Mhz draait niet meer locken ofwel de PC snapt niets meer van de USB poort.

Volgens het lijstje van Keil houdt het met een 12Mhz het met Timer1 inderdaad bij 4800 Baud gewoon op. Met Timer2 is 9600 en zelfs 14400 en 28800 mogelijk maar dat zit niet in de standaard range. 19200 valt er helaas buiten.

Ik kan nog wel eens proberen wat er gebeurt met een 16Mhz kristal. Dan zit er wel 19200 tussen en zelfs 38400 ook hier alleen met Timer2. Ik ben wel een beetje benieuwd wat het gaat doen met het LCD.

Heren (en mogelijkerwijs Dames) bedankt.
Soms zit je gewoon blind te staren op iets heel simpels.

Ik ben wel een beetje benieuwd wat het gaat doen met het LCD.

Andere timer gebruiken voor een nauwkeurige(re) delay ?. Dan kun je in je code je kristal als constante gebruiken.

Als die bitrate echt van belang is, zou je een externe UART kunnen overwegen. Er zijn er die prima parallel aan te sturen zijn (mits je genoeg poten hebt) of die dat via SPI doen.

Je probleem zit inderdaad in het Xtal. Je zou nog eens kunnen kijken of je aan die PC applicatie kunt trekken om daar een andere divisor te gebruiken. Dat zal echter wel snel ophouden.

Als smerige last-resort zou je een AVR met dual UART kunnen nemen en daar een soort van interspeeder mee kunnen klussen zodat je bitrates aan beide kanten redelijk kloppen. Is wel smerig, maar ja...

Overigens is het ook nogal PC-UART afhankelijk of iets 'werkt' of niet. Ik heb laatst bij wijze van experiment 460kbit/sec door een max202 heen getrokken. Redelijk (ahum) buiten spec (die eindigt bij 115k2), de ene UART snapt het zonder problemen, de andere maakt er geen chocolade van.
Met 'net niet' bitrates heb ik soortgelijke ervaringen. Ofwel: als het 'altijd' moet werken (en doorgaans is dat zo), zul je het netjes op moeten lossen. Ik houd zelf doorgaans en foutmarge van 1% als max. aan.

Als je die μC sneller clocked, wordt je divisor minder kritisch (1 rnaast is wat tijd betreft gewoon minder). Wellicht kun je daar nog wat mee spelen: op 24MHz kun je je fout al ongeveer halveren tov. 12MHz.

Nee de baudrate is niet zo superbelangrijk, alleen een verhaaltje als tekst moet wel in een fatsoenlijk tijds bestek van A naar B kunnen worden getransporteerd.

Dit project is nu in z'n laatste stadium, nog wat kleine bits en byte's opruimen en op naar het volgende project. Het is wel zo dat de volgende mischien wel veel kritischer is qua datarate, het zit er wel in dat de CPU moet gaan babbelen van het te testen product zelf, dan zit ik vast aan de snelheid van dat (eind)product.

Vandaag heb ik een bosje kristallen besteld van 24MHz die morgen binnen zullen komen, in het magazijn liggen nog 16MHz exemplaren. Ik wil het eerst proberen met 24MHz en kijken wat dat oplevert. Als het LCD met 24Mhz nog werkt werkt het met de rest ook. (misschien dat ik het ook nog even probeer met 40Mhz, dan zitten alle baudrate's erin).

Met 24Mhz kan ik kiezen tussen 57600, 19200, 9600, 4800 en lager. Met 16Mhz loopt het af vanaf 38400, 19200 etc. In de praktijk zie ik 19200 het meest.

Op de eindsnelheid van de totale applicatie zal het niet zo heel spannend veel invloed hebben of ik nu voor een 16Mhz of een 24MHz kristal kies, nu al moet ik soms onderdelen vertragen om de tekst op het LCD leesbaar te houden. daarnaast moet ik ook opletten dat een test voor een tester niet demotiverend wordt, als hij of zij 2 minuten kwijt is om 25 stekkers ergens in en op te prikken en de tester het product vervolgens in 3 seconden afraffeld is dat niet leuk, doe ik het in 10 sec kan de tekst op het LCD nog worden gelezen en kan de tester ook nog even aan zijn neus krabben voordat hij al die stekkers er weer uit kan trekken.
Het is beter dat ik de applicatie moet vertragen dan dat ik em niet sneller kan krijgen.

Overigens bij zowel de 24Mhz als de 16Mhz liggen de baudrate's binnen de 0.2%, volgens de RS232 standaard moet het binnen de 2% liggen. De praktijk zal wel wat minder weerbarstig zijn (zal liggen rond de 3%) maar laat ik me aan de standaard houden dan is iedereen tevreden.

U hoort nog van mij.

ik dacht dat die processor een dedicated timer heeft voor uart ... timer 3 of 4 ...

Op 20 maart 2008 19:59:07 schreef free_electron:
ik dacht dat die processor een dedicated timer heeft voor uart ... timer 3 of 4 ...

Nope, standaard gebruikt de 805x core Timer1 maar je kunt ook Timer2 gebruiken, hierin zijn er ook meer mogelijkheden om te kiezen welke waarden je laad, en hiermee zo dicht mogelijk tegen de werkelijke waarde aan gaan zitten.
meestal kom je dan binnen de 1% uit, met die 40Mhz zou ik bij 115k2 op 1.4% uitkomen maar ook dat ligt nog binnen de 2%.

Er zijn drie 16-bits timers beschikbaar, T0, T1 en T2 je kunt ze ook gebruiken als counter.

Trouwens, ik heb vanochtend met een (embedded) software specialist gesproken en hem voorgelegd hoe een virtuele poort op te tuigen is via het USB kanaal (het kan, maar ik weet niet hoe). Als ik dat voor elkaar kan krijgen is elke bitrate mogelijk bij elke klokfrequentie tussen de 3- en 40 Mhz.

standaard core hooft inderdaad 3 timers. maar de 8051 die ik ken met usb hebben een extra timer in hun peripherie zitten speciaal voor uart toestanden. zo ben je de defaults niet kwijt.

kijk eens goed in datasheet van dat ding
ik zie het BRG register. dat heeft een standaard 8051 nit. die van jou wel. gebruik dat blok als baudrate generator. das veel flexibeler dan timer 2.

op pagina 60 staat uitgelegd hoe de clocksource om te schakelen van timer 2 naar brg. ( brgcon register )

trouwnes je processor heeft ook nog een PCA array. misschien dat zelfs die te gebruiken is.

Update,

Inmiddels is het kristal vervangen door een exemplaar van 24Mhz, binnen Timer2 is het nu mogelijk op te schalen naar 57600 baud.
Het LCD zal het allemaal worst zijn, die doet het prima ik vermoed dat BASCOM ook de timing in de LCD driver voor z'n rekening neemt zodat het bij alle snelheden goed blijft gaan. Sayant detail: ik heb voor de gein eerst het kristal aangepast en daarna pas de software, in theorie moet dan de timing gecorrigeerd naar 12Mhz twee keer zo snel zijn (waitms = 2 is dan in werkelijkheid 1 ms wachttijd). Dus ook met de timing/2 ging het LCD vrolijk mee.

Het gebruik van Timer2 heeft natuurlijk een paar nadelen:
1. Je bent em simpelweg kwijt, wanneer die is ingezet voor het genereren van baudrate kan kun je em niet meer voor wat anders gebruiken.
2. Het aantal baudrates dat met het gekozen kristal beschikbaar is blijft beperkt, een paar belangrijke snelheden vallen er dan tussen uit.
3. De snelste (standaard) baudrate is niet beschikbaar, 115200 baud zit er gewoon niet tussen.

Zoals Free_electron al aangaf is er ook nog een interne baudrate generator BRDCON en BRL beschikbaar, nu ben ik een beetje roestig op dit gebied dus was het een nootje om te kraken.

Ik gebruik momenteel BASCOM om de software te schrijven, echter BASCOM heeft geen DAT-file voor AT89C5131 ofwel een aantal noodzakelijk registers om dit aan te trappen ontbreken gewoon. Daarnaast zijn er registers om de USB verbinding te manipuleren, welke kant ik daar precies mee op moet weet ik nog niet maar met de seriele poort kan ik het simpel op een terminal zichtbaar maken --> bij USB gaat dat wat meer voeten in aarde hebben.

De DAT-file heb ik al eerder gekopieerd van een standaard 805x exemplaar naar de nieuwe 89C5131.DAT het eerste wat ik aan heb kunnen passen was poort P4, toevallig de poort waarvan de onderste twee bits voor I2C gereserveerd zijn.
Inmiddels heb ik in die DAT file de registers "Brdcon", "Ckcon0", "Pcon" en "Brl" erbij gezet (Pcon was eral geloof ik) met deze registers heb ik de interne baudrate generator in de highspeed mode aan weten te trappen.
In de documentatie staan al waarden opgegeven die bij 24Mhz in dat "BRL" register moeten worden geladen om de diversen baudrate's op te wekken: dat werkt nu als een tierelier !!!


'----------------------------------------------------------------------
$crystal = 24000000                  '24 MHz crystal
'----------------------------------------------------------------------
'High speed serial using internal generator BRL -----------------------
'X2 = 1 SMOD1=1, SPD = 1
'
Brdcon = &B00011111                   'Use internal baudrate generator
Ckcon0 = &B00000001                   'Ckcon0 -> High speed
Pcon = &B10010000                     'Set double baudrate in mode 1 2 3
Brl = 243                             '115200 reload value
'Brl = 230                            '57600 reload value
'Brl = 217                            '38400 reload value
'Brl = 178                            '19200 reload value
'Brl = 100                            '9600 reload value
'
'Low speed serial using internal generator BRL ------------------------
'X2 = 0 SMOD1=0, SPD = 0
'
'Brdcon = &B00011101                  'Use internal baudrate generator
'Ckcon0 = &B00000000                  'Ckcon0 -> Low speed
'Pcon = &B00010000                    'Set single baudrate in mode 1 2 3
'Brl = 243                            '4800 reload value
'Brl = 230                            '2400 reload value
'Brl = 202                            '1200 reload value
'Brl = 152                            '600 reload value
'---------------------------------------------------------------------

Dus met de drie Timers ongebruikt kan het seriele kanaal in de high speed stand alles opwekken tussen de 115k2 en 9600 Baud met een maximale afwijking van 0.16%, in de lowspeed stand zijn baudrates mogelijk tussen de 4800 en 600 baud.

In die situaties dat ik gedwongen wordt te communiceren op een bepaalde snelheid (lees te testen product) heb ik nu dus keuzes genoeg.

O ja, 1200 Baud in de lowspeed stand heeft dan een afwijking van 3,55% en 300 Baud staat niet in het lijstje,
maar die lage waarden kan ik altijd nog uit Timer2 halen met voldoende nauwkeurigheid. en zal zelden of nooit voorkomen.

Het volgende project wordt een tester voor een stukje electronica dat aan een gassensor wordt gehangen. In dat stukje electronica moeten wat spanningen worden gemeten en moet de sensor worden gesimuleerd. De waarden die dat opleverd in de processor op de DUT (RS232 op TTL nivo) zullen terug moeten worden gehaald en worden vergeleken met wat er wordt aangeboden --> de kans dat ze dat op 300 of 600 baud hebben gedaan is heel goed mogelijk omdat er (na dat TTL nivo) afhankelijk van de opties RS232 of RS485 van wordt gemaakt, met een lage baudrate kan dat kan over kilometers lange kabels worden getransporteerd.

Over een lang verhaal gesproken..........
Sander.

Over een lang verhaal gesproken..........

Maar wel een zeer leerzame update !!.

Hmmm, dank je.

Een kleine toevoeging:
In de 89C5131.DAT file die op de achtergrond mee draait staat nu het volgende:


[BIT]
ACC = E0 , 00
B = F0 , 00
IE = A8 , 00
IP = B8 , 00
P0 = 80 , FF
P1 = 90 , FF
P2 = A0 , FF
P3 = B0 , FF
P4 = C0 , FF
PSW = D0 , 00
SCON = 98 , 00
TCON = 88 , 00
T2CON = C8 , 00

[BYTE]
SP = 81 , 07
DPL = 82 , 00
DPH = 83 , 00
PCON = 87 , 10
TMOD = 89 , 00
TL0 = 8A , 00
TL1 = 8B , 00
TH0 = 8C , 00
TH1 = 8D , 00
CKCON0 = 8F , 00
SBUF = 99 , 00
BRL = 9A , 00
BRDCON = 9B , 00
T2MOD = C9 , 00
TL2 = CC , 00
TH2 = CD , 00
RCAP2L = CA , 00
RCAP2H = CB , 00


[MISC]
I_TIMER2 = 2B
up = 89C5131
IRAM = 1024
org = 2E
clockdiv=12

Hierin zijn de extra registers opgenomen die in de software worden geset, de namen die ik heb gebruikt kun je terug vinden in de datasheet. Vermoedelijk zal dat lijstje in de toekomst nog wel verder uit worden gebreid.

Hier de support pagina van Keil voor die processor inclusief de door hun ondersteunde .H file :

http://www.keil.com/dd/chip/3533.htm

De include file :

http://www.keil.com/dd/docs/c51/atmel/at89c5131.h

[Bericht gewijzigd door bprosman op (21%)]

Ik was al een beetje verbaasd dat de knopjes (d'r zijn er drie van) hoewel ze door een debounce routine gaan erg tricky reageerde.

Het splash screen dat op het LCD verscheen was ook al erg snel verdwenen nadat de boel een herstart kreeg, wat de hele tester was flink sneller geworden.

Op zich niet zo'n bezwaar ware het niet dat de DUT geen tijd meer kreeg om uit zijn slaapstand (voedingsloos en met de Reset lijn hoog) te ontwaken en de aangeboden bytes te gaan verwerken.

Een laatste toe te voegen onderdeel was het uitschakelen van de LCD backlight na 240 sec van inactiviteit (4 minuten, staat wel zo netjes) gebruik makend van Timer0 (mode 2) en met een teller stand van 250 moest na berekening elke 125us een interupt optreden (24Mhz/12 = 2 Mhz).
In het programma werden 8000 van die interups verzameld en de 1 seconden is geboren, even door tellen naar de 20 (maar 20 seconden hoeven wachten is wat handiger) en voila klaar. Kledder dat ging dus niet door, binnen een paar seconden ging het scherm uit.

Het aanpassen van de seriele poort heeft namelijk nog een andere offspin, de interne klok van de processor wordt namelijk met het veranderen van register CKCON0 --> X2 bit nog een tandje sneller gezet, in de standaard mode draait de processor intern op Fosc/12 echter in met bitje X2 geset wordt het ineens Fosc/6.

Omdat de meeste ontwerpjes gebasserd zijn op bijvoorbeeld 12Mhz kom je (gedeeld door 12) uit op een 1Mhz interne klok
(periodetijd is dan 1us) laad je vervolgens de timer met een teller waarde van 250 krijg je dus elke 250us een interupt. Vermenigvuldig dat vervolgens met 4000 en de seconden is geboren.

In dit project gingen er dus 2 dingen "mis" 1 het kristal was geen 12Mhz maar 24Mhz en die oscillator werdt niet meer gedeeld door 12 maar nog maar door 6 ofwel de interne frequentie was opgekrikt naar 4 Mhz.

Omdat de compiler de oscillater frequentie zelf deelde door 12 ipv 6 werden dus alle tijden effectief gehalveerd.
In de DAT file moet dus wanneer er over wordt geschakeld naar de de interne baudrate generator en X2 wordt op "1" gezet moet dus de "clockdiv" ook worden aangepast om de timing in de compiler te corrigeren (waitms 100 is dan weer 100ms ipv 50ms).


[MISC]
I_TIMER2 = 2B
up = 89C5131
IRAM = 1024
org = 2E
clockdiv=6

'-------------------------------------------------------------------------------
' Definieren van settings en variabelen
'-------------------------------------------------------------------------------
$crystal = 24000000                                      '24 MHz crystal

Config Timer0 = Timer , Gate = Internal , Mode = 2       'Use timer to shutdown backlight
On Timer0 Timer_0_int                                    'on timer interupt jump to subroutine
Load Timer0 , 200                                        'Loads 50us (200/4) in Timer0
Priority Set Timer0                                      'Timer0 priority
Enable Interrupts                                        'Enable interrupts
Enable Timer0                                            'Enable Timer0
Start Timer0                                             'Start Timer0

Dim Clock As Byte                                        'Use Clock and Clock1 to get 1 sec
Dim Clock1 As Byte                                       'Use Clock and Clock1 to get 1 sec
Dim Seconds As Byte                                      'After X sec turn off backlight

Config Debounce = 50                                     'Set debounce to 50 mS
Dim Button_left As Bit : Button_left = 0                 'Button "LEFT"
Dim Button_mid As Bit : Button_mid = 0                   'Button "MIDDLE"
Dim Button_right As Bit : Button_right = 0               'Button "RIGHT"
Dim Wacht As Integer : Wacht = 35                        'Preset Wacht tijd to 30ms
|
|
|
|
|

'-------------------------------------------------------------------------------
' Routine to find out state of Button left, middle and right
' Button_left = Button "LEFT" --> Konnektor K6
' Button_mid = Button "MIDDLE" --> Konnektor K7
' Button_right = Button "RIGHT" --> Konnektor K8
'-------------------------------------------------------------------------------
Button:
Button_left = 0                                          'Reset button state
Button_mid = 0                                           'Reset button state
Button_right = 0                                         'Reset button state
Debounce P3.5 , 0 , Press:                               'Check buttons
Debounce P3.6 , 0 , Press:                               'Check buttons
Goto Button:                                             'Loop button

Press:
If P3.5 = 1 And P3.6 = 0 Then Button_left = 1            'Find out which button is pressed
If P3.5 = 0 And P3.6 = 0 Then Button_mid = 1             'Find out which button is pressed
If P3.5 = 0 And P3.6 = 1 Then Button_right = 1           'Find out which button is pressed
Seconds = 0                                              'Reset timer to 0
If Backlight = 0 Then                                    'If LCD is dark use click to light up
   Backlight = 1                                         'Turn backlight on
   Goto Button                                           'Ignore button click (use it to turn on LCD)
End If
Return    

|
|
|
|

'-------------------------------------------------------------------------------
' Interupt afhandeling van Timer0
'-------------------------------------------------------------------------------
Timer_0_int:
Incr Clock                                               'increase clock every 50us
If Clock > 99 Then                                       'If clock larger then 5000us
   Clock = 0                                             'Reset clock to 0
   Incr Clock1                                           'Increase clock1 every 5000us
   If Clock1 > 199 Then                                  'If clock1 larger then 1000ms
      Clock1 = 0                                         'Reset clock1 to 0
      Incr Seconds                                       'Increase Seconds every 1sec
      If Seconds > 240 Then                              'If Seconds larger then 240 sec
         Backlight = 0                                   'Turn backlight off after 4:00 min
         Seconds = 0                                     'Reset seconds to 0 to prevent overflow
      End If
   End If
End If
Return

Langzaam maar zeker ontstaan er zo steeds meer brokken die ik zo opnieuw kan gebruiken.

Niets is wat het lijkt, je software goed aan de tand voelen is het halve werk.