You used assembly... Was it hard at beginning? Did you consider starting with C or was assembly your choice just to learn more in deep?
edit: however, it's not a simple "hello world", the program is quite complex to start with. Congrats!
I know both BASIC and some assembler for the PC. I tried C but actually found it harder than assembler so didn't bother learning it.
I've only used assembly for MCUs and it's not hard but it did take a few complies before my code worked:
The first time the code didn't compile because MPASM doesn't like decimal points, I tried 10/0.64 which has to be represented as d'10'/d'0.064" which it didn't like, then I tried .10/.0.064 which didn't work either so I just did 156.
The second time it compiled but it didn't work because I made a mistake with the code to turn on the fan.
The third time there was a mistake in the delay code.
Finally it worked, I don't think the third attempt is too bad considering I've never written a PIC program before.
well I have to say that as sinple as programming my DC-AC driver MCU was I prefered to do it in Basic as that's all i know and it was still a doddle, just a couple of registers to setup as I'd have to do in assembly and then about 10 lines of code, it would have been no more simple in assembly
The program is much more complicated than it needs to be but the main reason for assembly is to learn something. I could probably pick up BASIC in 5 minutes but you never learn much doing things the easy way!
Is there a switch debouncing library in BASIC? Does it get done automatically? If so, it's something you'll never learn how to do and you'll probably never even learn about the problem of switch bounce. The problem is, when a switch is pressed or released it bounces on and off for a couple of ms afterwards generating a stream of pulses which are accepted by the MCU so your program needs to ignore them.
In my program debouncing is implemented using the timer: the switch has to be pressed or released for at least 10ms, before the program considers it to be in the new state.
For example, to wait of the switch to be activated the BASIC the code would be something like:
' switch on GP3 which is low when activated.
' Set up timer and GP3, I don't know how this is done in basic
set timer to TOS ' timer counts clock pulses
set timer prescaler 64 ' set prescaler so timer counts every 64µs
set GP3 as input
do
do
TMR0 = 0 ' reset timer
loop while GP3 ' loop while switch is not pressed, GP3 is high
loop until TMR0 = 10/0.064 ' loop for 10ms
The assembly code is a little longer (mostly due to my comments) but it's not that bad, it's only more difficult to understand because you need to know what each instruction actually does and what the registers are.
;***** Initialisation
start
movlw b'111101' ; configure GP1 (only) as an output
tris GPIO
movlw b'10010101' ; enable internal pull-ups & configure Timer0:
; -0------ pullups enabled (/GPPU = 0)
; --0----- timer mode (T0CS = 0)
; ----0--- prescaler assigned to Timer0 (PSA = 0)
; -----101 prescale = 64 (PS = 101)
option ; -> increment every 64 us
clrf GPIO ; start with fan off
clrf sGPIO ; update shadow
; wait until switch pulled, debounce using timer0:
wait_dn clrf TMR0 ; reset timer
chk_dn btfsc GPIO,3 ; check for switch pull (GP3 low)
goto wait_dn ; continue to reset timer until button down
movf TMR0,w ; has 10ms debounce time elapsed?
xorlw .156 ; (156=10ms/64us)
btfss STATUS,Z ; if not, continue checking button
goto chk_dn
Another way of doing it is to check for the switch to be activated and simply wait 10ms until checking it again which is not quite so robust as a pulse of EMI might trigger it. My program also uses this method during the timing delay which also uses the timer - there's only one timer on the 12F509 and it can't be used for two different things simultaneously.
There are limitations to the 12F509 architecture which make the code longer and harder to understand, for example because addresses are limited to 9 bits, the 1024 words of program memory is split into two pages so to do a long jump the correct page has to be selected first e.g.
pagesel start
goto start ; jump to main code
The call instruction is limited to 8 bits so all subroutines need to appear at the start of a memory page i.e. the first 256 words so you need to do things like:
;************************************************************************
RESET CODE 0x000 ; effective reset vector
movwf OSCCAL ; update OSCCAL with factory cal value
pagesel start
goto start ; jump to main code
;***** Subroutine vectors
subroutine ; wait for switch to be released
pagesel subroutine_R
goto subroutine_R
;***** MAIN PROGRAM
MAIN CODE
;***** Initialisation
start
; your program code here
call subroutine
subroutine_R
; the code for the subroutine goes here
retlw
subroutine is called, which just selects the correct page and jumps to subroutine_R which is where the real code is.
Although I didn't need to worry about any of this, my program is under 256 words, I still did all of that as it's good practise and my program would break if it exceeded 256 words.
If you're using BASIC or C, this is all done for you so you never really learn how the MCU works.