Страница 194 из 400

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

Добавлено: Сб июл 06, 2013 15:35:26
Alexeyslav
Единственное что понял так это УМВР = "У Меня Всё Работает". Остальное, кажется, написано в ответ не на эту тему...

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

Добавлено: Вт июл 16, 2013 21:50:12
forfrends
Всем добрый день!
Пытаюсь освоить Ассемблер, проэкты тестирую на Атини2313.
Вот захотелось мне понять как сделать плавное включение/выключение светодиода. Ну, для примера, собрать простенькую схему: тинька, к порту PB0 подключен светодиод, другой контакт светодиода, через резистор, к "минусу". Вот так просто :)
А вот с прошивкой - у меня полный "0".
Точнее не представляю как устроить это самое "возгорание/затухание"
Поискал по форуму, наиболее похожую тему нашел здесь: http://radiokot.ru/forum/viewtopic.php? ... 8&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

Вот только я в этом коде запутался. Можете помочь отделить только то что отвечает за зажигание/гашение?

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

Добавлено: Вт июл 16, 2013 22:14:15
Alexeyslav
За это отвечает подпрограмма PWM.

Код вы слишком сложный взяли для "начинания". Очень тяжелый код, без коментариев, неочевидный и т.д.
Вся бодяга затеяна из-за 10 диодов. А тебе нужен ОДИН - для этого достаточно один канал ШИМ одного таймера. Переключаешь таймер в режим PWM разрешаешь аппаратный выход по сравнению, регистром сравнения задаешь скважность... осталось только в программе с задержкой наращивать значение скважности - это будет единственное что делает программа.

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

Добавлено: Ср июл 17, 2013 08:04:51
forfrends
Да, код для меня тяжелый...
Просто ничего другого не нашел. Да, я так и подумал что PWM отвечает за плавное включение/отключение, но не смог в ней разобраться.
Alexeyslav, можете показать пример кода где просто загорается светодиод, без всего лишнего, просто линейный алгоритм, без прыжков туда-сюда? Что бы PWM не было функцией, а основным кодом программы. То есть, включился контроллер, светодиод плавно загорелся, и на этом все.
Помогите в этом разобраться.

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

Добавлено: Ср июл 17, 2013 20:36:49
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 милисекунд.

Защиты от скорости равной нулю нет! Поэтому осторожней - при нулевой скорости из алгоритма выхода никогда не будет.

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

Добавлено: Чт июл 18, 2013 17:38:26
forfrends
Спасибо. Буду пробовать во всем этом разобраться

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

Добавлено: Чт июл 18, 2013 22:37:56
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.

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

Добавлено: Чт июл 18, 2013 22:47:33
Alexeyslav
Это конечно интересная штука, но для светодиода достаточно 8-битного ШИМа, а 16-битные таймеры всегда дефицит. Правда, там всеравно оговорок много, в частности яркость светодиода зависит нелинейно от скважности - примерно до 30% яркость меняется быстро, а дальше - едва заметно. нужна какая-то хотя-бы табличная коррекция по 16 опорным точкам.

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

Добавлено: Чт июл 18, 2013 23:11:56
zero648
Экспериментальный код из заначек, написан не для светодиода, но тоже пойдет, его плюсы в том, что можно плавно менять не только скважность, но и частоту ШИМа.

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

Добавлено: Пт июл 19, 2013 16:42:39
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

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

Добавлено: Пт июл 19, 2013 17:00:41
SmarTrunk
Живьем проверяете, или в симуляторе? Казалось бы, в AVR Studio несложно выявить проблему. Сходу кажется, что все хорошо.

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

Добавлено: Сб июл 20, 2013 14:16:37
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-й проект компилировался?

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

Добавлено: Сб июл 20, 2013 15:42:50
nirq
ldi r21,low(0x8005)

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

Компилятор имеет право обрезать лишнее молча. Или обрезать с предупреждением и продолжить. Или грязно выругаться и остановиться. На усмотрение компилятора.
К.О.

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

Добавлено: Сб июл 20, 2013 16:29:41
dr.doc
Спасибо огромное! Уже не ругается, добавил low(CRC16poly) и все стало нормально компилироваться. Про такой прием не знал (просто начинал с PIC контроллеров).

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

Добавлено: Сб июл 20, 2013 16:50:47
Alexeyslav
Просто компилятор у него был молчаливый, на самом деле обработка-то идет 16 бит, но при помощи 8-битных регистров.

CRC16poly>>8 заменить на high(CRC16poly)
а там где просто CRC16poly заменить на low(CRC16poly) это будет правильней.

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

Добавлено: Пн июл 22, 2013 14:28:20
Dessp
Всем привет. Такой вот вопрос.

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

а так нет

ldi temp,0b00000001
sts EIMSK,temp

почему?
Спасибо

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

Добавлено: Пн июл 22, 2013 14:42:15
zero648
Потому что когда OUT, то EIMSK=0x1d
а когда используете STS, то EIMSK должен быть 0x3d, т.е. +0x20.

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

Добавлено: Пн июл 22, 2013 15:28:00
Dessp
zero648 писал(а):Потому что когда OUT, то EIMSK=0x1d
а когда используете STS, то EIMSK должен быть 0x3d, т.е. +0x20.
а почему так происходит? я запутался в етих out и sts. если не сложно обясните пжл. если нет, даите хотсябы ссылку где детально про это написано. спасибо

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

Добавлено: Пн июл 22, 2013 15:54:35
Gudd-Head
Dessp писал(а):а почему так происходит?
Потому что младшие 32 байта области данных выделены под РОН, за ними идут РВВ, за ними — SRAM.

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

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