Beginners mini-course (part 1)

Be able to start with PIC Basic you must have any knowledge of electronics, program experience isn't been required, this is where this mini-course is for.
This mini-course is to help you on your way so that you can do some expirience with by your own programmed PIC's with the free trial Proton PIC Basic IDE compiler, fully usable but only a few PIC-types is supported and a limit from 50 lines of code, but enough for this mini-course.
The bought version can program all PIC devices.
The possibility's are so big, it's impossible to explain it all here, but once you get going, the rest will come from itself and you can look to program-listings from others, like the projects from this site, to learn further.
Use a PIC16F628A with suffix I / P or E / P.
As programmer I advice the Wisp648 programmer from Voti, which is not expensive (less than € 30,-) or build the Galva-Wisp PIC programmer from this site!

We start rapidly with as example, blink a LED, gradually we go extending it.


First connect the PIC
It's important that the PIC is connected on a stabilised 5V power.
If you give already no attention to the power, the rest is also meaningless, the PIC can do strange things on a negligent 5V power.
Pin 5 from the PIC16F628A is GND (= ground), connect this one to 0V.
Pin 14 is the Vcc, connect this one to +5V.
Direct over pin 5 and pin 14 you must connect a multilayer capacitor from 100n (see photo), connect it as short as possible to the PIC.
Finally connect a LED in serial with a 1k resistor between +5V and port A.1, that is on a 16F628A pin 18.
See also the electric scheme below:


Adjust the compiler first!
I get many times e-mails that the compiler doesn't work.
Almost always have the users not adjusted the compilersettings, because they want start rapidly with the course.
So please do this first, to avoid problems, specially point 1.

1. Long folder- and pathnames give problems by compiling, that's why it is important that the compiler is adjusted the right way!
2. Users from a Wisp648 programmer or the Galva-Wisp PIC programmer from this site can couple this program to the PIC Basic IDE.
3. To program the PIC itself must the programmer ofcourse connect (temporarily) with the PIC which must programmed (= the target PIC).

 

Program
Type the program underneath in the PIC Basic IDE:

DEVICE 16F628A                ;We use a 16F628A device
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;All analog inputs disabled

Again:                        ;Label with a name invent by yourself 
TOGGLE PORTA.1                ;When on then go off, when off then go on 
DELAYMS 500                   ;500 milliseconds = 0,5 second
GOTO Again                    ;Jump to 'Again' and go endless

END                           ;Program end

First the lines which must stay nearly on top in every program.

DEVICE is always placed on top of the program with after it which PIC device is being used.
If the device you wish to use is supported by Crownhill Proton+, the text on your screen is highlight bold, this also happens to all functions and commands.
So in this program it is: DEVICE 16F628A.

Under it CONFIG with INTRC_OSC_NOCLKOUT (= internal rc oscillator), provisional we use the build in oscillator, a crystal is not necessary at this simple program.
With CONFIG we can enable or disable the 'fuses' from the PIC.

Then ALL_DIGITAL TRUE, which tells the PIC that we're not work with analog input signals, all 1 or 0, only +5V or 0V, only on or off, so all digital.
ALL_DIGITAL TRUE disables the analog to digital converters (ADC) and comparators (if they are present in the device you choose).

Now we type in a label with a user-defined name, i.e. 'Again'.
A label must placed at the beginning of a line, ends with a colon (:) and must start with a letter.
In our example therefore: 'Again:'

We have the LED connected on port A.1, these must blink, for this the command TOGGLE exists.
TOGGLE PORTA.1 turns the situation of port A.1, when it is on then it is turned off and is it off, it is turned on again, this is called toggle.

Then there must build a delay in, because else the LED blinks this way rapidly that it seems that it dims.
Here are the delay commands DELAYMS and DELAYUS for.
DELAYMS for millisecond and DELAYUS for µsecond (microsecond).
One second = 1000 milliseconds, so for a half second we write DELAYMS 500.
The maximum value is 65535, about 65.5 seconds.
When you want a longer time, place a few from these commands under eachother.
For extremely long times (hours, days) there are other solutions.

The LED must blink continue, by means of GOTO we let start him again, hence the logical name 'Again' invented.
Therefore 'GOTO Again'.

With a push on F9 makes the compiler an assembler (.ASM) file and after that there becomes a .HEX file which you can program with your PIC-programmer into the PIC.
If you have already installed a programmer in the PIC Basic IDE then you can push F10 which does the same as F9, but starts also your programmers program.

Thats all!
Your first PIC-Basic program is ready!
The upper part tells the Proton+ compiler for which type of PIC device the program must be converted and that there is no crystal used.

The real program is the loop between 'Again' and 'GOTO Again'.
A program runs the order which you write down or jumps to where it is sent to.
In the program above stays TOGGLE PORTA.1, here it turns the LED on (or off, if it was already on)
Then there stays DELAYMS 500, the program waits here 500 milliseconds, thus a half second.
If this time is past, it runs further and comes to 'GOTO Again'.
Now it jumps back to the label 'Again' and this all starts over again, only by TOGGLE is the LED not turned on, but off and the next time on again, etc.


Now your program must be translated in a for the PIC understandable program, a .HEX file.
One push on a button (F9 key) turns the Basic program into assembler (.ASM) (= compiling) and is also a .HEX file created for your PIC programmer, which can this file program into the PIC.
To program the compiled program into the PIC itself you must thus have a PIC programmer.
If you have a Wisp648 or Galva-Wisp PIC programmer, then here is a description how this goes with the program BumbleBee, which runs under Windows:



It is very important to put information behind each line, what this line does, with the aid of the command REM (= remarks).

DELAYMS 500                   REM = 0,5 second 
DELAYMS 500                   ' = 0,5 second
DELAYMS 500                   ; = 0,5 second

Above 3 lines are all three the same, my preference goes to ';' because assembler only works with the semicolon, if you after a while put some assembler lines in your code (with ASM - ENDASM) you don't have to switch over again, because you have this way already got used it.

Be careful with GOTO
Above in the first example GOTO is used.
Immediately here the recommendation to look out that it became no mess with GOTO's because at multiple use the overview goes quickly lost.
The program mentioned below blinks also a LED without the use of GOTO but with the command WHILE - WEND.


Modify the previous program in the program mentioned below:

DEVICE 16F628A                ;We use a 16F628A device
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;All analog parts disabled

WHILE 1 = 1                   ;As long as 1 is equal to 1...
  TOGGLE PORTA.1              ;When on then go off, when off then go on 
  DELAYMS 500                 ;500 milliseconds = 0,5 second
WEND                          ;...execute this loop

END                           ;Program end

The label 'Again:' and GOTO are replaced by WHILE and WEND.
This command runs the program between the words WHILE and WEND, here toggling from a LED, so WHILE 1 is equal to 1, WEND (go back to WHILE), so the LED blinks always.
WHILE can't without WEND and they belong always both in the same program, else you get an error.
 

Variable
To make the function from WHILE - WEND more clear we let blink a LED 4x after the power from the PIC is switched on.
Therefore we have to make a variable.
A variable is a name which can remember a value, in this case it's a teller (counter) which keeps in mind how many times the LED has blinked.
Therefore exists the command DIM.
With DIM you make (declare) a variable with a name which sounds logical to the function it gets, in the program below it is 'DIM LedTeller AS BYTE'.

What now means AS BYTE?
Because a PIC does have a limited memoryspace, you have to give information till howfar you think the teller counts and a byte is 8 bits (= 8 memory places) which can have 256 different combinations, so the teller can count from 0 through 255 (not 256, namely 1 through 255 and the 256th is the value 0).
You can also type DIM LedTeller AS BIT, this takes only 1 memory place, but then you can have only 2 situations, namely 0 or 1, off or on, and must the LED blinks more than 256x then you have to write DIM LedTeller AS WORD, a word is 16 bits, by this you can count till 65535, but it takes also twice as much memory space than a byte.
You can count much further with DWORD, (Double word) which counts from -2147483647 through +2147483647, but it takes already 32 memory places (32 bits).
And there is DIM LedTeller AS FLOAT, for numbers with a floating point, which takes also 32 bits.
It is to be recommended to use DWORD and FLOAT as little as possible because calculations with these types use a lot of program-memory from the PIC, with BIT, BYTE and WORD you can usely do all the work.
And finally there is AS STRING, voor text on displays, but more about this one later.


Modify the previous program in the program mentioned below:

DEVICE 16F628A                ;We use a 16F628A device
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;All analog parts disabled

DIM LedTeller AS BYTE         ;Declare variable with name 'LedTeller'

CLEAR                         ;Clear all RAM area

;Mainprogram
WHILE LedTeller < 8           ;While 'LedTeller' hasn't reached 8...
  TOGGLE PORTA.1              ;On becomes off, off becomes on (blinking) 
  DELAYMS 500                 ;500 milliseconds = 0,5 second
  LedTeller = LedTeller + 1   ;Increase 'LedTeller' with 1
WEND                          ;...execute this loop

HIGH PORTA.1                  ;LED off

END                           ;Program end

Seen that the counter value reached a maximum of 8, because 4x LED on / off means 4x LED on and 4x LED off, you can use a byte, thus: DIM LedTeller AS BYTE.

Another new command is CLEAR.
Clear without a variable name behind it, erases the contents from all variables, not the variables itself but the value from every variable became 0, whereas 'CLEAR LedTeller' only erase the content from variable 'LedTeller' (set to 0).
A good habit is to clear all RAM area by putting the command CLEAR somewhere near the top of every program.

Then starts the mainprogram, as the REM line reports.
WHILE LedTeller < 8, what means something like: while the LedTeller is smaller than (<) 8, the programblock between WHILE and WEND must repeated.
In the block is an arrangement which adds LedTeller with 1, else LedTeller would always stay on 0 and then the LED blinks still forever.
This goes as follows: LedTeller = LedTeller + 1, which means: add the value from LedTeller with 1 and give the result (back) to the variable LedTeller, on this way LedTeller value increases with 1 every time the LED is set on or off.
It's possible to add every value as long as the result is not getting higher than 255, because you declared LedTeller as byte.

It frequently occurs that counters/tellers has to be count up or down with 1, herefore exists special commands:
INC LedTeller, does the same as LedTeller = LedTeller + 1. (increment)
DEC LedTeller, does the same as LedTeller = LedTeller - 1. (decrement)
This all works only when the counter has count up or down with 1.

Is the LedTeller 8x with 1 increased then LedTeller is no longer smaller than 8 and thus the WHILE - WEND condition isn't TRUE anymore, the program now goes further with the first command which comes after WEND.

And that's HIGH PORTA.1, something new again.
HIGH PORTA.1 means: make port A.1 (pin 18 from a PIC16F628A) high (= +5V).
And seen that the LED is connected between PORTA.1 and +5V, the LED goes off.
When the LED was connected between PORTA.1 and GND, the LED would go on.

Logically that there exists also a LOW command, which make a port low (= 0V).


We replace TOGGLE by HIGH and LOW and let the LED make a short blink for 5 times:

DEVICE 16F628A                ;We use a 16F628A device
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;All analog parts disabled

SYMBOL BlinkNumber = 5        ;Number that LED must blink
SYMBOL LedTime     = 150      ;mSec, Blink rapidity from LED

SYMBOL LED         = PORTA.1  ;The LED is connected with PORTA.1

DIM LedTeller      AS BYTE    ;Declare variable with name 'LedTeller'

CLEAR                         ;Clear all RAM area

;Mainprogram
WHILE LedTeller < BlinkNumber ;While LED hasn't blink it's number... 
  LOW  LED                    ;Low = LED on
  DELAYMS LedTime             ;Time that LED is on
  HIGH LED                    ;High = LED off
  DELAYMS LedTime * 4         ;Time LED off, 4 times longer than LED on
  INC LedTeller               ;Add 'LedTeller' with 1 (Increase)
WEND                          ;...execute this loop

END                           ;Program end

Don't forget to adjust the remark lines also every time.
Most of it is clearly now, only SYMBOL is unknown yet.
First of all you can with SYMBOL give a constant value a name.
You could have filled after DELAYMS direct 150, but in a bigger program where are lots of DELAYMS', you must searching which from these has to change, thats also why you must choose logical names, so that you know immediately what this constant or variable does, only by looking to the name.
Giving names doesn't take extra memory from the PIC.
It is the PIC Basic compiler which changed during compiling the names in the original values, before it's gonna programmed in the PIC, also a long name doesn't take more memory than a short one.

Also you can give a port a name with SYMBOL and it is logical that the name is related to the device which is connected to that port, thus names as Lamp, OutputA OutputB, Ventilator, Motor, Relay or like in our examples; LED. And for inputs names like PushButton, Switch, Sensor, Temperature, etc. The name must start with a letter, after then you may also use digits (0-9) in the names, like Lamp1, Lamp2, LED1Rd, LED8Grn, Pin18, IC1, IC2 en IC3.

It has several benefits:

In the program itself you can see immediately which component or connected device (here thus LED) you are programming with, if you choose the names at least logically.
Suppose that the LED during developing a PCB not ends up to PORTA.1 but to PORTA.0 (pin 17), then you must change all PORTA.1 in PORTA.0 in the program.
Now you have only nearly to the top of the program only one line:
SYMBOL LED = PORTA.1
changing in:
SYMBOL LED = PORTA.0
and the whole program is immediately adapted.

Make this a habit for yourself.

In the program here above you see that the LED burns 150mSec (LedTime = 150).
However the LED is off for 600 mSec because after HIGH LED comes a DELAYMS with behind it the calculation LedTime * 4, so 150mSec × 4 = 600mSec.
An asterisk ( * ) means multiply, because of this the LED is always 4x longer off than on, even if you change the constant 'LedTime' in another time.



Beside WHILE - WEND there is also REPEAT - UNTIL:

DEVICE 16F628A                ;We use a 16F628A device
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;All analog parts disabled

SYMBOL BlinkNumber = 5        ;Number that LED blinks
SYMBOL LedTime     = 500      ;mSec, blink frequency

SYMBOL LED         = PORTA.1  ;The LED is connected with PORTA.1

DIM LedTeller      AS BYTE    ;Declare 'LedTeller' as BYTE variable

CLEAR                         ;Clear all RAM area

;Mainprogram
LedTeller = BlinkNumber       ;Set 'LedTeller' first
REPEAT                        ;Herhaal onderstaande lus...
  LOW  LED                    ;Low = LED on
  DELAYMS LedTime             ;Time that LED is on
  HIGH LED                    ;High = LED off
  DELAYMS LedTime / 2         ;Time that LED is off, 2 times shorter than on 
  DEC LedTeller               ;Decrease 'LedTeller' with 1
UNTIL LedTeller = 0           ;...till 'LedTeller' reached 0

END                           ;Program end

The difference between WHILE - WEND and REPEAT - UNTIL is that WHILE examined the condition before it will go into the loop, when the condition is FALSE, the loop is never executed and the program runs further with the command after WEND.
REPEAT - UNTIL runs first the loop and then it examined if it have to do the loop once more, a REPEAT - UNTIL loop is always minimal execute for one time.
A WHILE - WEND loop is executed as long as the condition is TRUE.
A REPEAT - UNTIL loop is executed as long as the condition is FALSE.

This time is not added up with INC but count down with DEC, dat implies that we have to give the variable 'LedTeller' a value first, before a loop (REPEAT - UNTIL or WHILE - WEND) starts.
The program block between REPEAT and UNTIL is executed until LedTeller = 0.

In the program above you see that the LED burns 500 mSec (LedTime = 500).
However the LED is only off for 250 mSec because after 'HIGH LED' stands a DELAYMS with behind it the calculation LedTime / 2, thus 500mSec ÷ 2 = 250mSec.
A slash-forward ( / ) means divide, because of this the LED is always 2x shorter off than on, even if you change the constant 'LedTime' in another time.


A couple of things which you must make immediately a habit for yourself:

Give 1 or 2 spaces to a block with instructions which belongs to each other, as the part between REPEAT and UNTIL in the program above. It's much more clearly to see where the REPEAT...UNTIL loop starts en ends.
Skip regulary lines, it's more clearly if instruction blocks that belong to each other stand to each other.
Put declarations nearly on top of the program like DIM and SYMBOL, in alphabetic order.
Now you can still overlook it, but when the programs getting bigger it will be much more difficult.
Use GOTO as many times you want, but keep it clear, with GOTO you can make it easy a mess.
Try to give constant values an alias name with SYMBOL as much as possible, like we did in the examples with 'BlinkNumber' and 'LedTime'.
Reserve for variables always the smallest memory space, but pay attention; if you, for example, count with a byte variable further than 255, the value starts counting from 0 again.
Give constants, variables and ports logical names.
It's really important to give comment with REM. Ofcourse it must be useful comment, writing ';Wait 200mSec' behind DELAYMS 200 isn't very useful, you can see that without REM too, it's better to write i.e. ;Braketime motor 3

You see, programming PIC's with PIC Basic is easy.
In mini-course part 2 we make the output-signals dependent from input-signals.
Unfortunately only in Dutch language (see the Dutch part).