Перейти к содержанию

помощь написания протокола на АСМе


Roman_msk

Рекомендуемые сообщения

Добрый день,

прошу помочь в реализации протокола общения между Atmega32 и компером ... язык только АСМ, т.к. Си плохо разумею)))

Ниже привожу протокол:

*********************

система команд:
<ID>, <comand>, <data>
<ID> это число или слово в ASCII
<data> это слово размером 1 байт
<comand>:
-SA -- установить значение по напряжению, следующий байт значение от 0 до 255
-SV -- установить значение по току, следующий байт значение от 0 до 255
-M1  -- установить режим работы - ток
-M2  -- установить режим работы - напряжение
-M3  -- установить режим работы - импульсный
-D  -- установить все параметры по умолчанию
-N  -- включить ус-во
-F  -- выключить ус-во
-RA -- передать мастеру действующее значение тока, следующий байт значение от 0 до 255
-RV -- передать мастеру действующее значение напряжения, следующий байт значение от 0 до 255
-RT -- передать мастеру значение температуры, следующий байт значение от 0 до 255
-RM -- передать мастеру характер нагрузки ток/напряжение, в ответ следует значение 'A' или 'V' в ASCII
-RQ -- передать мастеру состояние аварии, если ус-во в штатном рехжиме то возвращается значение "0", если произошла остановка работы по причине аварии, то возвращается "1" - перегрузка по току во вторичной цепи, "2" - КЗ в нагрузке, "3" - температура 95С и выше, в ASCII
*********************
может кто может оказать поддержку? Рассматриваю также денежную компенсацию за активную помощь в реализации кода ...

 

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

 

Прием и передача для Атмеги8, переделаешь в Атмегу32.

Скрытый текст

;*****************************************************************
; Подпрограмма передачи байта в буфер UART_OUT из регистра tmp3 *
;*****************************************************************
.cseg
MovsBuf:
push ZL ;Сохранение содержимого регистров в стеке
push ZH
push tmp1
;
cbi UCSRB,UDRIE ;Запрещение прерывания UDRE (взаимоисключение программ
 ;имеющих доступ к одному буферу
lds ZL,UART_OUT_T ;Считать указатель хвоста очереди
inc ZL ;Увеличить его на 1
andi ZL,$0f ;Если величина указателя больше 15, вернуться к началу буфера
lds tmp1,UART_OUT_H ;Считать указатель головы очереди
cp ZL,tmp1 ;Сравнить адрес головы и новый адрес хвоста
brne Movs1 ;Если они еще не равны (буфер еще не заполнен), перейти
; sbr bufstat,full_b ;Иначе сообщить головной программе, что буфер переполнен
 ;и последний байт в него не записан
rjmp EndMovs ;и выйти из подпрограммы
;
Movs1:
sts UART_OUT_T,ZL ;Сохранить в памяти новое значение указателя хвоста
; cbr bufstat,full_b ;Сообщить головной программе, что запись байта в буфер успешна
clr ZH ;Очистить старший байт регистра указателя RAM
dec ZL
andi ZL,$0f
subi ZL,-UART_OUT ;Добавить адрес начала буфера UART_OUT к значению указателя хвоста
st Z,tmp3 ;Записать байт в буфер
;
EndMovs:
sbi UCSRB,UDRIE ;Разрешить прерывание UDRE
;
pop tmp1 ;Восстановить из стека значения регистров
pop ZH
pop ZL
ret
;
;*****************************************************************
; Подпрограмма обработки прерывания от UDRE при передаче данных *
;*****************************************************************
;
TransInt:
push ZL ;Сохранить содержимое регистров в стеке
push ZH
push tmp1
in tmp1,sreg
push tmp1
;
lds ZL,UART_OUT_H ;Считать указатель головы очереди
clr ZH
subi ZL,-UART_OUT ;Вычислить абсолютный адрес первого в очереди байта
ld tmp1,Z ;Считать из буфера этот байт
out UDR,tmp1 ;Вывести его в UART
;
lds ZL,UART_OUT_H ;Не стал ли буфер теперь пустым?
;
inc ZL
andi ZL,$0f
lds ZH,UART_OUT_T
cp ZL,ZH
brne Trans1 ;Если еще нет, перейти на Trans1
;
cbi UCSRB,UDRIE ;Если буфер пуст, запретить дальнейшие прерывания
 ;по флагу UDRE (передатчик пуст)
Trans1:
sts UART_OUT_H,ZL ;Сохранить в памяти новое значение указателя головы очереди
;
pop tmp1 ;Восстановить из стека значения регистров
out sreg,tmp1
pop tmp1
pop ZH
pop ZL
reti
;
;*********************************************************************
;Подпрограмма обработки прерывания при поступлении очередного байта *
;в приемник UART			 *
;*********************************************************************
;
ReceiveInt:
push ZL ;Сохранить содержимое регистров в стеке
push ZH
push tmp1
in tmp1,sreg
push tmp1
;
in tmp1,UDR ;Считать байт из регистра данных приемника
;
lds ZL,UART_IN_T ;Увеличить количество считанных байт на один
inc ZL
cpi ZL,17 ;Если считанных байт более 16
brcc Receive1 ;то выход
;
sts UART_IN_T,ZL ;Сохранить количество считанных байт
dec ZL ;Уменьшить так как был inc ZL
clr ZH
subi ZL,-UART_IN ;Вычислить адрес места байта в буфере приема
st Z,tmp1 ;Записать байт в буфер приема
;
Receive1:
pop tmp1 ;Восстановить значения регистров из стека
out sreg,tmp1
pop ZH
pop ZL
reti

.dseg
;
UART_OUT: .byte 16 ;Адрес буфера передачи UART в RAM, должен быть кратен 16
;
UART_IN: .byte 16 ;Адрес буфера приема UART в памяти
UART_IN_T: .byte 1 ;Адрес указателя на хвост очереди UART_IN
;
UART_OUT_T: .byte 1 ;Адрес указателя на хвост очереди UART_OUT
UART_OUT_H: .byte 1 ;Адрес указателя на голову очереди UART_OUT

 

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

У него не вложение, а скрытый текст. Кликайте на "Показать содержимое", и он откроется.

ЗЫ: По сабжу. Какую помощь ожидаете ? Если "сделайте всё за меня", то ошиблись разделом.
 

Ссылка на комментарий
Поделиться на другие сайты

to Alex,

если бы я рассчитывал на халяву, то не сообщал бы что готов оплатить помощь ... меня интересует совет как лучше в цикле обработать, мало ли кто может выполнял похожее и есть возможность поделиться опытом!

Ссылка на комментарий
Поделиться на другие сайты

to Alex,

ну так в нижней строке в первом моем сообщении, мелким почерком изложено: " Рассматриваю также денежную компенсацию за активную помощь в реализации кода ... ")))

Ссылка на комментарий
Поделиться на другие сайты

Не заметил.

Я это всё к чему. Вопросы бы задавать более конкретнее, а не "помогите реализовать протокол" и выложить кусок его описания. Такой пост тянет только на "сделайте всё за меня", не более. Ибо не понятно, чем конкретно нужно помочь, что Вы уже сами сделали, что не понятно, на чём застряли, ... И почему именно на АСМе ? Если Вы в нём сильнее шарите, чем в другом языке, почему тогда возникли проблемы ?



 

Ссылка на комментарий
Поделиться на другие сайты

to Alex,

согласен с Вами, сейчас у меня есть железо которое работоспособно, под него для теста написал простенькую примочку для проверки приема/передачи, через терминал все работает. Ранее я писал на АСМе, но так и не освоил Си ... изначально когда делал железо, была договоренность с одним товарищем что он поможет с кодом, но как часто такое бывает, человек слился ... сейчас хотел бы найти помощи, возможно что так и выглядит как Вы пишете "сделайте за меня", но я бы сказал что не совсем ... для меня сложность правильно принять 4 байта, правильно интерпретировать и полученные данные в <data> и передать далее. Ус-во, это источник питания (по командам уже понятно я так думаю) тема сама не нова, если кто будет заинтересован в паритетном сотрудничетве, то со своей стороны поделюсь описанием железа (принципиалка, печатка, сила и пр.)

Ссылка на комментарий
Поделиться на другие сайты

Например применительно к тому, что Я выложил:

1. Команды которые принимает Атмега лучше типа S1+data, S2+data, S3+data, и т.д., т.е. одной длины, короче будет программа обработки принятых данных. Это не обязательно.

2. Принимаем данные: так как Атмега выполняет свою основную работу, то в то время когда "она свободна", так как критических команд не увидел, проверяет UART_IN_T, как появилось там количество байт соответствующих одной команде с данными, считывай UART_IN, проверяй какая команда пришла, и отрабатывай данные. Обнуляем UART_IN_T.

Ну, а дальше если будут вопросы, ответим.

Ссылка на комментарий
Поделиться на другие сайты

к примеру, основной цикл как лучше строить ... на поиске ID и как говорит Геннадий, открывать сессию:

main:  sbis UCSRA, RXC

           rjmp main

           in R16, UDR

           cpse R16, 0x10 ;(идентификатор к примеру)

           rjmp main

receive_2: sbis UCSRA, RXC

           rjmp receive_2

           in R16, UDR

           cpse .... и т.д. перебирать команды?

           

Ссылка на комментарий
Поделиться на другие сайты

to Donec,

благодарю за предоставленный код, но к сожалению с прерываниями ранее не работал, боюсь это не придаст мне ускорения ... мне бы разобраться с обработкой без захода в прерывания! Задачи микроконтроллера - работа с ПК и установка данных в цифровой пенциомметр (как расширение - работа с АЦП), чувствительными цепями занимается аналог, поэтому если не поступит посылка от ПК до ус-ва, то можно и продублировать. Скорость выбрана классическая 9600, если на этапе отладки будут возникать баги где потребуется введение прерываний, то тогда будем думать ... сейчас для меня это темный лес, без разжевывания не разберусь самостоятельно ...

Ссылка на комментарий
Поделиться на другие сайты

To Donec,

я понимаю что Вам проще, поскольку Вы постоянно практикуете и вопросов не возникает ... тогда ниже привожу шаблон, не совсем понятно как организовать в основном теле работу циклическим буфером ... плиз продемонстрируйте на примере:

*****************************************************************

          .nolist               ;данная директива отключает генерацию кода в листинг, т.е. далее в файле *.lss не будет фиксироваться ассемблерный код
          .include "m32def.inc"    ;подключение стандартного заголовочного файла для ATmega32 
          .list                     ;данная директива включает генерацию кода в листинг, т.е. далее в файле *.lss будет фиксироваться ассемблерный код

          .equ fCK         =  8000000             ;частота в герцах
          .equ BAUD        =  9600                ;скорость для UART в бодах
          .equ UBRR_value  =  (fCK/(BAUD*16))-1   ;расчитываем значение для регистра UBRR

          .dseg

UART_IN: .byte 4 ;Адрес буфера приема UART в памяти
UART_IN_T: .byte 1 ;Адрес указателя на хвост очереди UART_IN

          .cseg          ;данная директива означает, что дальше идет код программы
          .org 0      ;данная директива означает, что код программы будет располагаться с 0ого адреса в FLASH

  ;ВЕКТОР ПРЕРЫВАНИЙ 
          rjmp  initial         ;прерывание от … , ссылаемся на обработчик прерывания - initial
          rjmp  0                        ;rjmp  service_INT0 ;внешнее прерывание 0      
          rjmp  0                        ;rjmp  service_INT1 ;внешнее прерывание 1     
          rjmp  0                        ;rjmp  service_OC2  ;совпадение TCNT2 и OCR2  
          rjmp  0                        ;rjmp  service_OVF2 ;переполнение TCNT2       
          rjmp  0                        ;rjmp  service_ICP1 ;захват в ICP1           
          rjmp  0                        ;rjmp  service_OC1A ;совпадение TCNT1 и OCR1A 
          rjmp  0                        ;rjmp  service_OC1B ;совпадение TCNT1 и OCR1B 
          rjmp  0                        ;rjmp  service_OVF1 ;переполнение TCNT1       
          rjmp  0                        ;rjmp  service_OVF0 ;переполнение TCNT0       
          rjmp  0                        ;rjmp  service_SPI  ;прерывание от модуля SPI 
          rjmp  ReceiveInt         ;rjmp  service_URXC ;получение байта по USART 
          rjmp  0                        ;rjmp  service_UDRE ;опустошение UDR в USART  
          rjmp  0                        ;rjmp  service_UTXC ;передача байта по USART  
          rjmp  0                        ;rjmp  service_ADCC ;прерывание от АЦП        
          rjmp  0                        ;rjmp  service_ERDY ;завершение записи в EEPROM
          rjmp  0                        ;rjmp  service_ACI  ;прерывание от компаратора 
          rjmp  0                        ;rjmp  service_TWI  ;прерывание от модуля TWI  
          rjmp  0                        ;rjmp  service_SPMR ;завершение выполнения spm 

  ;УСТАНОВКА СТЕКА
initial:  ldi   R16,low(RAMEND)    ;скопируем в R16 младщий байт из константы RAMEND, которая определена в m8def.inc и хранит размер SRAM
          out   SPL,R16            ;скопируем значение из R16 в SPL
          ldi   R17,high(RAMEND)   ;скопируем в R16 старший байт из константы RAMEND, которая определена в m8def.inc
          out   SPH,R17            ;скопируем значение из R17 в SPH

 ;ПОДПРОГРАММА ИНИЦИАЛИЗАЦИИ USART МОДУЛЯ

init_USART: ldi  R16,high(UBRR_value)   ;устанавливаем скорость 9600 бод
            out   UBRRH,R16
            ldi   R16,low(UBRR_value)   
          out   UBRRL,R16
            ldi   R16,(1<<TXEN) | (1<<RXEN)        ;разрешаем работу передатчика и приемника
          out   UCSRB,R16        

  ;КОД ОСНОВНОЙ ПРОГРАММЫ
main: 
loop:      rjmp  loop

;*********************************************************************
;Подпрограмма обработки прерывания при поступлении очередного байта *
;в приемник UART             *
;*********************************************************************
;
ReceiveInt:
push ZL ;Сохранить содержимое регистров в стеке
push ZH
push tmp1
in tmp1,sreg
push tmp1
;
in tmp1,UDR ;Считать байт из регистра данных приемника
;
lds ZL,UART_IN_T ;Увеличить количество считанных байт на один
inc ZL
cpi ZL,4 ;Если считанных байт более 4
brcc Receive1 ;то выход
;
sts UART_IN_T,ZL ;Сохранить количество считанных байт
dec ZL ;Уменьшить так как был inc ZL
clr ZH
subi ZL,-UART_IN ;Вычислить адрес места байта в буфере приема
st Z,tmp1 ;Записать байт в буфер приема
;
Receive1:
pop tmp1 ;Восстановить значения регистров из стека
out sreg,tmp1
pop ZH
pop ZL
reti 

*************************************************************

я использовал только блок на прием, как обрабатывать полученную команду, т.е. определить что это соответствует идентификатору и определить принадлежность к командам? Есть ли в Асме возможность сравнить одновременно сравнить с 3-4 байтами?

просьба указать на ошибки ...

Ссылка на комментарий
Поделиться на другие сайты

можете посмотреть как это реализовано в AVR910 (программатор), правда команды там однобайтные

http://www.atmel.com/images/doc0943.pdf

http://www.atmel.com/Images/AVR910.zip

 

Ссылка на комментарий
Поделиться на другие сайты

Написал первое, что пришло в голову, дальше разбирайся.

Скрытый текст

.def tmp1    =    r16
.def tmp2    =    r17
.def tmp3    =    r18
.def tmp4    =    r19
          .equ fCK         =  8000000             ;частота в герцах
          .equ BAUD        =  9600                ;скорость для UART в бодах
          .equ UBRR_value  =  (fCK/(BAUD*16))-1   ;расчитываем значение для регистра UBRR

          .dseg
UART_IN:    .byte 16 ;Адрес буфера приема UART в памяти
UART_IN_T:    .byte 1 ;Адрес указателя на хвост очереди UART_IN

          .cseg          ;данная директива означает, что дальше идет код программы
          .org 0      ;данная директива означает, что код программы будет располагаться с 0ого адреса в FLASH

  ;ВЕКТОР ПРЕРЫВАНИЙ
          jmp  initial        ;1            
          jmp  0            ;2               
          jmp  0            ;3               
          jmp  0            ;4              
          jmp  0            ;5                 
          jmp  0            ;6                    
          jmp  0            ;7             
          jmp  0            ;8             
          jmp  0            ;9                   
          jmp  0            ;10                   
          jmp  0            ;11             
          jmp  0            ;12                
          jmp  0            ;13              
          jmp  ReceiveInt  ;14             
          jmp  0            ;15                    
          jmp  0            ;16           
          jmp  0            ;17            
          jmp  0            ;18              
          jmp  0            ;19             
          jmp  0            ;20             
          jmp  0            ;21            

  ;УСТАНОВКА СТЕКА
initial:  ldi   R16,low(RAMEND)    ;скопируем в R16 младщий байт из константы RAMEND, которая определена в m8def.inc и хранит размер SRAM
          out   SPL,R16            ;скопируем значение из R16 в SPL
          ldi   R17,high(RAMEND)   ;скопируем в R16 старший байт из константы RAMEND, которая определена в m8def.inc
          out   SPH,R17            ;скопируем значение из R17 в SPH

 ;ПОДПРОГРАММА ИНИЦИАЛИЗАЦИИ USART МОДУЛЯ
init_USART: ldi  R16,high(UBRR_value)   ;устанавливаем скорость 9600 бод
            out   UBRRH,R16
            ldi   R16,low(UBRR_value)   
            out   UBRRL,R16
            ldi   R16,(1<<TXEN) | (1<<RXEN)        ;разрешаем работу передатчика и приемника
            out   UCSRB,R16        
            ldi r16, (1<<URSEL)|(1<<USBS)|(3<<UCSZ0)
            out UCSRC,r16
  ;КОД ОСНОВНОЙ ПРОГРАММЫ
main:
loop:      
            lds tmp1,UART_IN_T
            cpi tmp1,4
            brne loop

            clr tmp1
            sts UART_IN_T,tmp1

            lds tmp1,UART_IN
            lds tmp2,UART_IN+1
            lds tmp3,UART_IN+2
            lds tmp4,UART_IN+3

            cpi tmp1, 'S'
            brne loop

            cpi tmp2, '1'
            breq m1

            cpi tmp2, '2'
            breq m2

            cpi tmp2, '3'
            breq m3

            jmp loop

m1:
m2:
m3:

rjmp  loop

;*********************************************************************
;Подпрограмма обработки прерывания при поступлении очередного байта *
;в приемник UART             *
;*********************************************************************
;
ReceiveInt:
            push ZL ;Сохранить содержимое регистров в стеке
            push ZH
            push tmp1
            in tmp1,sreg
            push tmp1
;
            in tmp1,UDR ;Считать байт из регистра данных приемника
;
            lds ZL,UART_IN_T ;Увеличить количество считанных байт на один
            inc ZL
            cpi ZL,4 ;Если считанных байт более 4
            brcc Receive1 ;то выход
;
            sts UART_IN_T,ZL ;Сохранить количество считанных байт
            dec ZL ;Уменьшить так как был inc ZL
            clr ZH
            subi ZL,-UART_IN ;Вычислить адрес места байта в буфере приема
            st Z,tmp1 ;Записать байт в буфер приема
;
Receive1:
            pop tmp1 ;Восстановить значения регистров из стека
            out sreg,tmp1
            pop ZH
            pop ZL
            reti   

 

 

Ссылка на комментарий
Поделиться на другие сайты

  • 4 недели спустя...

С прерываниями все отлично получается, но надо въехать в это.

Timeout обязателен!

Вот код моего обработчика M328, но не суть будет работать даже на тини2313, только команды джампа исправить.

 

 

Вектор прерывания USART RX

.org   0x0024
URXCaddr_:        ; USART Rx Complete
jmp    _rxd     ; 
 

основной цикл, как раз твой вариант, но здесь все на любителя

;************************************************************

init_flags:            ; 
clr    flags           ; Clear flags 
;----------------------; 
boot_main:             ; 

;----------------------;
sbrc   flags,0         ; Check 0 bit 
rjmp   read_blockx     ; Read blockX

;----------------------; 
sbrc   flags,1         ; Check 1-st bit 
rjmp   write_blockx    ; write blockX

;----------------------; 
sbrc   flags,2         ; Check 2-nd bit 
rjmp   read_blocki2c   ; read  eeprom 24c02 block

;----------------------; 
sbrc   flags,3         ; Check 3-rd bit 
rjmp   write_blocki2c  ; write eeprom 24c02 block

;----------------------; 
sbrc   flags,4         ; Check 4-th bit 
rjmp   read_EEb        ; read internal eeprom byte

;----------------------; 
sbrc   flags,5         ; Check 5-th bit 
rjmp   write_EEb       ; write internal eeprom byte

;----------------------; 
sbrc   flags,6         ; Check 6-th bit 
rjmp   Get_Info        ; Get device S/N; Bootloader Version;

;----------------------; 
sbrc   flags,7         ; Check 7-th bit 
rjmp   check_b_com     ; Compare Boot commands 

;----------------------; end of boot main handler loop
rjmp   boot_main       ; jump to boot clear flags 

;************************************************************

 

 

 

 

;--------------------------;
_rxd:                      ; USART0 receive interrupt
cbi     ledp,lst           ; LED --> 1
                           ; we've got (1) byte from USART0
push    tmp                ; store register in stack
in      tmp,SREG           ; store SREG
push    tmp                ; store register in stack      
push    yl                 ; store register in stack
push    yh                 ; store register in stack 
;--------------------------; 
                           ; received bytes max length
lds     tmp,UDR0           ; tmp= RXD byte
ldi     yl,low (StatusH)   ; RAM pointer H
ldi     yh,high(StatusH)   ; RAM pointer L
add     yl,cnt             ; add RXD counter
adc     yh,zero            ; RAM pointer + RXD bytes loop 
st      y,tmp              ; save RXD byte in RAM   
inc     cnt                ; Received bytes pointer +1
;--- Header + Message -----; check Packet 11 bytes 
cpi     cnt,packet         ; если у нас принят пакет с нужным количеством байт                           
brsh    mstore_rxdc        ; его нужно немедленно обработать!
;--------------------------; 
;ldi     tmp,111            ; Set counter Timer0
out     TCNT0,zero         ; 
ldi     tmp,4              ; RXD Timeout ~ 5ms
out     TCCR0B,tmp         ; (F.clk/64) normal mode time overflow (~ )
rjmp    minterrupt_exit    ; 
;--------------------------; 

 

 

;--------------------------;
mstore_rxdc:               ; store RXD bytes counter 
sts     bcnt,cnt           ; save amount received bytes 
ori     flags,0x80         ; set 7-th bit Check Commands
stop_T0:                   ; 
clr     cnt                ; clear received bytes counter 
out     TCCR0B,zero        ; Stop Timer 0
out     TCNT0,zero         ; Clear counter Timer 0
sbi     ledp,lst           ; LED --> 0
;--------------------------; 
minterrupt_exit:           ; Same code for interrupts 
pop     yh                 ; Restore YH  from STACK
pop     yl                 ; Restore YL  from STACK
pop     tmp                ; Restore tmp from STACK
out     SREG,tmp           ; Restore SREG
pop     tmp                ; Restore tmp from STACK
reti                       ; Interrupt exit 
;--------------------------;

 

 

Ссылка на комментарий
Поделиться на другие сайты

@Roman_msk , чем вызван именно такой формат команд? 

Если именно тем что это будет вбивать человек из окна терминалки, то мнемоника команд нифига, как говорят, не интуитивно понятна. Поэтому на мой взгляд ничем не лучше команд типа S1, S2, S3 (как уже предлагал @donec, подчеркивая что они одной длинны. Я же добавлю что применение последовательных значений циферь в команде так же способствует упрощению их декодирования). Для упрощения жизни лучше было бы хотя бы привести к одной длине (всего три команды D, N F усложняют жизнь необходимостью работы с данными переменной длинны).

Все таки если есть возможность следует доработать систему команд, что упростит впоследствии кодинг.

В 19.09.2016 в 21:47, Roman_msk сказал:

....

как обрабатывать полученную команду, т.е. определить что это соответствует идентификатору и определить принадлежность к командам? Есть ли в Асме возможность сравнить одновременно сравнить с 3-4 байтами?

....

Странный вопрос. Обрабатывать следует согласно принятому протоколу, который кстати не очень то и описан. Но из того что есть в топике можно сделать вывод что из терминальной программы будет посылаться фрейм состоящий из идентификатора устройства к которому обращаются (видимо mega32 будет хостом для множества хреновин), команды и данных. По описаниям команд видно что есть какой-то там мастер, кто он? mega32 и если да то почему до терминала ответ не следует доводить? Корече фиг знает че там задумано.

Atmega32  камень восьмибитный, поэтому команды сравнения работают с байтами. При необходимости сравнить несколько байт их берут и сравнивают:  сначала первый байт, затем второй, затем третий и так пока не кончатся. По окончании выносится вердикт о равенстве. (Неожиданно правда? :D)

Рекомендую оформить это в виде макроса.

Нет никакой заслуги тому, кто даёт золото, думая, что даёт камень (Будда)

Ссылка на комментарий
Поделиться на другие сайты

Вот накидал кодик, по сравнению двух байтовых слов. Должно работать (не компилил):

 

; в SRAM размещаем буфер для сравниваемых данных
buff:	.byte	2

; во flash размещаем эталоны
ref_1:
.db	0x53, 0x41
ref_2:
.db	0х54, 0x42

.macro compare
	ldi	ZL,	low(@0*2)
	ldi	ZH,	high(@0*2)
	rcall	compare_
.endm
; ---------------------------------------
compare_:
	push	r16
	in	r16,	SREG
	push	r16
	push	r17
	ldi	YL,	low(buff)
	ldi	YH,	high(buff)
	lpm	r16,	Z+	; берем байт эталона
	ld	r17,	Y+	; берем байт из буфера
	cp	r16,	r17	; сравниваем их
	brne	mismatch	; переходим если значения не совпадают
	; сравниваем вторые байты (если нужно более 2х байт лучше организовать цикл)
	lpm	r16,	Z+	; берем второй байт эталона
	ld	r17,	Y+	; берем второй байт из буфера
	cp	r16,	r17	; сравниваем их
	brne	mismatch	; переходим если значения не совпадают
	; Ух ты, все байты равны
	pop	r17
	pop	r16
	out	SREG,	r16
	pop	r16
	SEZ		; SREG.Z <-- 1
	ret
mismatch:
	pop	r17
	pop	r16
	out	SREG,	r16
	pop	r16
	CLZ		; SREG.Z <-- 0
	ret
; ---------------------------------------
; 		Применение:
; Перед сравнением заносим сравниваемые данные в буфер
; допустим хотим проверить на равенство значению ref_1:
	compare ref_1
; после выполнения вышеуказанной подпрограммы в регистре состояния во
; флаге Z будет результат сравнения, далее уже используем команды
; работающие с этим флагом brne или breq, т.е. как если бы мы использовали команду CP
; (compare меняет только флаг Z)

 

Изменено пользователем Microchip

Нет никакой заслуги тому, кто даёт золото, думая, что даёт камень (Будда)

Ссылка на комментарий
Поделиться на другие сайты

Какой смысл читать эталон из памяти программ? Разве нельзя сравнивать принятый код сразу с константами, т.к. у автора "хотелок" команд аж 13шт. И все их надо сравнить за один проход декодирования команды. Зачем играться с чтением из памяти программ и индексными регистрами? Разве что для удобства чтения/редактирования исходника, в остальном - излишняя сложность алгоритма.

Ссылка на комментарий
Поделиться на другие сайты

 

Согласен. Ток это я так, для примеру.

И таки да, удобство чтения и редактирования исходника я считаю не последним делом, разве что кроме случаев критичных к скорости исполнения. Особо не настаиваю.

Вот вариант кода без не целевого расходования социалистической ячеек flash памяти:

 

 


.equ ref_SA	= 0x5341
.equ ref_SV	= 0x5356
	...

.macro compare
	ldi	r17,	low(@0*2)
	ldi	r18,	high(@0*2)
	rcall	compare_
.endm
; ---------------------------------------
compare_:
	in	r16,	SREG
	push	r16
	ldi	YL,	low(buff)
	ldi	YH,	high(buff)
	ld	r16,	Y+	; берем байт из буфера
	cp	r16,	r18	; сравниваем
	brne	mismatch	; переходим если значения не совпадают
	; сравниваем вторые байты (если нужно более 2х байт лучше организовать цикл)
	ld	r16,	Y+	; берем второй байт из буфера
	cp	r16,	r17	; сравниваем
	brne	mismatch	; переходим если значения не совпадают
	; Ух ты, все байты равны
	pop	r16
	out	SREG,	r16
	SEZ		; SREG.Z <-- 1
	ret
mismatch:
	pop	r16
	out	SREG,	r16
	CLZ		; SREG.Z <-- 0
	ret
; ---------------------------------------
; 		Применение:
	compare ref_SA
	breq	label_SA	; Переходим если команда совпала
	compare ref_SV
	breq	label_SV	; Переходим если команда совпала
    ; ...
; временные регистры r16, r17 и r18 сохранять в стэк не стал (если че)

 

Изменено пользователем Microchip

Нет никакой заслуги тому, кто даёт золото, думая, что даёт камень (Будда)

Ссылка на комментарий
Поделиться на другие сайты

А если так:

.equ ref_SA	= 0x5341
.equ ref_SV	= 0x5356
	...

.macro compare
	ldi	r18,	low(@0*2)
	ldi	r19,	high(@0*2)
	rcall	compare_
.endm
; ---------------------------------------
compare_:
	ldi	YL,	low(buff)
	ldi	YH,	high(buff)
	ld	r16,	Y+	; берем байт из буфера
	ld	r17,	Y
	cp	r16,	r18	; сравниваем
	cpc	r17,	r19 ; с переносом
;сдается мне, что нижний код можно удалить, т.к. флаг сравнения остается неизменным при возврате из подпрограммы
	breq	all_ok	; переходим если значения не совпадают
	CLZ		; SREG.Z <-- 0
	rjmp	exit_compare
all_ok:
; Ух ты, все байты равны
	SEZ		; SREG.Z <-- 1
exit_compare:
	ret

; ---------------------------------------
; 		Применение:
	compare ref_SA
	breq	label_SA	; Переходим если команда совпала
	compare ref_SV
	breq	label_SV	; Переходим если команда совпала

 

Согласно замечания, можно и так:

.equ ref_SA	= 0x5341
.equ ref_SV	= 0x5356
	...

.macro compare
	ldi	r18,	low(@0*2)
	ldi	r19,	high(@0*2)
	rcall	compare_
.endm
; ---------------------------------------
compare_:
	ldi	YL,	low(buff)
	ldi	YH,	high(buff)
	ld	r16,	Y	; берем байт из буфера
	ldd	r17,	Y+1 ; не изменяя индексного регистра
	cp	r16,	r18	; сравниваем
	cpc	r17,	r19 ; с переносом
	ret

; ---------------------------------------
; 		Применение:
	compare ref_SA
	breq	label_SA	; Переходим если команда совпала
	compare ref_SV
	breq	label_SV	; Переходим если команда совпала

 

А вот "баловаться" с сохранением регистра статуса и индексных регистров нужно в прерываниях или в подпрограммах, где это действительно необходимо. Согласитесь, так компактнее.

Изменено пользователем Геннадий
редактирование
Ссылка на комментарий
Поделиться на другие сайты

Согласен. Красивый кодик получился. Только не нужно ли поменять местами байты при сравнений? Т.е. 

cp	r16,	r19	; сравниваем
cpc	r17,	r18 ; с переносом

В r19 должен быть старший байт константы (первый символ команды). В buff я полагаю первый символ первым и располагается (помещается в r16). Знамо и сравнивать нужно r16 и r19:

Ну или поменять порядок в макросе

.macro compare
	ldi	r19,	low(@0*2)
	ldi	r18,	high(@0*2)
	rcall	compare_
.endm

+  !!!! Косяк детектед.

С тех пор когда константы были определены через директиву .equ нужно было удалить из макроса умножение на два. Вот так:

.macro compare
	ldi	r18,	low(@0)
	ldi	r19,	high(@0)
	rcall	compare_
.endm

 

Изменено пользователем Microchip
косяк нашел

Нет никакой заслуги тому, кто даёт золото, думая, что даёт камень (Будда)

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...