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)