View Full Version : Discussion storing value in 12f675 PIC
robe_uk
Mar 17, 2007, 09:29 PM
Hi all
I would like to get into working with PIC's and the ones a have are 12f675.
My background is electronics (although basic :p ) some basic programming (commodare64) a bit of C and assembly at college (a few years ago now) so I would like to pull my interests togeather. Planes..helis... DIY cnc router... if the wife see another hobby she may not be pleased lol.
Anyway back on topic.
Starting with a basic project of an RC switch ie when a RC channel is at a certain value on output is switched on.
For my example I wish to make a glow driver so when the throttle reaches a certain level power is applied to the glow plug via a FET.
I will attempt to code in assembly to understand how the PIC works.
My question (finally) is, when I have the throttle position at a certain value and decoded in the program can I store this value in the 12f675 so that after a power down the value can be used again.
The value will be the trigger point for the glow to be switched on or off and I intend to cause the value to be store by holding down a button tied to a pin for a second or so.
The reason I would like to have a value that can be changed is so that the circuit could be used for other applications.
Thanks for any help Rob
rmteo
Mar 17, 2007, 09:49 PM
The 12F675 has 128 bytes of non-volatile EEPROM. Just write the desired value to a location of the EEPROM and it will be retained even when the PIC is powered down.
Richard Ingram
Mar 17, 2007, 10:42 PM
Here is basic program that I did for the 16F629. May be of some help :
'RC Remote Glow Driver with programmable set point -R. Ingram 01-15-04 Rev 1.0
Device 12F629
Config INTRC_OSC_NOCLKOUT, MCLRE_OFF, WDT_OFF, CP_OFF
Symbol RXIN = GPIO.3 'Input from throttle channel of receiver
Symbol OUT = GPIO.2 'Output to solid state relay PVN012
Symbol PROGRAM = GPIO.0 'Make pin low to set program mode
Symbol SWITCH = GPIO.1 'Switch for throttle reverse, high = Normal / Low = Rev
Symbol GPPU = OPTION_REG.6 'weak pull ups
Symbol TOCS = OPTION_REG.5 'Internal clock source
Dim Pulsenormal as Byte
Dim Pulsereverse as Byte
Dim Pulselen as byte
OSCCAL = $9C 'Int. Osc. Calibration value. Read from $1FF before programming.
CMCON = 7 ' Comparator mode off 12F675,629 only
'TRISIO = $001011 'set I/O direction
Input RXIN
Input SWITCH
Input PROGRAM
Output OUT
PORTB_PULLUPS = ON 'enable weak pullups so inputs don't float
TOCS = 0 'clock source internal
LOW OUT 'Init output to relay
Delayms 1000 ' Let RX settle down with good signal to RXIN
If PROGRAM = 0 AND SWITCH = 1 Then ' Program set point
Pulsenormal = PULSIN RXIN, HIGH
EWRITE 0, [Pulsenormal]
HIGH OUT
Delayms 500
Low OUT
Delayms 500
HIGH OUT
Delayms 500
LOW OUT
Elseif Program = 0 AND Switch = 0 Then
Pulsereverse = PULSIN RXIN, HIGH
EWRITE 1, [Pulsereverse]
HIGH OUT
Delayms 500
Low OUT
Delayms 500
HIGH OUT
Delayms 500
LOW OUT
Endif
Pulsenormal = EREAD 0
Pulsereverse = EREAD 1
LOOP:
Pulselen = PULSIN RXIN, HIGH 'Measure pulse length at RX input
If Pulselen < 80 Then
LOW OUT
GOTO LOOP 'Pulse out of range or no signal
ElseIf Pulselen > 220 Then
LOW OUT
GOTO LOOP 'same
ElseIf Pulselen > Pulsenormal AND SWITCH = 1 Then
High OUT 'close relay to turn on glowplug
GOTO LOOP
ElseIF Pulselen < Pulsereverse AND SWITCH = 0 Then
High OUT
GOTO LOOP
Else LOW OUT
GOTO LOOP
Endif
Bruce Abbott
Mar 18, 2007, 12:22 AM
Here's the code I use for storing and retrieving data from the 12F675's EEPROM:-
;---------------------------------------------------------------------
; Write Byte to EEPROM
;
; Input: W=Byte EEADR=address
WriteEEPROM:
banksel EECON1
wait_write: btfsc EECON1,WR ; wait for end of previous write
goto wait_write
movwf EEDATA ; store Byte to be written
bcf INTCON,GIE ; disable interrupts
; start the write (must follow this sequence exactly!)
movlw 0x55
movwf EECON2 ; Write 55h
movlw 0xAA
movwf EECON2 ; Write AAh
bsf EECON1,WR ; Set WR bit
; write now in progress
banksel 0
bsf INTCON,GIE ; re-enable interrupts
return
;----------------------------------------------------------------------
; Read Byte from EEPROM
;
; Input: W=address
; Output: W=Byte
;
ReadEEPROM:
banksel EECON1
wait_read: btfsc EECON1,WR ; wait for end of previous write
goto wait_read
movwf EEADR ; select address
bsf EECON1,RD ; initiate READ
movf EEDATA,W ; transfer Byte to W
banksel 0
return
;--------------------------------------------------------------------
; Example usage
;--------------------------------------------------------------------
; enable EEPROM
banksel EECON1
bsf EECON1,WREN ; allow writing to EEPROM
banksel 0
; write contents of a file register to EEPROM address 1
banksel EECON1
movlw 1 ; EEPROM address 1
movwf EEADR
banksel 0
movf my_file_reg,w
call WriteEEPROM
; read data from EEPROM address 1, store in a file register
movlw 1 ; EEPROM address 1
call ReadEEPROM
movwf my_file_reg
Malc C
Mar 18, 2007, 06:24 AM
In PicBASIC you can use the Read and Data statements to read storred values from the eeprom area. In the following example the DATA statement is used to store the values for a light display using PORT B, but you could use it to store values from an A/D conversion, or some sensor.. it all depends on the PIC used and how much memory it has. 128 bytes is not a lot compared to the 2K, 4k and even more that some of the other PICs have these days.
Patt1 DATA 1,2,4,8,16,32,64,128,128,64,32,16,8,4,2,1
places the decimal values for Patt1 into the memory
Then later in the code somethink like
READ (Patt1+counts), PORTB can be used to retreive each value (counts is simply part of a for next loop, so as the code loops round counts reads in the next value and displays it on PORT B, eg when counts=5 decimal 16 is sent to PORT B, the next time round counts =6 so 32 will be sent).
Hope that this gives you some idea...
robe_uk
Mar 18, 2007, 09:21 AM
Gee guys that is a lot a usful info :cool:
Thank you all.
Now I must get stuck in and put it to use :D
xorcise
Mar 18, 2007, 01:38 PM
In mikroBasic:
Eprom_Write(10, %00110011) ' write byte value to address 10
MyVal = Eprom_Read(127) ' read byte value in address 127
robe_uk
Mar 19, 2007, 06:50 PM
Hi Guys
Thought I would post the code I have written (now no laughing, at least out loud)
Am sure some of you will recognize bit of code, but wheels are round ;)
I wasn’t to sure about how to decode the PPM, or how to compare two numbers is assembly to find which is greater. Code needs tidying as there could be some toggling at setpoint.
;************************************************* *********************
;
;************************************************* *********************
; *
; Files required: *
; 12F675.lkr *
; *
; *
;************************************************* *********************
; *
; Notes: +V [ ] GND *
; O/P [ ] Rx IN *
; LED [ ] no connection *
; +v or Gnd DIR [ ] Button, pull to gnd. Require pullup *
; *
;************************************************* *********************
list p=12f675 ; list directive to define processor
#include p12f675.inc ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.
;***** VARIABLE DEFINITIONS (examples)
; example of using Shared Uninitialized Data Section
INT_VAR UDATA_SHR 0x20
RX EQU GP0 ;Define bit 0 as rx input
BUT EQU GP2 ;define bit 2 as but (button) i/p
DIR EQU GP3 ;define bit 3 as DIR i/p
LED EQU GP4 ;define bit 4 as LED
OP EQU GP5 ;define bit 5 as output
WIDTH EQU 20H ;define store location in general register
STPT EQU 21H ; "
Delay1 EQU 22H ;delay counters
Delay2 EQU 23H ;
Delay3 EQU 24H ;
STPTA EQU 25H ;
;************************************************* *********************
RESET_VECTOR CODE 0x000 ; processor reset vector
goto main ; go to beginning of program
; these first 4 instructions are not required if the internal oscillator is not used
main
call 0x3FF ; retrieve factory calibration value
bsf STATUS,5 ; set file register bank to 1
movwf OSCCAL ; update register with factory cal value
bcf STATUS,5 ; set file register bank to 0
; Wait for PIC to stabilise
movlw d'250'
Call DelayMS
; enable EEPROM
banksel EECON1
bsf EECON1,WREN ; allow writing to EEPROM
banksel 0
; remaining code goes here
call setports ;call subroutine to set ports
;code to test rx input and get value (WIDTH)
rxinput
hi btfsc GPIO,RX ;is rx input hi
goto hi ;yes skip this line
lo btfss GPIO,RX ;rx line is low wait to go hi
goto lo ;rx line lo
call measure ;
btfss GPIO,BUT ;Test is button is pressed, pulls to zero
call btsp ;yes calibrate setup with new setpoint
; read data from EEPROM address 1, store in a file register
movlw 1 ; EEPROM address 1
call ReadEEPROM ;recall sepoint saved
movwf STPT ;write to STPT for comparison to WIDTH
;Testing widht input
incf STPT,f ;used to test STPT
decfsz STPT,f ;and make sure it not
goto stpt1 ;zero before going
incf STPT,f ;into test loop
stpt1 decfsz STPT,f ;Dec STPT and test if zero
goto wid ;No goto wid
goto on ;YES then assume STPT is bigger than
;WIDHT so goto on
wid decfsz WIDTH,f ;DEC WIDHT and test if zero
goto stpt1 ;NO goto stpt1
goto off ;YES assume WIDHT is bigger than STPT
;so goto on
;set output
on btfsc GPIO,DIR ;check direction pin for zero
goto on1
bsf GPIO,OP ;YES then turn output ON
goto rxinput
on1 bcf GPIO,OP ;NO then turn output OFF
goto rxinput
off btfsc GPIO,DIR ;check direction pin for zero
goto off1
bcf GPIO,OP ;YES then turn output OFF
goto rxinput
off1 bsf GPIO,OP ;NO then turn output ON
goto rxinput
;************************************************* **************
;measure routine
measure
clrf WIDTH ;clear file WIDTH
repeat nop ;5 nop to
nop ;pad out routine
nop ;to give total loop
nop ;of 10uS
nop ;
btfss GPIO,RX ;is rx high
goto done ;No goto done
incfsz WIDTH,f ;Inc WIDTH counter
goto repeat ;loop for another 10uS
done return
;************************************************* *****************
;setup WIDTH with button press
btsp movlw d'4' ;move numder of 1/4 secs of
Call DelaySec ;delay required
btfsc GPIO,BUT ;Test if button is still held down
return ;NO return
;Yes write WIDTH to setpoint eeprom
; write contents of a file register to EEPROM address 1
banksel EECON1
movlw 1 ; EEPROM address 1
movwf EEADR
banksel 0
movf WIDTH,w
call WriteEEPROM
bsf GPIO,LED ;Turn on LED to indicate save
hold btfss GPIO,BUT ;holds up till button
goto hold ;is released
movlw d'1' ;call delay
call DelaySec ;
bcf GPIO,LED ;turn off LED
return ;return
;************************************************* *******
DelaySec ;delays the number of 1/4 sec in W on entry
;************************************************* *******
movwf Delay3
Secloop
movlw d'250'
call DelayMS
decfsz Delay3,f
goto Secloop
return
;************************************************* ************
DelayMS ;Delays the number of millisecs in W on entry
movwf Delay2 ; save 'W'
MSloop
movlw d'100'
Call DelayuS
decfsz Delay2, f
goto MSloop
Return
;************************************************* ************
DelayuS ;Delays 10x 'W' microsecs on entry
movwf Delay1 ; save 'W' in a register of our own
uSloop
nop ; each nop is 1 microsec
nop
nop ; each total loop is 10 microseconds
nop
nop
nop
nop
decfsz Delay1, f ; this is 1 microsec if skip not taken
goto uSloop ; this is 2 X 1 microsec
Return
;Code used to setup ports, eusure analogue set to digital
;gp0-gp2 set as i/p, gp3 default i/p, gp4&5 o/p
;weak pullup enabled on gp2
setports
bcf STATUS,5 ;switch to bank 0
clrf GPIO ;Init gpio
movlw 07h ;set gp 0:2 to be inputs
movwf CMCON
bsf STATUS,5 ;switch to bank 1
clrf ANSEL ;set to digital i/o
movlw b'111' ;set gp0-gp2 as i/p
movwf TRISIO
bsf WPU,BUT ;enable weak pull-up gp2
bsf WPU,DIR ; " gp3
bcf STATUS,5 ;switch to bank 0
return
;---------------------------------------------------------------------
; Write Byte to EEPROM
;
; Input: W=Byte EEADR=address
WriteEEPROM:
banksel EECON1
wait_write: btfsc EECON1,WR ; wait for end of previous write
goto wait_write
movwf EEDATA ; store Byte to be written
bcf INTCON,GIE ; disable interrupts
; start the write (must follow this sequence exactly!)
movlw 0x55
movwf EECON2 ; Write 55h
movlw 0xAA
movwf EECON2 ; Write AAh
bsf EECON1,WR ; Set WR bit
; write now in progress
banksel 0
bsf INTCON,GIE ; re-enable interrupts
return
;----------------------------------------------------------------------
; Read Byte from EEPROM
;
; Input: W=address
; Output: W=Byte
;
ReadEEPROM:
banksel EECON1
wait_read: btfsc EECON1,WR ; wait for end of previous write
goto wait_read
movwf EEADR ; select address
bsf EECON1,RD ; initiate READ
movf EEDATA,W ; transfer Byte to W
banksel 0
return
; initialize eeprom locations
EE CODE 0x2100
DE 0x00, 0x01, 0x02, 0x03
END ; directive 'end of program'
This was my first attempt at coding and programming, it works on breadboard, found that even with weak pull ups enabled I still had to pull up to +v via 1k resistor.
Am sure there are better was to do things so all comments welcome
Rob
xorcise
Mar 19, 2007, 09:54 PM
... or how to compare two numbers is assembly to find which is greater.
If you subtract the numbers you can figure which is larger by checking STATUS.0 (carry bit). If the operation is the larger number subtracting the smaller or is equal, then the Carry bit is Set. If it's the other way around the Carry bit is Cleared.
movf num1, W
subwf num2, W
btfsc STATUS, C
goto somewhere when num2 is larger
goto somewhere when num1 is larger
This was my first attempt at coding and programming, it works on breadboard, found that even with weak pull ups enabled I still had to pull up to +v via 1k resistor.
I'm surprised. The "weak" pullup is rated at 200uA which is enough to pull the "floating" input to a high logic. Using a 5V supply, that's equivalent to using a 25K pullup resistor. I've had good success with the internal pullups in my circuits. 1K is a pretty hard pullup, rated at 5ma constant current draw. My experience has found 10K sufficiently hard.
robe_uk
Mar 20, 2007, 03:08 AM
Hi xorcise
Thanks for the tips, :cool:
I was surprised about having to use a pullup myself, maybe just the chip am using? I was looking for 10k's but typical of all things, just not there when needed lol.
I will have a go at tiding the code a bit more, plus am going to bring the reverse function into software selected via the button. ie hold for a second to store the current ppm position, after LED flash that indicates store, push buttion again within 1/2 sec to change reverse then double flash.
Gee this programming lark is addictive, at least am in the living room and the wifes happy :D
Dan Baldwin
Mar 20, 2007, 11:02 AM
GP3 has no weak pull up resistor built in. Is that the where you had to add a external pull up?
Dan
robe_uk
Mar 20, 2007, 02:39 PM
GP3 has no weak pull up resistor built in. Is that the where you had to add a external pull up?
Dan
Oh i didnt realise that, when I was having trouble I added pullup resistors to GP2 & GP3. Maybe it was just GP3 was giving trouble, I will try again later without the pullup resistor on GP2.
Will post again with my progress, hopefully other newbies can learn from my experiences.
Rob
xorcise
Mar 20, 2007, 06:03 PM
If you are interested in capturing pulses, why not get a 12F683? It's virtually identical to the 12F675 and has a CCP module. Also, it features twice the ROM, twice the RAM, and 256 bytes of EEPROM.
robe_uk
Mar 20, 2007, 06:20 PM
Hi
It is 12f675 chips I have about, but will look at the 683.
tried taking out the pullup from GP02 but it wouldnt run.
no time to look more tonight, have I the weak pullup set correctly?
Cheers
Rob
Bruce Abbott
Mar 21, 2007, 06:30 AM
You also have to clear the GPIO Pullup Enable bit in the Option register, eg.
Banksel OPTION_REG
bcf OPTION_REG, NOT_GPPU
Banksel 0
robe_uk
Mar 21, 2007, 10:35 AM
You also have to clear the GPIO Pullup Enable bit in the Option register, eg.
Banksel OPTION_REG
bcf OPTION_REG, NOT_GPPU
Banksel 0
Oh, I was setting the bit
;Code used to setup ports, eusure analogue set to digital
;gp0-gp2 set as i/p, gp3 default i/p, gp4&5 o/p
;weak pullup enabled on gp2
setports
bcf STATUS,5 ;switch to bank 0
clrf GPIO ;Init gpio
movlw 07h ;set gp 0:2 to be inputs
movwf CMCON
bsf STATUS,5 ;switch to bank 1
clrf ANSEL ;set to digital i/o
movlw b'111' ;set gp0-gp2 as i/p
movwf TRISIO
bsf WPU,BUT ;enable weak pull-up gp2
bcf STATUS,5 ;switch to bank 0
return
so i should change this to bcf, (sorry about the formatting)
ok will try after work,
Thanks
Bruce Abbott
Mar 21, 2007, 08:33 PM
Don't change that code! You are setting the WPU register bits correctly.
However, you also have to enable weak pull-ups in the Option register (the NOT_GPPU bit is set on powerup and is active low, so it must be Cleared to enable weak pull-ups).
robe_uk
Mar 22, 2007, 06:54 PM
Bruce You da man, I got the weak pullup working and it was the option_reg :D
Well I now have the code running and seems to run well, I am very happy with it as it was my first PIC project. Really has me considering a project development board as it would help speed things up, maybe someday.
So how to work it,
1. On first-ever power up after programming the setpoint has zero value so a setting has to be stored.
2. to store a value connect to Rx channel you wish to use and have the Tx transmitting the position you wish the setpoint to be active, gound pin 5 (GP02) for 1sec then you get an LED flash once then on solid till you release GP02 from ground.
3. If you find it is active in the wrong direction it can be reversed,
carry out step 2 above, when you release the button press it again within 1/2 and hold. The LED will flash twice then go solid till released. It is now reversed.
The direction and setpoint is stored into the eeprom so will remain even after power off
You will have to add whatever driver to the o/p pin to drive whatever load you wish to switch. My project was for a simple rc switch for a glow driver, so I will put on a FET.
I had a problem then when the Tx stick position was at the setpoint the output would toggle on and off but I was able to get around this in code :)
This is a beginners project which am sure a real coder could do far nicer, Big thanks to all who helped me get it done.
I guess it could be expanded and have glitch counter, lost signal etc.
Hope someone picks up something from it.
(formatting looks better on MPLAB)
;************************************************* *********************
; This file is a basic code template for object module code *
; generation on the PICmicro PIC12F675. This file contains the *
; basic code building blocks to build upon. As a project minimum *
; the 12F675.lkr file will also be required for this file to *
; correctly build. The .lkr files are located in the MPLAB *
; directory. *
; *
; If interrupts are not used all code presented between the *
; code section "INT_VECTOR and code section "MAIN" can be removed. *
; In addition the variable assignments for 'w_temp' and *
; 'status_temp' can be removed. *
; *
; Refer to the MPASM User's Guide for additional information on *
; features of the assembler and linker (Document DS33014). *
; *
; Refer to the respective PICmicro data sheet for additional *
; information on the instruction set. *
; *
;************************************************* *********************
; *
; Filename: ppmv2.asm *
; Date: 18/03/07 *
; File Version: 1.2 *
; *
; Author: R. Evans *
; Company: *
; *
; *
;************************************************* *********************
; *
; Files required: *
; 12F675.lkr *
; *
; *
;************************************************* *********************
; *
; Notes: +V [ ] GND *
; O/P [ ] Rx IN *
; LED [ ] no connection *
; no connection [ ] Button, pull to gnd. Require pullup *
; *
;************************************************* *********************
list p=12f675 ; list directive to define processor
#include p12f675.inc ; processor specific variable definitions
errorlevel -302 ; suppress message 302 from list file
__CONFIG _CP_OFF & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file.
; See data sheet for additional information on configuration word settings.
;***** VARIABLE DEFINITIONS (examples)
; example of using Shared Uninitialized Data Section
INT_VAR UDATA_SHR 0x20
RX EQU GP0 ;Define bit 0 as rx input
BUT EQU GP2 ;define bit 2 as but (button) i/p
LED EQU GP4 ;define bit 4 as LED
OP EQU GP5 ;define bit 5 as output
WIDTH EQU 20H ;define store location in general register
STPT EQU 21H ; "
Delay1 EQU 22H ;delay counters
Delay2 EQU 23H ;
Delay3 EQU 24H ;
DIRR EQU 25H ;
STPT1 EQU 26H
;************************************************* *********************
RESET_VECTOR CODE 0x000 ; processor reset vector
goto main ; go to beginning of program
; these first 4 instructions are not required if the internal oscillator is not used
main
call 0x3FF ; retrieve factory calibration value
bsf STATUS,5 ; set file register bank to 1
movwf OSCCAL ; update register with factory cal value
bcf STATUS,5 ; set file register bank to 0
; Wait for PIC to stabilise
movlw d'250'
Call DelayMS
; enable EEPROM
banksel EECON1
bsf EECON1,WREN ; allow writing to EEPROM
banksel 0
; remaining code goes here
call setports ;call subroutine to set ports
;read direction from EEPROM
movlw 2 ; EEPROM address 2
call ReadEEPROM ;recall sepoint saved
movwf DIRR ;write to DIRR for direction required
;code to test rx input and get value (WIDTH)
rxinput
hi btfsc GPIO,RX ;is rx input hi
goto hi ;yes skip this line
lo btfss GPIO,RX ;rx line is low wait to go hi
goto lo ;rx line lo
call measure ;
btfss GPIO,BUT ;Test is button is pressed, pulls to zero
call btsp ;yes calibrate setup with new setpoint
; read data from EEPROM address 1, store in a file register
movlw 1 ; EEPROM address 1
call ReadEEPROM ;recall sepoint saved
movwf STPT ;write to STPT for comparison to WIDTH
;Testing widht input********************************************* *******
;If you subtract the numbers you can figure which is larger by checking
;STATUS.0 (carry bit). If the operation is STPT = or < WIDTH
;then the Carry bit is Set.
;If it's the other way around the Carry bit is Cleared.
movf STPT, W ;
subwf WIDTH, W ;
btfsc STATUS, C ;
goto on ;WIDHT is => than STPT goto on
;set outputs
;off routine
decf STPT
movfw STPT ;dec value STPT to try
subwf WIDTH,W ;and stop toggling, test makes
btfsc STATUS,C ;sure width is 2 below STPT before
goto rxinput ;turning off
btfsc DIRR,0 ;check direction Reg for zero
goto off1
bcf GPIO,OP ;YES then turn output OFF
goto rxinput
off1 bsf GPIO,OP ;NO then turn output ON
goto rxinput
on btfsc DIRR,0 ;check direction Reg for zero
goto on1
bsf GPIO,OP ;YES then turn output ON
goto rxinput
on1 bcf GPIO,OP ;NO then turn output OFF
goto rxinput
;************************************************* **************
;measure pulse routine
measure
clrf WIDTH ;clear file WIDTH
repeat nop ;5 nop to
nop ;pad out routine
nop ;to give total loop
nop ;of 10uS
nop ;
btfss GPIO,RX ;is rx high
goto done ;No goto done
incfsz WIDTH,f ;Inc WIDTH counter
goto repeat ;loop for another 10uS
done return
;************************************************* *****************
;setup STPT with button press and direction
;************************************************* *****************
btsp movlw d'3' ;move numder of 1/4 secs of
Call DelaySec ;delay required
btfsc GPIO,BUT ;Test if button is still held down
return ;NO return
;Yes write WIDTH to STPT eeprom
; write contents of a file register to EEPROM address 1
banksel EECON1
movlw 1 ; EEPROM address 1 to W reg
movwf EEADR ; move Wreg to eeprom address reg
banksel 0 ;select bank 0
movf WIDTH,w ;move value of WIDTH to Wreg
call WriteEEPROM ;call rotine to store data
bsf GPIO,LED ;Turn on LED to indicate save
movlw d'1' ;call delay
call DelaySec ;
bcf GPIO,LED ;turn off LED
movlw d'1' ;call delay
call DelaySec ;
bsf GPIO,LED ;Turn on LED to indicate save
hold1 btfss GPIO,BUT ;holds up till button
goto hold1 ;is released
bcf GPIO,LED ;turn off LED
;set direction
movlw d'4' ;pause for 1/2 sec
call DelaySec ;
btfsc GPIO,BUT ;is button repressed
return ;no: exit
movlw d'3' ;Yes
call DelaySec ;
btfsc GPIO,BUT ;Is button still held afer 1 sec
return ;NO: exit
btfsc DIRR,0 ;Yes: Test DIRR bit 0 is zero
goto clearbit ;NO goto clear bit
bsf DIRR,0 ;set DIRR bit to 1
btfss DIRR,0 ;test if bit 1, yes and it skips next line
;used instead of goto as build kept give error
clearbit bcf DIRR,0 ;clear DIRR bit 0 to zero
;store direction to EEPROM
banksel EECON1
movlw 2 ; EEPROM address 2
movwf EEADR
banksel 0
movf DIRR,w
call WriteEEPROM
;double flash to indicate store of direction
bsf GPIO,LED ;Turn on LED to indicate save
movlw d'1' ;call delay
call DelaySec ;
bcf GPIO,LED ;turn off LED
movlw d'1' ;call delay
call DelaySec ;
bsf GPIO,LED ;Turn on LED to indicate save
movlw d'1' ;call delay
call DelaySec ;
bcf GPIO,LED ;turn off LED
movlw d'1' ;call delay
call DelaySec ;
bsf GPIO,LED ;Turn on LED to indicate save
hold2 btfss GPIO,BUT ;holds up till button
goto hold2 ;is released
bcf GPIO,LED
return ;return
;************************************************* *******
DelaySec ;delays the number of 1/4 sec in W on entry
;************************************************* *******
movwf Delay3
Secloop
movlw d'250'
call DelayMS
decfsz Delay3,f
goto Secloop
return
;************************************************* ************
DelayMS ;Delays the number of millisecs in W on entry
movwf Delay2 ; save 'W'
MSloop
movlw d'100'
Call DelayuS
decfsz Delay2, f
goto MSloop
Return
;************************************************* ************
DelayuS ;Delays 10x 'W' microsecs on entry
movwf Delay1 ; save 'W' in a register of our own
uSloop
nop ; each nop is 1 microsec
nop
nop ; each total loop is 10 microseconds
nop
nop
nop
nop
decfsz Delay1, f ; this is 1 microsec if skip not taken
goto uSloop ; this is 2 X 1 microsec
Return
;************************************************* *******
;Code used to setup ports, eusure analogue set to digital
;gp0-gp2 set as i/p, gp3 default i/p, gp4&5 o/p
;weak pullup enabled on gp2
;************************************************* *******
setports
Banksel OPTION_REG ;
bcf OPTION_REG, NOT_GPPU;
Banksel 0
bcf STATUS,5 ;switch to bank 0
clrf GPIO ;Init gpio
movlw 07h ;set gp 0:2 to be inputs
movwf CMCON
bsf STATUS,5 ;switch to bank 1
clrf ANSEL ;set to digital i/o
movlw b'111' ;set gp0-gp2 as i/p
movwf TRISIO
bsf WPU,BUT ;enable weak pull-up gp2
bcf STATUS,5 ;switch to bank 0
return
;---------------------------------------------------------------------
; Write Byte to EEPROM
;
; Input: W=Byte EEADR=address
;************************************************* ********************
WriteEEPROM:
banksel EECON1
wait_write: btfsc EECON1,WR ; wait for end of previous write
goto wait_write
movwf EEDATA ; store Byte to be written
bcf INTCON,GIE ; disable interrupts
; start the write (must follow this sequence exactly!)
movlw 0x55
movwf EECON2 ; Write 55h
movlw 0xAA
movwf EECON2 ; Write AAh
bsf EECON1,WR ; Set WR bit
; write now in progress
banksel 0
bsf INTCON,GIE ; re-enable interrupts
return
;----------------------------------------------------------------------
; Read Byte from EEPROM
;
; Input: W=address
; Output: W=Byte
;
ReadEEPROM:
banksel EECON1
wait_read: btfsc EECON1,WR ; wait for end of previous write
goto wait_read
movwf EEADR ; select address
bsf EECON1,RD ; initiate READ
movf EEDATA,W ; transfer Byte to W
banksel 0
return
; initialize eeprom locations
EE CODE 0x2100
DE 0x00, 0x01, 0x02, 0x03
END ; directive 'end of program'
MatC
Mar 22, 2007, 07:07 PM
Good work robe... would have been easier in C though :)
/Mat
JimDrew
Mar 22, 2007, 08:30 PM
NOTHING is easier in C!
xorcise
Mar 22, 2007, 11:16 PM
I concur. I prefer Basic, although I still admire the efficiency of C syntax.
robe_uk
Mar 23, 2007, 03:19 AM
Thanks Lads
C, basic, assembly........ done a very small amount in the past just at college so its hard to know which way to go
I think I will try some C, I have downloaded BoostC to try out, so may try and redo project with it.
Cheers
Rob
MatC
Mar 23, 2007, 12:53 PM
ASM is fastest, but you trade a lot of development time. I'd suggest avoiding it unless you know you need it (which isn't to say you shouldn't learn to read it, see below).
C is your most portable option (between different devices, etc)
Basic often comes with powerful features (PWM output, Serial access, etc) that makes getting things off the ground fast, at the expense of tying yourself into a relatively vendor-defined platform.
For myself, I write in C for microcontrollers (mostly PIC) and hand-optimise or manually write the ASM for the highest performance bits. I find that writing and improving the C version saves time that can be put into performance improvements elsewhere.
I've been happy with Hi-tech's C so far, but it's worth keeping an eye on the asm output: often you can tweak the C code slightly and make a big difference to the asm speed/size.
JimDrew
Mar 23, 2007, 01:17 PM
I disagree. Assembly development time (at least for me and my peers) is substantially faster than C or BASIC. Portability is the only downfall.
xorcise
Mar 25, 2007, 10:51 AM
I disagree. Assembly development time (at least for me and my peers) is substantially faster than C or BASIC. Portability is the only downfall.
Somehow that doesn't gibe with the reason high level structured programming languages exist. You're writing a lot more code to do the same functions. Then, debugging/stepping 2000 lines of assembly is more time consuming than debugging/stepping 300-400 lines of a high level language. How is that faster?
How about automatic constant and variable assignments in memory and automatic bank selection for SFR's and variables? How about the handling of strings, multidimension arrays, and structures? How about moving, shifting, adding, subtracting, comparing 2-byte and 4-byte variables with a name and symbol only? Also, as an assembly program grows in size it gets quite unweildly to manage and slows any perceived advantage in productivity, something that a structured Basic and C can organize easily.
As far as portability, there is no essential difference between assembly and Basic/C. All used registers must match the designated PIC, and most hardware functions such as ADC, USART, SPI, etc., are essentially the same across a family. Actually, different versions of Basic's and C's for PIC's all seem to be incompatible at some level.
I program in both ASM and Basic. I have yet to realize any productivity advantage programming in ASM except those places where optimization and timing are critical. By the way, I do like assembly.....I am published on MIT's PICList:
http://www.piclist.com/techref/microchip/math/radix/bp2b-2d8b.htm
vBulletin® Copyright ©2000-2009, Jelsoft Enterprises Ltd.