hallo,
Ik ben een voltmeter aan het maken, dus ik gebruik de ADC en wil een 10 bit resolutie, want 8 bit was niet nauwkeurig genoeg.
Nu heb ik een probleem, ik werk met de z-pointer en een tabel waar ik dan mijn waardes uithaal na de adc convertie en dan stuur mijn lcd schermpje deze waardes toe .
ik doe het volgende :

ldi ZH,HIGH(tabel_tientallen*2)
ldi ZL,LOW(tabel_tientallen*2)

in zl , adcl
in zh , adch
lsr zh
ror zl
lsr zh
ror zl

dus ik laad mijn resultaat in het z-pointer register en die gaat dan waardes uit mijn tabel halen,
MAAR dan krijg ik rare tekens op mijn lcd schempje hoe komt dit wat doe ik fout ?

alvast bedankt !

je gaat dat getal moeten omzetten naar ascii he jongen ...

En ook nog eerst nog van binair naar bcd omzetten.


je leest:
- 10 bit binare waarde range 1023..0 of hex $1FF..$000
- Dat moet omzetten naar 4 byte bcd waardes:
   0000 000d   duizend-  tallen
   0000 hhhh   honderd-  tallen
   0000 tttt   tien-     tallen
   0000 eeee   eenheden
- Daar moet je ascii van maken ( OR met $30 van je bcd getallen)
- Deze 4 bytes ascii waarden naar je display sturen.

Zoals free_electron al aangaf moet je eerst van Hex naar het decimale stelsel en dan naar ASCII.

Hoe ?.

stel je getal is: 0x1234 (hex) dat kan maximaal dus 65535 (dec) zijn.
Hoe zet je het om ?. je deelt het getal door 10 (dec) en de rest zet je om naar ascii tot je het complete getal hebt gemaakt.


In pseudo C code:

ASCII_0 = (Number % 10) + 0x30    //  ( 0x1234 % 0xA ) + 0x30 = 0x30 = ASCII 0
Number  = Number / 10            //  ( 0x1234 / 0xA ) = 0x1D2
ASCII_1 = (Number % 10) + 0x30   //  ( 0x01D2 % 0xA ) + 0x30 = 0x36 = ASCII 6
Number  = Number / 10            //  ( 0x01D2 / 0xA ) = 0x002E
ASCII_2 = (Number % 10) + 0x30   //  ( 0x002E % 0xA ) + 0x30 = 0x36 = ASCII 6
Number  = Number / 10            //  ( 0x002E / 0xA ) = 0x0004
ASCII_3 = (Number % 10) + 0x30   //  ( 0x0004 % 0xA ) + 0x30 = 0x34 = ASCII 4
Number  = Number / 10            //  ( 0x0004 / 0xA ) = 0x0000
ASCII_4 = (Number % 10) + 0x30   //  ( 0x0000 % 0xA ) + 0x30 = 0x30 = ASCII 0

dus 0x1234 = 04660 (dec) => 4660 op je display.


; Bin16 to Packed BCD
;********************
; 	input:	r17		16 bit high input
;			r16 	16 bit low  input
; 	Reg:	r21
;			XH
;			XL
; 	Output:	r20 	packed BCD value high nibble
;			r19 	packed BCD value
;			r18 	packed BCD value low  nibble
Hex_Bcd: 
	clr     r18
	clr     r19
	clr     r20
	clr     XH
	ldi     r21, 16

Hex_Bcd1: 
	ldi     XL, 20 + 1

Hex_Bcd2:
	ld      r22,-X
	subi    r22,-3
	sbrc    r22,3
	st      X,r22
	ld      r22,X
	subi    r22,-0x30
	sbrc    r22,7
	st      X, r22
	cpi     XL,18
	brne    Hex_Bcd2
	lsl     r16
	rol     r17
	rol     r18
	rol     r19
	rol     r20
	dec     r21
	brne    Hex_Bcd1
	ret 

; ADC_UBAT binary to ascii BCD
; ****************************
LCD_Ubat:
	lds	r17,ADC_UBAT_HIGH	; Read High byte ADC
	lds	r16,ADC_UBAT_LOW	; Read low  byte ADC
	lsl	r16
	rol	r17			; multiplay by 2 range 20.47V .. 00.00V
	rcall	Hex_Bcd			; return r20:r19:r18 = BCD value 
	mov	r16,r19
	andi	r16,0b11110000
	lsr	r16
	lsr	r16
	lsr	r16
	lsr	r16
	ori	r16,0b00110000
	sts	LCD_RAM+VB_OFFSET1,r16	; Tiental display
	mov	r16,r19
	andi	r16,0b00001111
	ori	r16,0b00110000
	sts	LCD_RAM+VB_OFFSET2,r16	; Eenheden display
	mov	r16,r18
	andi	r16,0b11110000
	lsr	r16
	lsr	r16
	lsr	r16
	lsr	r16
	ori	r16,0b00110000
	sts	LCD_RAM+VB_OFFSET3,r16	; Tienden na dp display
	mov	r16,r18
	andi	r16,0b00001111
	ori	r16,0b00110000
	sts	LCD_RAM+VB_OFFSET4,r16	; hondersten na dp display
        ret

Hierbij een voorbeeldje hoe ik het gebruik. Merkop dat mijn range 20.47 tot 00.00 is. Daarom wordt de 10 bit ADC waarde eerst X2 gedaan. Dit om spanningen boven de 10V te kunnen weergeven. Ik gebruik altijd een stukje SRAM buffer waar ik alle display data in formateer. Het uitgeven zelf van die data naar de LCD display gebeurd in een afzonderlijke routine die op events werkt. Zo moet de toepassing slechts in de SRAM schrijven en zich niet moeien hoe die data naar het display zelf gaat.
LCD_RAM is hier het start adres van die sram
De OFFSET1, OFFSET2, OFFSET3 en OFFSET4 zijn de plaatsen waar die waarden in de buffer komen. Die OFFSET waarden staan in een header definitie waar ik de juiste plaatsen kan bepalen zonder opnieuw in deze routines te moeten duikelen.

Voor m'n eerste projecten (bv toerenteller voor een brommer] haalde ik veel van deze website:

http://www.avr-asm-tutorial.net

Binary to ascii

http://www.avr-asm-tutorial.net/avr_en/calc/CONVERT.html#bin2asc

[edit]binary to bcd
http://www.avr-asm-tutorial.net/avr_en/calc/CONVERT.html#bin2bcd

[Bericht gewijzigd door Gatze op (17%)]