elomax

[ Techniek ] [ Shop ] [ Site map
Standaard ] Signalen ] Data transport ] RS232 op de SIMPLEX ] SCI ] Aansturing ] Speciale toepassingen ] Registers ] [ Voorbeelden ]

Terug
Omhoog

Voorbeelden van het gebruik van de seriële poort

Hieronder volgen enkele voorbeelden van de manier waarop de seriële poort gebruikt zou kunnen worden.

Op de PC kan de seriële poort aangestuurd worden mbv het programma 'hyperterminal'. Ook in de programmeer software die u hier kunt downloaden zit de mogelijkheid met de SIMPLEX te communiceren.

De Baudrate van de seriële poort in de micro-controller wordt ingesteld in het BAUD register. Twee bits hierin bepalen een deelfactor voor de klok van de processor (die op de SIMPLEX 2 MHz is) en drie andere bits bepalen een tweede deelfactor. De resulterende frequentie bepaalt de Baudrate.

De eerste deelfactor is:

SCP1

SCP0

deelfactor

hoogste Baudrate

0

0

1

125 kiloBaud

0

1

3

41.666 kiloBaud

1

0

4

31.250 kiloBaud

1

1

13

9600 Baud

De eerste deelfactor kan het beste ingesteld worden op een hoogste Baudrate van 9600 Baud. Met de tweede deelfactor kan deze Baudrate eventueel verder omlaag gebracht worden. Het programma voor de PC moet natuurlijk op dezelfde Baudrate ingesteld worden, het is standaard ingesteld op 9600 Baud.

De tweede deelfactor is:

SCR2

SCR1

SCR0

Deelfactor

Baudrate

0

0

0

1

9600 Baud

0

0

1

2

4800 Baud

0

1

0

4

2400 Baud

0

1

1

8

1200 Baud

1

0

0

16

600 Baud

1

0

1

32

300 Baud

1

1

0

64

150 Baud

1

1

1

128

75 Baud

Heen- en weer typen

Het eerste voorbeeld programma voor de SIMPLEX zendt alle tekens zoals ze van de PC ontvangen werden, onmiddellijk weer terug naar de PC. In het voorbeeld kunt U zien hoe de seriële poort geïnitialiseerd moet worden, zodat communicatie mogelijk wordt. Alles wat U op het toetsenbord van de PC typt, wordt naar de SIMPLEX gestuurd. Hier wordt het ontvangen, en meteen weer teruggestuurd. Na ontvangst zet de PC het teken op het scherm.

Probeer in de hoofdlus, tussen het ophalen van een teken en het weer terugzenden daarvan, het teken eens te veranderen. Dit kan bijvoorbeeld eenvoudig door een 'decb' instructie in te voegen tussen de instructies 'bsr getchar' en 'bsr putchar'. Hierdoor wordt de ASCII waarde van het ontvangen teken met één verlaagd voordat het weer wordt teruggestuurd naar de PC. Een 'B' wordt dan een 'A', een 'C' wordt een 'B', etc.

*************************************************
* definiëren van de geheugen map
*************************************************
		incl "map512.asm"

*************************************************
* start van het programma
*************************************************
PROGRAM		space		|kies het programma gebied

reset		equ $		|na reset begint de micro op deze plaats
		lds #stackend	|begin met de stackpointer te laden

		ldx #databeg	|en zet dan het volledige datagebied op 00
clearram	clr 0,x
		inx
		cpx #dataend
		bls clearram

		ldx #regsbeg	|laat IX op de bank met I/O registers wijzen

*************************************************
* seriële poort
*************************************************
PROGRAM		space
clistart	equ $		|het beginadres van deze module

* initialisatie
* initialiseer de seriële poort
		ldab #(scp1+scp0)
		stab baud	|kies 9600 BAUD ( 8MHz kristal)
		ldab #(te or re)
		stab sccr2	|en zet zender en ontvanger aan
		bra cliend	|einde van de initialisatie

* subroutines voor de seriële poort

PROGRAM		space

* kijk of er een karakter ontvangen is
* zoja, zet dan de zero﷓vlag op '0'
serincheck	equ $
		pshb
		ldab scsr	|lees de status vlaggen
		andb #rdrf	|en test op het 'receiver full' bit
		pulb
		rts

* kijk of de seriele poort gereed is om een teken te versturen
* zoja, zet dan de zero﷓vlag op '0'
seroutcheck	equ $
		pshb
		ldab scsr	|lees de staus vlaggen
		andb #tc	|en test op het 'transmitter empty' bit
		pulb
		rts

* haal een teken op uit de ontvanger, en zet het in accumulator B
getchar		equ $
		bsr serincheck	|wacht totdat er een teken ontvangen is
		beq getchar
		ldab scdr	|en lees het teken uit het ontvanger register
		rts

* verstuur een teken via de seriële poort
putchar		equ $
		bsr seroutcheck	|wacht totdat de zender gereed is
		beq putchar
		stab scdr	|en zet dan het teken in het verzend﷓register
		rts

cliend		equ $		|einde van de cli module


*************************************************
* het hoofdprogramma
*************************************************
PROGRAM		space

main0		bsr getchar	|wacht totdat er iets ontvangen is
		bsr putchar	|en verstuur dat daarna ook weer
		bra main0
		end

Besturing via de seriële poort

In dit voorbeeld wordt de seriële poort gebruikt om de LED uitgangen van de SIMPLEX te besturen vanuit de PC, en enkele ingangen van de SIMPLEX op te sturen naar de PC, waar ze op het scherm getoond worden.

Het programma reageert als volgt op de opdrachten vanaf de PC:

Toets LED 1 LED 2
'0' aan aan
'1' aan uit
'2' uit aan
'3' uit uit

De digitale ingangen van poort E worden naar de PC gestuurd, na te zijn omgezet in 8 ASCII nullen en enen. Een open ingang van poort E wordt gezien als een '1'. Om hiervan een '0' te maken, moet U de betreffende ingang kortsluiten met massa. De massa (GND) is ook uitgevoerd op de connector.

*************************************************
* definiëren van de geheugen map
*************************************************
		incl "map512.asm"

*************************************************
* start van het programma
*************************************************
PROGRAM		space		|kies het programma gebied

reset		equ $		|na reset begint de micro op deze plaats
		lds #stackend	|begin met de stackpointer te laden

		ldx #databeg	|en zet dan het volledige datagebied op 00
clearram	clr 0,x
		inx
		cpx #dataend
		bls clearram

		ldx #regsbeg	|laat IX op de bank met I/O registers wijzen

*************************************************
* seriële poort
*************************************************
PROGRAM		space
clistart	equ $		|het beginadres van deze module

* initialisatie
* initialiseer de seriële poort
		ldab #(scp1+scp0)
		stab baud	|kies 9600 BAUD ( 8MHz kristal)
		ldab #(te or re)
		stab sccr2	|en zet zender en ontvanger aan
		bra cliend	|einde van de initialisatie

* subroutines voor de seriële poort

PROGRAM		space

* kijk of er een karakter ontvangen is
* zoja, zet dan de zero﷓vlag op '0'
serincheck	equ $
		pshb
		ldab scsr	|lees de status vlaggen
		andb #rdrf	|en test op het 'receiver full' bit
		pulb
		rts

* kijk of de seriele poort gereed is om een teken te versturen
* zoja, zet dan de zero﷓vlag op '0'
seroutcheck	equ $
		pshb
		ldab scsr	|lees de staus vlaggen
		andb #tc	|en test op het 'transmitter empty' bit
		pulb
		rts

* haal een teken op uit de ontvanger, en zet het in accumulator B
getchar		equ $
		bsr serincheck	|wacht totdat er een teken ontvangen is
		beq getchar
		ldab scdr	|en lees het teken uit het ontvanger register
		rts

* verstuur een teken via de seriële poort
putchar		equ $
		bsr seroutcheck	|wacht totdat de zender gereed is
		beq putchar
		stab scdr	|en zet dan het teken in het verzend﷓register
		rts

cliend		equ $		|einde van de cli module

*************************************************
* real-time interrupt
*************************************************
PROGRAM		space
rtistart	equ $		|het beginadres van deze module
rtirate		equ 33		|het aantal interrupts dat geteld wordt

DATA		space
rticount	rmb 1		|deze teller wordt bij elke interrupt verhoogd

* initialisatie van de real-time interrupt
PROGRAM		space

		ldx #regsbeg	|IX wijst naar de I/O registers
		ldab #$7E	|vul de entry in de interrupt﷓tabel in
		stab rtiint	|met een sprong instructie naar de routine
		ldd #rtiintentry
		std rtiint+1	|die de interrupt afhandelt

		bset pactl+regsbeg,x,(rtr1 or rtr0)
				|zet de real-time interrupt tijd op 32.768ms
				|met 8MHz Kristal (E / 2^16)
		bset tmsk2+regsbeg,x,rtii
				|laat de interrupts door
		bra rtiend	|einde van de initialisatie

* subroutine voor de afhandeling van de real-time interrupt
PROGRAM		space
rtiintentry	equ $
		ldab #rtif
		stab tflg2	|reset de interrupt-vlag
		inc rticount	|en tel de interrupt
		rti

***** real-time interrupt interface routines
PROGRAM		space

* test op time-out. zet de zero-vlag indien er een time-out is.
checktimeout	equ $
		pshb
		sei		|houd interrupts tijdelijk tegen
		ldab rticount	|kijk hoe vaak er een interrupt was
		subb #rtirate	|indien er minimaal 'rtirate' interrupts
		blo checkrti9	|zijn geweest, dan is er een time﷓out en moet
		stab rticount	|'rtirate' van de teller worden afgetrokken
		clrb		|daarnaast moet de zero﷓vlag gezet worden
checkrti9	cli		|daarna kunnen de interrupts weer worden
		pulb		|doorgelaten
		rts

rtiend		equ $		|einde van de real-time interrupt module

*************************************************
* het hoofdprogramma
*************************************************
PROGRAM		space
		bra main0

* subroutine om een byte (in B) te verzenden in 8 enen of nullen
sendbyte	equ $
		psha
		tba
		pshx
		pshb
		ldab #$0D	|verstuur eerst een carriage-return
		jsr putchar
		ldx #8		|er zijn 8 bits te versturen
sendbyte0	ldab #'0'	|neem aan dat er een '0' verstuurd moet
		tsta		|verstuur het meest linkse bit van A
		bpl sendbyte1	|dit is een '1' als A negatief is, en anders
		ldab #'1'	|een '0'
sendbyte1	jsr putchar
		lsla		|schuif het volgende bit naar links
		dex		|er is een bit gedaan
		bne sendbyte0	|ga door met zenden totdat alle 8 bits gedaan
		pulb
		pulx
		pula
		rts

main0		jsr serincheck	|kijk of er iets ontvangen is
		beq main1	|ga door als er niets is ontvangen
		jsr getchar	|haal anders het teken op
		aslb		|schuif de twee laatste bits 5 plaatsen naar links
		aslb
		aslb
		aslb
		aslb
		stab porta	|en zet het op de outputs (LED1 en LED2)

main1		jsr checktimeout
		bne main2	|kijk of de inputs al verstuurd moeten worden
		ldab porte	|zoja, haal dan de inputs op
		jsr sendbyte	|en verstuur ze naar de PC

main2		bra main0	|blijf dit herhalen

		end

 

Debuggen met de seriële poort.

Debuggen is het vinden en corrigeren van fouten in het programma. Wanneer er fouten gevonden moeten worden, betekent dit dat het programma grondig getest moet worden. Het is meestal erg lastig een compleet programma in één keer te testen. Daarom is het verstandig het programma op te bouwen uit verschillende afgeronde stukken (modulen.) Deze stukken kunnen dan stuk- voor stuk getest en bewezen worden.

Om een module te testen moet U er meestal wat code 'omheen' schrijven. Dit testprogramma moet de module gebruiken zoals het uiteindelijke programma de module zou gebruiken, en de resultaten op de één of andere manier controleren of zichtbaar maken zodat U de resultaten zelf kunt controleren.

Met behulp van de seriële poort en de PC, kunt U tussenresultaten in het programma zichtbaar maken op het scherm van de PC. Door op strategische plaatsen in het programma enkele tussenresultaten naar de PC op te sturen, kunt U op het scherm van de PC redelijk volgen wat het programma aan het doen is.

Om tussenresultaten zichtbaar te kunnen maken, moeten deze in 'leesbare' vorm naar de PC gestuurd worden. Hiertoe dienen de volgende routines. De routines stellen U in staat getallen naar hexadecimale of decimale ASCII te converteren, en vervolgens op te sturen via de seriële poort.

*************************************************
* Strings en getal conversies
*************************************************
*
* Strings bestaan uit reeksen bytes in het geheugen, met aan het eind
* een NULL teken ($00). Deze $00 behoort niet tot de string, maar geeft
* het einde van de string aan.
* De string I/O vereist een routine 'putchar', die het teken in (B) naar
* een seriële poort stuurt.
*
PROGRAM		space

stringstart	equ $		|het beginadres van deze module
		jmp stringend

* verstuur een string, die door IX aangewezen wordt, en afgeloten is met 00
* laat IX na aanroep op het eind van de string wijzen
pstring		equ $
		pshb
pstring1	ldab 0,x	|haal een karakter van de string op
		beq pstring2	|en stop als het een NULL is
		jsr putchar	|anders wordt het karakter verzonden
		inx		|en wordt het volgende karakter bekeken
		bra pstring1
pstring2	pulb
		rts

* verstuur een carriage-return en een line-feed
crlfstring	fcb $0D, $0A, 00
newline		equ $
		pshx
		ldx #crlfstring
		bsr pstring
		pulx
		rts

* subroutine om een word (in D) te verzenden als 4 hexadecimale cijfers
sendword	equ $
		pshb		|bewaar het minst significante byte
		tab		|en verstuur het meest significante eerst
		bsr sendbyte
		pulb		|verstuur dan het minst significante byte

* subroutine om een byte (in B) te verzenden als twee hexadecimale cijfers
sendbyte	equ $
		pshb
		lsrb		|verstuur eerst de vier meest sign. bits
		lsrb
		lsrb
		lsrb
		bsr sendnibble	|en dan de andere vier bits
		pulb

* subroutine om een nibble (4 bits) in B te verzenden als een hex. cijfer
sendnibble	equ $
		andb #$0F	|zorg ervoor dat het echt een nibble is
		addb #'0'	|maak er een cijfer van
		cmpb #'9'	|en als het groter is dan een '9'
		bls sendnibble0	|maak er dan een letter A..F van
		addb #('A' ﷓ '9' ﷓ 1)
sendnibble0	jsr putchar
		rts

* converteer een 16 bits waarde in D naar een decimaal getal
* en stuur het resultaat van 5 karakters naar de seriële poort
pdecimal	equ $
DATA		space
binvalue	rmb 2		|buffer voor de binaire versie van het getal
bcdvalue	rmb 3		|buffer voor de BCD versie van het getal
PROGRAM		space
		pshb		|bewaar de registers op de stack
		psha
		std binvalue	|bewaar het te converteren getal
		ldd #0		|maak de BCD representatie van het getal 0
		std bcdvalue
		staa bcdvalue+2
		ldab #16	|nu moeten er 16 bits naar BCD omgezet worden
pdecimal2	lsl binvalue+1	|schuif de te converteren waarde een bit links
		rol binvalue	|dit komt overeen met vermenigvuldigen met 2
		ldaa bcdvalue+2	|de carry wordt by het BCD getal opgeteld
		adca #0
		staa bcdvalue+2
		decb		|kijk of alle 16 bits reeds gedaan zijn
		beq pdecimal3	|zo niet, vermenigvuldig het BCD getal dan ook
		adda bcdvalue+2	|met twee, door het bij zichzelf op te tellen
		daa		|in BCD natuurlijk
		staa bcdvalue+2
		ldaa bcdvalue+1
		adca bcdvalue+1
		daa
		staa bcdvalue+1
		ldaa bcdvalue
		adca bcdvalue
		daa
		staa bcdvalue
		bra pdecimal2	|en ga terug om de rest van het getal te doen
pdecimal3	ldab bcdvalue	|het getal is nu in BCD beschikbaar
		jsr sendbyte	|BCD is eenvoudig om te zetten naar ASCII
		ldd bcdvalue+1	|converteer alle BCD digits
		jsr sendword	|en verstuur ze via de seriele poort
		pula		|haal de registers terug van de stack
		pulb
		rts

stringend	equ $

Vorige ]

© 2005...2008 Elomax [Voorwaarden ]