You are on page 1of 10

Coding The PIC Microcontroller With PIC C 1.

0 Coding in C:
C is the language we use to code PIC microcontrollers. Some people also use Assembl ! we call them sadists. 1.1 Creating Variables: A "ariable is a name gi"en to a section o# memor . Memor is cataloged b things called addresses. These addresses are the locations #or "ariables in memor . With PIC C! ou will tend to deal with two t pes o# "ariables. In one case! ou will create a "ariable and ha"e the chip itsel# handle what address it goes to. This is the case when ou do not desire to create a "ariable #or a certain part o# memor ! ou $ust want to store a "alue. The other case is when ou want to re#er to a speci#ic part o# the memor ! this will be dealt with in the PIC speci#ic section. %or now! lets loo& at $ust creating "ariables and not caring where the are stored. In order to create a "ariable! one must #irst &now what &ind o# data that "ariable is going to store. Since the "ariable is $ust ser"ing to re#er to a certain section o# memor ! one must speci# two things. The #irst is the amount o# memor that "ariable is going to ta&e up! the second is the "alue that the "ariable will ha"e. 'suall ! the si(e )amount o# memor * o# the "ariable is going to be proportional to the range o# "alues which it has to deal with. I# one wants to create a "ariable that will recei"e inputs ranging #rom 0 to +0000! the will not choose a "ariable which can onl co"er a range o# 0,-++. Thus! it is important to alwa s &now be#ore hand what &ind o# data will be stored and handled. To create a "ariable! one uses the #ollowing s nta.:
variable_type type_specifier variable_name/

Variable_type re#ers to the &ind o# data one is tr ing to store! and b wa o# that it also speci#ies how much memor it will ta&e up. Type_specifier is used to speci# certain properties about that "ariable. Variable_name is the name which ou will use to re#er to that section o# memor . The chart below shows the "ariable t pes! special settings #or those t pes! how much memor those t pes ta&e up! and what the t pes are generall used #or. Variable_type Type-specifier int1! short int1! int signed! unsigned signed! unsigned Range of Values unsigned: 0:1 unsigned: 0 :1+ signed: ,1 : 2 Memory Used for Usage 1 bit 0ogical "alues! true and #alase 1 bit Small integer "alues

int13! long!

signed! unsigned

unsigned: 0 : -++ signed: 1-4 ,1-+ :

13 bit

0arger integer "alues 7er large "alues! chances are ou will not need this. %or dealing with decimal "alues! real numbers %or dealing with te.t Indicates no speci#ic data t pe

int5-!

signed! unsigned

unsigned: 0 4-64632-63 signed: ,-142415341 -142415342

: 5- bit

: 5- bit

#loat

Automaticall signed

char 7oid 8othing

1 bit 0 bit

So i# I wanted to store a "alue that I &new would range #rom 0,-00! I would enter:
int13 hume/

9ou ma notice that I did not enter a t pe,speci#ier! that is because all "ariables besides #loat are assumed unsigned. I# one wanted to deal with "alues ranging #rom ,100 to 100! then ou would declare the "ariable as:
signed int13 hume/

Another neat thing is that i# one wants to declare se"eral "ariables that ha"e the same variable_type! one can easil do this using the #ollowing #ormat:
variable_type type_specifier1 variable_name1, type_specifierN variable_name"/ type specifier2 variable_name!, :

So #or e.ample! i# ou were creating se"eral "ariables with the same variable_type! sa two o# them in the range #rom ,100 to 100 and - in the range #rom 0 to -++! then ou would enter:
int1 hume! turing! signed godel! signed sartre/

This is good and all! but what i# we had one hundred "ariables we needed to store #rom 0 to 100; Would we #ill up se"eral lines with $ust declaring

"ariables; The answer is 8<! instead we use what is called an arra . An arra allows ou to use one variable_name! but ha"e it store multiple "alues. What one does is basicall create an inde. o# "ariables! where each "ariable is gi"en a uni=ue number! but the are all under the same heading o# the variable_name. The #ormat #or this is:
variable_type type_specifier variable_name>inde#_si$e?/

This can be used in the #ollowing wa . Sa ou want to store 100 di##erent "ariables that are integers that range #rom ,-0 to 100! then ou would enter the #ollowing code:
signed int1 hume>100?/

Something to &eep in mind is that i# ou want to declare an arra ! all the elements in that arra will ha"e the same variable_type and type_specifier. I# ou want to create a "ariable! and assign it a "alue also! this can be done in the #ollowing #ashion/
variable_type type_specifier variable_name % value/

Where "alue is what ou want the "ariable to be e=ual to. 7ariables are also dependent on where the are declared. I# a "ariable is declared inside a #unction! it considered to be @localA to that #unction. This means that it onl e.ists in that #unction! and when the #unction is e.ited! the "ariable too ceases to e.ist. It also means that the "ariable is onl created when that #unction is called. The opposite o# this is the @globalA "ariable! which e.ists outside o# all #unctions and can be used in an part o# the code. It is created when the program is run. This will be co"ered in more depth in section 1.+. 1.! Creating &unctions: %unctions are how one manipulates "ariables. It is eas to create a collection o# "ariables! some o# them large and "er impressi"e. Bowe"er! the are no good i# not used properl ! or at all #or that matter. I# one wants to create a #unction! it will generall ta&e the #ollow #orm:
variable_type type_specifier &unction_name )"ariableCt pe t peCspeci#ier "ariableCname1! : "ariableCt pe8 t peCspeci#ier8 "ariableCname8* D 'perations return somet(ing) E

The general structure o# a #unction is such that it ta&es in data in the #orm o# "ariables between the ) * parentheses! does something with that inputted data in operations that are written in between these D E brac&ets! and then outputs a "alue with the return statement. Bere is an

e.ample #unction which will ta&e in se"eral "alues and add them. This #unction will be designed to onl handle signed integers.
signed int5- godel )int13 signed russell! int13 signed whitehead* D godel F russell G whitehead/ return godel/ E

%unctions can contain an number o# operations. The can also contain an number o# inputted "ariables. Something to &eep in mind is that a #unction is e.ited once the return statement is run. I# this #unction were to be called )e.ecuted* elsewhere in this program! it would be done this wa :
SomeC"ariable F godel)anotherC"ariable! etCanotherC"ariable*/

When creating a program! ou must create a main #unction. A #unction with the name main is what the computer )microcontroller* will run when it is #irst turned on. This means that a main #unction is primaril used to organi(e all the other #unctions and "ariables so that the wor& together. A main #unction is declared $ust li&e an other #unction! $ust that its name is main:
7oid main)* D operations) E

9ou ma notice that I did not include a return statement in the abo"e #unction. This is because an #unction created with the variable_type "oid is not supposed to return a "alue. This is true #or all #unctions! not $ust main. 1.* Controlling +rogram &lo,: The #low o# a program is basicall the order in which it e.ecutes the operations or #unctions that ha"e been entered. When a program is written that has no @#low controlA elements! it will simple run down each operation in se=uence. %or e.ample:
7oid main)* D int1 hume! #e nman/ 1 signed int13 escher/ escher F hume G #e nman/ 5 E

This program when e.ecuted will per#orm the #ollowing commands in series! that is it will go #rom 1 to 5. Bowe"er! sometimes it is not bene#icial #or the program to run through a bunch o# operations in se=uence. This means that some how one will ha"e to ma&e it so that the order in which the operations are written is not necessaril the order in which the are e.ecuted. <ne simple wa to change this is b ma&ing the e.ecution o# an operation dependent on something. This in"ol"es using what is called an i# statement. An i# statement can be written as #ollows:
i# )somet(ing_is_true* D operations) E

Something is true when it is not e=ual to 0. This is because c reser"es 0 as being e=ual to #alse. The t pes o# arguments that can be tested #or whether the are true and #alse are: Argument t pe H=ui"alence And <r Test LreaterM0ess Than 0a out a FF b True when: a is the same "alue as b a II b a and b are both true )not 0* a JJ b Hither a or b is true a When a is not 0 a NF b! a OF b! a is greater than a O b! a N b or e=ual to b! etc %alse when: a and b are di##erent "alues Hither a or b is #alse Koth a and b are #alse When a is 0. a is less than or not e=ual to b 'sed to: Chec& #or whether a certain pa

'sed mainl in counters! to tell when a #unction has been e.ecuted a desired number o# times.

The ne.t wa to control what operations are done and what ones are not is with else statements. When an else statement proceeds and i# statement! then the else statement will e.ecute i# the i# statement is shown to be untrue. %or instance:
i# )somet(ing_is_true* D operations/ E else D operations/ E

I# one is going to do a lot o# i# statements! and these i# statements will be chec&ing #or e=ui"alence #or a "ariable! then it ma be best to use a switch statement. This allows one to select a "ariable that will act as a @switchA. <ne then has a series o# case "alues! each case being a possible "alue o# the "ariable being used as the switch.
switch )variable* case possible_value: operations/ brea&/ case possible_value!: operations/ brea&/ case possible_value": operations/ brea&/ else brea&/

I# ou want to repeat a certain operation o"er and o"er again! one would use a loop. There are three t pes o# loops! while! do while! and #or. An e.ample o# each is gi"en below. Hach o# the loops count up to a certain "alue and each turn output that "alue.
while )variable - constant* D variableGG/ print#)variable\n\r*/ E do D variableGG/ print#)variable\n\r*/ E while )variable O constant* #or )variable F 0/ variable O constant/ variableGG* D print#)variable\n\r*/ E

-.0 PIC Speci#ic %unctions and 7ariables:


!.1 .etting up a +/C: This in"ol"es declaring the settings that are going to be used on the PIC. There are man settings that are used depending on the tas& on wants to do. %or our purposes we will alwa s use the header written below/
Pinclude O13#122.hN

P#uses BS! 8<KQ<W8<'T! 8<WRT Puse dela )cloc& F -0000000*

!.!

0ata /1' 2it( a +/C: Rata IM< can be done se"eral di##erent wa s with the PIC. It reall depends on what &ind o# data one wants to gi"e out. In general! i# one is outputting data that is $ust speci# ing things such as whether to #lip a switch on or o##! then it ma be best to select a single pin and $ust modi# its state. The other t pe o# outputted data would be a "ariable such as an integer! in that case It wor&s better to output it using the PICSs built in serial capabilities. These will be e.plored in the ne.t section. To modi# speci#ic pins on the PIC! there are se"eral methods. Bowe"er! the same thing that is needed #or all o# them is to declare the state o# the pins being used on the PIC. This is done with the setCtris #unction:
setCtrisCport)0bsome_byte3

What this means is that one can select the port )A!K!C!R:* on the PIC which the wish to setup. The 0b stands #or b te! and tells the compiler that ou will be using a b te to speci# the ports. This can also be done with he.! and in that case one would enter 0x! but the b te #ormat is easier to understand at #irst glance. The some_byte is a series o# 1 0s and 1s which speci#ies whether a pin on a certain port is input or output. I# a pin is input! then one enters a 1! i# the pin is an output! then the pin enters a 0. The e.ample below shows one how to setup a port! port A speci#icall ! so that pins 0,4 on port A are inputs! and +,2 are outputs.
setupCadc)ARCC<%%*/ setCtrisCa)0b00011111*/

9ou ma be wondering wh I included setupCadc)ARCC<%%*/ in this code. The reason was that port A happens to be the same port where ARC #unctions are per#ormed! and thus one must turn the ARC capabilities o# that port o## so that it can act correctl . An wa ! once the pins on a port ha"e been declared the ne.t step is to read them or change their states. To read a pin! use:
input)PI8CportIpin*/

What that does is output the state o# the pin on the port. So! i# we wanted to read #rom our input pin 1 on port A! we would add the code:
Input)PI8CA1*/

The other tas& is to set an output pin to a "alue! this is done a similar wa . The onl di##erence is that ou ha"e to speci# in the #unction what "alues ou want to output. Since the pins onl output either a 0 or 1! ou ha"e two #unctions:
outputChigh)PI8CportIpin*/

#or high! or:


outputClow)PI8CportIpin*/

This is a simple wa to do input and output! howe"er it can get e"en simpler. This is done b declaring a "ariable that is to e=ual a certain pin or port. This is done with the Pbit or Pb te directi"e! respecti"el . In this case! ou do not use the PI8CportIpin #ormat to speci# the pin or port! instead ou use a numerical e.pression. Pbit "ariable F port.pin Pb te "ariable F port In these cases! port A is +! K is 3! C is 2! and R is 1. %or PICs which more IM< pins! the trend should continue. The pin @decimalsA run #rom 0 to 2. So i# I wanted to create a "ariable #or each pin on port A! I would: Pbit pina0 F +.0 Pbit pina1 F +.1 Pbit pina- F +.Pbit pina5 F +.5 Pbit pina4 F +.4 Pbit pina+ F +.+ Something to note here! the astute reader will not that I did not create "ariables #or pins 3 and 2. This is because port a onl has 3 pins! howe"er the compilier treats it li&e it has 1 )as in the setCtris e.ample*! this is $ust one e.ample o# the PIC C cra(iness which will be encountered as ou learn to wor& with PICs. 8ow that we can declare "ariables #or speci#ic PI8s! we can chec& the "alue o# an input pin b simpl calling the "ariable! an we can change the "alue o# an output pin b setting it to a "alue. While this is all good! it is sometimes better to control a whole port. In this case! we set a "ariable e=ual to the port. This is where the Pb te command comes in. Pb te porta F + This means that i# we set porta e=ual to a "alue! it would ad$ust its pin "alues )assuming all are output! setCtrisCa)0b00000000** e=ual to the binar representation o# that b te. <n the other hand! one can also read the "alue o# all the pins on port a! and interpret it as a b te )assuming all are input! setCtrisCa)0b11111111**. !.* .erial Communication:

Serial communication is done on a PIC b speci# ing se"eral things! the output pin! the input pin! the baud )connection speed*! and se"eral possible speci#ic serial settings. To setup up a serial connection is eas . 8ote! onl one serial connection can be setup at a time. To setup up a serial connection is eas . 8ote! onl one serial connection can be setup at a time.
Puse rs-5-)baud F some_value! rc" F PI8CportIpin! .mit F PI8CportIpin! other*

<ne also needs to ma&e sure that the pins speci#ied #or rc" )input* and .mit )output* in the serial communication operation are also speci#ied the same wa in the setCtris operation. To do output! that is send a signal through the .mit pin! one would:
print#)variable*/

To do input! two things must be done. The #irst is to wait #or the input to come in. this is done with the &bhit)*/ #unction! the second is to grab that input. This is done with the getc)*/ #unction. To do this right! one must create a loop that runs until &bhit)* is true. The ne.t step is to getc)*:
While)T&bhit)**/ variable F getc)*/

This code waits #or a character to be inputted! then sets "ariable e=ual to whate"er was inputted. !.4 5nalog to 0igital Converter .etup: An Analog to Rigital Con"erter )ARC* is a circuit that ta&es a "oltage in! and e.presses that "oltage as a b te. %or robotics! this is especiall use#ul #or sensor s stems which rel on continuous "oltage changes to indicated changes in the real world. %or the PIC! port A is the designated ARC port. This means that to read ARC data! port A must be used. <ne #irst needs to declare which pins the are going to use #or the ARC inputs! this is done b using the setupCadcCports #unction.
setupCadcCports)A8A0<LCQIpin*/

An e.ample o# this is:


setupCadcCports)A8A0<LCQA0CQA1*/

This would turn ports A0 and A1 into ARC ports. A#ter the ports ha"e been declared! one then sets the cloc& to be used b the ARC. This is done with:
setupCadc)adcCcloc&Cinternal*/

A#ter that! one then sets up the ARC channel. 0i&e the serial port! onl one channel can be read at a time. So i# ou want to change channels! ou will ha"e to redo setCadcCchannel. It is also recommended that ou dela the reading o# the ARC port #or a short time $ust so that it can gi"e ou a more accurate reading. So! i# we want to setup a channel! and then wait a couple ms be#ore reading! we would enter:
SetCadcCchannel)pin*/ Rela Cms)s(ort_time*/ Variable F readCadc)*/

The two #unctions introduced abo"e! dela Cms and readCadc! do e.actl what the are named. Rela Cms waits s(ort_time number o# ms until resuming the program. QeadCadc reads the ARC pin as declared in the setCadcCchannel.