ejemplos pic 16f887 pbp
TRANSCRIPT
PICBASIC PRO PROGRAM TO READ POTENTIOMETERS ON 16F887 ADC.
PICBASIC PRO PROGRAM TO READ POTENTIOMETERS ON 16F887 ADC.
' Name : adcx.pbp
' Compiler : PICBASIC PRO Compiler 2.60
' Assembler : PM or MPASM
' Target PIC : 40-pin 16F887
' Hardware : Lab-X1
' Oscillator : 4MHz external crystal
' Keywords : ADC, ANALOG, LCDOUT, LCD
' Description : PICBASIC PRO program to read pots on 16F887 ADC
' Define LCD pins
Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
' Define ADCIN parameters ********************************
ADCON1 = %00000000 ' Left-Justify result in ADRESH:ADRESL registers
ANSEL = %00001011 ' Set AN0, AN1, AN3 to analog, others digital
ANSELH = %00000000 ' Set AN8 and higher channels to digital operation
'**********************************************************
' Allocate variables
x Var Byte
y Var Byte
z Var Byte
Low PORTE.2 ' LCD R/W line low (W)
Pause 100 ' Wait for LCD to start
Goto mainloop ' Skip subroutines
' Subroutine to read a/d convertor
getad:
Pauseus 100 ' Wait for channel to setup
ADCON0.1 = 1 ' Start conversion
Pauseus 100 ' Wait for conversion
Return
' Subroutine to get pot x value
getx:
ADCON0 = $41 ' Set A/D to Fosc/8, Channel 0, On
Gosub getad
x = ADRESH
Return
' Subroutine to get pot y value
gety:
ADCON0 = $45 ' Set A/D to Fosc/8, Channel 1, On
Gosub getad
y = ADRESH
Return
' Subroutine to get pot z value
getz:
ADCON0 = $4D ' Set A/D to Fosc/8, Channel 3, On
Gosub getad
z = ADRESH
Return
mainloop:
Gosub getx ' Get x value
Gosub gety ' Get y value
Gosub getz ' Get z value
Lcdout $fe, 1, "x=", #x, " y=", #y, " z=", #z ' Send values to LCD
Pause 100 ' Do it about 10 times a second
Goto mainloop ' Do it forever
End
PICBASIC PRO PROGRAM FOR LCD CLOCK USING THE DALLAS 1202/1302 RTC.
' Name : RTCX.pbp
' Compiler : PICBASIC PRO Compiler 2.60
' Assembler : PM or MPASM
' Target PIC : 40-pin 16F887
' Hardware : LAB-X1 Experimenter Board
' Oscillator : 4MHz external crystal
' Keywords : LCDOUT, SHIFTIN, SHIFTOUT
' Description : PICBASIC PRO program for LCD clock using the
' Dallas 1202/1302 RTC ICs.
'
' Define LOADER_USED to allow use of the boot loader.
' This will not affect normal program operation.
Define LOADER_USED 1
Include "MODEDEFS.BAS" ' Include Shiftin/out modes
Define LCD_DREG PORTD ' Define LCD connections
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
' Alias pins
RST Var PORTA.2
IO Var PORTC.1
SCLK Var PORTC.3
' Allocate variables
rtcyear Var byte
rtcday Var byte
rtcmonth Var byte
rtcdate Var byte
rtchr Var byte
rtcmin Var byte
rtcsec Var byte
rtccontrol Var byte
Low RST ' Reset RTC
Low SCLK
ANSEL = %00000000 ' Make AN0-AN7 digital
ANSELH= %00000000 ' Make AN8-AN13 digital
Low PORTE.2 ' LCD R/W low = write
Pause 100 ' Wait for LCD to startup
' Set initial time to 8:00:00AM 07/16/99
rtcyear = $99
rtcday = $06
rtcmonth = $07
rtcdate = $16
rtchr = $08
rtcmin = 0
rtcsec = 0
Gosub settime ' Set the time
Goto mainloop ' Skip subroutines
' Subroutine to write time to RTC
settime:
RST = 1 ' Ready for transfer
' Enable write
Shiftout IO, SCLK, LSBFIRST, [$8e, 0]
RST = 0 ' Reset RTC
RST = 1 ' Ready for transfer
' Write all 8 RTC registers in burst mode
Shiftout IO, SCLK, LSBFIRST, [$be, rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, 0]
RST = 0 ' Reset RTC
Return
' Subroutine to read time from RTC
gettime:
RST = 1 ' Ready for transfer
Shiftout IO, SCLK, LSBFIRST, [$bf] ' Read all 8 RTC registers in burst mode
Shiftin IO, SCLK, LSBPRE, [rtcsec, rtcmin, rtchr, rtcdate, rtcmonth, rtcday, rtcyear, rtccontrol]
RST = 0 ' Reset RTC
Return
' Main program loop - in this case, it only updates the LCD with the time
mainloop:
Gosub gettime ' Read the time from the RTC
' Display time on LCD
Lcdout $fe, 1, hex2 rtcmonth, "/", hex2 rtcdate, "/" , hex2 rtcyear,_
" ", hex2 rtchr, ":", hex2 rtcmin, ":", hex2 rtcsec
Pause 300 ' Do it about 3 times a second
Goto mainloop ' Do it forever
End
PICBASIC PRO PROGRAM TO DEMONSTRATE THE USE OF TIMER1 INTERRUPT FOR A REAL-TIME CLOCK.
' Name : TMR1CLKX.pbp
' Compiler : PICBASIC PRO Compiler 2.60
' Assembler : PM or MPASM
' Target PIC : 40-pin 16F887 or similar
' Hardware : LAB-X1 Experimenter Board
' Oscillator : 4MHz external crystal
' Keywords : ASSEMBLY INTERRUPTS, LCDOUT, TIMER1
' Description : PICBASIC PRO program that demonstrates the use of
' Timer1 interrupt for a real-time clock. Written for the LAB-X1
' experimenter board with a 16F887.
'
' Define interrupt handler
Define INTHAND myint
wsave VAR BYTE $20 system
wsave1 VAR BYTE $a0 system ' Necessary for devices with RAM in bank1
wsave2 VAR BYTE $120 system ' Necessary for devices with RAM in bank2
wsave3 VAR BYTE $1a0 system ' Necessary for devices with RAM in bank3
ssave VAR BYTE bank0 system
psave VAR BYTE bank0 system
TICK VAR BYTE bank0 ' make sure that the variables are in bank 0
' if they are to be used in the interrupt handler
seconds VAR BYTE ' Elapsed seconds
minutes VAR WORD ' Elapsed minutes
minutes = 0 ' Clear time
seconds = 0
T1CON = $01 ' Turn on Timer1, prescaler = 1
INTCON = $C0 ' Enable global interrupts, peripheral interrupts
PIE1 = $01 ' Enable TMR1 overflow interrupt
GoTo main ' jump over the interrupt handler and sub
' Assembly language interrupt handler
Asm
myint
; Uncomment the following if the device has less than 2k of code space
;movwf wsave ; Save W
;swapf STATUS,W ; Swap STATUS to W (swap avoids changing STATUS)
;clrf STATUS ; Clear STATUS
;movwf ssave ; Save swapped STATUS
;movf PCLATH,W ; Move PCLATH to W
;movwf psave ; Save PCLATH
; Set the high register of Timer1 to cause an interrupt every
; 16384 counts (65536-16384=49152 or $C000). At 4MHz, prescale
; set to 1, this equates to a tick every 16384uS. This works
; out to about 61 ticks per second, with a slight error. The
; error could be reduced substantially by setting the TMR1L
; register and playing with different values for the prescaler
; and the ticks per second.
movlw 0C0h ; Prepare to set TMR1 high register
movwf TMR1H ; Set TMR1H to C0h
incf _TICK,F ; INCREMENT TICK COUNT
bcf PIR1,0 ; Clear interrupt flag
movf psave,W ; restore the state of everything
movwf PCLATH
swapf ssave,W
movwf STATUS
swapf wsave,F
swapf wsave,W
retfie ; Return from interrupt
EndAsm
' PicBasic subroutine to update the minutes and seconds variables
get_time:
' Update the time when needed. The TICK variable will
' overflow if you don't update within 4 seconds. This could
' be done in the interrupt handler, but it's easier to do
' it in PicBasic, and you usually want the interrupt handler
' to be as short and fast as possible.
PIE1 = 0 ' Mask the interrupt while we're messing with TICK
seconds = seconds + (tick/61) ' Add the accumulated seconds
tick = tick // 61 ' Retain the left-over ticks
PIE1 = $01 ' Interrupt on again
minutes = minutes + (seconds / 60) ' Add the accumulated minutes
seconds = seconds // 60 ' Retain the left-over seconds
Return ' Return to the main program
main
' Begin program code here. The minutes and seconds variables can
' be used in your code. The time will be updated when you call the
' get_time routine. Disable interrupts while executing timing-critical
' commands, like serial communications.
DEFINE LCD_DREG PORTD
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTE
DEFINE LCD_RSBIT 0
DEFINE LCD_EREG PORTE
DEFINE LCD_EBIT 1
loops VAR WORD
loops = 0
ANSEL = %00000000 ' Make PORTA and PORTE digital
ANSELH= %00000000 ' Make PORTA and PORTE digital
Low PORTE.2 ' Enable the LCD
Pause 150 ' Pause to allow LCD to initialize
LCDOut $fe,1 ' Clear LCD
mainloop:
loops = loops + 1
LCDOut $fe,$C0,"Loops Counted: ", DEC5 loops
GoSub get_time ' Update minutes and seconds
LCDOut $fe, 2, "Time: ",DEC5 minutes, ":", DEC2 seconds ' Display the elapsed time
GoTo mainloop ' Repeat main loop
End
PICBASIC PRO PROGRAM TO MEASURE VOLTAGE (0-5VDC) AND DISPLAY ON LCD WITH 2 DECIMAL PLACES. THIS PROGRAM USES THE */ OPERATOR TO SCALE THE ADC RESULT FROM 0-1023 TO 0-500. THE */ PERFORMS A DIVIDE BY 256 AUTOMATICALLY, ALLOWING MATHS WHICH WOULD NORMALLY EXCEED THE LIMIT OF A WORD VARIABLE.
' Name : VMETERX.pbp
' Compiler : PICBASIC PRO Compiler 2.60
' Assembler : PM or MPASM
' Target PIC : 40-pin 16F887 or similar
' Hardware : LAB-X1 Experimenter Board
' Oscillator : 4MHz external
' Keywords : ADCIN, LCDOUT
' Description : PICBASIC PRO program to measure voltage (0-5VDC)
' and display on LCD with 2 decimal places.
' This program uses the */ operator to scale the ADC result from 0-1023
' to 0-500. The */ performs a divide by 256 automatically, allowing math
' which would normally exceed the limit of a word variable.
' Connect analog input to channel-0 (RA0)
' Define LCD registers and bits
Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
' Define ADCIN parameters ********************************
Define ADC_BITS 10 ' Set number of bits in result
Define ADC_SAMPLEUS 50 ' Set sampling time in uS
'Define ADC_CLOCK 3 ' This define is inoperative on 16F88x
ADCON0 = %11000000 ' Set ADC_CLOCK to RC (DEFINE ACD_CLOCK inoperative on the 16F88x)
ADCON1 = %10000000 ' Right-Justify result in ADRESH:ADRESL registers
ANSEL = %00000001 ' Set AN0-AN7 to digital with the exeption of AN0
ANSELH = %00000000 ' Set AN8 and higher channels to digital operation
'**********************************************************
adval Var Word ' Create adval to store result
TRISA = %11111111 ' Set PORTA to all input
Low PORTE.2 ' LCD R/W line low (W)
Pause 500 ' Wait .5 second
mainloop:
Adcin 0, adval ' Read channel 0 to adval (0-1023)
adval = (adval */ 500)>>2 ' Equates to: (adval * 500)/1024
Pause 100 ' Wait .1 second
LCDOut $FE, $80, "DC Volts= ",DEC (adval/100),".", DEC2 adval ' Display the decimal value
Goto mainloop ' Do it forever
End
PICBASIC PRO PROGRAM FOR SERVO CONTROL USING ON INTERRUPT. USES TMR0 AND PRESCALER. WATCHDOG TIMER SHOULD BE SET TO OFF AT PROGRAM TIME AND NAP OR SLEEP SHOULD NOT BE USED. BUTTONS ON KEYPAD ARE USED TO MOVE SERVOS.
' Name : SERVOSX.pbp
' Compiler : PICBASIC PRO Compiler 2.60
' Assembler : PM or MPASM
' Target PIC : 40-pin 16F887
' Hardware : LAB-X1 Experimenter Board
' Oscillator : 4MHz external crystal
' Keywords : ON INTERRUPT, TIMER0
' Description : PICBASIC PRO program for servo control using On Interrupt.
' Uses TMR0 and prescaler. Watchdog Timer should be set to off at program
' time and Nap and Sleep should not be used. Buttons on LAB-X1 keypad are
' used to move servos.
'
Define LCD_DREG PORTD ' Define LCD connections
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
Servo1Pos VAR Word ' Servo 1 position
Servo2Pos VAR Word ' Servo 2 position
ServoSelect VAR Bit ' Servo selection
Servo1 VAR PORTC.1 ' Alias first servo pin
Servo2 VAR PORTC.0 ' Alias second servo pin
ServoSelect = 0 ' Set to first servo
Low Servo1 ' Set up servos
Low Servo2
Servo1Pos = 500 ' Center servos
Servo2Pos = 500
ANSEL = %00000000 ' Make PORTA and PORTE digital
ANSELH= %00000000 ' Make PORTA and PORTE digital
Low PORTE.2 ' LCD R/W low = write
Pause 100 ' Wait for LCD to startup
Lcdout $fe, 1 ' Clear screen
OPTION_REG = $7f ' Enable PORTB pullups
' Set TMR0 to interrupt every 16.384 milliseconds
OPTION_REG = $55 ' Set TMR0 configuration and enable PORTB pullups
INTCON = $a0 ' Enable TMR0 interrupts
ON Interrupt GoTo timerint
' Main program loop
mainloop:
PORTB = 0 ' PORTB lines low to read buttons
TRISB = $fe ' Enable first button row (RB0=output=LOW)
' Check for button press to move servo
IF PORTB.4 = 0 Then ' SW1 on LAB-X1 keypad
GoSub left1
Endif
IF PORTB.5 = 0 Then ' SW2 on LAB-X1 keypad
GoSub right1
Endif
IF PORTB.6 = 0 Then ' SW3 on LAB-X1 keypad
GoSub left2
Endif
IF PORTB.7 = 0 Then ' SW4 on LAB-X1 keypad
GoSub right2
Endif
Lcdout $fe, $80, "Position1 = ", #Servo1Pos, " "
Lcdout $fe, $c0, "Position2 = ", #Servo2Pos, " "
GoTo mainloop ' Do it all forever
' Move servo 1 left
left1:
IF Servo1Pos < 1000 Then
Servo1Pos = Servo1Pos + 1
Endif
Pause 10 ' Debounce
Return
' Move servo 1 right
right1:
IF Servo1Pos != 0 Then
Servo1Pos = Servo1Pos - 1
Endif
Pause 10 ' Debounce
Return
' Move servo 2 left
left2:
IF Servo2Pos < 1000 Then
Servo2Pos = Servo2Pos + 1
Endif
Pause 10 ' Debounce
Return
' Move servo 2 right
right2:
IF Servo2Pos != 0 Then
Servo2Pos = Servo2Pos - 1
Endif
Pause 10 ' Debounce
Return
' Interrupt routine to handle timer
Disable ' Disable interrupts during interrupt handler
timerint:
IF ServoSelect Then tiservo2
Servo1 = 1 ' Do first servo
PauseUs 1000 + Servo1Pos
Servo1 = 0
GoTo tiexit
tiservo2:
Servo2 = 1 ' Do second servo
PauseUs 1000 + Servo2Pos
Servo2 = 0
tiexit:
ServoSelect = ServoSelect + 1 ' Point to next servo
INTCON.2 = 0 ' Reset timer interrupt flag
Resume
End
PICBASIC PRO PROGRAM TO DISPLAY RESULT OF 8-BIT A/D CONVERSION ON LCD. CONNECT ANALOGUE INPUTS TO CHANNELS 0, 1, 3 (RA0, 1, 3).
' Name : adcin3x.pbp
' Compiler : PICBASIC PRO Compiler 2.60
' Assembler : PM or MPASM
' Target PIC : 40-pin 16F887
' Hardware : Lab-X1
' Oscillator : 4MHz external crystal
' Keywords : ADC, ADCIN, ANALOG, LCDOUT, LCD
' Description : PICBASIC PRO program to display result of
' 8-bit A/D conversion on LCD
'
' Connect analog inputs to channels 0, 1, 3 (RA0, 1, 3)
' Define LCD registers and bits
Define LCD_DREG PORTD
Define LCD_DBIT 4
Define LCD_RSREG PORTE
Define LCD_RSBIT 0
Define LCD_EREG PORTE
Define LCD_EBIT 1
' Define ADCIN parameters ********************************
Define ADC_BITS 8 ' Set number of bits in result
Define ADC_SAMPLEUS 50 ' Set sampling time in uS
'Define ADC_CLOCK 3 ' This define is inoperative on 16F88x
ADCON0 = %11000000 ' Set ADC_CLOCK to RC (DEFINE ACD_CLOCK inoperative on the 16F88x)
ADCON1 = %00000000 ' Left-Justify result in ADRESH:ADRESL registers
ANSEL = %00001011 ' Set AN0, AN1, AN3 to analog, others digital
ANSELH = %00000000 ' Set AN8 and higher channels to digital operation
'**********************************************************
adval Var Byte ' Create adval to store result
TRISA = %11111111 ' Set PORTA to all input
Pause 500 ' Wait .5 second
mainloop:
Lcdout $fe, 1 ' Clear the LCD
Adcin 0, adval ' Read the first ADC channel
Lcdout "0=", #adval ' Send it to the LCD
Adcin 1, adval ' Read the second ADC channel
Lcdout " 1=", #adval ' Send it to the LCD
Adcin 3, adval ' Read the third ADC channel
Lcdout " 3=", #adval ' Send it to the LCD
Pause 200 ' Delay for time to read the display
Goto mainloop ' Do it forever
End