как правильно выключить таймер ( asm )

Обсуждаем контроллеры компании Atmel.
Ответить
Модератор
Аватара пользователя
Сообщения: 19077
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

ARV писал(а):и как тогда вы назовете две "полуконстанты"?
у меня и в мыслях никогда не возникало, чтобы их как-то назвать. я просто пишу так:
ldi R16, 0b10100011 ; таймер1, Clear OC1A/OC1B on Compare Match, PWM, Phase Correct, 10-bit
out TCCR1A, R16
ldi R16, 0b00000001 ; таймер1, PWM, Phase Correct, 10-bit, без предделителя
out TCCR1B, R16
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Замечательный пример как писать НЕ надо.
В случае неправильного поведения придется смотреть не на комментарии (они могут не соответствовать коду) а самому коду. Возможно, вы настолько профессионал, что помните, какие биты в каких регистрах за что отвечают, но остальным придется лезть в даташит и искать номера битов там. Совсем весело, когда в коде нет комментариев, а под рукой - даташита.

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

ldi temp, (0b10<<COM1A0 | 0b10<<COM1B0 | 1<<WGM11 | 1<<WGM10) ;неинверсный ШИМ на каналах A и B, phase-correct PWM, TOP=0x03FF
out TCCR1A,temp
ldi temp, (0b001<<CS10 | 0<<WGM13 | 0<<WGM12) ; f_ck = F_CPU/1 = 1 MHz
out TCCR1B,temp
Такая запись гораздо понятнее и проще в изменении. Если надо поменять предделитель сразу видно где биты CS12:CS10, если режим работы - где биты WGM13:WGM10. Запись 0b001<<CS10 удобнее записи 0<<CS12 | 0<<CS11 | 1<<CS10, но только когда эти биты идут последовательно, поэтому WGM13:WGM10 настраиваются независимо. Кроме того, в ассемблер не зря ввели директиву .def - осмысленные имена переменных это удобно.
Реклама
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

ARV писал(а):но вот так просто задать константу для режима Fast PWM уже не получится - надо менять 2 регистра, и как тогда вы назовете две "полуконстанты"?
Ну, можно, допустим, так, как в примере ниже. Хотя, конечно, уроды еще те. Ладно, еще Fast PWM. А у 8515 эти придурки ухитрились 4 несчастных бита Sleep Mode размазать по ТРЁМ регистрам! Вот уж действительно поубивал бы!..
COKPOWEHEU писал(а):Такая запись гораздо понятнее и проще в изменении.
Ни разу она не понятнее. Те же "магические" числа, только покороче. Понятным было бы, если бы производители предоставили в заголовочном файле что-то, вроде этого.
Спойлер

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

; Compare Output Modes for channel A

.equ    COM1aOff        =0x00 ; OC1A disconnected.
.equ    COM1aTogg       =0x40 ; Toggle OC1A on Compare Match
.equ    COM1aClr        =0x80 ; Clear OC1A on Compare Match
.equ    COM1aSet        =0xC0 ; Set OC1A/OC1B on Compare Match
.equ    COM1aTO         =0x80 ; True PWM output (chan A)
.equ    COM1aCO         =0xC0 ; Complement PWM output (chan A)



; Compare Output Modes for channel B

.equ    COM1bOff        =0x00 ; OC1B disconnected.
.equ    COM1bTogg       =0x40 ; Toggle OC1B on Compare Match
.equ    COM1bClr        =0x80 ; Clear OC1B on Compare Match
.equ    COM1bSet        =0xC0 ; Set OC1B on Compare Match
.equ    COM1bTO         =0x80 ; True PWM output (chan B)
.equ    COM1bCO         =0xC0 ; Complement PWM output (chan B)



; Waveform Generation Modes for tccr1A

.equ    WGM1aNorm       =0x00 ; Normal
.equ    WGM1aPWMPC8     =0x01 ; PWM Phase Correct 8-bit
.equ    WGM1aPWMPC9     =0x02 ; PWM Phase Correct 9-bit
.equ    WGM1aPWMPC10    =0x03 ; PWM Phase Correct 10-bit

.equ    WGM1aCTCo       =0x00 ; CTC, top - OCR1A
.equ    WGM1aFPWM8      =0x01 ; Fast PWM 8-bit
.equ    WGM1aFPWM9      =0x02 ; Fast PWM 9-bit
.equ    WGM1aFPWM10     =0x03 ; Fast PWM 10-bit

.equ    WGM1aPWMPFCi    =0x00 ; PWM, Phase & Frequency Correct, top - ICR1
.equ    WGM1aPWMPFCo    =0x01 ; PWM, Phase & Frequency Correct, top - OCR1A
.equ    WGM1aPWMPCi     =0x02 ; PWM Phase Correct, top - ICR1
.equ    WGM1aPWMPCo     =0x03 ; PWM Phase Correct, top - OCR1A

.equ    WGM1aCTCi       =0x00 ; CTC, top - ICR1
;.equ    WGM1aRSRV       =0x01 ; (Reserved)
.equ    WGM1aFPWMi      =0x02 ; Fast PWM, top - ICR1
.equ    WGM1aFPWMo      =0x03 ; Fast PWM, top - OCR1A


; Waveform Generation Modes for tccr1B

.equ    WGM1bNorm       =0x00 ; Normal
.equ    WGM1bPWMPC8     =0x00 ; PWM Phase Correct 8-bit
.equ    WGM1bPWMPC9     =0x00 ; PWM Phase Correct 9-bit
.equ    WGM1bPWMPC10    =0x00 ; PWM Phase Correct 10-bit

.equ    WGM1bCTCo       =0x08 ; CTC, top - OCR1A                     
.equ    WGM1bFPWM8      =0x08 ; Fast PWM 8-bit
.equ    WGM1bFPWM9      =0x08 ; Fast PWM 8-bit
.equ    WGM1bFPWM10     =0x08 ; Fast PWM 10-bit

.equ    WGM1bPWMPFCi    =0x10 ; PWM, Phase & Frequency Correct, top - ICR1
.equ    WGM1bPWMPFCo    =0x10 ; PWM, Phase & Frequency Correct, top - OCR1A
.equ    WGM1bPWMPCi     =0x10 ; PWM Phase Correct, top - ICR1
.equ    WGM1bPWMPCo     =0x10 ; PWM Phase Correct, top - OCR1A

.equ    WGM1bCTCi       =0x18 ; CTC, top - ICR1
;.equ    WGM1bRSRV       =0x18 ; (Reserved)
.equ    WGM1bFPWMi      =0x18 ; Fast PWM, top - ICR1
.equ    WGM1bFPWMo      =0x18 ; Fast PWM, top - OCR1A



; Timer 1 Clock Select

.equ    Tim1csOff        =0x00  ; No clock source. (Timer/Counter stopped)

.equ    Tim1cs1          =0x01  ; clk_IO / 1 (No prescaling)
.equ    Tim1cs8          =0x02  ; clk_IO / 8
.equ    Tim1cs64         =0x03  ; clk_IO / 64
.equ    Tim1cs256        =0x04  ; clk_IO / 256
.equ    Tim1cs1024       =0x05  ; clk_IO / 1024

.equ    Tim1csExtFall    =0x06  ; External clock source on T1 pin. Clock on falling edge.
.equ    Tim1csExtRis     =0x07  ; External clock source on T1 pin. Clock on rising edge
Вот тогда запись этих же действий становится действительно понятной:

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

     LDI     temp,(COM1aTO | COM1bTO | WGM1aPWMPC10) ;неинверсный ШИМ на каналах A и B, phase-correct PWM, TOP=0x03FF
     out     TCCR1a,temp
     LDI     temp,(WGM1bPWMPC10 | Tim1cs1) ; f_ck = F_CPU/1 = 1 MHz
     OUT     TCCR1b,temp
Но это, опять же, самопал. Если бы такое предоставили производители, можно было бы даже простить им тот факт, что некоторые поля размазаны по нескольким регистрам. То же поле WGM. Если вдруг в каком-либо камне это поле окажется в одном регистре, то, вместо префиксов WGM1a и WGM1b, для всех его значений можно было поставить префикс WGM1, без "a" и "b", при переносе имеющегося текста программы на новый камень, компилятор сам выдаст в виде ошибок список строк, которые надо поправить.

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

А как сделали заголовочные материалы для таблицы векторов - руки рвать! Впрочем в даташитах присутствует правильная таблица векторов, в виде листинга, который можно скопипастить в начало своей программы, убрав колонку Address. Где-нибудь в конце кодовой секции копипастим ее еще раз, но убираем не только адресную колонку, но и колонку с кодом операции (JMP/RJMP) и все пробелы перед и после этих колонок, а операнды бывших команд переходов переделываем в метки, добавляя после них двоеточие. Получаем таблицу для незапланированных прерываний, где можно поставить либо RTI, либо "ловушку" - хоть на все незапланированные прерывания сразу, хоть на каждое отдельную. А соберемся обслужить какое-то прерывание, находим его в этой таблице, копипастим соответствующую строчку в нужное место, а в таблице ее же закомментируем. Все. Не надо сочинять свои метки для программ обслуживания прерываний, их сочинили атмеловцы (правда метка ADC не годится, я ее подправляю до iADC), не надо думать, какую команду писать: RJMP или JMP, ее тоже написали атмеловцы...

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

Да, с таймером 1 я ни разу не работал, таблички для него сочинил за вчерашний вечер, так, что оно непроверенное.
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Сообщение COKPOWEHEU »

Вот тогда запись этих же действий становится действительно понятной:
Что за константа COM1aTO ? Она ничего не говорит о режиме, вы бы ей имя нормальное дали что ли, T1CPA_NINV (остальные 3 состояния - T1CPA_INV, T1CPA_DISC, T1CPA_TOG: неинвертированный ШИМ; инвертированный; вывод отключен; вывод инвертируется).
Но если уж ударяться в абстракции, проще написать набор процедур для настройки, например, так

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

timer_mode(1, T1MODE_FAST10);
timer_cpA(1, T1CPA_NINV);
timer_prescaler(1, 128);
Это займет больше объема флеша и будет дольше выполняться. Впрочем, это инициализация, не критично.
А как сделали заголовочные материалы для таблицы векторов - руки рвать!
А там что не устраивает?

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

; ***** INTERRUPT VECTORS ************************************************
.equ	INT0addr	= 0x0001	; External Interrupt 0
.equ	INT1addr	= 0x0002	; External Interrupt 1
.equ	ICP1addr	= 0x0003	; Timer/Counter Capture Event
.equ	OC1addr	= 0x0004	; Timer/Counter1 Compare Match
Заменить .equ на .org, а знак равенства и все что после - на jmp/rjmp/reti

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

.org INT0addr
  rjmp INT0_vect
.org INT1addr
  rjmp INT1_vect
Выковыривать тоже самое из даташита не проще.
ухитрились 4 несчастных бита Sleep Mode размазать по ТРЁМ регистрам! Вот уж действительно поубивал бы!..
Это ладно, настройки не так часто менять нужно. Хуже как они решили нехватку адресов в новых контроллерах. Они тупо выкинули все что не влезло в ОЗУ, пофиг насколько часто оно используется. Например, TCCR0A, TCCR0B доступны через in/out, а более критичный к скорости UDR0 - только через ОЗУ.
Реклама
Эиком - электронные компоненты и радиодетали
afz
Опытный кот
Аватара пользователя
Сообщения: 744
Зарегистрирован: Сб дек 22, 2012 08:17:42
Откуда: Караганда, Казахстан

Сообщение afz »

COKPOWEHEU писал(а):Что за константа COM1aTO ? Она ничего не говорит о режиме, вы бы ей имя нормальное дали что ли, T1CPA_NINV (остальные 3 состояния - T1CPA_INV, T1CPA_DISC, T1CPA_TOG: неинвертированный ШИМ; инвертированный; вывод отключен; вывод инвертируется).
Так там же справа все подписано. Compare Output Mode timer 1 chan A True Output - все большие буквы и единичка вошли в название. Что касается TO - так, обычно, в даташитах подписывают выходы триггеров. True Output - прямой выход, Complement Output - инверсный выход. OFF вместо DISConnected, на мой взгляд, вполне адекватно. Вместо TOG я написал TOGG. Ну, и префикс COM я взял по аналогии с оригиналом. Было у меня желание сэкономить набор и вместо COM1 написать T1, но я его успешно поборол. :)

Внимательно гляньте на то, что под спойлером, там справа все прокомментировано.
COKPOWEHEU писал(а):Выковыривать тоже самое из даташита не проще.
ИМХО, проще. Особенно если редактор умеет работать с несколькими строками сразу (редактировать блок). По крайней мере не нужно набирать руками метки для соответсвующих программ. И сочинять их не нужно, их любезно предоставили атмеловцы. Единственное, что нужно исправить - это метку для вектора АЦП. Они там написали ADC, забыв, что есть такая команда. Ну, или то, что в их асме нельзя пользовать метки, совпадающие с кодами команд. Я, обычно, приписываю к ADC буковку "i" спереди.

Ну, и смотрится оно красивее...

Вот, что у меня вышло после нескольких дней вдумчивой работы с даташитом 8-й Меги. (Несколько дней - это, в общем-то, 3 * несколько вечеров) :)
Кто мешает тебе выдумать порох непромокаемый? (К. Прутков, мысль № 133)
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2896
Зарегистрирован: Сб ноя 13, 2010 12:53:25
Откуда: приходит весна?

Сообщение B@R5uk »

Starichok51 писал(а):у меня и в мыслях никогда не возникало, чтобы их как-то назвать. я просто пишу так:
ldi R16, 0b10100011 ; таймер1, Clear OC1A/OC1B on Compare Match, PWM, Phase Correct, 10-bit
out TCCR1A, R16
ldi R16, 0b00000001 ; таймер1, PWM, Phase Correct, 10-bit, без предделителя
out TCCR1B, R16
:beer: Делаю точно так же. Разве только двоичную сразу в шестнадцатиричную перевожу для краткости (в уме естественно).

Добавлено after 5 minutes 18 seconds:
afz писал(а):
COKPOWEHEU писал(а):Такая запись гораздо понятнее и проще в изменении.
Ни разу она не понятнее. Те же "магические" числа, только покороче. Понятным было бы, если бы производители предоставили в заголовочном файле что-то, вроде этого.
Абсолютно согласен. Кстати, предложенный вами вариант активно используется в заголовочных файлах, поставляемых для компилятора Си к микроконтроллерам STM32. Очень удобная вещь.
Реклама
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

B@R5uk писал(а):Делаю точно так же. Разве только двоичную сразу в шестнадцатиричную перевожу для краткости
Не понял, в чем тут краткость. Скомпилируется в один и тот же код.

А недостаток у такой записи есть. Несмотря на подробный комментарий, проблема в том, что комментарий никак не связан с операндом, определяющим результат выполнения команды. И если Вы не помните назубок номер бита COM1B1, то не сможете без сверки с даташитом определить, соответствует ли запись ldi R16, 0b10100011 стоящему за ней комментарию.
Вы начали писать код, скопипастили из другого места код инициализации таймера, исправили комментарий на тот, который нужен, собрались, сверяясь с даташитом, выставить биты двоичного числа, а Вас отвлекли, а вернувшись, Вы забыли, что редактирование строки не было завершено. И вуаля, у Вас в программе верный комментарий, но неверный код.
В то время, как в записи

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

ldi R16,(1<<COM1A1)|(1<<COM1B1)|(1<<WGM11)|(1<<WGM10)
сразу видно, что именно делается.
Собутыльник Кота
Аватара пользователя
Сообщения: 2708
Зарегистрирован: Сб май 14, 2011 21:16:04
Откуда: г. Чайковский

Сообщение Z_h_e »

Не редко в моем коде коммент остается неисправленным из-за копипасты из другого фрагмента программы. Комменты эта важная часть, но рутина, особенно в отладке, когда начинаешь пробовать , "а если вот так или вот так" и может коммент остаться от "так", а у тебя уже "вот так". Так что лучше когда констатна сама является комментом, со сдвигом она или без, особенно когда на кой-то ляд нужна краткость исходника.
Поддерживаю предыдущий пост.
Изображение
Добро всегда побеждает зло. Поэтому кто победил - тот и добрый.
Модератор
Аватара пользователя
Сообщения: 19077
Зарегистрирован: Сб авг 14, 2010 15:05:51
Откуда: г. Озерск, Челябинская обл.

Сообщение Starichok51 »

COKPOWEHEU писал(а):Возможно, вы настолько профессионал, что помните, какие биты в каких регистрах за что отвечают, но остальным придется лезть в даташит и искать номера битов там.
я не профессионал, а самоучка, потому и пишу так. и даташит у меня постоянно открыт, чтобы там смотреть позиции битов.
COKPOWEHEU писал(а):Что за константа COM1aTO ? Она ничего не говорит о режиме
она говорит только тому человеку, который придумал это имя. а всем остальным не говорит ровным счетом ничего...
Alkul писал(а):Вы начали писать код, скопипастили из другого места ...а вернувшись, Вы забыли, что редактирование строки не было завершено.
при ЛЮБОЙ форме записи битов, можно забыть, что редактирование строки не было завершено.
форма записи и склероз - вещи не взаимосвязанные.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Собутыльник Кота
Аватара пользователя
Сообщения: 2896
Зарегистрирован: Сб ноя 13, 2010 12:53:25
Откуда: приходит весна?

Сообщение B@R5uk »

Alkul писал(а):И если Вы не помните назубок номер бита..., то не сможете без сверки с даташитом определить...
Никогда ничего не помню. И всегда смотрю в даташит. Два раза, а то и три. Зачем забивать голову, когда можно посмотреть в даташит и написать комментарий?

Добавлено after 4 minutes 21 second:
Z_h_e писал(а):Комменты эта важная часть, но рутина, особенно в отладке, когда начинаешь пробовать , "а если вот так или вот так" и может коммент остаться от "так", а у тебя уже "вот так".
Есть такая проблема. Но тут, как говорится, лентяй — сам себе Буратино.
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Сообщение Alkul »

Starichok51 писал(а):форма записи и склероз - вещи не взаимосвязанные.
Бесспорно. Однако вероятность того, что Вы заметите такую ошибку при рекомендуемой мной форме записи выше, чем Вашей форме записи.
B@R5uk писал(а):Никогда ничего не помню. Зачем забивать голову, когда можно посмотреть в даташит и написать комментарий?
Специально зазубривать даташит, естественно, глупо, и никто этого не делает. Тем не менее, при регулярном программировании оно как-то само запоминается. Но все же не настолько, чтоб запомнить положение бита в байте. А вот имя бита вполне доступно к запоминанию, тем более, что имена бит выбираются, исходя из определенной логики.

О чем мы спорим-то? Ну ведь естественно, что осмысленная буквенно-цифровая запись человеку более понятна и лучше им воспринимается, нежели запись в двоичном коде. Иначе нам не были бы нужны мнемоники ассемблера, так бы и кодили в машинных кодах.
Ответить

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