我已经在这个问题上工作了一段时间(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。我在主要部分写的部分是打开和关闭灯(我认为)。我也相信如果正确的话,我到目前为止的代码可以用于使用版本的中断以及非中断版本。但是,就我现在而言,我有点丢失代码。
答案 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
而不是PORT
:Difference 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
嗯,这基本上就是我记忆中的记忆。如果您发现错误,请告诉我,以便我可以编辑此回复。