Ассемблер (ASM) для AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Alexeyslav »

Единственное что понял так это УМВР = "У Меня Всё Работает". Остальное, кажется, написано в ответ не на эту тему...
forfrends
Вымогатель припоя
Сообщения: 546
Зарегистрирован: Вс дек 30, 2012 00:32:06
Откуда: Николаев / Украина
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение forfrends »

Всем добрый день!
Пытаюсь освоить Ассемблер, проэкты тестирую на Атини2313.
Вот захотелось мне понять как сделать плавное включение/выключение светодиода. Ну, для примера, собрать простенькую схему: тинька, к порту PB0 подключен светодиод, другой контакт светодиода, через резистор, к "минусу". Вот так просто :)
А вот с прошивкой - у меня полный "0".
Точнее не представляю как устроить это самое "возгорание/затухание"
Поискал по форуму, наиболее похожую тему нашел здесь: http://radiokot.ru/forum/viewtopic.php?f=3&t=48068&start=60

Там был выложен код прошивки для МК:
Спойлер

Код: Выделить всё

;=========================
;                      Плавное зажигание 10 светодиодов                         
;                                                                                       
;=========================
;
;       10led.asm
;
;       Copyright 2011 ploop <ploopgm@gmail.com>
;
;       This program is free software; you can redistribute it and/or modify
;       it under the terms of the GNU General Public License as published by
;       the Free Software Foundation; either version 2 of the License, or
;       (at your option) any later version.
;
;       This program is distributed in the hope that it will be useful,
;       but WITHOUT ANY WARRANTY; without even the implied warranty of
;       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;       GNU General Public License for more details.
;
;       You should have received a copy of the GNU General Public License
;       along with this program; if not, write to the Free Software
;       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
;       MA 02110-1301, USA.
;                                                                               
;=========================

.device ATtiny2313

;----------
;                Определения портов
;----------
.equ led0_port = PORTB
.equ led1_port = PORTB
.equ led2_port = PORTB
.equ led3_port = PORTB
.equ led4_port = PORTB
.equ led5_port = PORTB
.equ led6_port = PORTB
.equ led7_port = PORTB
.equ led8_port = PORTD
.equ led9_port = PORTD

.equ led0_bit = 7
.equ led1_bit = 6
.equ led2_bit = 5
.equ led3_bit = 4
.equ led4_bit = 3
.equ led5_bit = 2
.equ led6_bit = 1
.equ led7_bit = 0
.equ led8_bit = 6
.equ led9_bit = 5

.equ btn_pause_inc_port = PORTD
.equ btn_pause_inc_pin  = PIND
.equ btn_pause_inc_bit  = 1

.equ btn_pause_dec_port = PORTD
.equ btn_pause_dec_pin  = PIND
.equ btn_pause_dec_bit  = 0

.equ btn_pow_inc_port   = PORTA
.equ btn_pow_inc_pin    = PINA
.equ btn_pow_inc_bit    = 1

.equ btn_pow_dec_port   = PORTA
.equ btn_pow_dec_pin    = PINA
.equ btn_pow_dec_bit    = 0

; Для gavrasm
.def XH = R27
.def XL = R26
.def YH = R29
.def YL = R28
.def ZH = R31
.def ZL = R30

.def counter = r25      ; счетчик
.def max_l = r24        ; максимальная яркость
.def null = r23         ; ноль
.def delay = r22        ; задержка

.def btn_tsk = R8             ; регистр задач по нажатию кнопок.
;|7|6|5|4|3|2|1|0|
;|       | 3-0 действие по нажатию
;|7-4 действие по отпусканию
.def btn_press = R7           ; регистр состояния кнопок (3-0 нажаты)
;
.equ btn_pause_inc = 3
.equ btn_pause_dec = 2 
.equ btn_pow_inc = 1 
.equ btn_pow_dec = 0 


;=========================
; EEPROM
;=========================

.ESEG           ; Хранение настроек
.org 0

e_bright:
.db 0           ; яркость

e_delay:
.db 1         ; задержка

;=========================
; RAM
;=========================
.DSEG

del_buf: .byte 10       ; буфер переменных сравнения для 10 каналов

;----------
.cseg

;----------
; Векторы прерываний
;----------

.org 0x0000
rjmp RESET ; Reset Handler
.org 0x0001
reti ;rjmp INT0 ; External Interrupt0 Handler
.org 0x0002
reti ;rjmp INT1 ; External Interrupt1 Handler
.org 0x0003
reti ;rjmp TIM1_CAPT ; Timer1 Capture Handler
.org 0x0004
reti ; Timer1 CompareA Handler
.org 0x0005
reti ;rjmp TIM1_OVF ; Timer1 Overflow Handler
.org 0x0006
reti ;rjmp TIM0_OVF ;rjmp TIM0_OVF ; Timer0 Overflow Handler
.org 0x0007
reti ; USART0 RX Complete Handler
.org 0x0008
reti ;rjmp USART0_DRE ; USART0,UDR Empty Handler
.org 0x0009
reti ;rjmp USART0_TXC ; USART0 TX Complete Handler
.org 0x000A
reti ;rjmp ANA_COMP ; Analog Comparator Handler
.org 0x000B
reti ;rjmp PCINT ; Pin Change Interrupt
.org 0x000C
reti ;rjmp TIMER1_COMPB ; Timer1 Compare B Handler
.org 0x000D
rjmp TIMER0_COMPA ; Timer0 Compare A Handler
.org 0x000E
reti ;rjmp TIMER0_COMPB ; Timer0 Compare B Handler
.org 0x000F
reti ;rjmp USI_START ; Usi Start Handler
.org 0x0010
reti ;rjmp USI_OVERFLOW ; USI Overflow Handler
.org 0x0011
reti ;rjmp EE_READY ; EEPROM Ready Handler
.org 0x0012
reti ;rjmp rjmp WDT_OVERFLOW ; Watchdog Overflow Handler


.org 0x0013

;----------
;                          Прерывание по переполнению
;----------

TIMER0_COMPA:
set               ; устанавливаем флаг срабатывания таймера
reti

;----------
;                                 Инициализация
;----------

reset:

ldi null,0
ldi max_l,0

ldi r16,low(RAMEND)
out spl,r16

ldi r16,$FF
out DDRB,r16

out PORTB,null

ldi r16,0b01100000
out DDRD,R16

ldi r16,0b00000011
out PORTD,R16

ldi r16,0b00000000
out DDRA,r16
ldi r16,0b00000011
out PORTA,r16

;--------  таймер ---------
ldi r16,(1<<WGM01)
out TCCR0A,r16

ldi r16,250
out OCR0A,r16

ldi r16,(1<<OCIE0A)          ; прерывание по совпадению
out TIMSK,r16


ldi r16,(1<<CS00)|(1<<CS02)  ; 1/1024
out TCCR0B,r16


;=========================
;                          Старт программы
;=========================

start:


rcall upd_max_light   ; заполняем буфер минимальными значениями

ldi r17,e_bright      ; Чтение настроек яркости и задержки
rcall EERead
mov max_l,r16


ldi r17,e_delay     
rcall EERead
mov delay,r16

rcall big_delay       ; задержка 

;----------

; основной цикл
clr counter
clr r17               ; В r17 указатель на текущий светодиод
clt
sei


ldi r19,15               ; счетчик проходов,
main_loop:               ; чтобы скорость не зависила от яркости
  brtc no_timer          ; Если флаг T не установлен, значит таймер не сработал
    clt                  ; иначе сбрасываем его
    dec r19
    breq next_diode      ; Если счетчик циклов =0 - следующий диод
    cp r19,max_l         ; проверим, не меньнше ли счетчик проходов максимального
    brcs no_timer        ; если меньше - зацикливаем

    ldi YH,high(del_buf) ; берём значение яркости
    ldi YL,low(del_buf)
    add YL,r17
    adc YH,null
    ld r18,Y
    dec r18              ; уменьшаем (увеличиваем яркость)
    st Y,r18
    rjmp no_timer
  next_diode:
    ldi r19,15
    inc r17              ; если максимальная, увеличиваем счетчик светодиодов
    cpi r17,10           ; если светодиод последний - выходим
    breq exit_loop
  no_timer:
    rcall pwm
    rjmp main_loop

;----------
;                   простой цикл после прохода эффекта
;----------
exit_loop:

rcall pwm         ; ШИМ
rcall btn_test    ; Опрос кнопок
rcall btn_set     ; Реакция на кнопки

rjmp exit_loop


;=========================
;                          цикл прохода ШИМ по 10 каналам
;=========================
pwm:

ldi XH,high(del_buf)
ldi XL,low(del_buf)

ld r16,X+                      ; загружаем значение сравнения 0-го канала
cp r16,counter                 ; сравниваем со счетчиком
brne pwm_1
sbi led0_port,led0_bit         ; если равны - включаем канал


pwm_1:
ld r16,X+
cp r16,counter
brne pwm_2
sbi led1_port,led1_bit

pwm_2:
ld r16,X+
cp r16,counter
brne pwm_3
sbi led2_port,led2_bit

pwm_3:
ld r16,X+
cp r16,counter
brne pwm_4
sbi led3_port,led3_bit

pwm_4:
ld r16,X+
cp r16,counter
brne pwm_5
sbi led4_port,led4_bit

pwm_5:
ld r16,X+
cp r16,counter
brne pwm_6
sbi led5_port,led5_bit

pwm_6:
ld r16,X+
cp r16,counter
brne pwm_7
sbi led6_port,led6_bit

pwm_7:
ld r16,X+
cp r16,counter
brne pwm_8
sbi led7_port,led7_bit

pwm_8:
ld r16,X+
cp r16,counter
brne pwm_9
sbi led8_port,led8_bit

pwm_9:
ld r16,X+
cp r16,counter
brne pwm_x
sbi led9_port,led9_bit

pwm_x:

inc counter         ; инкрементируем счетчик
sbrc counter,4      ; и проверяем на переполнение
rjmp ch_off
ret

ch_off:             ; если переполнился - сбравываем счетчик и все порты
clr counter
out PORTB,null
cbi PORTD,6
cbi PORTD,5
ret

;=========================
;              заполнение буфера значениями яркости
;=========================

upd_max_light:
ldi XL,low(del_buf)
ldi XH,high(del_buf)
ldi r16,10
ldi r17,16
l0:
  st X+,r17
  dec r16
  brne l0
ret

upd_light:
ldi XL,low(del_buf)
ldi XH,high(del_buf)
ldi r17,10
l1:
  st X+,r16
  dec r17
  brne l1
ret

;=========================
;                      Подпрограмма опроса кнопок
;=========================
btn_test:
mov r16,btn_press
mov r17,btn_tsk

sbic  btn_pause_inc_pin,btn_pause_inc_bit
rjmp bt01                       ; если кнопка нажата
  sbrc r16,3                    ; проверяем, была ли она нажата ранее
  rjmp bt02                     ; если да - выходим
  ori r17,(1<<3)                ; если нет - устанавливаем действие по нажатию
  ori r16,(1<<3)                ; и факт нажатия
  rjmp bt02
bt01:                           ; если не нажата
  sbrs r16,3                    ; и не была нажата ранее
  rjmp bt02                     ; выходим
  andi r16,~(1<<3)              ; иначе сбрасываем факт нажатия
  ori r17,(1<<7)                ; ставим действие по отпусканию
bt02:
;----------
sbic  btn_pause_dec_pin,btn_pause_dec_bit
rjmp bt03                       ; если кнопка нажата
  sbrc r16,2                    ; проверяем, была ли она нажата ранее
  rjmp bt04                     ; если да - выходим
  ori r17,(1<<2)                ; если нет - устанавливаем действие по нажатию
  ori r16,(1<<2)                ; и факт нажатия
  rjmp bt04
bt03:                           ; если не нажата
  sbrs r16,2                    ; и не была нажата ранее
  rjmp bt04                     ; выходим
  andi r16,~(1<<2)              ; иначе сбрасываем факт нажатия
  ori r17,(1<<6)                ; ставим действие по отпусканию
bt04:
;----------
sbic  btn_pow_inc_pin,btn_pow_inc_bit
rjmp bt05                       ; если кнопка нажата
  sbrc r16,1                    ; проверяем, была ли она нажата ранее
  rjmp bt06                     ; если да - выходим
  ori r17,(1<<1)                ; если нет - устанавливаем действие по нажатию
  ori r16,(1<<1)                ; и факт нажатия
  rjmp bt06
bt05:                           ; если не нажата
  sbrs r16,1                    ; и не была нажата ранее
  rjmp bt06                     ; выходим
  andi r16,~(1<<1)              ; иначе сбрасываем факт нажатия
  ori r17,(1<<5)                ; ставим действие по отпусканию
bt06:
;----------
sbic  btn_pow_dec_pin,btn_pow_dec_bit
rjmp bt07                       ; если кнопка нажата
  sbrc r16,0                    ; проверяем, была ли она нажата ранее
  rjmp bt08                     ; если да - выходим
  ori r17,(1<<0)                ; если нет - устанавливаем действие по нажатию
  ori r16,(1<<0)                ; и факт нажатия
  rjmp bt08
bt07:                           ; если не нажата
  sbrs r16,0                    ; и не была нажата ранее
  rjmp bt08                     ; выходим
  andi r16,~(1<<0)              ; иначе сбрасываем факт нажатия
  andi r16,~(1<<0)              ; иначе сбрасываем факт нажатия
  ori r17,(1<<4)                ; ставим действие по отпусканию
bt08:
;----------

mov btn_press,r16
mov btn_tsk,r17

ret


;=========================
;                        Действия при нажатии кнопок
;=========================

btn_set:

mov r20,btn_tsk
; сбросим все биты
mov r17,btn_tsk
andi r17,0b11110000
mov btn_tsk,r17

; условные переходы
sbrc r20,btn_pause_inc
rcall pause_inc
sbrc r20,btn_pause_dec
rcall pause_dec
sbrc r20,btn_pow_inc
rcall pow_inc
sbrc r20,btn_pow_dec
rcall pow_dec

ret

;=========================
; Подпрограмма записи в EEPROM (r17 - адрес, r16 - данные)
;=========================

EEWrite:   
  sbic EECR,EEWE    ; Ждем готовности памяти к записи. Крутимся в цикле
  rjmp EEWrite

  cli               ; запрещаем прерывания.
  out EEAR,r17      ; Загружаем адрес нужной ячейки
  out EEDR,r16      ; и сами данные из rx1

  sbi EECR,EEMWE    ; взводим предохранитель
  sbi EECR,EEWE     ; записываем байт
  sei               ; разрешаем прерывания
ret

;=========================
; Подпрограмма чтения в EEPROM (r17 - адреса, r16 - данные)
;=========================
EERead:
  sbic EECR,EEWE     ; Ждем пока будет завершена прошлая запись.
  rjmp EERead         
  out EEAR, r17      ; загружаем адрес нужной ячейки
   
  sbi EECR,EERE      ; Выставляем бит чтения
  in r16,EEDR        ; Грузим из регистра данных результат
ret

;=========================
;                            увеличение задержки
;=========================
pause_inc:

cpi delay,251               ; проверка на максимум
breq exit_pause_inc

subi delay,-10              ; увеличение задержки и запись в EEPROM
mov r16,delay
ldi r17,e_delay
rcall EEWrite
rjmp reset

exit_pause_inc:
ret

;=========================
;                            уменьшение задержки
;=========================
pause_dec:


cpi delay,1                 ; проверка на минимум
breq exit_pause_dec

subi delay,10               ; уменьшение задержки и запись в EEPROM
mov r16,delay
ldi r17,e_delay
rcall EEWrite
rjmp reset

exit_pause_dec:
ret

;=========================
;                            увеличение яркости
;=========================
pow_inc:

cpi max_l,0               ; проверка на ноль. 0 - максимальная яркость
breq exit_pow_inc

dec max_l                 ; увеличение яркости и запись в EEPROM
mov r16,max_l
ldi r17,e_bright
rcall EEWrite

rcall upd_light

exit_pow_inc:

ret

;=========================
;                            уменьшение яркости
;=========================
pow_dec:

cpi max_l,14               ; проверка на 15. 15 - минимальная яркость
breq exit_pow_dec

inc max_l                  ; увеличение яркости и запись в EEPROM
mov r16,max_l
ldi r17,e_bright
rcall EEWrite

rcall upd_light

exit_pow_dec:
ret

;=========================
;                            задержка
;=========================
big_delay:
ldi r16,0                         
ldi r17,0
mov r18,delay
del_loop:     
  dec r16               
  brne del_loop           
  dec r17
  brne del_loop
  dec r18
  brne del_loop
ret


Вот только я в этом коде запутался. Можете помочь отделить только то что отвечает за зажигание/гашение?
Сделать своими руками всегда интересней чем просто купить и пользоваться
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Alexeyslav »

За это отвечает подпрограмма PWM.

Код вы слишком сложный взяли для "начинания". Очень тяжелый код, без коментариев, неочевидный и т.д.
Вся бодяга затеяна из-за 10 диодов. А тебе нужен ОДИН - для этого достаточно один канал ШИМ одного таймера. Переключаешь таймер в режим PWM разрешаешь аппаратный выход по сравнению, регистром сравнения задаешь скважность... осталось только в программе с задержкой наращивать значение скважности - это будет единственное что делает программа.
forfrends
Вымогатель припоя
Сообщения: 546
Зарегистрирован: Вс дек 30, 2012 00:32:06
Откуда: Николаев / Украина
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение forfrends »

Да, код для меня тяжелый...
Просто ничего другого не нашел. Да, я так и подумал что PWM отвечает за плавное включение/отключение, но не смог в ней разобраться.
Alexeyslav, можете показать пример кода где просто загорается светодиод, без всего лишнего, просто линейный алгоритм, без прыжков туда-сюда? Что бы PWM не было функцией, а основным кодом программы. То есть, включился контроллер, светодиод плавно загорелся, и на этом все.
Помогите в этом разобраться.
Сделать своими руками всегда интересней чем просто купить и пользоваться
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Alexeyslav »

Вот собственно: [ATTINY13]
Конфигурация таймера:

Код: Выделить всё

set_io SPL, low(RAMEND)

 ; установить порты ввода-вывода
 set_io DDRB,   0b00011111  ; 1 - выход, 0 - вход.
 
; настройка таймера
;прескалер выставить на 8, Fast PWM частота будет 4.8Мгц/(8*512) ~ 1.1кГц

 set_io TCCR0A, 0b10110001  ; режим таймера 01 - PWM(Phase Correct). Clear OC0A on Compare Match when up-counting. 
                                                                   ; Set   OC0A on Compare Match when down-counting.
                                                   ; Set   OC0B on Compare Match when up-counting.
                                                   ; Clear OC0B on Compare Match when down-counting.
 set_io TCCR0B, 0b00000010  ; Счетчик работает c предделителем = 8.


Данная конфигурация делает прямой вывод OC0A, и инверсный для OC0B, если для второго выхода надо прямой - почитай даташит, по поводу регистра TCCR0A.

Макрос установка ШИМа: (оба канала получают одно и то же значение, но их можно устанавливать раздельно)

Код: Выделить всё

.macro set_led
  set_reg      ledv, R16  ; Копия в текущее значение, для последующих плавных переходов.
  OUT      OCR0A,   R16
  OUT      OCR0B,   R16
.endmacro

Оба ШИМ устанавливаются в значение из регистра R16.

для плавного нарастания и спада я использую такой набор подпрограмм:

Код: Выделить всё


.DEF LEDV = R1    ; Текущая Яркость
.DEF tmp  = R11

; Счетчики в регистрах
.DEF cyclecount = R16
.DEF target     = R17
.DEF speed      = R18


.macro trans_light
  LDI   target, @0
  LDI   speed,  @1
  rcall   tr_light
.endmacro

.macro actualize_led
  mov   accum, ledv
  OUT   OCR0A,   ACCUM
  OUT   OCR0B,   ACCUM
.endmacro

tr_light:
 clr tmp      // будет выполнять роль суб-счетчика, который будет наполнятся speed
             // и по переполнению выполнятся инкремент/декремент главного значения.
tr_loop:
 CP ledv, target
 BREQ tr_end // значение уже равно необходимому, выходим наф
 BRLO tr_inc // target оказался больше чем ledv, нужен инкремент.

tr_dec:     // остался только вариант ledv > target, нужен декремент
 add tmp, speed
 BRCC tr_no   // нет переполнения субсчетчика - не меняем яркость
 DEC ledv
 actualize_led
 rjmp tr_no

tr_inc:
 add tmp, speed
 BRCC tr_no
 INC ledv
 actualize_led

tr_no:
 rcall delay_step
 rjmp tr_loop
tr_end:
RET



Вызывается переход яркости простым алгоритмом:

"trans_light 0x00, 0xFF" - до значения "0" со скоростью 255 т.е. каждую задержку ШИМ будет изменять значение на "1" если указать скорость 128 - каждые две задержки, указать 1 - каждые 256 задержек на 1 единицу, таким образом при скорости "1" от 0 до 255 пройдет времени на 65536 заданных интервалов. При заданном интервале 1мс это будет 65 секунд. при скорости 255 - 255 милисекунд.

Защиты от скорости равной нулю нет! Поэтому осторожней - при нулевой скорости из алгоритма выхода никогда не будет.
forfrends
Вымогатель припоя
Сообщения: 546
Зарегистрирован: Вс дек 30, 2012 00:32:06
Откуда: Николаев / Украина
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение forfrends »

Спасибо. Буду пробовать во всем этом разобраться
Сделать своими руками всегда интересней чем просто купить и пользоваться
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение zero648 »

Вот еще небольшой примерчик:
Спойлер

Код: Выделить всё


            .include "tn2313def.inc"  ; Используем ATtiny2313

.equ Vpwr_mV = 5000    ; Питание = 5000 mV
.equ Vout_mV = 3000    ;   Выход = 0 - 5000 mV

; ROM ===============

            .CSEG                     ; ROM
            .org $000

            rjmp RESET                ; External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset
            reti                      ; INT0          Внешнее прерывание 0
            reti                      ; INT1          Внешнее прерывание 1
            reti                      ; TIMER1 CAPT   Захват таймера/счетчика Т1
            reti                      ; TIMER1 COMPA  Совпадение «А» таймера/счетчика Т1
            reti                      ; TIMER1 OVF    Переполнение таймера/счетчика Т1
            reti                      ; TIMER0 OVF    Переполнение таймера/счетчика Т0
            reti                      ; USART,RX      USART, прием завершен
            reti                      ; USART,UDRE    Регистр данных USART пуст
            reti                      ; USART,TX      USART, передача завершена
            reti                      ; ANA_COMP      Аналоговый компаратор
            reti                      ; PCINT         Pin Change Interrupt
            reti                      ; TIMER1 COMPB  Совпадение «В» таймера/счетчика Т1
            reti                      ; TIMER0 COMPA  Timer/Counter0 Compare Match A
            reti                      ; TIMER0 COMPB  Timer/Counter0 Compare Match B
            reti                      ; USI START     USI Start Condition
            reti                      ; USI OVERFLOW  USI Overflow
            reti                      ; EE READY      EEPROM, готово
            reti                      ; WDT OVERFLOW Watchdog Timer Overflow
           
; ---------- R E S E T ----------

            .ORG   INT_VECTORS_SIZE   ; Конец таблицы прерываний

RESET:
            cli
            ldi     r16, RAMEND       ; Set Stack Pointer to top of RAM
            out     SPL, r16          ;

; ---------- M A I N  P R O G R A M M ----------

PORTS_Init:
            ldi   r16, 0b00001000
            out   DDRB, r16

PWM_16_A_Init:
            ldi   r16, low(Vout_mV)  ;
            ldi   r17,high(Vout_mV)  ;
            out   OCR1AH, r17        ;
            out   OCR1AL, r16
            ldi   r16, low(Vpwr_mV)  ;
            ldi   r17,high(Vpwr_mV)  ;
            out   ICR1H, r17         ;
            out   ICR1L, r16
            ldi   r16, (0b10<<WGM10) ; Set PWM, Phase Correct mode with resolution ICR1.
            ldi   r17, (0b10<<WGM12) ; Set PWM, Phase Correct mode with resolution ICR1.
            ori   r16, (0b10<<COM1A0); Clear OC1A on Compare Match, set OC1A at ICR1
            ori   r17, (0b001<<CS10) ; Prescaler 001=1:1
            out   TCCR1A, r16        ;
            out   TCCR1B, r17        ; Enable TCNT1
            sei

MAIN_loop:
            in    r16,MCUCR
            ori   r16, (1<<SE)
            out   MCUCR, r16
            sleep                     ; Отдыхаем пока не началось
            rjmp  MAIN_loop           ; Go again               




Здесь яркость задает переменная "Vout_mV", остальсь только вставить в главный цикл алгоритм её изменения от 0 до Vpwr_mV и загрузки в регистр OCR1A.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Alexeyslav »

Это конечно интересная штука, но для светодиода достаточно 8-битного ШИМа, а 16-битные таймеры всегда дефицит. Правда, там всеравно оговорок много, в частности яркость светодиода зависит нелинейно от скважности - примерно до 30% яркость меняется быстро, а дальше - едва заметно. нужна какая-то хотя-бы табличная коррекция по 16 опорным точкам.
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение zero648 »

Экспериментальный код из заначек, написан не для светодиода, но тоже пойдет, его плюсы в том, что можно плавно менять не только скважность, но и частоту ШИМа.
Аватара пользователя
BlYur
Открыл глаза
Сообщения: 52
Зарегистрирован: Пн май 27, 2013 17:02:32

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение BlYur »

Подскажите, почему моя первая простейшая программа не работает?
ATMega16, программа должна зажигать светодиод при нажатой кнопке и гасить при отпущенной.

Код: Выделить всё

ldi r17, 0b11111111
   out ddrb, r17      ; Порт В на выход
   ldi r16, 0b00000000
   out ddrc, r16      ; Порт С на вход
   out PortC, r17      ; Подтяжка порта С
Main:
   sbic pinc, 4      ; Проверим состояние входа кнопки РС4
   rjmp LEDOff         ; Переход, если не нажата (на РС4 высокий уровень)
   out PortB, r17      ; Включим светодиод
   

   RJMP   Main
LEDOff:
   out PortB, r16      ; Выключим светодиод
   rjmp Main


Гоняю в AVR Studio, там всё вроде нормально, но вот в контролере тупо зажигает светодиод и всё.

Разобрался, ёклмн!
Классические вилы. Порт С по дефолту работает на жтаг и потому те выводы его , что служат жтагу (TDI TDO ЕСЛ TMS) не могут использоваться как порт. Жтаг можно отключить либо фуз битами. Либо поправив регистр MCUCSR поставив там бит JTD
Последний раз редактировалось BlYur Пт июл 19, 2013 19:06:27, всего редактировалось 3 раза.
SmarTrunk
Друг Кота
Сообщения: 6014
Зарегистрирован: Чт ноя 26, 2009 11:16:50
Откуда: Москва

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение SmarTrunk »

Живьем проверяете, или в симуляторе? Казалось бы, в AVR Studio несложно выявить проблему. Сходу кажется, что все хорошо.
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение dr.doc »

Доброго времени суток, уважаемые коты!
Разбираясь с кодом Игоря Чешко (если правильно прочел по чешски), столкнулся со следующим:

ldi bitcount,CRC16poly>>8 ;do bitcount CRC polynom - vrchny byte
eor temp1,bitcount ;a urob XOR zo zvyskom a CRC polynomom - vrchny byte
ldi bitcount,CRC16poly ;do bitcount CRC polynom - spodny byte
eor temp0,bitcount ;a urob XOR zo zvyskom a CRC polynomom - spodny byte


Регистр bitcount - R21, 8-ми битный, а переменная - 16-ти. При компиляции в АВР студио 6.0 выпадает ошибка:
Error 5 Operand(s) out of range in 'ldi r21,0x8005' - на 3-ю строку
Вопрос: Как мне изменить запись, чтобы ее (ошибку) обойти. Разбивать константу не очень хочется - код ведь чужой! И почему у автора в 4-й проект компилировался?
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
nirq
Опытный кот
Сообщения: 758
Зарегистрирован: Вс фев 10, 2013 15:26:00

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение nirq »

ldi r21,low(0x8005)

Или high, или byte1/2/3/4 - как задумано. Полностью 16 бит в 8 не влезут ну никак.

Компилятор имеет право обрезать лишнее молча. Или обрезать с предупреждением и продолжить. Или грязно выругаться и остановиться. На усмотрение компилятора.
К.О.
Аватара пользователя
dr.doc
Это не хвост, это антенна
Сообщения: 1368
Зарегистрирован: Вс мар 28, 2010 12:52:22
Откуда: Беларусь

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение dr.doc »

Спасибо огромное! Уже не ругается, добавил low(CRC16poly) и все стало нормально компилироваться. Про такой прием не знал (просто начинал с PIC контроллеров).
«Еще я хотел бы, чтобы наши ученые изобрели какой-то новый источник энергии, чтобы мы на коленях не ползали даже перед нашими братьями, умоляя их и выпрашивая тонну нефти или кубометр газа», — рассказал белорусский президент.
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Alexeyslav »

Просто компилятор у него был молчаливый, на самом деле обработка-то идет 16 бит, но при помощи 8-битных регистров.

CRC16poly>>8 заменить на high(CRC16poly)
а там где просто CRC16poly заменить на low(CRC16poly) это будет правильней.
Dessp
Встал на лапы
Сообщения: 136
Зарегистрирован: Ср янв 23, 2013 10:58:31

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Dessp »

Всем привет. Такой вот вопрос.

Пишу программу на асемблере для атмега88
так работает
ldi temp,0b00000001
out EIMSK,temp

а так нет

ldi temp,0b00000001
sts EIMSK,temp

почему?
Спасибо
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение zero648 »

Потому что когда OUT, то EIMSK=0x1d
а когда используете STS, то EIMSK должен быть 0x3d, т.е. +0x20.
Dessp
Встал на лапы
Сообщения: 136
Зарегистрирован: Ср янв 23, 2013 10:58:31

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Dessp »

zero648 писал(а):Потому что когда OUT, то EIMSK=0x1d
а когда используете STS, то EIMSK должен быть 0x3d, т.е. +0x20.


а почему так происходит? я запутался в етих out и sts. если не сложно обясните пжл. если нет, даите хотсябы ссылку где детально про это написано. спасибо
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Gudd-Head »

Dessp писал(а):а почему так происходит?

Потому что младшие 32 байта области данных выделены под РОН, за ними идут РВВ, за ними — SRAM.
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Alexeyslav
Друг Кота
Сообщения: 4550
Зарегистрирован: Чт май 05, 2011 21:26:34
Откуда: Украина, Славутич
Контактная информация:

Re: Ассемблер (ASM) для AVR в вопросах и ответах

Сообщение Alexeyslav »

Потому что OUT работает только с УВВ со своим диапазоном адресов, а STS работает со всей областью доступной памяти, в которую входит регистры, адреса устройств ввода-вывода, RAM. Смотри как эти адреса распределяются в общей адресации. а OUT просто адресует внутри конкретного кусочка адресов, и все УВВ с адресами меньше 0x3F объявлены в инклуднике под команду OUT, можно изменить соответствующим образом инклуд на конкретный контроллер и пользоваться только командой STS. Выигрыша в тактах - никакого.
Ответить

Вернуться в «AVR»