реклама на сайте
подробности

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> Как написать код на ассемблере AVR-на "С"-понятно.
serj32
сообщение Sep 21 2013, 18:31
Сообщение #16


Участник
*

Группа: Участник
Сообщений: 29
Регистрация: 25-01-13
Из: Брянск
Пользователь №: 75 345



Цитата(_Pasha @ Sep 21 2013, 19:56) *
Не учите людей плохому sm.gif
Код
ldi zL,low(constant1); загрузки по нормальному оформляют в виде макроса
ldi zH,high(constant1);

in temp1,ADCL
in temp2,ADCH
cp temp1,zL
cpc temp2,zH
brge kakaya_to_metka; или brlo или что там еще

Итд в таком же духе
Авровский асм имеет много псевдонимов у команд, но они хорошо отражают смысл того, что происходит, поэтому можно не стесняться

Здравствуйте Pasha,интересный код сейчас буду разбираться.
По рекомендации zombi написал код,если не трудно проверьте пожалуйста.
И сомневаюсь там где NOP нодо ли мне это делать.Спасибо.
Код
.include "m8def.inc"
.def temp1 = R16
.def temp2 = R17

.equ cons1 = 256
.equ cons2 = 384

;----вершина стека , инициализация портов,АЦП и т.д

in temp1,ADCL             ;младший байт результата АЦП
in temp2,ADCH             ;старший.................АЦП

         cpi temp2,high(cons1)  ;сравниваем ADCH с старшим байтом константы 256
         breq  metka1        ;если temp2 = high(cons1) флаг Z будет установлен и произойдёт переход на metka1

         brcs  metka2        ;если старший байт ADCH > старшего байта константы 256-high(cons1) то флага C не будет и
         out PORTD,0b00000011;перехода на metka2 не будет и включим 2 крайних светодиода

         rimp step2             ;никчему проверять младшие байты-надо перепрыгнуть на проверку следующей константы

metka1:  cpi temp1,low(cons1);в связи с тем ,что старшие байты равны - сравниваем младшие,если байт в ADCL >младшего
         breq  metka3        ;байта константы то и перехода на metka3 не будет и соответственно
         out PORTD,0b00000011;включим два крайних светодиода

metka2:  nop
metka3:  nop

step2:   cpi temp2,high(cons2)  ;сравниваем ADCH с старшим байтом константы 384
         breq  setka1            

         brcs  setka2            
         out PORTD,0b00000111;включим три крайних светодиода

         rimp step3              

setka1:  cpi temp1,low(cons2)    
         breq  setka3            
         out PORTD,0b00000111;включим три крайних светодиода

setka2:  nop
setka3:  nop

step3:;и так далее в конце надо будет ещё задержку на таймере думать


Сообщение отредактировал serj32 - Sep 21 2013, 20:39
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Sep 22 2013, 04:18
Сообщение #17


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Посмотрел.
1. out PORTD,0b00000011; - такой команды нет, есть две команды
Код
ldi  r16, 0b00000011; загрузка регистра непосредственными данными
out PORTD,r16; вывод в порт значения из регистра


2. Таки переделайте сравнение в то,что я написАл постом ранее, потому что вариант, предложенный Zombi путанный и методологически неправильный.
Go to the top of the page
 
+Quote Post
ae_
сообщение Sep 22 2013, 04:31
Сообщение #18


Участник
***

Группа: Свой
Сообщений: 462
Регистрация: 2-04-07
Из: Иркутск
Пользователь №: 26 695



Если я правильно понял о чём речь, то в итоге должно получиться что-то вроде индикатора уровня: чем больше значение в ADC, тем больше включено разрядов PORTD.
Это можно сделать для 8 сравнений с разными константами и разными значениями для PORTD например так:
Код
.def    temp    =R16
.def    uL    =R20
.def    uH    =R21
;---------------------------------
.macro    inw        ; чтение в RH:RL из ioadrH:ioadrL
    in    @0L, @1L; RL <- ioadrL
    in    @0H, @1H; RH <- ioadrH
.endm
;---------------------------------
.macro    cpiw        ; сравнение RH:RL с 16-бит константой
    ldi    temp, high(@1); используя временный регистр
    cpi    @0L, low(@1); сравнить младшие байты
    cpc    @0H, temp; сравнить старшие байты с учётом переноса
.endm
;---------------------------------
.macro    caseADC
    cpiw    u, @0    ; сравнить значение u с 16-бит константой
    brlo    skip    ; перейти, если u < const
    ldi    temp, @1; иначе загрузить в temp значение для вывода в PORTD
    rjmp    done    ; выход, пропустить все оставшиеся сравнения
skip:            ; перейти к следующему сравнению
.endm
;---------------------------------
; выше было только описание констант, макросов и регистров
; вот сама программа:

    inw    u, ADC        ; прочитать в uH:uL значение из ADCH:ADCL
    caseADC    1001, 0b11111111; сравниваем от бОльших значений
    caseADC    701,  0b01111111; к меньшим
    caseADC    526,  0b00111111
    caseADC    394,  0b00011111
    caseADC    296,  0b00001111
    caseADC    222,  0b00000111
    caseADC    166,  0b00000011
    caseADC    125,  0b00000001
    ldi    temp, 0b00000000; значение для PORTD в случае, когда ADC<min
done:
    out    PORTD, temp    ; выводим в PORTD значение, соответствующее ADC
Go to the top of the page
 
+Quote Post
zombi
сообщение Sep 22 2013, 08:15
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Цитата(_Pasha @ Sep 22 2013, 07:18) *
потому что вариант, предложенный Zombi путанный и методологически неправильный.

biggrin.gif
Однако дополнительных регистров не требует.
Путанная реализация.
На вкус и цвет ...
Go to the top of the page
 
+Quote Post
serj32
сообщение Oct 10 2013, 17:59
Сообщение #20


Участник
*

Группа: Участник
Сообщений: 29
Регистрация: 25-01-13
Из: Брянск
Пользователь №: 75 345



Считаю,что тема была бы не законченной не приведя законченный код индикатора.Спасибо всем за помощь.
Не сомневаюсь,что не совсем хорошо,но я ещё только начинающий.

Код
;******************************************
;Автор:                     *
;Дата :10/10/2013                          *
;Имя файла:indADC.asm                     *
;Для AVR : ATmega8A,в корпусе DIP28       *
;Тактовая частота:3.686 Мгц.              *
;Исследование АЦП. Индикатор на           *
;светодиодах.Прерывание .Однократный      *
;режим преобразования АЦП.                *
;******************************************
.include "m8Adef.inc"           ;Файл определений для ATmega8A
.list                           ;Включение листинга
.def temp = r16                 ;Временный регистр
.def leder = r19                ;Регистр индикации
.def temp1 = r20
;**** Описание макроса ********************

.macro    caseADC
       ldi temp1,high(@2)
       cpi zL,low(@2)
       cpc zH,temp1
       brlo  t@0
       ldi leder,@1
       out PORTD,leder
t@0:
.endm

;****Векторы прерываний *******************
.org $0                         ;Установка текущего адреса на ноль по "RESET"
       rjmp init                 ;Переход на начало программы

.org $00E                       ;Вектор прерывания АЦП
       rjmp adca                 ;преобразование завершено                 ;
;****Модуль инициализации******************

init: ldi temp,low(RAMEND)      ;Установка указателя стека
       out SPL,temp              ;на последнюю
       ldi temp,high(RAMEND)     ;ячейку
       out SPH,temp              ;ОЗУ
       ldi temp,0b11111111       ;Порт PD на вывод
       out DDRD,temp             ;используем выводы PD0...PD7
       out PORTD,temp            ;Погасим светодиоды на PD0...PD7

       clr temp                  ;Аналоговые входы порта PC
       out DDRC,temp             ;на выводе PC0 "сидит" канал ADC0
       out PORTC,temp            ;отключаем подтягивающие резисторы
      
      
;****Инициализация АЦП *********************
       ldi temp,0b10001101       ;ADEN=1,ADIE=1,Fadc=Fclk/32,ADFR=0(режим однократного преобразования)
       out ADCSRA,temp           ;Fadc=115 кГц при Fclk=3,69 МГц
       ldi temp,0b01000000       ;Выбираем канал ADC0 по выводу PC0
       out ADMUX,temp            ;Опорное напряжение AVCC=VCC равно напр.питания 5 вольт,ADLAR=0 (выравнивание по правому)
       sei                       ;Разрешение прерываний
       sbi ADCSRA,ADSC           ;Запуск преобразования
loop: rjmp loop                 ;Цикл ожидания прерываний
;****Обработка прерывания от АЦП **********
adca: in zL,ADCL               ;
       in zH,ADCH               ;

        cbi ADCSRA,ADIE          ;Запрет прерывания от АЦП
        ldi temp1,high(128)
        cpi zL,low(128)
        cpc zH,temp1
        brlo t0
        ldi leder,0b11111110
        out PORTD,leder

        rjmp t1
t0:    ldi leder,0b11111111
        out PORTD,leder

t1:      
caseADC  2,0b11111100,256
caseADC  3,0b11111000,384
caseADC  4,0b11110000,512
caseADC  5,0b11100000,640
caseADC  6,0b11000000,768
caseADC  7,0b10000000,896
caseADC  8,0b00000000,1020
    
        sbi ADCSRA,ADIE         ;Разрешение прерывания от АЦП
        sbi ADCSRA,ADSC         ;Пуск преобразования
        reti
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Oct 10 2013, 19:04
Сообщение #21


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Код
cbi ADCSRA,ADIE         ;Запрет прерывания от АЦП
sbi ADCSRA,ADIE        ;Разрешение прерывания от АЦП

Лишнее


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Oct 10 2013, 20:46
Сообщение #22


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(serj32 @ Oct 10 2013, 21:59) *
Код
.....
.org $0                        ;Установка текущего адреса на ноль по "RESET"
       rjmp init                ;Переход на начало программы

.org $00E                      ;Вектор прерывания АЦП
       rjmp adca                ;преобразование завершено                ;
;****Модуль инициализации******************
...       ldi temp,0b11111111      ;Порт PD на вывод
...;****Обработка прерывания от АЦП **********
...


Код
.org   $00E

и иже лучше писать как
Код
.org    INT6addr

где INT6addr это объявленное уже(!) смещение в файлики который вы с верху в исходнике заинклюдили, то биш "m8Adef.inc"

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

маски в регистр лучше загружать человекопонятными. Т.е. перед кодом (или в своём отдельном инклудники) делаете дефайны, а потом их юзаете на масках. Это если их нет в волшебном файлике "m8Adef.inc" (что редкость!).
тогда код будет читаться более понятнее (даже через пару десяткофф лет). Как пример:

Код
    ori        tempA,((1 << LED_DIG1) | (1 << LED_DIG2) | (1 << LED_DIG3))
....
    ori        tempA,(1 << OCIE0)
    out        TIMSK,tempA


это так-же можно применять к портам и пинам вывода-ввода информации. Тогда вы получаете следующие профиты:
1) код легче портируем, наименование порта меняется в заголовке файла или инклудника.
2) код легче читаем - понятно что в порт(к примеру) дисплея вывели символ, или там выдали разрешение, или там синхросигнал...
3) код легче воспринимаем - т.к. идёт абстрагирование от конкретного порта, вольно или не вольно человек концентрируется на логике кода, а не названии порта и его соответствие со схемой.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 10 2013, 21:04
Сообщение #23


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (kolobok0 @ Oct 10 2013, 23:46) *
3) код легче воспринимаем - т.к. идёт абстрагирование от конкретного порта, вольно или не вольно человек концентрируется на логике кода, а не названии порта и его соответствие со схемой.

4) сложнее ошибиться в номере бита где-то в одном обращении из многих. Скорее уж эта ошибка будет в том самом глобальном файле объявлений, а исправив ее там исправятся сразу все обращения. Не нужно будет скрупулезно шерстить все файлы исходников в поисках обращений к одному и тому же биту порта.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

2 страниц V  < 1 2
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 17:10
Рейтинг@Mail.ru


Страница сгенерированна за 0.01462 секунд с 7
ELECTRONIX ©2004-2016