PI C Язык ассемблера - цикл decfsz - PullRequest
1 голос
/ 07 января 2020

Я работаю с микроконтроллером PI C 18F от Microchip, чтобы непрерывно генерировать прямоугольный сигнал angular. Код самого сигнала: label5.

Мне нужно сгенерировать 255 * 20 импульсов этого сигнала. В общем, мне нужно повторить инструкции из первых 4 строк на этикетке 5 255 * 20 раз. Поскольку у меня не может быть чисел, превышающих 2 ^ 8, мне нужно было написать число таким образом.

    label5  BSF portd,5
            call timer1
            BCF portd,5
            call timer2

В приведенном ниже коде я попытался добиться такого поведения. Я дал variable1 значение 255 и уменьшал это значение до тех пор, пока variable1 не станет равным нулю, и в этом случае я вернулся на label2 и перезапустил программу. Каждый раз, когда я уменьшал variable1, я звонил label4. Аналогичные вещи происходят в label4. Здесь у меня есть другая переменная, variable2, которая также уменьшается до тех пор, пока она не достигнет нуля (и вот идет основная программа генерации сигнала, повторяемая с каждой операцией уменьшения), и в этом случае программа возвращает.

Может кто-нибудь, пожалуйста, скажите мне, если я на правильном пути?


label2      movlw .255
            movwf variable1

label3      call label4
            decfsz variable1,1
            goto label3

            goto label2

; """"""""""""""

label4      movlw .20
            movwf variable2

label5      BSF portd,5
            call timer1
            BCF portd,5
            call timer2
            decfsz variable2,1
            goto label5
            return

            end

    ```

Ответы [ 2 ]

1 голос
/ 10 января 2020

Другим способом будет использование 16-битного счетчика l oop со значением 255 * 20.

Примерно так:

;
;
;
TIMER1_CODE code
timer1:
        return
;
;
;
TIMER2_CODE code
timer2:
        return
;
;   main application
;
MAIN_CODE   code
main:

    bcf     TRISD,5         ; make RD5 an output

ProcessLoop:
    movlw   D'255'          ; Compute loop count
    movwf   PRODL
    movlw   D'20'
    mulwf   PRODL           ; PRODH:PRODL = 255*20 = 5100

OutBitLoop:
    movlw   0xFF            ; Decrement loop count
    addwf   PRODL,F
    addwfc  PRODH,F
    bnc     Stop            ; Stop when done enough loops

    bsf     LATD,5          ; Set output bit high
    call    timer1
    BCF     LATD,5          ; Set output bit low
    call    timer2
    bra     OutBitLoop

    bra     ProcessLoop

Stop:
    bra     Stop
    end

Обратите внимание, что код Вы опубликовали, использует регистр PORTD, чтобы установить или очистить выходной бит с кодом операции, который выполняет чтение-изменение-запись. Это плохой выбор.

Для PIC18F всегда используйте выходной регистр защелки (LATD) при изменении состояния выходных битов.

1 голос
/ 07 января 2020

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

Два способа сделать так, чтобы oop занимал больше времени, и я очень ржавею Кодирование PI C, поэтому рассмотрим этот psuedocode:

variable2 = 0
label:
  decfsz variable2,1
  goto label

Это, по сути, 256 циклов, да? и вы можете посчитать инструкции, включая дополнительные часы или что-то еще, для времени, когда оно равно нулю ...

variable2 = 0
label:
  nop
  nop
  decfsz variable2,1
  goto label

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

Или если вы хотите сделать больше циклов, и у вас есть только 8 битов для подсчета, то вложите циклы

variable1 = 20
variable2 = 0
outer:
inner:
  ; other stuff goes here?
  decfsz variable2,1
  goto inner
  decfsz variable1,1
  goto outer

внутренний l oop будет подсчитывать 256 раз, внешнее l oop будет считать 20, поэтому вы получите 20 * 256 полных циклов

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

Я бы не использовал этот подход на cortex-m, может быть, msp430, может быть, avr, но не что-то конвейерное и не то, что было куплено IP у кого-то другого (arm не делает чипы, st и nxp и другие делают чипы и просто покупают IP с руки, так как большая часть остальных чипов не является IP руки и каждый вендор может настроить ip, когда его получают, чтобы одно и то же ядро ​​(например, cortex-m0 + rev xy) в разных чипах не обязательно вели себя одинаково).

...