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

Динамическая индикация на ассемблере


Юстас

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

Пытаюсь освоить динамическую индикацию на ассемблере. Заюзал МК ATmega16. Нашёл много полезной инфы по данному вопросу. Даже видеоурок откопал, ниже. В коде отладчику не нравится строчка "ldi XL, lov(Visible) " Установлена Atmel Studio 6.1 Подскаите, что не так с кодом? Код ниже, в нём есть пометка-коментарий.

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

/*
 * led.asm
 *
 *  Created: 22.10.2016 23:05:07
 *   Author: Admin
 */

 /*
 * Dinamitheskaya_indikaciya.asm
 *
 *  Created: 22.10.2016 22:10:33
 *   Author: Admin
 */ 
 .include "m16def.inc"
 .def temp = r16
 .def razr1 = r17
 .def razr2 = r18
 .def razr3 = r19
 .def sys = r20
 .def try = r21

 .equ ch1 = 0b01100000
 .equ ch2 = 0b11011010
 .equ ch3 = 0b11110010
 .equ ch4 = 0b01100110
 .equ ch5 = 0b10110110
 .equ ch6 = 0b10111110
 .equ ch7 = 0b11100000
 .equ ch8 = 0b11111110
 .equ ch9 = 0b11110110
 .equ ch0 = 0b11111100

 .dseg
 Visible:
 .byte 6
 .cseg
 .org 0
 jmp RESET
 .org $012
 jmp TIM0_OVF

 RESET:
  ldi temp, CH1
 sts visible, temp
  ldi temp, CH2
 sts visible+1, temp
  ldi temp, CH3
 sts visible+2, temp
  ldi temp, CH4
 sts visible+3, temp
  ldi temp, CH5
 sts visible+4, temp
  ldi temp, CH6
 sts visible+5, temp


 


 ldi temp, high(RAMEND)
 out SPH, temp
 ldi temp, low(RAMEND)
 out spl, temp
 ldi temp, 0b11111111
 out DDRB, temp
 Out DDRD, temp

 ldi temp, 0b00000010
 out TCCR0, temp
 ldi temp, 0b00000001
 out TIFR, temp
 out TIMSK, temp

 ldi temp, 0xFE
 out TCNT0, temp
 ldi sys, 0b10000000
 sei

 PROGA:
 rjmp PROGA

 TIM0_OVF:
 cli
 lsr sys
 cpi sys, 0b00000010
 breq Mary
 out PORTD, sys

 Vix:
 ldi temp, 0x00
 out TCNT0, temp
 sei
 reti

 Mary:
 ldi sys, 0b10000000
 out PORTD, sys
 ldi XH, high(Visible)
 ldi XL, lov(Visible) ; ВОТ ТУТ ЧТО-ТО ОТЛАДЧИКУ НЕ НРАВИТСЯ, ГОВОРИТ СИНТАКСИС ЕРРОР
 ldi temp, X
 out PORTB, temp
 rjmp Vix





 





 






 

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

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

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

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

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

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

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

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

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

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

  • 2 месяца спустя...

всем привет. Нужен совет.

Задумал написать программу на ассемблере для attiny2313, чтобы на 7-ми  сегментном 4-х разрядном индикаторе отображалось число (для начала). Что задумал: чтобы значения каждого разряда индикатора хранились в ОЗУ и при необходимости их можно было перезаписать.  Индикация по переполнению таймера 0. При попытке откомпилировать выдает ошибку :

"Error    1    syntax error, unexpected REGDEF "  

на строчке " lds DigTemp, Digits+DigNum" .

Что я не так делаю? Текст пополз, сорри

 Схему прилагаю. (автор кстати Goodefine, спасибо ему за проект на Си, схема оттуда).


 .nolist              
 .include "tn2313def.inc"	
 .list			        
 .def temp = r16             ;рабочая переменная
 .def DigNum = r17           ; номер разряда
 .def DigTemp = r18          ; содержимое разряда текущее
 .dseg
 		  Digits: .byte 4    ; отводим 4 байта для хранения 4-х значений индикатора

 .cseg		                 
 .org 0x00	                

          ;ВЕКТОР ПРЕРЫВАНИЙ 
          rjmp  Reset               ;прерывание от RESET, ссылаемся на обработчик прерывания 
          reti; rjmp INT0           ; External Interrupt0 Handler
          reti; rjmp INT1           ; External Interrupt1 Handler
          reti; rjmp TIM1_CAPT      ; Timer1 Capture Handler
          reti; rjmp TIMER1_COMPA    ; Timer1 CompareA Handler
          reti; rjmp TIM1_OVF       ; Timer1 Overflow Handler
		  rjmp TIMER0_OVF           ; Timer0 Overflow Handler
          reti; rjmp USART0_RXC     ; USART0 RX Complete Handler
          reti; rjmp USART0_DRE     ; USART0,UDR Empty Handler
          reti; rjmp USART0_TXC     ; USART0 TX Complete Handler
          reti; rjmp ANA_COMP       ; Analog Comparator Handler
          reti; rjmp PCINT          ; Pin Change Interrupt
          reti; rjmp TIMER1_COMPB   ; Timer1 Compare B Handler
          reti; rjmp TIMER0_COMPA   ; Timer0 Compare A Handler
          reti; rjmp TIMER0_COMPB   ; Timer0 Compare B Handler
          reti; rjmp USI_START      ; USI Start Handler
          reti; rjmp USI_OVERFLOW   ; USI Overflow Handler
          reti; rjmp EE_READY       ; EEPROM Ready Handler
          reti; rjmp WDT_OVERFLOW   ; Watchdog Overflow Handler
 
 .org 0x20	

 ;УСТАНОВКА СТЕКА
 Reset:   ldi temp,RAMEND        ;загрузка указателя стека
          out SPL,temp
  
 ;начальные настройки контроллера
	      ldi temp, 0b11111111   ;настройка портов
	      out DDRB, temp      
		  ldi temp, 0b01110100   
	      out DDRD, temp      

		  ldi temp, 0b00000010   ;разрешить прерывание по переполнению таймера0
		  out TIMSK, temp

		  ldi temp, 0b00000100   ; настройка предделителя тактовый сигнал  (011 /64, 100 /256, 101 /1024)
		  out TCCR0B, temp

          ldi Temp,0            ;обнуление таймера
          out TCNT0,Temp

		  sei ; Enable interrupts

 ;начальные значения переменных         
		  ldi DigNum, 0           ; начинаем индикацию с 0-го разряда

		  ldi temp, 5
		  sts Digits,temp          ;записываем произвольное для отображения число в ОЗУ  5720   
		  ldi temp, 7
		  sts Digits+1,temp
		  ldi temp, 2
		  sts Digits+2,temp
		  ldi temp, 0
		  sts Digits+3,temp

Main:
  rjmp Main

;******************************
; обработчик прерывания таймера
;******************************
TIMER0_OVF:
         cli
         cpi DigNum, 4         ; проверка на переполнение переменной номера разряда
		 breq InitDigNum       ; если переполнена - то обнуляем

     	 ; *********включение текущего разряда - вывод в порт D ************
		 ldi ZH,High(Array2*2)  ;загрузка начального адреса массива
         ldi ZL,Low(Array2*2)

         ldi Temp, DigNum      ;прибавление внутр. адреса
         add ZL,0
         adc ZH,Temp
		 lpm                   ;загрузка значения из массива
		 mov Temp,R0           ;копирование в РОН
		 out PortD,Temp        ;вывод в порт 

		 
		 lds DigTemp, Digits+DigNum ; загрузка значения разряда индикатора
		 
		 ; *********зажигаем abcdefg - вывод в порт B************
		 ldi ZH,High(Array1*2)  ;загрузка начального адреса массива
         ldi ZL,Low(Array1*2)

         ldi Temp, DigTemp    ;прибавление внутр. адреса
         add ZL,0
         adc ZH,Temp
		 lpm                   ;загрузка из ПЗУ

         mov Temp,R0           ;копирование в РОН
         out PortB,Temp        ;вывод в порт 
	     
		 inc DigNum            ; "двигаем" разряд

		 sei
         reti                  ;выход из обработчика

InitDigNum:                    ; обнуление значения счетчика разрядов индикатора
         ldi DigNum,0          
         ret

Array1:

.db   0b10010001 ; 0
.db   0b00100100 ; 1
.db   0b00011000 ; 2
.db   0b01101110 ; 3
.db   0b11100111 ; 4
.db   0b10000001 ; 5
.db   0b11101001 ; 6
.db   0b11101111 ; 7
.db   0b00111011 ; 8
.db   0b00001111 ; 9

Array2:
.db   0b00000100 ; 0
.db   0b00010000 ; 1 смещение - один вывод порта планируется для других целей (на нем будет прерывание)
.db   0b00100000 ; 2
.db   0b01000000 ; 3

tacho_circuit.jpg

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

Перечитайте описание команды lds. В качестве аргумента она принимает РОН и константу, а вы подсовываете РОН и арифметическую операцию. Надо загрузить в регистровую пару (X, Y или Z) адрес начала буфера, потом прибавить номер разряда и, наконец, считать из ОЗУ по полученному адресу в регистр с помощью команды ld.

ldi XH, high(Digits)
ldi XL, low(Digits)
ldi temp, 0
add XL, Digit_Num
adc XH, temp
ld temp, X

Примерно так. Под конкретную задачу можно оптимизировать.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

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

спасибо, сдвинулось с места! Почему-то думал, что адреса в ОЗУ однобайтовые. Вроде что-то даже заработало, пока не проверял досконально. Только компилятор ругается на " adc ZH,Temp" вот тут: 

         ldi ZH,High(Array1*2)  ;загрузка начального адреса массива
         ldi ZL,Low(Array1*2)

         mov Temp, DigTemp    ;прибавление внутр. адреса ; здесь у меня тоже была ldi - изменил
         add ZL,0
         adc ZH,Temp

Закомментил, прокатило, но все равно непонятно - почему? Ошибка "Invalid register". Пока вот так оставил: 

         mov Temp, DigTemp    ;прибавление внутр. адреса
         add ZL,Temp
         ;adc ZH,Temp
		 lpm                   ;загрузка из ПЗУ

Еще компилятору не понравилась запись массива, пришлось переделать вот так: 

.db   0b10010001, 0b00100100, 0b00011000, 0b01101110, 0b11100111, 0b10000001, 0b11101001, 0b11101111, 0b00111011, 0b00001111 

 

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

8 часов назад, COKPOWEHEU сказал:

В качестве аргумента она принимает РОН и константу, а вы подсовываете РОН и арифметическую операцию.

нашел в учебниках: 

lds Temp1,Digit+1

Так понимаю, что арифметическая операция допустима с константой

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

а почему компилятор может ругаться на строчку "adc ZH, 0" сообщением об ошибке "invalid register" ?

         ldi ZH,High(Array2*2)  ;загрузка начального адреса массива
         ldi ZL,Low(Array2*2)

         mov Temp, DigNum      ;прибавление внутр. адреса
         add ZL,Temp
         adc ZH,0
		 lpm                   ;загрузка значения из массива
		 mov Temp,R0           ;копирование в РОН
		 out PortD,Temp        ;вывод в порт 

 

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

19 минут назад, cucumber сказал:

почему компилятор может ругаться на строчку "adc ZH, 0" сообщением об ошибке "invalid register" ?

Компилятор,  может, и скорее всего воспринимает 0 не как число, а как аппаратный адрес. Смотрите как нотируются числа в Вашем ассемблере.
 

PS делать сдвиг таблицей, это моветон. Есть операторы сдвига. 
 

Errare humanum est. Коли людЯм позволено, что же о нас то говорить!
 

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

25 минут назад, o_l_e_g сказал:

PS делать сдвиг таблицей, это моветон. Есть операторы сдвига

у меня один пин порта Д зарезервирован под внешнее прерывание, или мы о разных вещах?

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

45 минут назад, o_l_e_g сказал:

Компилятор,  может, и скорее всего воспринимает 0 не как число, а как аппаратный адрес. Смотрите как нотируются числа в Вашем ассемблере.

заменил 0 на регистр с нулевым значением - ошибка исчезла, спасибо

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

Я про это:

Array2:
.db   0b00000100 ; 0
.db   0b00010000 ; 1 смещение - один вывод порта планируется для других целей (на нем будет прерывание)
.db   0b00100000 ; 2
.db   0b01000000 ; 3

Логичнее пользоваться командами

LSR Rn — логический вправо, при этом слева в байт лезут нули.
 LSL Rn — логический влево, при этом справа в байт лезут нули.

и через перенос.

ROL и ROR


 

3 минуты назад, cucumber сказал:

заменил 0 на регистр с нулевым значением

Не ищем легких путей? А просто заменить на 0x00?
 

Errare humanum est. Коли людЯм позволено, что же о нас то говорить!
 

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

17 минут назад, o_l_e_g сказал:

Логичнее пользоваться командами

LSR Rn — логический вправо, при этом слева в байт лезут нули.
 LSL Rn — логический влево, при этом справа в байт лезут нули.

и через перенос.

ROL и ROR

тогда придется пользоваться командами сравнения, чтобы "перескочить" используемый пин, попробую

18 минут назад, o_l_e_g сказал:

Не ищем легких путей? А просто заменить на 0x00?

попробовал - не работает. Попробовал 0b00000000 - тоже не работает. Компилятор ATMEL Studio

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

7 минут назад, cucumber сказал:

попробовал - не работает

Верно, не будет. У adc, операнды только регистры.
 

Errare humanum est. Коли людЯм позволено, что же о нас то говорить!
 

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

Подсвечивать цифры будут.

1 час назад, cucumber сказал:

у меня один пин порта Д зарезервирован под внешнее прерывание...

Значит уже сейчас, развиваемый код - ботва.

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

4 минуты назад, Геннадий сказал:

Подсвечивать цифры будут

почему? Что-то имеет "инерционность" кроме глаз? Не понял, о чем речь:mellow:

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

Ваш алгоритм построен по следующему порядку "переключаем анод - меняем цифру - переключаем анод - меняем цифру...". В промежутках между "переключаем анод - меняем цифру" значение предыдущего разряда будет отсвечивать на следующем (до смены значения цифры). 

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

11 минуту назад, Геннадий сказал:

Значит уже сейчас, развиваемый код - ботва

ну это же 2313, ну добавлять дешифратор на разряды... ну не знаю, пока просто мучаю его. Неужели это так критично? 

2 минуты назад, Геннадий сказал:

Ваш алгоритм построен по следующему порядку "переключаем анод - меняем цифру - переключаем анод - меняем цифру...". В промежутках между "переключаем анод - меняем цифру" значение предыдущего разряда будет отсвечивать на следующем (до смены значения цифры). 

согласен, надо переделывать, или очищать портБ предварительно

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

а про ботву - как переделать, если нужные для прерывания ноги висят "посередине" порта? Дешифратор добавить? Сразу вопрос - хотел сделать тахометр, принцип с динамической индикацией можно оставить прежним? Т.е . мне показалось, что будет верным отвести в ОЗУ 4 ячейки под значения индикатора, а далее в прерывании по сигналу с ножки менять содержимое? (пока не знаю как)

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

Решение про 4 ячейки верное. Неверное построение "скелета" программы. Main пустой, прерывания забиваются кодом.

И перестаньте использовать пример учебника R16=TEMP. Регистров 32, не будете же давать им всем имена собственные (запутаетесь), да и temp1, temp2, temp3... глупо выглядит. Так и пишите R16, R17 - понятнее.

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

Поменять вывод в порты - поменяю местами два куска программы - сначала  вывод в 7 сегментов, затем вывод в разряды, сделаю сдвиг, как посоветовали выше, а что в моем случае можно запихнуть в Main? Должен ли я что-то поменять в корне, или выше перечисленное и есть изменения в корне?

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

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

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

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

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

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

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

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

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

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

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

×
×
  • Создать...