Понадобилось мне передавать с терминала в МК числа, причём обычным текстом. Например отправляю строку "A15CFF", а в микроконтроллере получаю числа 0xA1 0x5C 0xFF.
Алгоритм получился такой:
1. принять первый символ числа и сохранить его в ОЗУ
2. принять второй символ и тоже сохранить
3. конвертировать первый символ
4. умножить полученное число на 0x10, чтобы получить десятки. Было 0x0A стало 0xA0.
5. конвертировать второй символ
6. полученное число (единицы) прибавить к десяткам
Объявление переменных:
.def TEMP = r17
.def CHAR = r20 ;символ
.def NUM = r21 ;байт в HEX то что получится после конвертирования
.equ CHAR_H = 0x60 ;число в ASCII десятки
.equ CHAR_L = 0x61 ;число в ASCII единицы
Ну и сам код:
;**********************************************************
; Функция конвертирующая два символа ASCII в
; число HEX, результат в переменной NUM
;**********************************************************
STRING_to_HEX:
; взять первый символ из памяти
lds char,char_h
; конвертировать первый символ в число HEX
; умножить результат на 0x10
; и поместить в переменную NUM
rcall CHAR_to_HEX
ldi temp,0x10
mul char,temp
mov num,r0
; взять второй символ из памяти
lds char,char_l
; конвертировать второй символ в число HEX
; и прибавить его к NUM
rcall CHAR_to_HEX
add num,char
ret
;*****************************************************************
; Функция переводит символ ASCII (переменная CHAR)
; в число HEX результат в переменной CHAR
;*****************************************************************
CHAR_to_HEX:
; число больше или равно 48 ('0' ASCII) ?
ldi temp,48
cp char,temp
brge AH_1
rjmp AH_3
; число больше или равно 48.
; число меньше или равно 57 ('9' ASCII) ?
AH_1:
ldi temp,57
cp temp,char
brge AH_2
rjmp AH_3
; число больше или равно 48 и меньше или равно 57 ('0'-'9' ASCII).
; получаю число от 0x00 до 0x09
AH_2:
subi char,48
ret
; число больше или равно 48 и больше или равно 57.
; число больше или равно 65 ( 'A' ASCII ) ?
AH_3:
ldi temp,65
cp char,temp
brge AH_4
ret
; число больше или равно 65.
; число меньше или равно 70 ( 'F' ASCII ) ?
AH_4:
ldi temp,70
cp temp,char
brge AH_5
ret
; число больше или равно 65 и меньше или равно 70 ('A'-'F' ASCII).
; получаю число от 0x0A до 0x0F
AH_5:
subi char,55
ret
Оригинал статьи