Пытаюсь написать на МК Atmega8535 программу, представляющую собой одноканальную СИФУ, осуществляющую вывод короткого импульса на фазы А,В,С с фазовым сдвигом 120. эл градусов. (PinA4,Pina5,Pina6 соответственно) пишу на ассемблере. Поскольку для синхронизации в одноканальной СИФУ требуется 1 фаза, например А, то алгоритм таков: сеть переменного тока будет имитировать генератор прямоугольных импульсов частотой 50 Гц. По переднему фронту происходит прерывание, в котором перезапускается таймер Т0, отвечающий за выработку импульса в фазе А. Таймер досчитывает до записанного предварительно в регистр сравнения ocr0 значения "угла управления", срабатывает прерывание таймера Т0, в котором происходит выдача импульса в фазу А, в этом же прерывании происходит запуск таймера Т2, и когда он досчитает до значения 208 (при настройке Т2 с предделителем 256 время как раз составит 120 Эл градусов). Как только таймер Т2 досчитает, сработает прерывание таймера Т2, в котором произойдёт выдача импульса в фазу В, в этом же прерывании я перенастраиваю таймер на новые 120 Эл. градусов, и когда таймер опять досчитает, опять сработает прерывание, но произойдёт уже выдача импульса в фазу С (выбор нужной фазы реализован следующим образом, во время первого перехода в прерывание таймера Т2 мы увеличиваем значение регистра r24 на 1 (inc r24), потом сравниваем значение с числом 2, поскольку в r24 значение не равно 2 (проверку осуществляем командой breq - перейти, если равно), то осуществляется переход на выдачу импульса в фазе B, во время второго срабатывания значение в r24 уже будет равно 2, поэтому осуществится переход на выдачу импульса в фазе С. Код приложен ниже
CODE
.include "m8535def.inc"
.cseg
.org 0
rjmp reset
.org 0x001
rjmp synchr
.org 0x003
rjmp impulseT2
.org 0x013
rjmp impulseT0
.org 0x015
reset:
;????????????? ?????:
ldi r16,high(RAMEND)
out sph,r16
ldi r17,low(RAMEND)
out spl,r16
;????????? ??????:
ldi r16,0b11111000
out ddra,r16
ldi r16,0b00000111
out porta,r16
ldi r16,0b11111011
out ddrb,r16
ldi r16,0xff
out ddrc,r16
;????????? ??????? ??????????:
ldi r16,0b01100000
out gicr,r16
ldi r16,0b00000011
out mcucr,r16
ldi r16,0b01000000
out mcucsr,r16
;????????? ?????????? ?? ?????????? ??????? ? ?????? ???????:
ldi r16,0b00000010
out timsk,r16
ldi r16,0b00001101
out tccr0,r16
ldi r20,0b00001111
out ocr0,r20
main:
k1:
sbic pina,0
rjmp k1
sei
k2:
sbic pina,1
rjmp k2
cli
rjmp main
synchr:
cli
in r15,sreg
;?????????? ???????:
ldi r16,0b00000000
out timsk,r16
ldi r16,0b00011000
out tccr0,r16
clr r16
out tcnt0,r16
;????????? ???????:
ldi r16,0b00000010
out timsk,r16
ldi r16,0b00001101
out tccr0,r16
out sreg,r15
sei
reti
impulseT0:
cli
in r15,sreg
ldi r16,0b00000000
out timsk,r16
ldi r16,0b00011000
out tccr0,r16
clr r16
out tcnt0,r16
ldi r16,0b00010111
out porta,r16
clr r18
I1:
inc r18
cpi r18,0xff
brne I1
ldi r16,0b00000111
out porta,r16
ldi r16,0b00000110
out tccr2,r16
ldi r16,0b11010000
out ocr2,r16
ldi r16,0b10000000
out timsk,r16
out sreg,r15
sei
reti
impulseT2:
cli
in r15,sreg
ldi r16,0b00000000
out timsk,r16
ldi r16,0b00000000
out tccr2,r16
ldi r16,0b00000000
out tcnt2,r16
inc r24
cpi r24,0b00000010
breq C
B:
ldi r16,0b00000110
out tccr2,r16
ldi r16,0b11010000
out ocr2,r16
ldi r16,0b10000000
out timsk,r16
ldi r16,0b00100111
out porta,r16
clr r18
I11:
inc r18
cpi r18,0xff
brne I11
ldi r16,0b00000111
out porta,r16
out sreg,r15
sei
reti
C:
ldi r16,0b00000000
out timsk,r16
ldi r16,0b00000000
out tccr2,r16
clr r16
out tcnt2,r16
ldi r16,0b01000111
out porta,r16
clr r18
I111:
inc r18
cpi r18,0xff
brne I111
ldi r16,0b00000111
out porta,r16
out sreg,r15
sei
reti
Вроде алгоритм верный, но протеус выдаёт следующую ерунду:
Помогите разобраться, в чём причина, вроде алгоритм верный. Самое интересное, что в этом случае можно было сослаться на глюк протеуса, но реальный МК выдаёт такие же сигналы.
P.S. С помощью программной задержки делать импульсы получалось.
Сообщение отредактировал IgorKossak - Jan 8 2015, 19:32
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!