Zamiana ASCII na HEX - assembler 8051
Zamiana ASCII na HEX - assembler 8051
Witam !! Mam pytanko. czy jest jakiś algorytm bądź też sposób na zamianę wartości w ascii na hex ?? Czyli żeby odbierając z portu komputera znaki ascii 3F, czyli 33h 46h procesor odczytał faktyczną wartość, czyli 3Fh. Oczywiście konwersja odbywałaby się po stronie procesorka. Pozdrawiam i proszę o odpowiedź.
Re: Zamiana ASCII na HEX - assembler 8051
Oczywiście, że jest. Każdą odebraną cyfrę hex (znakowo ASCII) należy zamienić na wartość binarną, czyli przerobić 33hex (ascii) na 3 (binarnie), 46hex (ascii) na 15 (binarnie). Konwersji dokonujesz 3*16+15=63 (dec) = 3F hex.Raflles pisze:Witam !! Mam pytanko. czy jest jakiś algorytm .....
Gaweł, a jak przekonwertujesz 'AA'...
Raflles, stanowczo nie mam dziś natchnienia do pisania w asm,
więc tylko opis słowno-muzyczny...
zauważ taką rzecz:
cyfry '0'...'9' mają kody ASCII od 30H do 39H
literki 'A'...'F' mają kody ASCII od 41H do 46H (zauważ - to duże litery, małe mają inne kody)
przyjmijmy że w rejestrze R1 jest literka 'E', w rejestrze R0 jest literka '5'
czyli konwertujemy napis 'E5'
przyjmijmy więc, że starsza połówka bajtu jest w R1,
młodsza w R0 a z tego ma nam wyjśc 0E5H (czyli po C-owemu 0xE5 )
bierzesz R1,
sprawdzasz, czy R1 > 39H
jeżeli nie, to od zawartości R1 odejmujesz 30H czyli #'0'
w ten sposób uzyskasz wartości 0...9
jeżeli jest większe - od wartości R1 odejmujesz 41H czyli #'A'
w ten sposób uzyskasz 0...5 i do tego wyniku nalezy dodać 0AH (czyli dziesięć)
aby uzyskać 0AH...0FH
w taki oto sposób masz przeliczoną starszą połówkę bajtu,
choć wynik jest składowany na czterech młodszych bitach...
to samo robisz dla R0
na koniec należy poskładać wynik w całość, czyli przesunąc bitowo o 4 w lewo wynik z R1
(lub wykonać swap) ustawią się starsze cztery bity, młodsze należy wyzerować.
tę wartość należy dodać do wartości wyliczonej z R0...i gotowe, o!

tasza
PS.
tu masz tabelkę z kodami ASCII
http://www.lookuptables.com/
Raflles, stanowczo nie mam dziś natchnienia do pisania w asm,
więc tylko opis słowno-muzyczny...
zauważ taką rzecz:
cyfry '0'...'9' mają kody ASCII od 30H do 39H
literki 'A'...'F' mają kody ASCII od 41H do 46H (zauważ - to duże litery, małe mają inne kody)
przyjmijmy że w rejestrze R1 jest literka 'E', w rejestrze R0 jest literka '5'
czyli konwertujemy napis 'E5'
przyjmijmy więc, że starsza połówka bajtu jest w R1,
młodsza w R0 a z tego ma nam wyjśc 0E5H (czyli po C-owemu 0xE5 )
bierzesz R1,
sprawdzasz, czy R1 > 39H
jeżeli nie, to od zawartości R1 odejmujesz 30H czyli #'0'
w ten sposób uzyskasz wartości 0...9
jeżeli jest większe - od wartości R1 odejmujesz 41H czyli #'A'
w ten sposób uzyskasz 0...5 i do tego wyniku nalezy dodać 0AH (czyli dziesięć)
aby uzyskać 0AH...0FH
w taki oto sposób masz przeliczoną starszą połówkę bajtu,
choć wynik jest składowany na czterech młodszych bitach...
to samo robisz dla R0
na koniec należy poskładać wynik w całość, czyli przesunąc bitowo o 4 w lewo wynik z R1
(lub wykonać swap) ustawią się starsze cztery bity, młodsze należy wyzerować.
tę wartość należy dodać do wartości wyliczonej z R0...i gotowe, o!
tasza
PS.
tu masz tabelkę z kodami ASCII
No wiesz księżniczko, Raflles pytał o algorytm, to mu z grubsza podałem. Nie określił poziomu szczegółowości, ale skoro jasno określił problem, to uznałem, że tak oczywiste zamiany kodów znaków na wartości liczbowe sam zrobi. Zrobiłaś to w doskonały sposób, więc: nic już nie ma do dodania.tasza pisze:Gaweł, a jak przekonwertujesz 'AA'...![]()
...
Jak Raflles będzie chciał, to gdzieś odszukam tekst odpowiedniego programu, ale może sam spróbuje.
Dzięki wszystkim za pomoc. Narazie sam spróbuję, a jak polegnę to poproszę o gotowca
Ale jeżeli się uda to wrzucę tutaj kod bo może się komuś jeszcze przyda. Pozdrawiam !!
[ Dodano: 2006-08-15, 18:42 ]
takie małe pytanko. Czy jest jakaś instrukcja w assemblerze, która porównuje, albo sprawdza relacje ??
[ Dodano: 2006-08-15, 18:42 ]
takie małe pytanko. Czy jest jakaś instrukcja w assemblerze, która porównuje, albo sprawdza relacje ??
a kto to wie, tyle ich tam jestRaflles pisze:Czy jest jakaś instrukcja w assemblerze, która porównuje, albo sprawdza relacje
a szczególnie:
aha, i może taki kawalątek kodu (pod assembler uC/51 jakby coś.... )
Kod: Zaznacz cały
.segment start, org $0
;
; jakis_znaczek = '0' ; mniej_lub_rowne_9
; jakis_znaczek = '8' ; mniej_lub_rowne_9
; jakis_znaczek = '9' ; mniej_lub_rowne_9
jakis_znaczek = 'A' ; wiecej_niz_9
; jakis_znaczek = 'F' ; wiecej_niz_9
;
mov A, #jakis_znaczek
;
subb A,#3Ah ; '9' + 1 = 3AH
jnc wiecej_niz_9
;
mniej_lub_rowne_9:
; to sie wykona dla <= '9'
ljmp mniej_lub_rowne_9
;
wiecej_niz_9:
; tu skoczy jak > '9'
ljmp wiecej_niz_9
tasza
Witam !!!!
Podaje obiecany kod zamiany ASCII na wartość znaku w HEX. Proszę o krytykę, jeżeli coś dało się zrobić łatwiej i szybciej i żeby zajmowało mniej miejsca. Pozdrawiam !!!!
PS: Program reaguje tylko na znaki z klawiatury od 0-9 i od A-F. Narazie wersja półbajtowa.
Podaje obiecany kod zamiany ASCII na wartość znaku w HEX. Proszę o krytykę, jeżeli coś dało się zrobić łatwiej i szybciej i żeby zajmowało mniej miejsca. Pozdrawiam !!!!
Kod: Zaznacz cały
;Zamiana ASCII na HEX.
mov A,#38h ;wpisujemy do akumulatora znak odebrany przez RS232
setb RS1
mov R0,A
clr RS1
setb RS1
mov A,R0
clr RS1
zamiana:
sprawdzenie1: ;sprawdza, czy liczba hex jest z zakresu 30 - 4F
anl A,#0F0h ;zerujemy mlodszy polbajt akumulatora
cjne A,#30h,czy40 ;sprawdzamy, czy rozne od 30h, jesli rozny to skok do "dalej"
ljmp rowne30 ;skok do "dalej"
czy40:
cjne A,#40h,zla_wartosc ;sprawdzamy czy rozne od 40h,
ljmp rowne40
rowne30:
setb RS1
mov A,R0
clr RS1
subb A,#30h
cjne A,#0Ah,czy0Bh
ljmp zla_wartosc
czy0Bh:
cjne A,#0Bh,czy0Ch
ljmp zla_wartosc
czy0Ch:
cjne A,#0Ch,czy0Dh
ljmp zla_wartosc
czy0Dh:
cjne A,#0Dh,czy0Eh
ljmp zla_wartosc
czy0Eh:
cjne A,#0Eh,czy0Fh
ljmp zla_wartosc
czy0Fh:
cjne A,#0Fh,ile
ljmp zla_wartosc
rowne40:
setb RS1
mov A,R0
clr RS1
subb A,#37h
anl A,#0Fh
cjne A,#00h,czy01h
ljmp zla_wartosc
czy01h:
cjne A,#01h,czy02h
ljmp zla_wartosc
czy02h:
cjne A,#02h,czy03h
ljmp zla_wartosc
czy03h:
cjne A,#03h,czy04h
ljmp zla_wartosc
czy04h:
cjne A,#04h,czy05h
ljmp zla_wartosc
czy05h:
cjne A,#05h,czy06h
ljmp zla_wartosc
czy06h:
cjne A,#06h,czy07h
ljmp zla_wartosc
czy07h:
cjne A,#07h,czy08h
ljmp zla_wartosc
czy08h:
cjne A,#08h,czy09h
ljmp zla_wartosc
czy09h:
cjne A,#09h,ile
ljmp zla_wartosc
ile:
mov P1,A
ljmp ile
zla_wartosc:
ljmp zla_wartosc
Widzisz, jak się chce, to da się zrobić. W kwestii krytyki, to jest tak: kryterium jest takie: działa lub nie działa. Jeżeli twój program działa, to jest OK, koniec krytyki.Raflles pisze:Witam !!!!
Podaje obiecany kod zamiany ASCII na wartość znaku w HEX. Proszę o krytykę, jeżeli coś dało się zrobić łatwiej i szybciej i żeby zajmowało mniej miejsca. Pozdrawiam !!!!
Natomiast można zastanowić się, czy można to zrobić inaczej. Owszem, można: rozwiązań będzie tyle ilu autorów. Jeżeli każde z nich będzie działać, to jest OK.
Podobnie jak u ciebie: program reaguje tylko na znaki od 0-9 i od A-F i wersja jest bajtowa.
Moja propozycja rozwiązania ma algorytmem znacząco innym od tego jaki zaproponowała ci Tasza:
Kod: Zaznacz cały
$mod51
;
$NODEBUG
$LIST
$OBJECT
;
CSEG
org 0
ljmp reset
;
;-----------------------------------------------------------------------------
HexTable:db '0123456789ABCDEF',0
CnvCh: ;funkcja CnvCh: parametr wywolania: rej. B-znak
;***** ;wynik: A + wskaznik C ;
mov r0,#0 ;
mov dptr,#HexTable ;
CnvCh2: mov a,r0 ;
movc a,@a+dptr ;
jz CnvCh0 ;
cjne a,b,CnvCh1 ;
mov a,r0 ;
setb c ;
ret ;
CnvCh0: clr c ;
ret ;
CnvCh1: inc r0 ;
ljmp CnvCh2 ;
;-----------------------------------------------------------------------------
ConvHex: ;funkcja ConvHex: parametr wywolania: rej. r6 i r7 - znaki
;******* ;wynik w A + wskaznik C
mov b,r6 ;
lcall CnvCh ;
jnc CnvHx0 ;
swap a ;
push acc ;
mov b,r7 ;
lcall CnvCh ;
pop b ;
jnc CnvHx0 ;
orl a,b ;
setb c ;
CnvHx0: ret ;
;-----------------------------------------------------------------------------
reset: nop ;
;przyklad uzycia:
mov r6,#'A' ;
mov r7,#'B' ;
lcall ConvHex ;rej A=ConvHex('AB');
;w wyniku w rej A jest AB hex oraz wsk C=1 ===> OK
jnc blad ;
mov p1,a ;
mov r6,#'7' ;
mov r7,#'X' ;
lcall ConvHex ;rej A=ConvHex('7X');
;w wyniku wsk C=0 ===> error
jnc blad ;
mov p1,a ;
ljmp $ ;
blad: nop ;
ljmp $ ;
;-----------------------------------------------------------------------------
END
Witam,
jakoś tak to było....to z MIK02 S.Gardynika ( https://elportal.pl/index.php?module=Co ... y&ceid=133 )
może zerknijcie na to....sama funkcja hex2bin:
w takim otoczeniu ją testowałam:
najpoważniejszą wadą mojej hex2bin jest brak jakiejkolwiek weryfikacji sensu podawanych
do R1,R0 danych wejściowych i w tym kontekście Wasze funkcje są lepiej napisane.
a w kwestii weryfikacji, chyba najfajniej byłoby napisać taką funkcję,
która dostanie znak do zbadania i wskaźnik na tabelkę w segmencie CODE,
w której są aktualnie przez nas dopuszczalne do użycia znaczki....
zresztą, różnie to można...
tasza
[ Dodano: 2006-08-21, 12:51 ]
jakoś nie mam natchnienia na nic lepszego, ale macie też funkcyjkę do prostej weryfikacji....
gdy znaczek jest w zbiorze podanym via DPTR i zakończonym 0h
funkcja zwraca C = 1, a gdy go tam nie ma daje C = 0....
tasza
jakość programisty jest odwrotnie proporcjonalna do ilości wstawionych w kod skoków bezwarunkowychRaflles pisze:Proszę o krytykę, jeżeli coś dało się zrobić łatwiej i szybciej i żeby zajmowało mniej miejsca
jakoś tak to było....to z MIK02 S.Gardynika ( https://elportal.pl/index.php?module=Co ... y&ceid=133 )
może zerknijcie na to....sama funkcja hex2bin:
Kod: Zaznacz cały
;-----------------------------------------
; we: R1,R0 - 2 x ascii do konwersji
; wy: ACC - wersja binarna
hex2bin:
mov A, R1 ; starsza literka
lcall h2b ; f.pomocnicza
swap A ; bity 0...3 --> 4...7
mov R1,A ; wynik z powrotem do R1
mov A, R0 ; tera młodsza literka
lcall h2b ; f.pomocnicza
orl A, R1 ; A = A | R1
ret ; wyjście
; procedurka pomocnicza,
; konwertuje zawartość ACC podaną w ascii na bin
h2b:
jb ACC.4, h2b_conv_digit
; tu literka
subb A, #37h
; w Acc jest A...F
ret
; tu cyfra
h2b_conv_digit:
subb A, #30h
; w Acc jest 0...9
ret
;
;
Kod: Zaznacz cały
.include <../include/reg51.def>
.segment start, org $0
;
mov SP,#20h ; stos
;
; R1,R0 = '9A'
mov R1, #'9'
mov R0, #'A'
lcall hex2bin
;
; wynik pokaż na porcie P2
mov P2, A
;
petelka_na_koniec:
ljmp petelka_na_koniec
;
;
do R1,R0 danych wejściowych i w tym kontekście Wasze funkcje są lepiej napisane.
a w kwestii weryfikacji, chyba najfajniej byłoby napisać taką funkcję,
która dostanie znak do zbadania i wskaźnik na tabelkę w segmencie CODE,
w której są aktualnie przez nas dopuszczalne do użycia znaczki....
zresztą, różnie to można...
tasza
[ Dodano: 2006-08-21, 12:51 ]
jakoś nie mam natchnienia na nic lepszego, ale macie też funkcyjkę do prostej weryfikacji....
gdy znaczek jest w zbiorze podanym via DPTR i zakończonym 0h
funkcja zwraca C = 1, a gdy go tam nie ma daje C = 0....
Kod: Zaznacz cały
.include <../include/reg51.def>
.segment start, org $0
;
mov SP,#20h ; stos
;
mov DPTR, #hex_digits
mov A, #'5'
lcall ascii_in_set
jnc err_nie_hex
;
petelka_na_koniec:
ljmp petelka_na_koniec
;
err_nie_hex:
ljmp err_nie_hex
;
;
;
;---------------------------------------
; we: ACC - badany znak
; DPTR - adres tabelki z akceptowalnymi
; znaczkami ascii, koniec tabelki to 00h
; wy: C = 1 - znaczek w zbiorze
; C = 0 - znaczek poza zbiorem
; funkcja zamazuje zawartość R0 !
ascii_in_set:
mov R0, A ; zabezpiecz A
clr A
movc A, @A+DPTR
; w A jest jeden z elementów tabelki
cjne A, #00, ascii_in_set_not_finish ; czy koniec? ( 00h ? )
; juz koniec a tu nie ma takiego...skasuj C i sio!
clr C
ret
;
ascii_in_set_not_finish:
; więc teraz porównaj wybrany znak z zadanym
subb A, R0
jz ascii_in_set_found ;jest taki znaczek, koniec szukania
inc DPTR ; DPTR = DPTR + 1
mov A, R0 ; odtwórz A z kopii trzymanej w R0
; powtórz cykl
sjmp ascii_in_set
;
ascii_in_set_found:
; jest taki znaczek, ustaw C i wyjdź
setb C
ret
;
;
; dopuszczalne znaczki
hex_digits:
.dc.b "0123456789ABCDEF", 0h
;
;
Witam ponownie !! Żeby nie zaczynać kolejnego tematu, chciałem poprosić o pomoc z następującym problemem. A więc do wyjścia mikrokontrolera podłączone są trzy szeregowo połączone rejestry z wejściem szeregowym i wyjściem równoległym typu 74LS164. Problem polega na tym, że wysyłając znaki szeregowo z mikrokontrolera na wyjściach rejestrów powstają błędy. Każdy ze scalaka jest odsprzęgnięty zaraz przy nóżce z zasilania kondensatorem 100uF/16V. Dane wychodzące z procesora są napewno poprawne, a i w powolnej prędkości wysuwu tych danych widać, że błędy popełniają rejestry. każdy z pinów równoległych rejestrów jest obciążony diodą i rezystorem podłączoną do masy. Czy dioda była podciągnięta do plusa, czy do masy takie same błędy wyskakują. Poniżej zrobiony na szybko schemat urządzenia. albo i nie
Nie mam nigdzie na sieci możliwości załadowania obrazka. Pozdrawiam i proszę o pomoc !! A cha. Kolejny rejestr jest wejściem podłączonym do wyjścia równoległego najstarszego bitu poprzedniego rejestru. jedno z wejść szeregowych jest podłączone do plusa zasilania a drugie do wyjścia mikrokontrolera. reset i clock każdego z rejestrów też jest bezpośrednio podłączony do pinów procesora.
oj,oj,oj....kłania się zagadnienie odsprzęgania zasilania w układach impulsowych (cyfrowych)....Raflles pisze:Każdy ze scalaka jest odsprzęgnięty zaraz przy nóżce z zasilania kondensatorem 100uF/16V.
opracowań jest wiele, pierwsze z brzegu, które znalazłam:
chodzi o to, że do odsprzęgania zasilania używa się kondensatorów o małej indukcyjności własnej
a elektrolityczne (a już takie 100uF) mają ją dość dużą,
Indukcyjność dla sygnałów szybkozmiennych (a taki charakter mają zakócenia w cyfrówce)
stanowi duży opór (reaktancję indukcyjną) i taki kondensator jest wtedy zwykłą atrapą...
na sztuki jest i nic nie wnosi.
Należy zastosować np. ceramiczne kondensatorki o małej wartości....47-100 nF
No, ale to taka uwaga na boku, ponieważ nie sądzę, że to jest przyczyna....
Schemat na bazie Twojego opisu - w załączniku...
I jeżeli spinasz wyjście QH (n) z wejściem A(n+1) czyli tworzysz łańcuch/kaskadę rejestrów
to sygnały /RESET i CLOCK muszą być wspólne
inaczej układ, choć elektrycznie poprawny, jest po prostu bez sensu....
czy masz tak jak narysowałam?
Powiedz proszę co oznacza:
Jakiego rodzaju?Raflles pisze:Problem polega na tym, że wysyłając znaki szeregowo
z mikrokontrolera na wyjściach rejestrów powstają błędy.
dostajesz losowe kombinacje bitów? czy podobne do tych co niby wgrywasz
do rejestrów, ale regularnie poprzestawiane?
No i przydałby się choć kawalątek kodu, który odpowiada za wpisywanie danych,
może po prostu masz gdzieś błąd...
Aha, tak mi przyszło do głowy....
Do którego portu MCU masz podpięte sygnały sterujące liniami rejestru?
Jeżeli do portu P0, to poczytaj proszę to co było przerabiane u radzia:
brak rezystorów podciągajacych na końcówkach P0 też może być przyczyną
takich dziwnych zachowań....jak coś, profilaktycznie daj R o wartości 5.1K..10K
tasza
- Załączniki
-
- kaskada_74164.gif
- (12.31 KiB) Pobrany 686 razy
Dzięki Tasza !! Jak zwykle jesteś niezastąpiona !!!! Rejestry były podłączone dokładnie jak na twoim schemacie, ale faktycznie były podłączone do portu P0 i zapomniałem o podciągnięciu przez rezystory do plusa. Ale zastanawia mnie fakt, że rejestr podłączony bezpośrednio do portu P0 wskazywał zawsze prawidłową wartość, a źle pokazywały te dwa kolejne. Ciekawe czemu ?? A do pierwszego rejestru zawsze wchodziła prawidłowa wartość, a błędy powstawały dopiero podczas przesuwu. Pozdrawiam !!!!