如何在PIC​​16F1938上使用timer2在装配中每秒打开和关闭一个指示灯(一秒钟后打开,下一个打开后关闭)?

时间:2013-11-16 18:59:08

标签: assembly timer pic

我已经在这个问题上工作了一段时间(2个月),从几年前我在PIC大会上制作的pong克隆中挽救了一些旧代码。我已经完成了所有的数学计算,我想像伪代码格式的程序看起来像这样:

使用timer2,将后分频器位设置为1001,将预分频器位设置为11.在12,500开始倒计时。启动计时器。每当定时器寄存器溢出,递减计数器1和复位定时器。当倒计时到零时,翻转位对应于灯亮或亮(如果为1,则变为0,如果0变为1)。重置计时器和倒计时。

相关资料: LED连接到RB5 不完全知道如何实现倒计时变量(或任何以汇编开头的变量),即使参考pong clone,我只是理解其中的一部分。 需要创建2个程序,一个使用中断,一个不使用中断。

这是我到目前为止的实际代码(它不起作用,不完整),它不多(大部分实际上已经完成,只有应用程序标记区域中的部分由我完成) ,我甚至不知道它是否正确:

;; -- mode: asm; mode: outline-minor-mode; outline-regexp: ";;;+" --

;;; skeleton.asm list p=16f1938 include "p16f1938.inc"

SETBSR macro target movlb (target >> 7) ; gpasm assember's BANKSEL doesn't work for exhanced 16F parts. ;; BANKSEL target ; Use this instruction for MPASM endm

;;; PIC16F1938 ;; fcs 22 July 2006

    ;; Here is a dummy program to illustrate the how to write an application
    ;; that can be used with the Pikme bootloader or with a hardware
    ;; programmer.

    ;; The bootloader ignores the first 32-word block of memory.

    ;; Put the application's interrupt code at 0x0020 (either put a jump
    ;; to your actual interrupt handler code there or put a retfie
    ;; instruction there.

    ;; Put the application's start code at 0x0024.

    ;; The interrupt vector is effectively 0x0020 (because the bootloader's
    ;; interrupt vector jumps to 0x0020) and the program must begin at
    ;; 0x0024.

    ;; So, ORG your interrupt code at 0x0020 and put interrupt code in
    ;; the first 4 instructions (e.g. rtfie, nop, nop, nop) and then start
    ;; the application at 0x0024.  (The 3 'nop's are not actually necessary
    ;; as long is the 'org 0x0024' statement is present.)

    ;; uncomment and possibly edit following line if you include
    ;; any macros, etc.
;include "macros.inc"

    expand        
    ;noexpand

radix   dec

;========================================================================== ; __CONFIG 0x3F10

__CONFIG _CONFIG1, _FCMEN_OFF & _IESO_OFF & _CLKOUTEN_ON & _BOREN_OFF & _CP_OFF & _CPD_OFF & _MCLRE_OFF & _PWRTE_ON & _WDTE_OFF & _FOSC_INTOSC
__CONFIG _CONFIG2, _LVP_OFF & _BORV_19 & _STVREN_ON & _PLLEN_OFF & _VCAPEN_OFF & _WRT_OFF

    ;; Above configuration word will be ignored when using the bootloader but
    ;; will be programmed into the PIC when you use a hardware programmer.

;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; First 32-word block. ;;; This is ignored by the bootloader but is not ignored when ;;; using a hardware programmer. ;;; By putting this code here, the very same hex file can be used either ;;; with the bootloader or with a hardware programmer. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org 0x0000 goto UserApp

org 0x0004

ISR goto UserISR

;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; First block after protected memory. ;;; This is where the application's interrupt and application code ;;; go. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; org 0x0200 ;; Your interrupt handler must be org'd at 0x0020. ;; Use a return from interrupt instruction (retfie) or put ;; a jump to your actual interrupt handler (goto xxxx). UserISR retfie nop nop nop

    org 0x0204
    ;; Your application *must* be org'd at 0x0204, because that is
    ;; the address where the bootloader jumps.

UserApp ;; put your application code here. This code sets the internal oscillator to 32 Mhz.

movlb   (OSCCON >> 7)   ; Use this statement if your assembler does not support Enhanced BANKSEL

;; BANKSEL TRISB ; Use this statement if your assembler supports it.

movlw   0xF0        ; 8 Mhz, internal OSC, PLL on
movwf   OSCCON

hsploop: btfss OSCSTAT,HFIOFR bra hsploop

pllloop: btfss OSCSTAT,PLLR bra pllloop

;; Reset the BSR to Bank 0
SETBSR  PORTA

;; Main: This is where your applications goes. Make sure it is an infinite loop! main: bra main; relative branch main BCF TMR2; Clears register for timer 2.

SETBSR PORTB; Bank 0 movlw 0x01; move 0x01 to W movwf PORTB; move w to PORTB BCF PORTB,5; bit clear PORTB end

我想我的主要问题只是将我的大纲转换为汇编代码,特别是让倒计时工作并设置timer2。我在主要部分写的部分是打开和关闭灯(我认为)。我也相信如果正确的话,我到目前为止的代码可以用于使用版本的中断以及非中断版本。但是,就我现在而言,我有点丢失代码。

1 个答案:

答案 0 :(得分:2)

自从我为PIC16编写程序集已经有一段时间了,所以我为任何遗漏道歉。

我建议最初不要使用中断。如果你需要精确的时间,你只需要它们你的主代码运行得足够慢以甩掉时间。

首先,您需要设置Timer2。通过写T2CON

来做到这一点
movlw   0b01001111        ; set postscaler bits to 1001, prescaler bits to 11
movwf   T2CON

然后你需要在名为CountDownTimer的地方创建一个变量,并用你的起始值填充它。

movlw CountDownStartValue
movwf CountDownTimer, 1

你想要完全256个滴答的溢出?你可以通过写PR2

来缩短它

然后你需要检查中断标志是否在溢出时触发。注意:仅仅因为我们使用中断标志并不意味着我们必须使用中断服务程序。将TMR2IE设置为零,然后自行检查例程。这往往更容易调试。一旦你开始工作,如果你预计需要性能,你可以将它重构为中断服务程序。

btfsc   PIR1, TMR2IF
    call TimerOverflow

确保清除标记。然后递减你的柜台。一旦它达到零,你想要切换 输出。由于以下原因,我建议写信至LAT而不是PORTDifference between PORT and LATCH on PIC 18F

TimerOverflow:
    bcf  PIR1, TMR2IF              ; Clear the flag or else we'll continue to pop back in.
    decfsz  CountDownTimer, 1      ; Countdown variable. If not zero, then return
        return

    ;We skipped over the return, the countdown must have reached zero
    movlw CountDownStartValue
    movwf CountDownTimer, 1

    BTFSS LATB, 5     ; Is the LED already on or off?
       goto TurnOn
       goto TurnOff

 TurnOn:
    BSF   LATB, 5
    return            ; This returns from TimerOverflow call

 TurnOn:
    BCF   LATB, 5
    return            ; This returns from TimerOverflow call

嗯,这基本上就是我记忆中的记忆。如果您发现错误,请告诉我,以便我可以编辑此回复。