Top Banner
Introduction au 68HC11(F1) Jean-Michel FRIEDT, Mai 1999 (March 6, 2000) 1 Introduction Le choix du 68HC11F1 a ´ et´ e fait selon le crit` ere d’avoir une microcontroleur ne n´ ecessitant pas de programmeur, pouvant ˆ etre pro- gramm´ e au vol ` a partir d’un port s´ erie 1 et comportant des convertisseurs analogique-num ´ erique (A/D) tout en permettant l’interfac ¸age avec une RAM externe. L’assembleur utilis´ e ici est disponible gratuitement par anonymous ftp ` a ftp.cmf.nrl.navy.mil dans /pub/kenh/ (il s’agit de asxxxx-v1.51.tar.gz en Novembre 1999, bien que la version puisse changer ult´ erieurement). Cet assembleur a l’avantage d’ˆ etre facilement adaptable ` a n’importe quel microcontroleur CISC (et inclut notamment des versions pour le 6809 et le Z80). La m´ ethode de compilation utilis´ ee, que ce soit sous DOS ou Linux, est la suivante : ´ ecrire le programme en assembleur dans un ´ editeur de texte (le fichier sera ici nomm´ e prg.asm). Par rapport aux exemple donn´ es dans le texte, il ne faut taper que la partie droite (par exemple pour une ligne du type 0000 8E 01 FF lds #0h01FF ; setup : stack il ne faut entrer que lds #0h01FF suivi ´ eventuellement des commentaires (le texte apr` es le ’;’). Le d´ ebut de la ligne est l’adresse o` u se situe la ligne de code (ici d´ ebut du programme donc adresse 0000), puis les opcode correspondant ` a cette ligne apr` es assemblage (ici 8E 01 FF). C’est la suite de ces opcodes que nous enverrons via la liaison s´ erie au 68HC11. l’assembler par as6811 -o prg.asm sous DOS ou as6811 -o prg.rel prg.asm sous Linux pour g´ en´ erer le fichier prg.rel qui contient le code en hexad´ ecimal et d’autres informations. retirer les lignes ne commenc ¸ant pas par un ’T’(grep ˆT) et les 8 premiers caract` eres des lignes restantes (qui sont le ’T’ suivi de l’adresse de d´ ebut de ligne : cut -c9-60) et mettre le r´ esultat dans prg.out : grep T %1.rel | cut -c9-60 > %1.out sous DOS ou grep T $1.rel | cut -c9-60 > $1.out sous Linux. enfin, programmer le 68HC11F1 en ex´ ecutant le programme DOS hc11.exe prg.out,r´ esultat de la compilation de hc11.pas fourni en annexe A de ce document. ` A noter que le num´ ero du port s´ erie est en hard dans le programme sous le nom de variable PortId. Les programmes pr´ esent´ es dans ce document ont ´ et´ e g´ en´ er´ es par as6811 -l prg.asm sous Linux (apr` es ´ edition des lignes inutiles). La mˆ eme fonction est disponible sous DOS par as6811 -l prg.asm qui g´ en` ere automatiquement le fichier .lst. 2 en´ eralit´ es Les instructions de base. 2 registres 16 bits utilis´ es pour les acc` es m´ emoires : X, Y 2 registres g´ en´ eraux 8 bits : A, B qui peuvent se concat ´ ener en D=AB. Programme + data RAM Pile Registres ROM EEPROM vecteurs d’int. 0000 lds 03FF 1000 105F BF00 BFFF FE00 FFFF Les fonctions logiques habituelles : AND(A/B), LSL(A/B) (shift left), LSR(A/B) (shift right), ORA(A/B) Les op´ erations sur la pile : PSH(A/B/X/Y), PUL(A/B/X/Y) Les fonctions sur des bits : BCLR (bit clear), BSET (bit set) Les fonctions de saut relatif (court) : BRA (toujours), BNE ( 0), BSR (branch to subrou- tine), RTS Les fonctions de saut long : JMP, JSR, Les fonctions de chargement de valeur : LDA(A/B), LDD, LDS, LD(X/Y), ST(X/Y), STA(A/B), STD Les sauts avec test : BRCLR (branche si apr` es masquage avec les bits ` a 0, le r´ esultat est nul), BRSET (r´ ealise un ET logique avec le masque fourni, et branche si le r´ esultat est 0) Interruptions : CLI (autorise les interruptions), RTI, SEI (arrˆ ete les interruptions) Comparaison : CP(X/Y), CMP(A/B) Arithm´ etique : DEC(A/B), DE(X/Y), INC(A/B), IN(X/Y), SUB(A/B), SUBD, ADD(A/B), ADDD. 1 La restriction sur le port RS232 vient de l’utilisation d’un palmtop HP200LX comme programmeur. Cet ordinateur ne poss` ede qu’un port s´ erie comme extension (absence de port parall` ele). 1
15
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 68hc11

Intr oduction au 68HC11(F1)Jean-MichelFRIEDT, Mai 1999(March6, 2000)

1 Intr oduction

Le choix du 68HC11F1a ete fait selonle critered’avoir unemicrocontroleurne necessitantpasde programmeur, pouvant etrepro-grammeauvol a partir d’un port serie1 et comportantdesconvertisseursanalogique-numerique(A/D) tout enpermettantl’interfacageavecuneRAM externe.

L’assembleurutilise ici estdisponiblegratuitementparanonymousftp a ftp.cmf.nrl.navy.mil dans/pub/kenh/ (il s’agitde asxxxx-v1.51.tar.gz en Novembre1999,bien quela versionpuissechangerulterieurement).Cet assembleura l’avantaged’etrefacilementadaptablea n’importequelmicrocontroleurCISC(et inclut notammentdesversionspourle 6809et le Z80).

La methodedecompilationutilisee,quecesoit sousDOSou Linux, estla suivante:

ecrire le programmeen assembleurdansun editeurde texte (le fichier seraici nomme prg.asm ). Par rapportaux exempledonnesdansle texte, il nefauttaperquela partiedroite(parexemplepouruneligne du type0000 8E 01 FF lds #0h01FF ; setup : stackil ne faut entrerque lds #0h01FF suivi eventuellementdescommentaires(le texte apres le ’ ; ’). Le debut de la ligne estl’adresseou sesituela ligne decode(ici debut du programmedoncadresse0000 ), puis lesopcodecorrespondanta cetteligneapresassemblage(ici 8E 01 FF). C’estla suitedecesopcodesquenousenverronsvia la liaisonserieau68HC11.

l’assemblerparas6811 -o prg.asm sousDOSou as6811 -o prg.rel prg.asm sousLinux pourgenererle fichierprg.rel qui contientle codeenhexadecimalet d’autresinformations.

retirerleslignesnecommenc¸antpasparun ’T’ (grep ˆ T) et les8 premierscaracteresdeslignesrestantes(qui sontle ’T’ suividel’adressededebut de ligne : cut -c9-60 ) et mettrele resultatdansprg.out : grep T %1.rel | cut -c9-60 >%1.out sousDOSou grep T $1.rel | cut -c9-60 > $1.out sousLinux.

enfin,programmerle68HC11F1enexecutantleprogrammeDOShc11.exe prg.out , resultatdelacompilationdehc11.pasfourni enannexeA decedocument.A noterquele numerodu port serieestenharddansle programmesousle nomdevariablePortId .

Lesprogrammespresentesdanscedocumentont ete generesparas6811-l prg.asmsousLinux (apreseditiondeslignesinutiles).La memefonctionestdisponiblesousDOSparas6811-l prg.asmqui genereautomatiquementle fichier .lst .

2 Generalit es

Lesinstructionsdebase.2 registres16bits utilisespourlesaccesmemoires: X, Y2 registresgeneraux8 bits : A, B qui peuventseconcatenerenD=AB.

Programme + dataRAMPile

Registres

ROM

EEPROMvecteurs d’int.

0000

lds

03FF

1000

105F

BF00

BFFF

FE00

FFFF

Les fonctions logiqueshabituelles: AND(A/B), LSL(A/B) (shift left), LSR(A/B) (shiftright), ORA(A/B)

Lesoperationssurla pile : PSH(A/B/X/Y), PUL(A/B/X/Y) Lesfonctionssurdesbits : BCLR (bit clear),BSET(bit set) Les fonctionsdesautrelatif (court) : BRA (toujours),BNE (

0), BSR(branchto subrou-tine),RTS

Lesfonctionsdesautlong : JMP, JSR, Les fonctions de chargementde valeur : LDA(A/B), LDD, LDS, LD(X/Y), ST(X/Y),

STA(A/B), STD Lessautsavectest: BRCLR(branchesi apresmasquageaveclesbits a0, le resultatestnul),

BRSET(realiseunET logiqueavecle masquefourni, etbranchesi le resultatest0) Interruptions: CLI (autoriselesinterruptions),RTI, SEI (arretelesinterruptions) Comparaison: CP(X/Y), CMP(A/B) Arithmetique: DEC(A/B), DE(X/Y), INC(A/B), IN(X/Y), SUB(A/B), SUBD, ADD(A/B),

ADDD.

1La restrictionsur le port RS232vient de l’utilisation d’un palmtopHP200LXcommeprogrammeur. Cet ordinateurnepossedequ’un port serie commeextension(absencedeport parallele).

1

Page 2: 68hc11

Organisationdela memoire:1024 premiersoctets(0000-03FF): RAM. L’executioncommencea l’adresse0000 par un opcodefetch. Danscettememoire,

noustrouvons: la pile (stack),positionneepar l’utilisateur aumoyende l’instruction lds , lespseudo-vecteursd’interruptions(si lesinterruptionsmateriellessontutilisees)de00C4a 00FFparpaquetsde3 octets(JMP@).

Lesregistresdeconfigurationsde1000a 105F(96 registres).La ROM contenantle codeaexecuterauboot,deBF00aBFFFL’EEPROM deFE00a FFC0(256octets)Il estanoterquel’organisationdela memoirepeutetreoptimiseeenfonctiondesbesoinsparla possibilitededeplacerlesregistres

deconfiguration,la RAM et l’EEPROM an’importequelemplacementdela formex000(x=0..F).Danstouslescasnousdemarronsenbootstrapmode,maisil estpossibleensuitedepasserenmodeetenduetainsiaccedera unememoireexterieure.

3 Mise enRAM localed’un programmeet execution

L’objectif dansun premiertempsestde testerle montagede basecomprenantuniquementle microcontroleur68HC11et la logiquede communicationpar port RS2322 ainsi que les logiciel associes (programmede communicationdu cote du PC pour envoyer leprogrammea executerparle microcontroleur, et programmea executerlui meme).

Le montageproposeestle suivant:

Le circuitestcomposesde3 elementsprincipaux: le68HC11F1,leMAX232, le4066.Quelquescomposantsdiscretssupplementairesdefinissentlesniveauxdequelquesbrochesdu HC11.

Le MAX232a pour role de convertir les signauxTTL provenantdesdeuxbrochesde communicationserie (TxD et RxD) a desniveaux 12V requisparle port RS232du PC.

Le 4066a pour role de passerdu mode“chargementdu programmedu port serie” au mode“executiondu programmestocke enEEPROM”. En effet, le HC11 emetau boot (cf Annexe B, p.25) le caractere0h00sur la brocheTxD, puis semet en ecoutede cequi sepassesur la brocheRxD. Si le caractere0h00estrecu, l’executionpassetout de suiteau debut de l’EEPROM. Si le caracteren’est pas0h00maispasnon plus 0hFF, alorsle HC11 tentede changerde baudrate(frequencede receptiondesdonnees).Enfin, lareceptiond’un caractere0hFFsignifiequ’il fautrecevoir lesoctetset lesplacerenRAM (adressecommenc¸anten0h0000),jusqu’a lafin de la communication.Ainsi, nousconstatonsquecourt-circuiterRxD et TxD aubootpermetdepassertout desuitea l’EEPROM.Cependant,court-circuiterdefinitivementRxD etTxD fait perdrela possibilited’utiliser le portserieulterieurement.Le roledesswitchsanalogiquesdu 4066estde commanderle court circuit pendantseulementles 10 premieresms apresle RESETen commandantlesinterrupteursparun circuit RC (sousle 4066: la capacite de330nF et la resistancede100kΩ. La resistancede10 kΩ au-dessusdu4066sertderesistancedepull-up). Cecourtcircuit estdepluspermisparun strap: si cestrapestouvert, il n’y a pascourtcircuit et leprogrammeestchargeparle port serie.Si cestrapestferme, il y acourtcircuit etdoncsautendebut d’EEPROM.

Enfin, pour le 68HC11, seulementquelquescomposantsdiscretsexternessont necessaires: le quartzet sesdeux capacitesdequelquespF pour le faireosciller (avecun resistanceoptionnellede10 MΩ), desresistancesde pull up (en basdu HC11)sur lesfilsreliesaTxD, RxD etRESET. Il seradeplusnecessaire,encasd’utilisationdesinterruptions,d’ajouterdeuxresistancesdepull upentrelesbrochesIRQ et Vdd et XIRQ et Vdd (sinonle HC11estcontinuellementinterrompuet le programmesebloqueapresexecutiondel’instructioncli ).

Les strapsdisponiblessontdonc : sousle HC11 (horizontal)pour le RESET(il s’agit en fait plutot de court-circuitercesdeuxbrochesavecun objet conducteurpour effectuerle RESET),le strap(horizontal)a gauchedu 4066qui determines’il faut charger leprogrammesurle port serie(ouvert)ou executecelui stockeenEEPROM (ferme),et enfinlesdeuxstraps(verticaux)enhautdu HC11etqui doiventnormalementetrefermespourlancerle HC11enbootstrapmode.

2La memoireutiliseepourstocker le programmeestinclusedansle microcontroleur(contrairementaplusloin ou nousnousefforceronsd’interfaceruneRAM externeavecle 68HC11).

2

Page 3: 68hc11

Nousprendronssoin, lors de la realisation,a placerdeuxsupportsde jumpersde facon verticaleen hautdu circuit (selectiondumodedefonctionnement: lesdeuxjumpersdoiventetremisenplacepourbooterenbootstrapmode)ainsiqu’un supportdejumperenbasdu circuit pourle Reset(realiseencourt-circuitanttemporairementcesupportdejumperavecun objetconducteurelectriquement).

0000 8E 00 FF lds #0h00FF0003 CE 10 00 ldx #0h10000006 86 FF ldaa #0hFF0008 A7 01 staa 0h01,x

000A 86 00 ldaa #0h00000C A7 00 boucle: staa 0h00,x000E 18 CE FF FF ldy #0hFFFF0012 18 09 wait: dey

0014 26 FC bne wait0016 4C inca0017 20 F3 bra boucle

Cepetit programmedetestfait defiler surle port A (horizontal,enbasdu circuit) la representationbinairedesnombresde0 a 255.Le resultatestvisualisableenconnectantun afficheur7 segmentsou unebarrettedeLEDssurle portA.

4 Lecturedesvaleursdu convertisseuranalogique-numerique

Il faut:

1. mettreenroutelesconvertisseursA/D enecrivantdansle registre0x1039.3.

2. pourchaquenouvelleconversion,ecrirele numerodu convertisseur(entre0 et 7) qui doit effectuerla conversiondansle registre0x1030(dansl’exempleci-dessous,nousutilisonsle convertisseurnumero3)

3. attendrele signaldefin deconversion(parpolling du registre0x1030).

4. lire la valeurobtenuedansle registre0x1034.

0000 8E 00 FF lds #0h00ff0003 86 FF ldaa #0hff0005 B7 10 01 staa 0h10010008 86 90 ldaa #0h90000A B7 10 39 staa 0h1039000D start:

000D 86 23 ldaa #0h23000F B7 10 30 staa 0h10300012 8D 05 bsr ad_read0014 B7 10 00 staa 0h10000017 20 F4 bra start

0019 B6 10 30 ad_read:ldaa 0h1030001C 2A FB bpl ad_read001E B6 10 34 ldaa 0h10340021 39 rts

Cetexemplelit la valeuranalogiquesurunedesvoiesdu port E (audessusdu 68HC11)- le canal3 - et renvoie la valeursurle portA (auquelonaurarelie unafficheur7 segmentsparexemple).Unevariationdela tensionappliqueesurla brocheduportE (entre0 et5V) doit setraduireparunvariationdela valeuraffichee.

5 La communication serie

Il faut:

1. mettrele portD enmodecommunication

2. determinerla vitesseet le protocoledetransmission

3. unefois cesinitialisationeffectuees,attendrela transmissiond’un caractereet le lire lorsqu’il a ete recu (parpolling).

Danslesprogrammesqui suivent, le 68HC11doit etrerelie parun cabledirect (non-croise) a un PCsur lequeltourneun logicield’emulationdeterminal(typeTerminalsousWindows3.11ou ProcomsousDOS).Dansle premierexemple,le 68HC11affichesurleportA (auquelonaurarelieunafficheur7 segmentsparexemple)la valeurASCII ducaractereenvoyeparle PC(parappuid’unetouchedu clavier du PC par exemple). Dansle secondexemple,le 68HC11envoie en continules caracteresASCII affichable: le terminaldoit continuellementafficherlessignesdeponctuation,leschiffreset l’alphabetenminusculesetmajuscules.Enfin, le dernierexemplecombinecesdeuxapplicationsparattendrel’envoi d’un caracteredu PCet le lui renvoyer.

Exempledelecturedesdonneesvenantsurle port seriedu68HC11:3Nousutiliseronsindifferemmentla notation0xyyyy(notationC),0hyyyy(notationassembleurnon-Motorola68HC11)ou$yyyy(notationPascal)pournoterle nombre

hexadecimalyyyy

3

Page 4: 68hc11

0000 8E 00 FF lds #0h00FF0003 CE 10 00 ldx #0h10000006 86 FF ldaa #0hFF0008 A7 01 staa 0h01,x000A 1C 28 20 bset 0h28,x,#0h20

000D 6F 2C clr 0h2c,x000F CC 33 0C ldd #0h330C0012 A7 2B staa 0h2B,x0014 E7 2D stab 0h2D,x0016 1F 2E 20 FC rc: brclr 0h2E,x,#0h20,rc

001A E6 2F ldab 0h2F,x001C E7 00 stab 0h00,x001E 20 F6 bra rc

Exempled’emissiondedonneessurle port seriedu 68HC11:

0000 8E 00 FF lds #0h00FF ; stack0003 CE 10 00 ldx #0h1000 ; config registers0006 86 FF ldaa #0hFF ; port A for output0008 A7 01 staa 0h01,x ; |000A 1C 28 20 bset 0h28,x,#0h20; port D OR mode

000D 6F 2C clr 0h2C,x ; set 2400 N81000F CC 33 0C ldd #0h330C ; |0012 A7 2B staa 0h2B,x ; |0014 E7 2D stab 0h2D,x ; |0016 86 20 ldaa #0h20 ; init value at ’ ’0018 1F 2E 80 FC boucle: brclr 0h2E,x,#0h80,boucle

001C A7 2F staa 0h2F,x ; send char001E 4C inca ; next char001F 81 7B cmpa #0h7B ; > ’z’ ?0021 26 F5 bne boucle0023 86 20 ldaa #0h20 ; restart at ’ ’0025 20 F1 bra boucle

Combinaisondesdeuxprogrammesprecedentspourlire unevaleursurle port serieet la renvoyerauPC:

0000 8E 00 FF lds #0h00FF0003 CE 10 00 ldx #0h10000006 86 FF ldaa #0hFF0008 A7 01 staa 0h01,x000A 1C 28 20 bset 0h28,x,#0h20

000D 6F 2C clr 0h2C,x000F CC 33 0C ldd #0h330C0012 A7 2B staa 0h2B,x0014 E7 2D stab 0h2D,x0016 1F 2E 20 FC xm: brclr 0h2E,x,#0h20,xm

001A E6 2F ldab 0h2F,x001C E7 00 stab 0h00,x001E 1F 2E 80 FC rc: brclr 0h2E,x,#0h80,rc0022 E7 2F stab 0h2F,x0024 20 F0 bra xm

6 Mise enEEPROM localeet executiond’un programme

6.1 Aspectlogiciel

L’EEPROM commenceen 0xFE00. Il nousfaut donc, en bootloadermode,charger un programmeen RAM dont la fonction estd’attendrele programmea stocker en EEPROM et executerla procedurede stockage.Nous avonschoisi de realiserla conversionhexadecimal-ASCIIversunevaleurnumeriqueauniveaudu PC(contrairementa l’AN1010 deMotorolaqui realisecettefonctionauniveaudu microcontroleur)etden’envoyerquelesoctetscorrespondantauprogramme(pasdechecksum,pasd’adressededebut ...).

0000 8E 00 FF lds #0h00FF ; stack0003 CE 10 00 ldx #0h1000 ; config registers offset0006 18 CE FE 00 ldy #0hFE00 ; start of EEPROM(cf 4.12 tech man)000A 86 00 ldaa #0h00 ; bprot - block protection disabled000C A7 35 staa 0h35,x ; |000E 1C 28 20 bset 0h28,x,#0h20 ; port D wired OR mode : set port D0011 6F 2C clr 0h2C,x ; set 2400 N810013 CC 33 0C ldd #0h330C ; |0016 A7 2B staa 0h2B,x ; |0018 E7 2D stab 0h2D,x ; |001A 86 FF ldaa #0hFF ; port A as output001C A7 01 staa 0h01,x ; |001E 86 22 ldaa #0h22 ; show ’22’ on display0020 A7 00 staa 0h00,x ; |0022 boucle:0022 1F 2E 20 FC brclr 0h2E,x,#0h20,boucle ; wait for datum0026 E6 2F ldab 0h2F,x ; store it in B0028 E7 00 stab 0h00,x ; echo on port A002A 86 16 ldaa #0h16 ; reset 1 byte002C 8D 12 bsr program ; write to location in EEPROM002E 86 02 ldaa #0h02 ; store 1 byte

0030 8D 0E bsr program ; write to location in EEPROM0032 18 08 iny ; goto next location in EEPROM0034 18 8C FF BF cpy #0hFFBF ; until we get to 0hFFBF0038 26 E8 bne boucle ; get next datum if not finished003A 86 08 ldaa #0h08 ; show ’8’ on display003C A7 00 staa 0h00,x003E 20 FE fin: bra fin

0040 program: ; cf procedure p.4.16 of tech manual0040 A7 3B staa 0h3B,x0042 18 E7 00 stab 0,y ; erase/program byte0045 6C 3B inc 0h3B,x0047 3C pshx0048 CE 1A 0A ldx #0h1A0A ; 2x0h0D05 (16 MHz Q) => 2xdelay_AN1010004B 09 wait: dex004C 26 FD bne wait004E 38 pulx ; put X=0h1000 back004F 6A 3B dec 0h3B,x0051 6F 3B clr 0h3B,x0053 39 rts

Le programmeee.asm dontle roleestderecevoir desdonneessurle port serie(2400,N81)et delesstocker enEEPROM.

6.2 Aspectmateriel

Nousavonsvu plus hautqu’uneserie d’interrupteursanalogiquesavaientete inclus sur la carte. Leur fonction estd’eventuellementpermettredecourt-circuiterpendantuntempsbref leslignesRxDetTxD decommunicationdemicrocontroleur. Eneffet, si a l’allumagele 68HC11estenbootstrapmode,il attendde recevoir un signalsur la brocheRxD et agit enconsequence.Si cesignalest0xFF, lebaudrateestcorrectet l’acquisitiondu programmea stockercommence.Si cesignalest0x00, l’executionsauteendebut d’EEPROM :le programmequi avait ete stocke la anterieurementestexecute. Danslesautrescas,le microcontroleurchangele baudrate.

Or a l’allumage,la premiereoperationduprogrammedubootloaderestd’envoyer0x00surla brocheTxD. Ainsi, encourt-circuitanttemporairementRxDet TxD, nouslanconsle programmeenEEPROM plutot qu’attendrel’acquisitiond’un programmea executerparle port serie.

Le court-circuitse fait simplementen connectantun circuit RC sur la commanded’un desinterrupteursanalogiqueselle memeconnectantla commanded’un autreinterrupteuranalogiquea la masse.La commandede cettesecondeporte logiqueestcependantmaintenuea l’ etathautparuneresistancedepull-upde10kΩ. Au reset,le niveaudela brocheRESETestbas.Cettebrocheestrelieeala commandedu premierinterrupteuranalogiquequi estdoncouvert,et la resistancedepull-upmaintientle secondinterrupteurferme,connectantTxD et RxD. Le circuit RC secharge, fermantle premierinterrupteurqui relie la commandedu secondinterrupteura lamasseet ouvredoncle contactentreTxD et RxD.

6.3 Aspectpratique

Le programmehc11.pas aeteprevupoureventuellementaccepterdeuxarguments.Nousavonsjusquela fourni unseulargument,leprogrammeenhexadecimala chargerdansla RAM du 68HC11.Si nousdonnonsdeuxargument,qui sontdansl’ordre le programme

4

Page 5: 68hc11

ee.out vu plus haut,suivi du nom du programmea chargeren EEPROM (nomme ici prg.out , hc11.exe ee.outprg.outchargeradansun premiertempsee.asm dansla RAM du HC11 ee dont le role estd’attendrela receptionde prg.out sur le port serie etde le stocker enEEPROM. Cecisefait parun delai d’unesecondeentrela fin de l’ emissiondeee.out et le debut de l’ emissiondeprg.out (delai suffisantpour demarreree). Il faudradeplus pensera relocaliser, a la compilation,prg.asm a l’adressede debutdel’EEPROM (0hFE00,puisquel’EEPROM va de0hFE00a 0hFFBF)par l’ajout desdeuxlignessuivantesendebut deprogramme:.area code (ABS) et .org 0hFE00 .

7 Branchementd’une RAM externe

Dansle casdela connexion d’un composantexterne,il fautfairepasserle 68HC11enmodeetendudefacon a cequelesportsF, B etC soientutilisescommebusd’adresse(octetsdepoidsfaibleet fort) et busdedonnees(sur8 bits), et pour faire fonctionnerle signald’ecritureR/W#. Cetteoperationsefait de facon logicielle : eneffet, il nousfaut tout d’abordetreenbootstrapmodepourchargerleprogrammeenRAM internedu 68HC11avantdepouvoir accedera la RAM externe.

Le branchementdela RAM sefait facilementenreliantlesbusd’adresseetdedonneeset,poureviterlesrisquesdeconflit aveclesmemoiresinternes,nousavonsrelie lessignauxd’adresse13 et 14 auxsignauxd’activationdela RAM pourfairecommencerl’espaceadressabledecelle-cia 0x2000.

0000 8E 00 FF lds #0h00FF0003 CE 10 00 ldx #0h1000 ; config regis-ters offset0006 18 CE 20 00 ldy #0h2000 ; RAM offset000A 86 FF ldaa #0hFF ; set A port for output000C A7 01 staa 0h01,x ; |000E 1C 28 20 bset 0h28,x,#0h20; set SPI clock rate0011 6F 2C clr 0h2C,x ; 2400 bauds, N81

0013 CC 33 0C ldd #0h330C ; |0016 A7 2B staa 0h2B,x ; |0018 E7 2D stab 0h2D,x ; |001A 86 E5 ldaa #0hE5 ; set extended mode001C A7 3C staa 0h3C,x ; |001E 1F 2E 20 FC xmi: brclr 0h2E,x,#0h20,xmi; read char0022 E6 2F ldab 0h2F,x ; |0024 E7 00 stab 0h00,x ; store on port A

0026 18 E7 00 stab 0h00,y ; store in RAM0029 18 E6 00 ldab 0h00,y ; read from RAM002C 18 08 iny ; goto next RAM address002E 1F 2E 80 FC rec: brclr 0h2E,x,#0h80,rec; echo char to serial port0032 E7 2F stab 0h2F,x ; |0034 7E 00 1E jmp xmi

Cecircuit peutfacilementetremodifiepoury adapteruneRAM de32K 62256: relever lesbroches1, 20 et 22 dela RAM et relier1 a la broched’adresse14 du 68HC11tandisquelesbroches20 et 22 sontrelieesa la massepourtoujoursactiver la RAM.

8 Resultat final : acquisition dedonnees,stockageenRAM puis envoiepar port serie

L’objectif dutravail presentejusqu’ici etaitderealiserunsystemecapabledefaireseulungrandnombre( 1000)d’acquisitionspendantunedureedetermineea l’avance(del’ordre dequelquesheures),et unefois lesdonneesobtenuesd’attendreun signalexterieur(sur leport serie)pourenvoyercesdonneesa un PCqui s’occuperadu traitementdesdonnees.

Le programmesuivant:

initialise le portdecommunicationet lesconvertisseursA/D puispasseenmodeetendupourpouvoir accedera la RAM externe.

lit periodiquementla valeuranalogiquesur le convertisseur3 et stocke la valeurobserveeen RAM externetout en affichantlavaleurlue surle port A.

unefois la RAM externepleine,attendun caractere(quelconque)sur le port serie, et affiche “00” sur le port A pour indiquerl’attente.

envoie lesdonneessur le port serie lorsquela requetea ete faiteet affichela valeurdu caractererecu sur le port A pourindiquerquela transmissionestencours.transmission.

Il faudraserapportera l’annexe C pour le programmeen Turbo Pascalde receptiondesdonneesde la RAM li eeau HC11 versl’IBM PCunefois l’acquisitionfinie.

0000 8E 01 50 lds #0h0150 ; stack0003 CE 10 00 ldx #0h1000 ; config regis-ters offset0006 18 CE 20 00 ldy #0h2000 ; RAM offset000A 86 FF ldaa #0hFF ; port A: output000C A7 01 staa 0h01,x ; |

000E 1C 28 20 bset 0h28,x,#0h20; port D OR mode0011 6F 2C clr 0h2C,x ; 2400 bauds, N810013 CC 33 0C ldd #0h330C ; |0016 A7 2B staa 0h2B,x ; |0018 E7 2D stab 0h2D,x ; |

001A 86 E5 ldaa #0hE5 ; set extended mode001C A7 3C staa 0h3C,x ; |001E 86 90 ldaa #0h90 ; en-able A/D converters0020 A7 39 staa 0h39,x ; store OP-TION register

5

Page 6: 68hc11

0022 CE 3F FF ad: ldx #0h3FFF0025 09 loop: dex ; wait be-fore next conversion0026 26 FD bne loop0028 CE 10 00 ldx #0h1000002B 86 23 ldaa #0h23 ; start conver-sion on AD3002D A7 30 staa 0h30,x ; |002F 8D 30 bsr ad_read0031 18 A7 00 staa 0h00,y ; store in RAM0034 A7 00 staa 0h00,x ; echo on port A0036 18 08 iny ; goto next RAM address0038 18 8C 24 00 cpy #0h2400 ; 256 values

003C 26 E4 bne ad ; get next da-tum if not finished003E 86 00 ldaa #0h00 ; displ. re-sult of convert on A0040 A7 00 staa 0h00,x ; |

0042 1F 2E 20 FC rcv: brclr 0h2E,x,#0h20,rcv; wait for 1 char0046 A6 2F ldaa 0h2F,x ; dis-play it on portA0048 A7 00 staa 0h00,x

004A 18 CE 20 00 ldy #0h2000 ; RAM offset004E 18 A6 00 read_ra:ldaa 0h00,y

; read from RAM0051 1F 2E 80 FC snd: brclr 0h2E,x,#0h80,snd; echo char to serial port0055 A7 2F staa 0h2F,x ; |0057 18 08 iny ; inc RAM @0059 18 8C 24 00 cpy #0h2400 ; end of filled RAM ?005D 26 EF bne read_ra ; get next datum005F 20 FE fin: bra fin

0061 A6 30 ad_read:ldaa 0h30,x0063 2A FC bpl ad_read ; wait convert end0065 A6 34 ldaa 0h34,x ; return res in A0067 39 rts

0

50

100

150

200

250

300

0 100 200 300 400 500 600

"out.dat"

0

20

40

60

80

100

120

140

160

180

0 200 400 600 800 1000 1200

"out.dat"

Exemple d’acquisition avec un fil du bus d’adressede la RAMdeconnecte (@5)

Exempled’acquisitioncorrecte

9 La communication SPI

68HC11Master

68HC11Slave

+5 V

SS#

IBM PCRS232

MOSI

MISO

SS#

GND

CK

SCKMISO

MOSI

GNDGND

Connexionsa ajouterauxcircuitspourfaireconnecterdeux68HC11enmodeSPI

La selectionde l’esclave a qui le messageestenvoye sefait par l’activationde SS# qui, au lieu d’etreconnecteea la masse,estrelieea unebrochedu port B. Dansnotreexempleou nousavonssimplementun maıtre envoyantun messagea un seulesclave, nous

6

Page 7: 68hc11

avonsdirectementrelie SS#del’esclave a la masse.Lesautresconnexionsconsistenta relier directementMOSI, MISOet SCK(signald’horloge)ainsiquelesmassesdesHC11communiquantentreeux.

Lesprogrammesqui suiventontpourbut detesterla communicationSPI: le maıtre emetdansunpremiertempslesnombresde0 a255surle portSPI(etsursonportA pourverification)et l’esclaveaffichesursonportA lesvaleurslues.LesdeuxafficheursconnectesauxportsA desortiedumaıtreetdel’esclavedoiventmontrerlesmemesvaleurs.Dansundeuxiemetemps,le maıtre lit desvaleurssurle port serieet lesaffichesursonport A toutenlestransmettanta l’esclave. Cesecondprogrammepermetdeverifierqu’il estpossibled’utiliser simultanementla communicationRS232etSPIqui sonttoutesdeuxconnecteesauport D dumaıtre.

0000 8E 00 FF lds #0h00FF0003 CE 10 00 ldx #0h10000006 86 FF ldaa #0hFF ; set port A for output0008 A7 01 staa 0h01,x000A 96 2F ldaa 0h2F ; SS# hi, SCk lo, mosi hi000C A7 08 staa 0h08,x ; store port D000E 86 38 ldaa #0h38 ; - - 1 1 1 0 0 00010 A7 09 staa 0h09,x0012 86 57 ldaa #0h57 ; 7=0111 : polarity, phase, rate1, rate0

; 5=0101 : int, enable, open drain, master0014 A7 28 staa 0h28,x ; set SPCR

0016 86 00 ldaa #0h00 ; start : counter=0

0018 A7 2A snd: staa 0h2A,x ; send datum001A A7 00 staa 0h00,x001C E6 29 wait: ldab 0h29,x001E 2A FC bpl wait ; wait until xfer finished0020 BD 00 26 jsr delay0023 4C inca0024 20 F2 bra snd

0026 18 CE FF FF delay: ldy #0hFFFF002A 18 09 wait_d: dey002C 26 FC bne wait_d002E 39 rts

Master: emissiondesnombresde0 a 255surle port SPI(D) et A.

0000 8E 00 FF lds #0h00FF0003 CE 10 00 ldx #0h10000006 96 2F ldaa 0h2F ; SS# hi, SCk lo, mosi hi0008 A7 08 staa 0h08,x ; store port D000A 86 38 ldaa #0h38 ; - - 1 1 1 0 0 0000C A7 09 staa 0h09,x ; store DDRD000E 86 47 ldaa #0h47 ; 7=0111 : polarity, phase, rate1, rate0

; 5=0101 : int, enable, open drain, master0010 A7 28 staa 0h28,x ; set SPCR0012 86 FF ldaa #0hFF

0014 A7 01 staa 0h01,x ; port A for output0016 86 88 ldaa #0h880018 A7 00 staa 0h00,x ; show 88 on port A while waiting001A rcv:001A E6 29 wait: ldab 0h29,x001C 2A FC bpl wait ; wait until xfer finished001E A6 2A ldaa 0h2A,x ; send datum0020 A7 00 staa 0h00,x0022 20 F6 bra rcv

Slave : receptiondessignauxsurle portSPIet affichagesurle portA

0000 8E 00 FF lds #0h00FF0003 CE 10 00 ldx #0h10000006 86 FF ldaa #0hFF ; set port A for output0008 A7 01 staa 0h01,x

; SPI SETUP000A 96 2F ldaa 0h2F ; SS# hi, SCk lo, mosi hi000C A7 08 staa 0h08,x ; store port D000E 86 38 ldaa #0h38 ; - - 1 1 1 0 0 00010 A7 09 staa 0h09,x0012 86 57 ldaa #0h57 ; 7=0111 : polarity, phase, rate1, rate0

; 5=0101 : int, enable, open drain, master0014 A7 28 staa 0h28,x ; set SPCR

; SERIAL PORT SETUP

; bset 0h28,X,#0h20 ; ne fontionne pas si D port en open-drain0016 6F 2C clr 0h2c,x0018 CC 33 0C ldd #0h330C ; set baudrate of serial port to 2400 baud, N81001B A7 2B staa 0h2B,x001D E7 2D stab 0h2D,x

001F 1F 2E 20 FC rs_rc: brclr 0h2E,x,#0h20,rs_rc; receive from RS2320023 E6 2F ldab 0h2F,x0025 E7 2A snd: stab 0h2A,x ; send datum to SPI0027 E7 00 stab 0h00,x0029 E6 29 wait: ldab 0h29,x002B 2A FC bpl wait ; wait until xfer finished002D 20 F0 bra rs_rc

Master: receptiondesvaleursASCII surle port seriepuisechosurle port SPIetA.

10 Contr oled’ ecran LCD :

Nousnousinteresseronsaux ecransbasessur le controleurHitachi HD44780.Dansnotrecasil s’agit d’un ecrande4 16 caracteres.Cetyped’ecranpossedeun connecteura 14 broches,qui sontdansl’ordre (enpartantdu borddel’ ecran): masse(GND), alimentation(+5V), contraste(dansnotrecas -5V), 3 bits decontrole et 8 bits dedonnees.Il existeun modedecommunicationsurseulement4bitsdedonnees,permettantainsidetotalementcontroler l’afficheuravecun seulbusde8 bits.

Les 3 bits de controle sont,de la brochede polarisation(versle bord de l’afficheur)versles brochesdu busde donnees: RSquideterminesi la valeursurle busdedonneesestuneinstruction(0) ouunedonnee(1), R/Wqui determinele sensdela transaction(0 pouruneecriture,1 pourunelecture),et E (enable)qui doit etrea 1 pour rendrel’afficheuractif. Suiventensuiteles lignesdedonneesencommenc¸antdela ligne0 (poidsle plusfaible)jusqu’ala ligne7 (poidsle plusfort, aubordduconnecteur).Enmodedecommunication4 bits,seulslesligne D4-D7sontutilisees.

Le modele plussimpled’utilisationestsur8 bitsdedonnees.Nousconnectonsle busdedonneesauportB du68HC11et le busdecontroleauport A. Lestableauxci-dessousresumentle brochage,lescommandesa envoyersurlesbusdedonneeset decontrole,ainsiquelesvaleurspossiblesdesvariablesdeconfigurationdel’ ecranet leur assignation(entreparentheses)dansnosexemples.

1 2 3 4 5 6 7 - 14Vss Vcc=+5V Vee 0V RS R/W E D0 - D7

Brochagedel’afficheurLCD (la broche1 estla plusprochedu borddel’afficheur)

7

Page 8: 68hc11

RS R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0ClearDisplay 0 0 0 0 0 0 0 0 0 1EntryModeSet 0 0 0 0 0 0 0 1 I/D SDisplayON/OFF 0 0 0 0 0 0 1 D C BFunctionSet 0 0 0 0 1 DL N F * *SetDD RAM address 0 0 1 A A A A A A AReturnHome 0 0 0 0 0 0 0 0 1 *CursorandDisplayShift 0 0 0 0 0 1 S/C R/L * *SetCGRAM address 0 0 0 1 A A A A A AReadbusyflag andaddress 0 1 BF A A A A A A AWrite datato CGor DD RAM 1 0 D D D D D D D DReaddatafrom CGor DD RAM 1 1 D D D D D D D DD (0) : displayon(1)/off(0)C (0) : curseuron(1)/off(0)B (0) : curseurclignotanton(1)/off(0)

DL (1) : interfacesur8 bits (4 bits si DL=0)N (1) : 2 lignesF (0) : font 5 x7

I/D (1) : incrementerla positiondu curseurapresaffichageS (0) : S=0lorsdesutilisationshabituelles(?!)

LCD Display LCD Display

-5V +5V GND

22k

Port A Port BHC11

3

-5V +5V GND

822k

34

HC11Port A

Nousn’utiliseronsqueles fonctionspresenteesdansla partiesuperieuredu tableau.Les fonctionsde la partieinferieureservent amodifierlescaracteresdisponiblessurl’afficheuret a lire l’ etatdu controleurdel’afficheur.

Il estprudentdetoujoursattendreaumoins40 µsapreschaqueinstruction.Connexion du68HC11a l’afficheurLCD pourunbusdedonneessur8 bits (gauche)et unbusdedonneessur4 bits (droite).

MA

X23

2

4066

68HC11F1

RS

232

conn

ecto

r

A0 : RS

A2 : EA1 : R/W

Dat

a bu

s

D8

D0

C E

B

F

A

A0-A2

MA

X23

2

4066

68HC11F1

RS

232

conn

ecto

r

A0 : RS

A2 : EA1 : R/W

C E

B

F

A

A0-A2A7-A4A4 : D4

A7 : D7

Vuededessusducircuit debasedu 68HC11avecpositiondesbusreliantl’ ecranLCD auxportsduHC11,dansle casd’unecommunicationen8 bits(gauche)et4 bits (droite).

0000 8E 01 FF lds #0h01FF ; setup : stack & port A for output0003 CE 10 00 ldx #0h10000006 86 FF ldaa #0hFF0008 A7 01 staa 0h01,x

; DISPLAY SETUP : START000A 86 01 on: ldaa #0h01 ; clear display000C 8D 21 bsr funct000E 86 F2 ldaa #0hF2 ; R/W#=1 + display ’F’0010 8D 4E bsr delai0012 86 38 set: ldaa #0h38 ; set : 0h38 (8 bit, 4 lines)0014 8D 19 bsr funct

;off: ldaa #0h08 ; display off : 0h08; bsr funct;

0016 86 0C blank: ldaa #0h0C ; displ2 : 0h0C0018 8D 15 bsr funct001A 86 06 entry: ldaa #0h06 ; entry mode : 0h06001C 8D 11 bsr funct

; END OF SETUP

001E 8D 50 bsr messg ; AFFICHE HELLO WORLD0020 86 15 ldaa #0h15 ; position0022 C6 33 ldab #0h33 ; char0024 8D 1C bsr gotoxy0026 set_dd:0026 5C incb0027 8D 24 bsr char ; display0029 C1 38 cmpb #0h38002B 26 F9 bne set_dd002D start:002D 20 FE bra start

; data bus (port A) a ete set to action | RS = 0 (set function); input : function in register A

002F A7 04 funct: staa 0h04,x0031 86 F0 ldaa #0hF0 ; bit 1 : R/W#=00033 8D 2B bsr delai0035 86 F4 ldaa #0hF4 ; bit 2 : E=10037 8D 27 bsr delai0039 86 F0 ldaa #0hF0 ; E=0

8

Page 9: 68hc11

003B 8D 23 bsr delai003D 86 F2 ldaa #0hF2 ; R/W#=1003F 8D 1F bsr delai0041 39 rts

; goto a wanted position and display a char (automat-icly shifts right after)

; input : char value in register B and position in register A0042 8A 80 gotoxy: oraa #0h80 ; reg A -> set @ to reg A0044 A7 04 staa 0h04,x0046 8D E7 bsr funct0048 E7 04 stab 0h04,x004A 8D 01 bsr char004C 39 rts

; data bus (port A) a ete set to char | RS = 1 (draw char); input : char value in register B

004D E7 04 char: stab 0h04,x004F 86 11 ldaa #0h11 ; RS=1, R/W#=0, E=00051 8D 0D bsr delai0053 86 15 ldaa #0h15 ; RS=1, R/W#=0, E=10055 8D 09 bsr delai0057 86 11 ldaa #0h11 ; E=00059 8D 05 bsr delai005B 86 12 ldaa #0h12 ; RS=0, R/W#=1, E=0005D 8D 01 bsr delai005F 39 rts

; attente0060 A7 00 delai: staa 0h00,x ; met le registre A sur le port A0062 86 01 ldaa #0h010064 18 CE 2F FF dedans: ldy #0h2FFF ; ldab #0h06 et ldy #0hFFFF => 693 ms

0068 18 09 dedans2:dey ; ----1 -- --- ------- => 115 ms006A 26 FC bne dedans2 ; ----1 -- --- #0h2FFF => 21.5 ms006C 4A deca006D 26 F5 bne dedans006F 39 rts

; DEBUT DE L’AFFICHAGE CST :0070 86 02 messg: ldaa #0h02 ; position (starts at 0)0072 C6 48 ldab #0h48 ; H0074 8D CC bsr gotoxy0076 C6 65 ldab #0h65 ; e0078 8D D3 bsr char ; display007A C6 6C ldab #0h6C ; l007C 8D CF bsr char007E C6 6C ldab #0h6C ; l0080 8D CB bsr char0082 C6 6F ldab #0h6F ; o0084 8D C7 bsr char0086 C6 20 ldab #0h20 ; ’ ’0088 8D C3 bsr char008A C6 57 ldab #0h57 ; W008C 8D BF bsr char008E C6 6F ldab #0h6F ; o0090 8D BB bsr char0092 C6 72 ldab #0h72 ; r0094 8D B7 bsr char0096 C6 6C ldab #0h6C ; l0098 8D B3 bsr char009A C6 64 ldab #0h64 ; d009C 8D AF bsr char009E 39 rts

Exempledeprogrammepouruneinterface8 bits

0000 8E 01 FF lds #0h01FF ; setup : stack & port A for output0003 CE 10 00 ldx #0h10000006 86 FF ldaa #0hFF0008 A7 01 staa 0h01,x

; DISPLAY SETUP : START

000A 8D 26 bsr delai

000C 86 28 set: ldaa #0h28000E 8D 2D bsr funct0010 86 01 on: ldaa #0h01 ; clear display0012 8D 29 bsr funct0014 86 F2 ldaa #0hF2 ; R/W#=1 + display ’F’0016 8D 1A bsr delai0018 86 0C blank: ldaa #0h0C ; displ2 : 0h0C001A 8D 21 bsr funct001C 86 06 entry: ldaa #0h06 ; entry mode : 0h06001E 8D 1D bsr funct

; END OF SETUP

0020 BD 00 B0 jsr messg ; AFFICHE HELLO WORLD0023 86 15 ldaa #0h15 ; position0025 C6 35 ldab #0h35 ; char0027 8D 42 bsr gotoxy0029 set_dd:0029 5C incb002A 8D 4A bsr char ; display002C C1 3B cmpb #0h3B002E 26 F9 bne set_dd0030 start:0030 20 FE bra start

; attente0032 A7 00 delai: staa 0h00,x ; met le registre A sur le port A0034 18 CE 3F FF ldy #0h3FFF0038 18 09 dedans2:dey003A 26 FC bne dedans2003C 39 rts

; data bus (port A) a ete set to action | RS = 0 (set function); input : function in register A

003D 36 funct: psha003E 37 pshb003F 36 psha0040 84 F0 anda #0hF0 ; hi = char ; lo = 00000042 A7 00 staa 0h00,x ; FIRST NIBBLE0044 8D EC bsr delai0046 1C 00 04 bset 0h00,x,#0h04 ;ldaa #0hF4 : bit 2 : E=10049 8D E7 bsr delai004B 1D 00 04 bclr 0h00,x,#0h04 ; E=0004E 8D E2 bsr delai0050 32 pula0051 48 lsla0052 48 lsla0053 48 lsla0054 48 lsla0055 A7 00 staa 0h00,x ; SECONDNIBBLE0057 8D D9 bsr delai0059 1C 00 04 bset 0h00,x,#0h04 ;ldaa #0hF4 : bit 2 : E=1005C 8D D4 bsr delai005E 1D 00 04 bclr 0h00,x,#0h04 ; E=00061 8D CF bsr delai0063 1C 00 02 bset 0h00,x,#0h02 ; R/W#=10066 8D CA bsr delai0068 33 pulb0069 32 pula006A 39 rts

; goto a wanted position and display a char (automat-icly shifts right after)

; input : char value in register B and position in register A006B 8A 80 gotoxy: oraa #0h80 ; reg A -> set @ to reg A006D A7 04 staa 0h04,x006F 8D CC bsr funct0071 E7 04 stab 0h04,x0073 8D 01 bsr char0075 39 rts

; data bus (port A) a ete set to char | RS = 1 (draw char); input : char value in register B

0076 36 char: psha0077 37 pshb0078 C4 F0 andb #0hF0007A E7 00 stab 0h00,x ; FIRST NIBBLE, RS=1, R/W#=0, E=0007C 1C 00 01 bset 0h00,x,#0h01 ; RS=1007F 8D B1 bsr delai0081 1C 00 04 bset 0h00,x,#0h04 ; RS=1, R/W#=0, E=10084 8D AC bsr delai0086 1D 00 04 bclr 0h00,x,#0h04 ; E=00089 8D A7 bsr delai008B 58 lslb008C 58 lslb008D 58 lslb008E 58 lslb008F C4 F0 andb #0hF00091 E7 00 stab 0h00,x ; SECONDNIBBLE, RS=1, R/W#=0, E=00093 1C 00 01 bset 0h00,x,#0h01 ; RS=10096 8D 9A bsr delai0098 1C 00 04 bset 0h00,x,#0h04 ; RS=1, R/W#=0, E=1009B BD 00 32 jsr delai009E 1D 00 04 bclr 0h00,x,#0h04 ; E=000A1 BD 00 32 jsr delai00A4 1C 00 02 bset 0h00,x,#0h02 ; RS=0, R/W#=1, E=000A7 1D 00 01 bclr 0h00,x,#0h01 ; RS=0, R/W#=1, E=000AA BD 00 32 jsr delai00AD 33 pulb00AE 32 pula00AF 39 rts

; DEBUT DE L’AFFICHAGE CST :00B0 86 02 messg: ldaa #0h02 ; position (starts at 0)00B2 C6 48 ldab #0h48 ; H00B4 8D B5 bsr gotoxy00B6 C6 65 ldab #0h65 ; e00B8 8D BC bsr char ; display00BA C6 6C ldab #0h6C ; l00BC 8D B8 bsr char00BE C6 6C ldab #0h6C ; l00C0 8D B4 bsr char00C2 C6 6F ldab #0h6F ; o00C4 8D B0 bsr char00C6 C6 20 ldab #0h20 ; ’ ’00C8 8D AC bsr char00CA C6 57 ldab #0h57 ; W00CC 8D A8 bsr char00CE C6 6F ldab #0h6F ; o00D0 8D A4 bsr char00D2 C6 72 ldab #0h72 ; r00D4 8D A0 bsr char00D6 C6 6C ldab #0h6C ; l00D8 8D 9C bsr char00DA C6 64 ldab #0h64 ; d00DC 8D 98 bsr char00DE 39 rts

Exempledeprogrammepouruneinterface4 bits. A noterquepourdesraisonsdeproblemesdedelaisdanslesinitialisations,il fautrelancerplusieursfois ceprogrammeavantqu’unmessagenes’affichesurl’ ecranLCD (effectuerun resetdu 68HC11maisnepaseteindrele generateurdetension

entredeuxreprogrammationsafin denepasre-initialisera chaquefois l’ ecranLCD).

9

Page 10: 68hc11

11 Les interruptions

11.1 Les interruptions materiellesIRQ#

11.1.1 Aspectmateriel

Modificationsau circuit initial : mettrele bit I du registrede controle par cli va rendreles interruptionsmateriellesactives. Pardefaut, toutesles sourcesinternesau 68HC11d’interruptionsmaterielles(principalementles timers)sont inactives. Il nousfaut deplusdesactiver lesbrochesd’interruptionsmateriellesXIRQ et IRQ (activesparun signalauniveaubas)enajoutantdeuxresistancesde pull-up entrel’alimentation(Vdd=+5V) et cesbroches.L’activationde l’interruption materielle IRQ sefait alorsen mettantcettebrocheauniveaubas(parexempleenfermantun interrupteurdansnotreexemple).

11.1.2 Aspectlogiciel

Principedespseudo-vecteurs: les vecteursd’interruptionssontsituesen ROM et ne sontdoncpasmodifiablespour pointervers lafonctiondel’utilisateur. Cesvecteurspointentversdespseudo-vecteurspre-definisqui sonteuxsituesenRAM. Il s’agit enfait detroisoctetsreservesa l’action aeffectuerlorsquel’interruptionestdeclenchee: uneinstructionJMP(0x7E)suivi des2 octetsdel’adressedela fonctiondel’utilisateur. La listedesadressesdespseudo-vecteursestdisponiblep. 3-18du68HC11ReferenceManualdeMotorola.

Le premierexempleque nousproposonsici sert a bien identifier la syntaxe permettantde recuperer l’adresseou se situe uneprocedure,et de voir commentmanipulercetteadresse.Dans le programmeci-dessous,la procedurenommee irq commenceal’adresse0x0026. Nousallonscherchercetteadresse,la stocker dansle registre16 bits X, puis transfererX dansD (qui esten faitla concatenationde A et B) de facon a pouvoir successivementaffichersur le port A les valeursdesregistresA et B et ainsipouvoirvisualiser(parexemplesurunafficheur7 segmentsconnecteauportA) l’adressedela procedure(cetteetapeintermediaire- le passagedeX a D - estobligatoirepour pouvoir visualiserla valeurstockeedansX. Il n’estpaspossibled’envoyer directementX, qui estsur16 bits, surun desportsd’entree-sortie8 bits). Il fautprendresoin,lors dela recherchedel’adressedela procedureirq , d’utiliser lasyntaxe ldx #irq qui renvoie l’adresseou setrouve irq (0h0023dansnotrecas),et nonpasldx irq qui renvoie le contenudel’octet setrouvanta l’adresseirq (0x86dansnotrecas,qui estl’opcodedel’instruction ldaa ).

IRQ

XIRQ

0000 8E 00 FF lds #0h00FF0003 86 FF ldaa #0hFF ; DDRA : output0005 B7 10 01 staa 0h10010008 86 7E ldaa #0h7E ; opcode de JMP000A 97 EE staa 0h00EE ; interrupt vector-1=JMP opcode000C CE 00 23 ldx #irq ; ISR de IRQ# : ldx irq=00 86 (opcode de jmp)->ldx #irq000F DF EF stx 0h00EF ; interrupt vector0011 CE 10 00 ldx #0h1000

; cli ; enable interrupts0014 18 DE EF ici: ldy 0h00EF ; BFF2=00 ; BFF3=EE ; 00EE=7E ; 00EF=86 ; F0=00; F1=240017 18 8F xgdy ; echange X et D0019 A7 00 staa 0h00,x ; afficher alternativement001B 8D 09 bsr delai ; ... A et B pour montrer001D E7 00 stab 0h00,x ; ... ce qui etait dans X001F 8D 05 bsr delai0021 20 F1 bra ici

0023 86 00 irq: ldaa #0h00 ; reset port A0025 3B rti

0026 18 CE FF FF delai: ldy #0hFFFF002A 18 09 wait: dey002C 26 FC bne wait002E 39 rts

Programmedelecturedela valeurstockeedansunpseudo-vecteurdu 68HC11etaffichagesurle portA (verificationdela programmationdel’adressedela fonctiondegestiondesinterruptions)

L’instructioncli metle bit I du registredecontrole a 0 et metainsienmarchelesinterruptionsmaterielles.Application au casde la re-initialisationd’une variablepar uneinterruptionmaterielle. Il estnecessairede passerpar unezone

memoireen RAM car l’appel a une fonction provoqueun empilementdesregistresqui serontensuitere-initialises a leurs valeursinitiales lors de l’instruction rti . Ceprogrammefait defiler lesnombresbinairessur le port A, et remetle compteura 0 chaquefoisqu’uneinterruptionmaterielleestprovoqueeparla fermeturedel’interrupteur.

0000 8E 00 FF lds #0h00FF0003 86 FF ldaa #0hFF ; DDRA : output0005 B7 10 01 staa 0h10010008 86 7E ldaa #0h7E ; opcode de JMP000A 97 EE staa 0h00EE ; interrupt vector-1=JMP opcode000C CE 00 24 ldx #irq ; ISR de IRQ# : ldx irq=00 86 (opcode de jmp)->ldx #irq000F DF EF stx 0h00EF ; interrupt vector0011 CE 10 00 ldx #0h10000014 0E cli ; enable interrupts0015 86 00 ldaa #0h000017 97 E0 staa 0h00E00019 96 E0 ici: ldaa 0h00E0001B 4C inca

001C 97 E0 staa 0h00E0001E A7 00 staa 0h00,x0020 8D 07 bsr delai0022 20 F5 bra ici

0024 86 00 irq: ldaa #0h00 ; PAS ldaa #0h00 directmt car rti pop regs0026 97 E0 staa 0h00E00028 3B rti

0029 18 CE FF FF delai: ldy #0hFFFF002D 18 09 wait: dey002F 26 FC bne wait0031 39 rts

10

Page 11: 68hc11

Exemplederemisea 0 parinterruptionmaterielled’un compteur: le portA affichelesvaleurscroissantesd’un constanted’un compteurqui estremisa 0 parla fermeturedel’interrupteurreliantla brocheIRQ a la masse.

11.2 Les interruptions materiellesli eesaux timers

Il fautpenser, pour touteutilisationdesinterruptionsmateriellesli eesaux timersinternesdu HC11,a effectuerla modificationsur lesbrochesIRQ et XIRQ (enlesreliantvia uneresistanced’environ 5 kΩ a l’alimentationVdd).

L’utilisationducompteurpresenteeici permetderealiserunschedulerlorsqueplusieurstachesdoiventetreexecuteessequentiellementavec une periodicite donnee, ou une modulationen largeur de pulse (PWM). Dans le but d’avoir le tempsde voir le compteurosciller, nousavons decide d’abaisserla frequencedu timer au 16eme de sa valeur par defaut en mettantPR1 et PR0 du registreTMSK2 (0h1024)a 1. Le compteurva de 0 a 65536 en 524.3/2ms (i.e. 4 µs par tic d’horloge). On le fait compterde 1 a0hDFFF=53248+3840+240+15=57343soit229.4msentredeuxincrementsducompteur.

La valeurdu compteur, incrementea chaqueinterruption,estafficheesurlesportsA et B. La broche6 duportA oscilledeplusa lafrequencedesinterruptions(sortiePWM).

0000 8E 00 FF lds #0h00FF ; stack0003 86 FF ldaa #0hFF ; set port A for output0005 B7 10 01 staa 0h1001 ; | on affiche cpt val sur A et B, et A6=PWM0008 86 7E ldaa #0h7E ; opcode de JMP000A 97 DC staa 0h00DC ; interrupt vector of OC2000C CE 00 2E ldx #int ; ISR de int000F DF DD stx 0h00DD ; interrupt vector+1 de OC2 = int @

0011 CE 10 00 ldx #0h10000014 1C 24 03 bset 0h24,x,#0h03 ; prescaler : ici, divise la vitesse par 16

0017 86 40 ldaa #0h40 ; only work on OC_2_0019 A7 23 staa 0h23,x ; clear any pending flag001B A7 22 staa 0h22,x ; enable OC2 interrupt001D 86 40 ldaa #0h40 ; intOC2 : 0h00 -> do not affect port A pin001F A7 20 staa 0h20,x ; 0h40 -> toggle output of port A6 on int

0021 86 00 ldaa #0h00 ; initialisation du compteur0023 97 E0 staa 0h00E0 ; octet en RAM stockant la valeur a afficher0025 0E cli ; enable interrupts : check pull ups on IRQ & XIRQ0026 96 E0 ici: ldaa 0h00E00028 A7 04 staa 0h04,x ; display counter value on port B002A A7 00 staa 0h00,x ; display counter value on port A002C 20 F8 bra ici

002E 96 E0 int: ldaa 0h00E0 ; PAS inca directmt car rti pop regs0030 4C inca ; incremente le compteur0031 97 E0 staa 0h00E0 ; stocke le result0033 CC DF FF ldd #0hDFFF ; 1/2 delay PWM<- duree entre 2 transitions0036 E3 12 addd 18,x ; add value of counter 2 to delay0038 ED 12 std 18,x ; store in counter -> time of next interrupt003A 86 40 ldaa #0h40003C A7 23 staa 0h23,x ; clear flag by setting 0100 0000 (OC2)003E 3B rti

11.3 Programmation multi-t a chesau moyendesinterruptions - l’instruction WAI

Jusqu’ici,nosprogrammesn’etaientcapablesqued’effectueruneoperationa la fois : soit faire l’acquisitionsde donneesprovenantdesconvertisseursanalogiques-numeriques,soit transmettredesdonneessur le port serie,soit attendrela receptionde donneessur leportRS232.L’utilisation desinterruptionsdansl’exemplequi suit vadonnerl’impressionquele 68HC11estcapabledesimultanementincrementerun compteurdefacon periodiquetout enetanta l’ ecoutedu port serie. De plus,mettretoutesles fonctionsa executerparle microcontroleursousinterruptionpermetuneeconomied’energieparl’ executiondel’instruction WAI lorsquequ’aucunetachen’estaexecuter. Cetteinstructionmetle 68HC11enmodeveille qui consommemoinsdecourant.Le microcontroleurestreactive lorsqu’uninterruptionqui a ete autorisee(dansnotrecasle timer, la receptiond’un messagesur le port serie ou l’activation de l’interruptionmateriellesurla brocheIRQ) estdeclenchee.

0000 8E 01 20 1 lds #0h0120 ; set stack0003 CE 10 00 2 ldx #0h10000006 86 00 3 ldaa #0h00 ; port A setup for input0008 A7 01 4 staa 0h01,x ; |

5000A 86 7E 6 ldaa #0h7E ; opcode de JMP000C 97 C4 7 staa 0h00C4 ; interrupt vector-1=JMP opcode000E CE 00 2F 8 ldx #irq ; ISR de IRQ# : ldx irq=00 86 (op-

code de jmp)->ldx #irq0011 DF C5 9 stx 0h00C5 ; interrupt vector0013 CE 10 00 10 ldx #0h10000016 0E 11 cli ; enable interrupts

120017 1C 28 20 13 bset 0h28,x,#0h20 ; serial port setup001A 6F 2C 14 clr 0h2c,x001C CC 33 2C 15 ldd #0h332C ; set baudrate, enable recv & tx001F A7 2B 16 staa 0h2B,x ; 2400 N81 with 16 MHz xtal

0021 E7 2D 17 stab 0h2D,x ; 2 de 2C : enable receive interrupt18

0023 19 main: ; ldaa 0h0100 ; read stored value20 ; staa 0h05,x ; and display on port F

0023 3E 21 wai ; low power sleep mode0024 20 FD 22 bra main

230026 18 CE FF FF 24 delai: ldy #0hFFFF002A 18 09 25 wait: dey002C 26 FC 26 bne wait002E 39 27 rts

28002F 1F 2E 20 FC 29 irq: brclr 0h2E,x,#0h20,irq ; reset serial port0033 A6 2F 30 ldaa 0h2F,x ; load received character0035 B7 01 00 31 staa 0h0100 ; store in memory0038 A7 05 32 staa 0h05,x ; display on port F003A 3B 33 rti ; end of interrupt service routine

Exempled’interruptiondeclencheea la receptiond’un caracteresurle port serie: le compteurestremplace parla valeurASCII du caractererecu.

0000 8E 01 20 1 lds #0h0120 ; set stack0003 CE 10 00 2 ldx #0h10000006 86 00 3 ldaa #0h00 ; port A setup for input0008 A7 01 4 staa 0h01,x ; |

56 ; setup serial port interrupt routine

000A 86 7E 7 ldaa #0h7E ; opcode de JMP000C 97 C4 8 staa 0h00C4 ; interrupt vector-1=JMP opcode <- se-

rial port000E 97 D0 9 staa 0h00D0 ; interrupt vector-1=JMP opcode <-

timer overflow10 ; staa 0h00EE ; interrupt vector-1=JMP opcode <- IRQ

0010 CE 00 4F 11 ldx #intrs2320013 DF C5 12 stx 0h00C5 ; interrupt vector0015 CE 00 41 13 ldx #ovltimr0018 DF D1 14 stx 0h00D1 ; interrupt vector

15 ; ldx #irq ;16 ; stx 0h00EF ; interrupt vector

001A CE 10 00 17 ldx #0h1000001D 0E 18 cli ; enable interrupts

19 ; setup serial port001E 1C 28 20 20 bset 0h28,x,#0h20 ; serial port setup0021 6F 2C 21 clr 0h2c,x0023 CC 33 2C 22 ldd #0h332C ; set baudrate, enable recv, tsmit & int0026 A7 2B 23 staa 0h2B,x0028 E7 2D 24 stab 0h2D,x

25 ; enable timer overflow interrupt002A 1D 25 7F 26 bclr 0h25,x,#0h7F ; clear overflow (if any)002D 1C 24 83 27 bset 0h24,x,#0h83 ; enable interrupt and prescaler=16

28 ; lsla : logic shift left A0030 86 00 29 ldaa #0h00 ; timer related interrupt0032 B7 01 01 30 staa 0h01010035 31 ici: ; ldaa 0h0100

32 ; staa 0h05,x0035 3E 33 wai0036 20 FD 34 bra ici

350038 18 CE FF FF 36 delai: ldy #0hFFFF003C 18 09 37 wait: dey003E 26 FC 38 bne wait0040 39 39 rts

400041 86 80 41 ovltimr:ldaa #0h800043 A7 25 42 staa 0h25,x ; clear overflow flag0045 B6 01 01 43 ldaa 0h01010048 4C 44 inca0049 A7 05 45 staa 0h05,x004B B7 01 01 46 staa 0h0101004E 3B 47 rti

48004F 49 intrs232: ; store char at memory location 0h100004F 1F 2E 20 FC 50 brclr 0h2E,x,#0h20,intrs232

11

Page 12: 68hc11

0053 A6 2F 51 ldaa 0h2F,x0055 B7 01 00 52 staa 0h0100

0058 A7 05 53 staa 0h05,x005A 3B 54 rti

Exempledecombinaisondesinterruptiontimer (incrementdu compteur)etdereceptionsurle port serie.Noterquela procedureprincipaleestuniquementformeed’unebouclesurla fonctionWAI dontl’int eretestl’ economiedecourant.

Nousatteignonsici leslimitesdu68HC11F1enmodemono-composantpuisquele gestionnairedeport serieetducompteuroccupepresquela totalite des512 octetsd’EEPROM disponibles. Il faut ensuiteajouterde l’EEPROM externeou trouver uneversiondumicrocontroleurpossedantplusdememoire.

A Programmed’envoi desdonneesdu PC vers le 68HC11: hc11.pas (Turbo Pascal(7), DOS)

Le programmehc11.pas fonctionnedela faconsuivante(routineRunTerminal() : le programmeenvoietoutd’abordle caractere0hFFpourprevenirle HC11quele programmeseratransfereparle portserie,puisouvrele fichierqui estpasseenpremierargument.Cefichier contient,sousformedecaracteresASCII, unesuitedenombreshexadecimaux.Le programmeprendchaquepairedecaracteres(separesparun espaceou un retourchariot),les interpretecommeun nombreenhexadecimal,et envoie le resultatsur le port serie. Sideuxargumentssontpassesenligne decommande,le programmesupposequele premierprogrammeestee.out (dont le role estderecupererlesdonneessur le port seriepour lesstocker en EEPROM) et relancedoncl’ emissiondesdonneesstockeesdansle secondfichier apresavoir attendu1 spourpermettrel’executiondeee .

Le role deceprogrammeestdoncd’initialiser le port serie (choisidanscetexemplecommeCOM1 avecunevitessede transmis-sion de 2400bauds)et d’envoyer un programmestocke commeunesuitede valeurshexadecimalesdansla RAM du 68HC11. Si leprogrammeenvoye en RAM est le logiciel charge de stocker desdonneesen EEPROM, le passageen secondargumentdu nom duprogrammea chargerdansl’EEPROM du 68HC11lancerala routinede transmissiondecesecondprogrammeapresavoir execute lepremierprogrammestockeenRAM.

La procedureRunTerminal pourra etre modifie selon les besoinsde communicationpar le port serie, par exemplepour larecuperationdesdonneesluesenRAM parle 68HC11et renvoyeesauPCparle port serie.

ADDITIONS & MODIFICATIONS by jmfriedt* removed the interactive terminal part* added an ugly delay() in the sndchar() procedure

program TERMINAL;

******************************************************************* ******* TERMINAL Turbo Pascal 7.0 Demo Programm Written 1995 by Stephan A. Maciej Internet: [email protected] For any questions, please mail to [email protected] ! WWW:http://www.muc.de/˜stephanm ******************************************************************* ******* This program is for demonstration purpose only. Any commercial use with- out the written permission of the author is illegal. Please report bugs, corrections or any other ideas to [email protected]. You are allowed to distribute this program as often as you want as long as you do not change it or edit it anyway. The author is not responsible for any damage or destruction caused - directly or indirectly - by this program. ******************************************************************* *******

uses Crt;

constTxDataReg = 0; transmitter data register RxDataReg = 0; reciever data register DivLow = 0; divisor latch, low byte DivHigh = 1; divisor latch, high byte IntrEnable = 1; interrupt enable register IntrId = 2; interrupt identification register FifoCtrl = 2; first-in/first-out buffer controller LineCtrl = 3; line controll register ModemCtrl = 4; modem controll register LineStatus = 5; line status register ModemStatus = 6; modem status register ScratchReg = 7; scratch pad (free useable)

constQueueLen = 1024; Length of a queue in bytes

type The TQueue type TQueue = record

Content: array[0..QueueLen - 1] of byte;Start: word;Stop: word;end;

type The TQuadString type TQuadString = string[4]; For the Hex-function

var The two queues, one for incoming characters, the other for outgoing characters. InQueue: TQueue; The two queues: one for input buffering, OutQueue: TQueue; the other for output buffering

constSpeedCount = 19; Number of valid speeds stored below

constAllowedSpeeds: array[0..SpeedCount] of longint =

( 50, 75, 110, 150, 300, 600, 900, 1200,1800, 2400, 3600, 4800, 7200, 9600, 14400, 19200,

28800, 38400, 57600, 115200);

Just add any other speeds supported by your UART/Modem - don’t forget to increase the SpeedCount

var Some global variables... PortNr: byte; Number of the used port (1, 2 etc.) PortBase: word; I/O base address of the used port Speed: longint; Speed in baud UARTType: byte; UART type (one of the UART_xxxx constants UsedIRQ: byte; The number of the used IRQ

procedure SendEOI; assembler; Send a EOI to the Interrupt Controller asm

mov al, 20hout 20h, al

end;

function GetPortBase(N: byte): word; assembler; Read the I/O base address of the desired port from the BIOS data segment asm

Load the segment address of the BIOS data segment into ES mov ax, 0040hmov es, ax Calculate the offset of the I/O port base address xor ax, axmov al, Ndec alshl ax, 1mov si, ax Read the desired value and return mov ax, es:[si]

end;

procedure SetIntVec(N: byte; P: pointer); assembler; Set an interrupt vector to the given address asm

push ds Just use the MS-DOS function 25h to set the vector mov ah, 25hmov al, N ds:dx contains the vector to set lds dx, Pint 21hpop ds

end;

function GetIntVec(N: byte): pointer; assembler; Get the interrupt vector asm

push es Use the MS-DOS function 35h to read the vector mov ah, 35hmov al, Nint 21h Move the vector from es:bx to dx:ax mov ax, bxmov dx, espop es

end;

12

Page 13: 68hc11

procedure ResetQueue(var Q: TQueue); Resets a Queue begin

Q.Start := 0;Q.Stop := 0;

end;

procedure PutQueueByte(var Q: TQueue; B: byte); Put a byte into the Queue begin

Put the byte into the Queue before incrementing the Queue end Q.Content[Q.Stop] := B;

Now increment the Queue end position. When Q.Stop reaches QueueLen, be sure you don’t increment Q.Stop but wrap it around to 0 again ! inc(Q.Stop);if (Q.Stop = QueueLen) then

Q.Stop := 0;

end;

function GetQueueByte(var Q: TQueue; var B: byte): boolean; Get a byte out of the Queue begin

if (Q.Stop = Q.Start) then If the Queue is empty, just return false. Don’t set B anyway. GetQueueByte := false

elsebegin

Queue is not empty: return true. GetQueueByte := true;

Get the first byte out of the Queue and return it in B. B := Q.Content[Q.Start];

Now increment the Queue position. Be sure to wrap it to zero if the Q.Start field reaches the QueueLen constant. inc(Q.Start);if (Q.Start = QueueLen) then

Q.Start := 0;end;

end;

procedure SerialInterrupt; interrupt; This procedure handles any incoming events from the UART. var

Id: byte;Trash: byte;

beginrepeat

Now read the Interrupt Identification register Id := Port[PortBase + IntrId];

Check if there’s any pending interrupt. if ((Id and 1) = 0) then

begin

Now select the event. case ((Id and 6) shr 1) of

$03: The Line Status register changed. begin

Just read the LSR to clear the event. Trash := Port[PortBase + LineStatus];

end;$02:

Data arrived at the UART. begin

Read out the data from the RxD register and store it in the incoming Queue. Trash := Port[PortBase + RxDataReg];PutQueueByte(InQueue, Trash);

end;$01:

The TxD register is empty. begin

If there’s any byte in the outgoing Queue, send it to the UART, else disable this interrupt. if (GetQueueByte(OutQueue, Trash)) then

Port[PortBase + TxDataReg] := Trashelse

Port[PortBase + IntrEnable] := $0D;

end;$00:

The Modem Status register changed. begin

Just read the MSR to clear the event. Trash := Port[PortBase + ModemStatus];

end;end;

end;

Handle all interrupts ! Just check if there’s one more interrupt pending.

until ((Id and 1) = 1);

Now tell the PIC our interrupt handler has finished it’s work. SendEOI;

end;

procedure SendChar(C: char); Send a char to the modem begin

Put the character into the outgoing queue. PutQueueByte(OutQueue, byte(C)); Enable the "Transmitter register empty" interrupt Port[PortBase + IntrEnable] := $0F;

end;

constUART_Bad = 0; Bad UART: not working or unidentifieable UART_8250 = 1; Standart 8250 UART UART_16450 = 2; 16450 UART (faster than 8250) UART_16550 = 3; 16550 UART (with buggy 16-byte FIFO) UART_16550A = 4; 16550A UART (with working FIFO)

function GetUARTType(Base: word): byte; assembler; Check which UART type is assigned to the appropriate port asm

First difference: The 16450 has a scratch register which is readable and writeable. Check if it’s there. If not, we’ve

got a 8250 UART. mov dx, Baseadd dx, ScratchRegmov al, 0AAhout dx, alin al, dxcmp al, 0AAhje @@1mov ax, UART_8250jmp @@5

@@1: Now check out if the UART has got a FIFO. If it has none, it’s a 16450, if it has one but it’s not working it’s a 16550. The UART will be identified as a 16550A if the FIFO is working. mov dx, Baseadd dx, FifoCtrlmov al, 01hout dx, alnopmov dx, Baseadd dx, IntrIdin al, dxand al, 0C0hcmp al, 0C0hjne @@2mov al, UART_16550Ajmp @@5

@@2: cmp al, 80hjne @@3mov al, UART_16550jmp @@5

@@3: cmp al, 0jne @@4mov al, UART_16450jmp @@5

@@4: mov al, UART_Bad@@5: nopend;

procedure UpCaseStr(var S: string); assembler; Convert all chars in a string to uppercase letters asm

les di, Sxor cx, cxmov cl, es:[di]inc di

@@1: mov al, es:[di]cmp al, ’a’jb @@2cmp al, ’z’ja @@2 Chars between ’a’ and ’z’ will be uppercased here. sub al, 20h

@@2: mov es:[di], alinc diloop @@1

end;

procedure GetCommandLine(var PortId: byte; var Speed: longint); Check the command line and extract all parameters var

S: string;I: byte;J: integer;

beginPortId := 2;Speed:=2400;end;

procedure EnableIRQ(IRQ: byte); assembler; Enable a given IRQ from 0 to 7 asm

mov cl, IRQmov bl, 1shl bl, clmov ah, 255sub ah, blin al, 21hand al, ahout 21h, al

end;

procedure DisableIRQ(IRQ: byte); assembler; Disable a given IRQ from 0 to 7 asm

mov cl, IRQmov bl, 1shl bl, clin al, 21hor al, blout 21h, al

end;

procedure PrintChar(Character: char); assembler; Print a character on the screen - fast asm

mov ah, 0Ehmov al, Characterxor bh, bhmov bl, 07hint 10h

end;

varOldInterruptVec: pointer;

procedure SetupPort(PortBase: word; Speed: longint; IRQ: byte); Setup the UART and prepare for communication. var

D: word;B: byte;

begin For startup, disable the IRQ for the UART. DisableIRQ(IRQ);

Get the address of the old interrupt handler and set the vector to our won interrupt handling procedure ("SerialInterrupt") OldInterruptVec := GetIntVec($08 + IRQ);SetIntVec($08 + IRQ, @SerialInterrupt);

Enable the "Recieved Data avaliable" interrupt so we can read all data out of the UART’s RxD register. Port[PortBase + IntrEnable] := $01;

13

Page 14: 68hc11

Now clear all pending interrupts - if any repeat

Read all important registers to clear any interrupt types, B is just used for temporary result storage B := Port[PortBase + RxDataReg];B := Port[PortBase + LineStatus];B := Port[PortBase + ModemStatus];

Just repeat until no more interrupts are pending. until ((Port[PortBase + IntrId] and 1) = 1);

Enable the IRQ line for the UART after all pending interrupts have been cleared. EnableIRQ(IRQ);

Calculate the divisor latch contents for the desired baud rate D := (115200 div Speed);

Set the DLAB bit to 1, then write the divisor latch low and high bytes Port[PortBase + LineCtrl] := $80;Port[PortBase + DivLow] := Lo(D);Port[PortBase + DivHigh] := Hi(D);

Now set the divisor latch bit to 0 and write all other values Port[PortBase + LineCtrl] := $03;Port[PortBase + ModemCtrl] := $0B;Port[PortBase + IntrEnable] := $0F;

Check if a 16550A UART is present... if (UARTType = UART_16550A) then

begin Clear the FIFO queues Port[PortBase + FifoCtrl] := $07;

Enable the FIFO queues Port[PortBase + FifoCtrl] := $C1;

Print a message so the user recognizes the FIFO queues are on writeln(’Enabling 16550A FIFO queues...’);

end;end;

procedure RunTerminal(PortBase: word;s:string;s2:string); Run the Terminal var

fc:file of char; 0..255b1,b2,bl:char;cnt,i:integer;

begin

sendchar(’H’);sendchar(’e’);sendchar(’l’);sendchar(’l’);sen dchar(’ o’);sendchar(’ ’);sendchar(’W’);sendchar(’o’);sendchar(’r’);sendchar(’l’) ;sendchar(’d’);sendchar(’ ’);

sendchar(chr(0)); repeat until keypressed;i:=0;assign(fc,s);reset(fc);b1:=’ ’;sendchar(chr($FF)); set baud rate while not EOF(fc) do begin

while ( ((b1=’ ’) or (b1=chr(10)) or (b1=chr(13)) ) and not eof(fc)) doif not eof(fc) then read(fc,b1);

if (ord(b1)>47) then begincnt:=0;read(fc,b2);if (ord(b1)>96) then b1:=chr(ord(b1)-32); min -> majif (ord(b2)>96) then b2:=chr(ord(b2)-32);if (ord(b1)<58) then cnt:=(ord(b1)-48)*16 else cnt:=(ord(b1)-55)*16;if (ord(b2)<58) then cnt:=cnt+(ord(b2)-48) else cnt:=cnt+(ord(b2)-55);sendchar(chr(cnt));inc(i);delay(5);write(cnt,’d=’,b1,b2,’h ’);

end;if not eof(fc) then read(fc,b1);

end;close(fc);

for cnt:=i to 1024 do sendchar(chr(0));

delay(1000);writeln(’RAM done’);

if (s2<>’ ’) then beginwriteln;writeln(’Press any key to continue’);repeat until keypressed;b1:=readkey;assign(fc,s2);reset(fc);b1:=’ ’;while not EOF(fc) do begin

while ( ((b1=’ ’) or (b1=chr(10)) or (b1=chr(13)) ) and not eof(fc)) doif not eof(fc) then read(fc,b1);

if (ord(b1)>47) then begincnt:=0;read(fc,b2);if (ord(b1)>96) then b1:=chr(ord(b1)-32); min -> majif (ord(b2)>96) then b2:=chr(ord(b2)-32);if (ord(b1)<58) then cnt:=(ord(b1)-48)*16 else cnt:=(ord(b1)-55)*16;if (ord(b2)<58) then cnt:=cnt+(ord(b2)-48) else cnt:=cnt+(ord(b2)-55);sendchar(chr(cnt));

write(cnt,’d=’,b1,b2,’h ’);repeat until keypressed;b1:=readkey; delay(500);

end;if not eof(fc) then read(fc,b1);

end;for cnt:=0 to 1023 do sendchar(chr(cnt));close(fc);

end;

end;

procedure ResetPort(PortBase: word; IRQ: byte); Reset UART and reset interrupt vectors begin

Reset the DLAB bit. Clear all other registers. Port[PortBase + LineCtrl] := Port[PortBase + LineCtrl] and $7F;Port[PortBase + ModemCtrl] := 0;Port[PortBase + IntrEnable] := 0;

Disable the IRQ for the UART, then restore the old interrupt vector. DisableIRQ(IRQ);SetIntVec($08 + IRQ, OldInterruptVec);

Inform the user that the terminal session was aborted. Writeln;Writeln(’Port closed.’);

end;

function Hex(W: word): TQuadString; Convert a number into hexadecimal outfit const

HexChars: array[0..15] of char = ’0123456789ABCDEF’;begin

Hex := HexChars[W shr 12] +HexChars[(W shr 8) and 15] +HexChars[(W shr 4) and 15] +HexChars[W and 15];

end;

procedure WritePortInfo; Output some info about the selected port begin

write(’Using COM’, PortNr, ’ (base address ’, Hex(PortBase), ’, IRQ ’,UsedIRQ);write(’, UART is a ’);

Print the detected UART type case UARTType of

UART_8250:write(’8250’);

UART_16450:write(’16450’);

UART_16550:write(’16550’);

UART_16550A:write(’16550A’);

end;

writeln(’)...’);end;

--- Main Routine ---begin

Just output some information. ClrScr;if (paramcount>0) then beginwriteln;writeln(’TERMINAL Version 1.00 Written 1995 by Stephan A. Maciej’);writeln(’Internet: [email protected] http://www.muc.de/˜stephanm’);writeln;

Check for some correct parameters on the command line. GetCommandLine(PortNr, Speed);PortBase := GetPortBase(PortNr);if (PortBase = 0) then

beginwriteln(’COM’, PortNr, ’: no such port !’);halt;

end;UsedIRQ := 4 - ((PortNr - 1) and 1);UARTType := GetUARTType(PortBase);

Reset both the incoming as well as the outgoing Queue. ResetQueue(InQueue);ResetQueue(OutQueue);

Write some information about the selected port. WritePortInfo;

Setup the port, run the terminal and reset the port when ready. SetupPort(PortBase, Speed, UsedIRQ);

if (paramcount>1) then RunTerminal(PortBase,paramstr(1),paramstr(2)) elseRunTerminal(PortBase,paramstr(1),’ ’);

ResetPort(PortBase,UsedIRQ);end else writeln(’progname filename’);

end.

B Programmed’envoi desdonneesdu PCversle68HC11: hc11 linux.c (gcc,Linux)

Le programmesuivantutilise la memesyntaxequecellevuedansla partieprecedente(A) pourprogrammerle 68HC11sousLinux. Leprogrammeestendeuxparties: le coded’initialisation du port seried’unepart (rs232.c ) et le codedelecturedu fichier contenantle programmea charger en hexadecimalet de communicationavec le HC11 (hc11 linux.c ). La compilationse fait par gcc -crs232.c;gcc-o hc11 linux hc11 linux.c rs232.o.

Le programmers232.c :

14

Page 15: 68hc11

/* All examples have been derived from miniterm.c *//* Don’t forget to give the appropriate serial ports the right permissions *//* (e. g.: chmod a+rw /dev/ttyS0) */

#include "rs232.h"

extern struct termios oldtio,newtio;

int init_rs232()int fd;

fd=open(HC11DEVICE, O_RDWR| O_NOCTTY);if (fd <0) perror(HC11DEVICE); exit(-1); tcgetattr(fd,&oldtio); /* save current serial port settings */bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */

/* newtio.c_cflag = BAUDRATE| CRTSCTS| CS8 | CLOCAL | CREAD; */newtio.c_cflag = BAUDRATE| CS8 | CLOCAL | CREAD; /* _no_ CRTSCTS*/newtio.c_iflag = IGNPAR | ICRNL |IXON;newtio.c_oflag = ONOCR|ONLRET|OLCUC;newtio.c_lflag = ICANON;newtio.c_cc[VINTR] = 0; /* Ctrl-c */newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */newtio.c_cc[VERASE] = 0; /* del */newtio.c_cc[VKILL] = 0; /* @ */newtio.c_cc[VEOF] = 4; /* Ctrl-d */newtio.c_cc[VTIME] = 0; /* inter-character timer unused */newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */

newtio.c_cc[VSWTC] = 0; /* ’\0’ */newtio.c_cc[VSTART] = 0; /* Ctrl-q */newtio.c_cc[VSTOP] = 0; /* Ctrl-s */newtio.c_cc[VSUSP] = 0; /* Ctrl-z */newtio.c_cc[VEOL] = 0; /* ’\0’ */newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */newtio.c_cc[VWERASE] = 0; /* Ctrl-w */newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */newtio.c_cc[VEOL2] = 0; /* ’\0’ */tcflush(fd, TCIFLUSH);tcsetattr(fd,TCSANOW,&newtio);printf("RS232 Initialization done\n");return(fd);

void sendcmd(int fd,char *buf)unsigned int i,j;

if((write(fd,buf,strlen(buf)))<strlen(buf))printf("\n No connection...\n");exit(-1);

for (j=0;j<5;j++) for (i=0;i<3993768;i++) /* usleep(attente); */

void free_rs232(int fd)tcsetattr(fd,TCSANOW,&oldtio);close(fd); /* restore the old port settings */

Le programmehc11 linux.c :

#include "rs232.h"

void vrfy_buf(char* buf,int i) /* verify buffer’s content */int j,k;

for (j=0;j<i;j++) k=(int)buf[j];if (k<0) k+=256;printf("%d ",k);printf("\n");

void send_hc11(FILE *f,int fd)char buf[255];int i=0,status;unsigned int j;

buf[0]=255;write(fd,buf,1); /* start with ’FF’ */do do status=fscanf(f,"%x",&j);buf[i]=(char)j;i++; /* read while !EOF */

while ((status!=EOF) && (i<255)); /* && less than 255 chars */

if (i<255) i--;vrfy_buf(buf,i);write(fd,buf,i);printf ("%d bytes sent\n",i);i=0;

while (status!=EOF);

void main(int argc,char **argv)int fd;FILE *f;

if (argc<2) printf("%s filename\n",argv[0]); else fd=init_rs232();f=fopen(argv[1],"r");send_hc11(f,fd);

/* free_rs232(); */

C Programme de r eceptiondesdonneesde la RAM : test ram.pas (Turbo Pascal(7), DOS)

Ceprogramme,tressemblableahc11.pas , apourrolededeclencherl’ emissiondesdonneesstockeesdansla RAM li eeauHC11(parl’envoi du caractere$20)et de recupererlesoctetstransmispar le microcontroleurpour lesstocker dansle fichier ram.dat . En faitla seuledifferenceparrapportauprogrammeprecedentresidedansla procedureRunTerminal() : nousenvoyonsun caracterepuisrecevonsram len octets(ram len etantpasse commeparametredeRunTerminal() ). Il suffit ensuitederealiserun petit traite-mentdeconversionduformatbinaire(suited’octets)versunesortiedansunfichierauformatASCII pourpouvoir afficherla courbedesresultatsobtenus(enTurboCsousDOS,fin=fopen("ram.dat","rb");for () fscanf(fin,"%c",&c);fprintf(fout,"%d",(int)c); .

Nousne fournissonsici quela nouvelle procedureRunTerminal()qui a ete modifieeet la procedureprincipale(entrele begin etend. final), le resteetantidentiqueahc11.pas .

RunTerminal(PortBase: word;ram_len:integer); Run the Terminal var

fc:file of char; 0..255b,b1,b2,bl:char;cnt,i:integer;

beginassign(fc,’ram.dat’);rewrite(fc);sendchar(chr($20));for cnt:=1 to ram_len 9000 do begin

while not(GetQueueByte(InQueue, byte(b))) do begin end;write(fc,b);writeln(byte(b));

end;close(fc);

end;

begin Just output some information. ClrScr;writeln;writeln(’TERMINAL Version 1.00 Written 1995 by Stephan A. Maciej’);writeln(’Internet: [email protected] http://www.muc.de/˜stephanm’);writeln;

Check for some correct parameters on the command line. GetCommandLine(PortNr, Speed);PortBase := GetPortBase(PortNr);if (PortBase = 0) then

beginwriteln(’COM’, PortNr, ’: no such port !’);halt;

end;UsedIRQ := 4 - ((PortNr - 1) and 1);UARTType := GetUARTType(PortBase); Reset both the incoming as well as the outgoing Queue. ResetQueue(InQueue);ResetQueue(OutQueue); Write some information about the selected port. WritePortInfo; Setup the port, run the terminal and reset the port when ready. SetupPort(PortBase, Speed, UsedIRQ);

if (paramcount>0) then beginval(paramstr(1),ram_len,cc);RunTerminal(PortBase,ram_len);endelse RunTerminal(PortBase,31736); $400 -> $7FF8

ResetPort(PortBase,UsedIRQ);end.

15