ejemplos pic 16f887 pbp

Upload: leo2tv

Post on 30-Oct-2015

293 views

Category:

Documents


0 download

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