Difference between revisions of "PIC Microcontrollers with C18 Compiler"

From Mech
Jump to navigationJump to search
 
(39 intermediate revisions by the same user not shown)
Line 1: Line 1:
__TOC__
__TOC__

==PIC Microcontroller==
The microcontroller used for this tutorial is the '''PIC18F4431''' made by [http://www.microchip.com Microchip]. This is an 8-bit microcontroller with motor PWM generators, a quadrature encoder interface (QEI), and other "peripherals".


==Compiler and IDE==
==Compiler and IDE==
Line 10: Line 9:
Microchip's IDE, MPLAB, is also available for free at Microchip's website.
Microchip's IDE, MPLAB, is also available for free at Microchip's website.


==Programming the PIC==
==Connecting the Programmer==
[[media:Using_ICD2_Poster.pdf|Connecting the ICD2 Programmer]]
===Setting Up===
For this project, Microchip's free MPLAB IDE and free C compiler were used to program the PIC18F4431. '''If you are using the ICD2 programmer, be sure to follow the installation instructions carefully, or Windows may attempt to install the wrong drivers.''' After installing both MPLAB and C18, create a new project with the project wizard. Follow the prompts, and you should end up with an empty project if you did not add any existing files.


==Writing the Code==
We must now add a linker script to your project. Make sure '''View>Project''' is checked, then right-click on '''Linker Scripts''' in the project panel and click on '''Add Files...'''. The linker scripts are in folder '''MCC18\lkr'''. Find the file that corresponds to your microcontroller (<tt>p18f4431.h</tt> (or <tt>p18f4431i.h</tt> if you are using the ICD2 programmer) for the PIC18F4431 microcontroller).
[[Writing Code with the C18 Compiler]]


==Example Projects==
We now add source and header files in the same manner. To make a new source or header file, go to '''File>New''', and then save the file as a <tt>.c</tt> or <tt>.h</tt> file. With the default settings, all the source and header files that you write must be in the same folder or MPLAB will give you an error message stating that it cannot find the files. You can change the environment variables by going to '''Project>Build Options...>Project.
[[PIC Analog-Digital-Converter Example]]


[[PIC Motor Control and Serial Port Example]]
===Reading and Writing to Registers===
The I/O ports and hardware peripherals on the PIC are controlled by SFRs, or special function registers. The values in these registers determines the behavior of the hardware. For example, Port B is an 8 channel digital I/O port that has corresponding SFRs TRISB, PORTB, and LATB (TRISB stands for Tri-State B, PORTB stands for Port B, and LATB stands for Latch B). Each of these registers is eight bits long, and each bit corresponds to a certain pin (channel) on the PIC. In this case, the least significat bit of the register affects pin RB0, and the most significant bit affects pin RB7. To write values to SFRs, we simply treat them like a global variable. Individual bits can usually be accessed by using the convention '''[SFR_name]bits.[bit_name]''', for example, '''PORTBbits.RB0'''. The names of the SFRs and bits can be found in the datasheet and the header file for the PIC (e.g. <tt>p18f4431.h</tt>).


[[PIC Motor Control with EEPROM and Interactive Menu Example]]
TRISB determines whether the pins on Port B are configured as inputs or outputs. If we wanted RB0, RB1, and RB5 to be inputs and the rest to be outputs, we would write:
<pre>
TRISB=0b00100011; //a "0b" prefix denotes that the following is a binary number
</pre>
Of course, we could have used a hexademical or decimal number instead.


For more examples, see the C18 User's Guide and the application notes on Microchip's website.
If we then wanted to set all the output ports high, we could write:
<pre>
LATB=0b11111111;
</pre>
LATB will not affect the pins designated as inputs.


==Tips and Troubleshooting==
If we wanted to read the state of pin RB0 and store the result into a variable named <tt>RB0_Status</tt>, then we would write:
[[PIC/C18 Compiler Tips and Troubleshooting]]
<pre>
RB0_Status=PORTBbits.RB0;
</pre>


==Documents==
Notice that when we read an input, we used PORTB, and when we wrote to an output, we used LATB. LATB will give us the values that we ''want'' the output pins to be, while PORTB will give us the actual state of the pin. Writing to PORTB will usually do the same thing, but could also lead to a [http://www.piclist.com/techref/readmodwrite.htm| Read-Modify-Write problem] that could distort the states of the pins.
===MPLAB and C18 Compiler===
[[media:MPLAB_GS.pdf | MPLAB Quick Start Guide]]


[[media:MPLAB_UG.pdf | MPLAB User's Guide]]
===Timers and Counters===
PICs generally have several timers or counters, each with different capabilities. For the 18F4431, Timer0, Timer1, and Timer5 can be used as counters as well as timers, while Timer2 can only be used as a timer. The difference between using a Timer in timer mode or counter mode is simply the source of the pulses &mdash; a timer runs off the system clock, while a counter increments when it sees a rising/falling edge on a certain pin. Timers on the PIC can only count up. Timer2 and Timer5 can generate interrupts on a period match, so are particularly suitable for implementing a real-time operating system. Read the datasheet for a detailed explanation for the operation of these timers. In the datasheet, '''FOSC/4''' refers to the frequency of the system oscillator divided by four.
====Pre/Post-Scalers====
Since a microcontroller can count from 0 to 65535 (sixteen bits) quite quickly, prescalers and postscalers can be used to slow down the timer or counter. A 1:8 prescaler will emit one pulse for every eight pulses it receives. In essence, the scaler will decrease the frequency of the timer or counter by some factor.


[[media:Microchip_C18_GS.pdf | C18 Compiler Getting Started]]
====Reading and Writing 16-bit registers====
The registers that hold the value of the 16-bit timers are split up into two 8-bit registers (e.g. TMR0H and TMR0L). TMR0H is not the actual counter register, but a buffer. Each time TMR0L is read, TMR0H is updated with the contents of the actual high byte of the timer register. Therefore, you must read TMR0L before you read TMR0H. This method prevents you from reading an erroneous vale due to an overflow or rollover in TMR0H while you are reading TMR0L.


[[media:Microchip_C18_UG.pdf | C18 Compiler User's Guide]]
When writing to a 16-bit register, you must write the high byte first, and both bytes will be loaded into the register simultaneously when you write the low byte.


[[media:Microchip_C18_libraries.pdf | C18 Compiler Libraries]]
(A full explanation can be found in Section 11.4 of the datahseet.)


===PWM===
===PIC18===
[[media:PIC18_config_settings.pdf | PIC18 Configuration Settings Addendum]]
(Beware that equations 17.1, 17.2, and 17.3 in the datasheet are '''wrong'''. See the errata for the correct equations.)


===PIC18F4431===
The PIC18F4431 has four Power Control PWM modules, as well as two CCP (Capture/Compare/PWM modules). This section will discuss the Power Control PWM modules (see section 17 in the datasheet). These PWM modules have the same frequency, but each can have its own duty cycle. The core of the PWM module is a 12-bit timer, whose count is kept by the eight bits of SFR PTMRL and the four LSBs of PTMRH. This timer will increment once every four clock cycles if the prescale is 1:1 (prescaling is determined by bits 3-2 of PTCON0). Another 12-bit SFR, PTPER (which is split into PTPERH and PTPERL), determines the period of the PWM. Each time PTMER reaches the same value as PTPER, it will reset to zero and start counting again if you used the default free-running count mode. (You can also make it start counting downwards; if you use the up-down counting mode; see the datasheet for more information on this.) PTMR and PTPER is shared all four PWM modules.

Each of the four PWM modules has a 14-bit register PDC (PDC0L and PDC0H for PWM module 0) which specifies the duty cycles for that module. The output of the PWM module is set high when PTMR is less than ''the most significant 12 bits of PDC'', and the output is set low when PTMR is greater than ''the most significant 12 bits of PDC'' but less than PTPER. When PTMR is equal to PTPER, PTMR is reset to zero and the PWM module's output is set high again. For example, if ''the most significant 12 bits of PDC'' is equal to 50 and PTPER is equal to 80, the PWM module's output will be high while PTMR is less than 50, and will be set low when PTMR is equal to 50. Once PTMR reaches 80, it will be reset to zero and the output is set high again. When the prescaler is 1:1, then the 2 least significant bits of PDC come into play. These two bits give you another two bits of resolution by allowing you to specify which of the four clock cycles you want the output to go low on (remember, PTMR only increments every ''four'' clock cycles). Using the same numbers as in the previous example, the last two bits essentially let you set PDC to be 50.0, 50.25, 50.5, or 50.75. If the prescaler is not 1:1, then these two bits are ignored.

===Tips===
====If MPLAB Has Trouble Connecting to the ICD2====
If MPLAB has trouble connecting with the ICD2, open the Device Manager ('''Control panel>System>Hardware>Device Manager''') and disable then re-enable the ICD2. Also, be sure that you followed in installation instructions in the manual when you installed the ICD2.

====Splitting Multi-Byte Data Types into Individual Bytes====
There are some situations where you may need to split a multi-byte variable into its component bytes (for example, writing to 16-bit registers or sending data through the serial port). One way to do this is to use the '''<tt>union</tt>''' data type. A <tt>union</tt> is like a <tt>struct</tt>, except all the members share the same location in memory. Therefore, if have a union with one <tt>int</tt> variable and an array of two <tt>char</tt> variables, writing to the <tt>int</tt> variable will automatically fill in the <tt>char</tt> as well.

Example:
<pre>
union UINT_UCHAR{
unsigned int intVal;
unsigned char charVal[2];
};
</pre>

In the memory, it looks like this:

[[Image:PIC_C18_union.gif]

(MSB=Most Significant Byte, LSB=Lease Significant Byte)

==Documents==
[[media:PIC18F4431_datasheet.pdf | PIC18F4431 Datasheet]]
[[media:PIC18F4431_datasheet.pdf | PIC18F4431 Datasheet]]


[[media:PIC18F4431_errata.pdf | PIC18F4431 Errata]]
[[media:PIC18F4431_errata.pdf | PIC18F4431 Errata]]

[[media:PIC18F4431_config_settings.pdf | PIC18F4431 Configuration Settings]]

Latest revision as of 15:23, 11 October 2007


Compiler and IDE

The C18 compiler is a C-language compiler for the Microchip PIC18 family of microcontrollers. The student version of this compiler is available for free at Microchip's website. The difference between the student version and the commercial version is the level of optimization available. For most purposes, the student version should suffice.

Be aware that there are some differences between Microchip's C18 compiler and C compilers for other platforms. For example, an int data type in C18 is 16 bits, instead of the usual 32 bits. Refer to the C18 user guide for more information.

Microchip's IDE, MPLAB, is also available for free at Microchip's website.

Connecting the Programmer

Connecting the ICD2 Programmer

Writing the Code

Writing Code with the C18 Compiler

Example Projects

PIC Analog-Digital-Converter Example

PIC Motor Control and Serial Port Example

PIC Motor Control with EEPROM and Interactive Menu Example

For more examples, see the C18 User's Guide and the application notes on Microchip's website.

Tips and Troubleshooting

PIC/C18 Compiler Tips and Troubleshooting

Documents

MPLAB and C18 Compiler

MPLAB Quick Start Guide

MPLAB User's Guide

C18 Compiler Getting Started

C18 Compiler User's Guide

C18 Compiler Libraries

PIC18

PIC18 Configuration Settings Addendum

PIC18F4431

PIC18F4431 Datasheet

PIC18F4431 Errata