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

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
Mr.Moss
Открыл глаза
Сообщения: 68
Зарегистрирован: Вт июл 24, 2007 23:34:23

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

Сообщение Mr.Moss »

Доброго времени суток всем.
Вопрос конечно нужно было задать в обучалке, но боюсь меня там не услышат, по этому прошу простить меня и помоч :cry:
Вопрос в следующем, пришел тот злащасный день когда мне понадобилась работа с не целыми числами типа 1,5 в ассемблере, ести ли какие либо стандартные варианты работы с такими числами или нужно чегото мудрить, если мудрить то как???
Может у кого есть заготовки для работы с такими числами.
Заранее спасибо.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

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

Мой уютный бложик... заходите!
Аватара пользователя
Aheir
Модератор
Сообщения: 4517
Зарегистрирован: Пн апр 03, 2006 11:43:25
Откуда: Санкт - Петербург
Контактная информация:

Сообщение Aheir »

Вот здесь посмотрите...
Оптимизм х (Опыт + Знания) = const
Аватара пользователя
Tohey
Грызет канифоль
Сообщения: 257
Зарегистрирован: Сб сен 09, 2006 19:00:18
Откуда: СССР

Сообщение Tohey »

На офф.сайте Атмел находил какие то экзамплы...
Аватара пользователя
Кошкелот
Встал на лапы
Сообщения: 97
Зарегистрирован: Пн июл 30, 2007 08:19:02
Откуда: Екатеринбург
Контактная информация:

Сообщение Кошкелот »

Я бы начал с выяснения, ассемблер КАКОГО таракана рассматривается. PIC, Atmel... да их же много. Вот в ассемблере IBM PC :) вполне можно работать с IEEE-шной плавучкой и командами сопроцессора :).

Второй вопрос - в каком диапазоне нужны числа и с какой точностью. По секрету: иногда помогаат ужасный прием: просто перейти в другой масштаб. Нужно "полтора"? Пиши 15 или 150... или 1500... Держи делитель в уме и не забудь скорректировать масштаб при выводе числа куда надо.
Аватара пользователя
Mr.Moss
Открыл глаза
Сообщения: 68
Зарегистрирован: Вт июл 24, 2007 23:34:23

Сообщение Mr.Moss »

Всем большое спасибо за советы, вроде разобрался, использую вариант с масштабом, работает!
Аватара пользователя
Инженер
Прорезались зубы
Сообщения: 232
Зарегистрирован: Сб ноя 24, 2007 09:03:29
Откуда: Ульяновск

Сообщение Инженер »

Здравствуйте!

Помогите пожалуйста в ассемблере. Нужно запустить 16 битный таймер, и в определенный момент его считать и сбросить. (ATTiny2313) Я смотрел datasheet и несколько переведенных статей. Мне нужны только CS12, CS11 и CS10 (001)-делитель частоты. А что делать с остальными битами настройки? В ноль их всех? И надо ли их вообще устанавливать если они мне не нужны?
Как устанавливать параметры таймера?
Так?
ldi r17,0b00000001
out TCCR1B,r17
Чтение и установка в даташите вроде понятно написано (с примером)
Как таймер запустить? Или он запускается автоматически? (вместе с МК)
Аватара пользователя
tych
Э...
Сообщения: 2792
Зарегистрирован: Ср апр 04, 2007 08:39:14
Откуда: Москва
Контактная информация:

Сообщение tych »

Последний раз редактировалось tych Чт май 15, 2008 11:34:30, всего редактировалось 1 раз.
Думайте сами, решайте сами ... а вот он-лайн перевод на корявый русский http://translate.ru
Аватара пользователя
Инженер
Прорезались зубы
Сообщения: 232
Зарегистрирован: Сб ноя 24, 2007 09:03:29
Откуда: Ульяновск

Сообщение Инженер »

Да я нашел его. Нужная вещь. Но это три бита из байта TCCR1B а остальные биты как ставить? Какие настройки нужно ОБЯЗАТЕЛЬНО настроить у таймера? Как насчет остальных вопросов?
Аватара пользователя
Инженер
Прорезались зубы
Сообщения: 232
Зарегистрирован: Сб ноя 24, 2007 09:03:29
Откуда: Ульяновск

Сообщение Инженер »

Там код не ассемблековский. Как установить параметры в ассемблере? Если кто может подсказать конкретней буду рад почитать ответ.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

Инженер писал(а):Как таймер запустить? Или он запускается автоматически? (вместе с МК)
таймер запускается сразу после установки нужного коэффициента предделителя. останавливается при задании CS10=CS11=CS12=0
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Mamonth
Вымогатель припоя
Сообщения: 534
Зарегистрирован: Пн янв 16, 2006 08:00:17
Откуда: Иркутск

Сообщение Mamonth »

Артур писал(а):Здравствуйте! Помогите разобраться пожалуйста? Я хочу чтоб контроллер установил порт В в высокий уровень и через 2 сек в низкий уровень и на этом всё прекратилось! А получается что он постоянно мигает :( будто программа запускается снова и снова
Вот сам код:

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

;подключаем файл описания регистров
.include "c:/wavrasm/include/tiny2313.inc"

;задаем имена регистрам для удобства
.def temp=r17
.def temp1=r18
.def temp2=r19

;присваиваем значения temp и temp1
ldi temp,0xff
ldi temp1,0x00

;установливаем порт В на выход
out ddrb,temp

;зажигаем порт В
out portb,temp
 
;вызываем подпрограмму задержки 2 секунды
rcall loop
   
;гасим порт В
out portb,temp1

;подпрограммa задержки 2 сек
loop:   
   ldi  R21, 0x48
loop0:  ldi  R22, 0xBC
loop1:  ldi  R23, 0xC4
loop2:  dec  R23
        brne loop2
        dec  R22
        brne loop1
        dec  R21
        brne loop0
        ldi  R21, 0x02
loop3:  dec  R21
        brne loop3
        nop
        nop
ret

В чем тут фишка? Спасибо!


Что-то я не вижу вектора прерывания reset... :shock:

А вообще есть два способа:
1. Поставить перед loop: оператор sleep и контроллер будет спать.
2. Перед loop написать:

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

main:
    rjmp main

тогда МК зациклиться на этом месте.
Today fine night...
Аватара пользователя
Артур
Нашел транзистор. Понюхал.
Сообщения: 157
Зарегистрирован: Пн дек 04, 2006 09:50:08
Откуда: Vladivostok

Сообщение Артур »

Спасибо Mamonth за идею! Можно действительно так поступить

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

main: 
    rjmp main

Но всётаки с чем простите связана эта аномалия выполнения программы циклически? Ведь в моём коде нет перехода на начало!
Конечно мы обманем и зациклим её в этом месте но хотелось бы всетаки с этим разобраться. Я уже и компиляторы разные попробовал - не в них дело!
Век живи! - Век учись!
ICQ-15B87330h
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

никакой аномалии нет - RET в конце твоего кода и заставляет программу начаться заново
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
Артур
Нашел транзистор. Понюхал.
Сообщения: 157
Зарегистрирован: Пн дек 04, 2006 09:50:08
Откуда: Vladivostok

Сообщение Артур »

ARV писал(а):никакой аномалии нет - RET в конце твоего кода и заставляет программу начаться заново
Спасибо! А как зделать так чтоб она не начиналась заново? А я мог потом использовать задержку из любого другого места программы ну типа так

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

rjmp loop
Век живи! - Век учись!
ICQ-15B87330h
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

структура программы должна быть такой:

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

; объявления констант, переменных и т.п.
     .org 0
     rjmp   Start  ; переход на начало основного участка программы
; тут размещаются векторы прерываний
     rjmp   Interrupt1 ; какой-то вектор прерываний
 
Start:
     ; тут начинается инициализация стека
     ; потом все подготовительные операции
     ; настройка портов, таймеров и т.п.
MainLoop:
    ; тут начинается участок основного цикла,
    ; т.е. тот код, который непрерывно циклически выполняется
    ; отсюда можно вызывать вспомогательные подпрограммы
    rcall    Delay

    rjmp   MainLoop ; переход к началу цикла
    ; если не надо зацикливаться, то надо как-то остановить выполнение кода в этой точке, например так:
    rjmp    PC   ; предыдущий rjmp не нужен, разумеется

; тут начинаются вспомогательные подпрограммы
Delay:
    ; подпрограмма задержки
    ret

OtherProc:
    ; еще какая-то подпрограмма
    ret

Interrupt1:
    ; обработчик какого-то прерывания
    reti

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

Мой уютный бложик... заходите!
Аватара пользователя
Артур
Нашел транзистор. Понюхал.
Сообщения: 157
Зарегистрирован: Пн дек 04, 2006 09:50:08
Откуда: Vladivostok

Сообщение Артур »

Спасибо! Всё понял! :)
И ещё вопросик почему не получается вызывать подпрограммы? Посмотрите пожалуйста код?

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

.include "C:\VMLAB\include\2313def.inc"
.def temp=r16
.def temp1=r17
.def temp2=r18
.def clear_display=r19
.def return_home=r20
.def display_on=r21
.def display_off=r22
.def function_set=r23
.def write_data=r24
.def write_command=r25
.cseg
.org 0
;векторы прерываний
rjmp RESET
       
RESET:
   rjmp START
reti
;начало проги
START:
;настройка портов
   ldi temp,0xff
   ldi temp1,0b01100000
   out ddrb,temp      ;port b выход
   out ddrd,temp1     ;port d 5 и 6 ножки выходы а остальные входы
   ldi temp,0x00
   ldi temp1,0x00
   ;порты настроены!!!

;создадим команды для дисплея
   ldi clear_display  ,0b00000001 ;записывать в порт b
   ldi return_home    ,0b00000010 ;записывать в порт b
   ldi display_on     ,0b00001100 ;записывать в порт b
   ldi display_off    ,0b00001000 ;записывать в порт b
   ldi function_set   ,0b00110100 ;записывать в порт b
   ldi write_data     ,0b00100000 ;записывать в порт D
   ldi write_command  ,0b00000000 ;записывать в порт D
   ;команды созданы

;инициализация дисплея
   out portd,write_command ; переводим дисплей в режим приема команд
   out portb,function_set  ; устанавливаем 8 битный интерфейс
   rcall E                 ; строб     -  (ВОТ ОТСЮДА МЫ ПЕРЕХОДИМ НА Е: И ЭТИМ ВСЁ ЗАКАНЧИВАЕТСЯ :( ...)
   out portb,display_on    ; включаем дисплей
   rcall E                 ; строб
   out portb,clear_display ; очищаем дисплей и обнуляем видеопамять
   rcall E                 ; строб

E:
   ldi temp,0b00100000
   out portd,temp
   nop
   ldi temp1,0b00000000
   out portd,temp1
   ret ;(здесь по идее должна прога Е: закончиться и перейти на строчку "out portb,display_on" ,но этого не происходит)
   

СПАСИБО!!! :)
Век живи! - Век учись!
ICQ-15B87330h
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

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

Мой уютный бложик... заходите!
Аватара пользователя
Brutaller
Встал на лапы
Сообщения: 87
Зарегистрирован: Пн ноя 05, 2007 12:44:43
Откуда: C:\Russia\SPb
Контактная информация:

Сообщение Brutaller »

Как я смотрю многие совсем совсем начинающие не понимают про векторы прерываний и даже если их не используют делают какие то не понятные прыжки в самом начале. Зачем? Если прерывания не используются, то можно начинать прямо с нулевого адреса писать программу, вот так например:

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

.nolist
.include "tn2313def.inc"
.list

.def Temp  = r16
.def Temp1 = r17
.def Temp2 = r18
.def Temp3 = r19
.def Temp4 = r20

.def Dig1 = r21
.def Dig2 = r22
.def Dig3 = r23
.def Dig4 = r24

.equ Dig1PortDdr = DDRD
.equ Dig1PortOut = PORTD
.equ Dig1PortBit = 2

.equ Dig2PortDdr = DDRD
.equ Dig2PortOut = PORTD
.equ Dig2PortBit = 3

.equ Dig3PortDdr = DDRD
.equ Dig3PortOut = PORTD
.equ Dig3PortBit = 4

.equ Dig4PortDdr = DDRD
.equ Dig4PortOut = PORTD
.equ Dig4PortBit = 5

.cseg
  .org 0

; начинаем программу прямо с нулевого адреса без всяких прыжков ;)
    ldi Temp, low(RAMEND)
    out SPL, Temp ; инициализируем указатель стэка

    ldi Temp,(1<<WDCE)|(1<<WDE)
    out WDTCSR,Temp
    ldi Temp,(1<<WDE)|(1<<WDP2)|(1<<WDP1)
    out WDTCSR,Temp     ;запускаем watchdog с интервалом 1 сек.

    sbi ACSR, ACD  ;отключаем аналоговый компаратор

; настраиваем порты
    ldi Temp, 0xFF
    out DDRB, Temp ; segments A-G + dot as outputs

    sbi Dig1PortDdr, Dig1PortBit
    sbi Dig2PortDdr, Dig2PortBit
    sbi Dig3PortDdr, Dig3PortBit
    sbi Dig4PortDdr, Dig4PortBit
; и так далее...
Аватара пользователя
Артур
Нашел транзистор. Понюхал.
Сообщения: 157
Зарегистрирован: Пн дек 04, 2006 09:50:08
Откуда: Vladivostok

Сообщение Артур »

Brutaller писал(а):Как я смотрю многие совсем совсем начинающие не понимают про векторы прерываний и даже если их не используют делают какие то не понятные прыжки в самом начале. Зачем? Если прерывания не используются, то можно начинать прямо с нулевого адреса писать программу


А попробуйте в VMLAB напишите программу как сказали выше? _Ошибку выдаст! Вектор RESET обязательный!

Люди, Будьте добры!
Расскажите пожалуйста про инициализацию стека?
Я читал что он на аппаратном уровне! Как его использовать?
Век живи! - Век учись!
ICQ-15B87330h
Ответить

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