Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 34

RTS Laboratory 2

Getting to grips with devices, data sheets and


graphics (as an example of a device library)

Todays material
Looking at PICs (in general)
Getting a working system

What does a pic look like

PICs (you will remember) range in cost, size,


speed and complexity
You pick the chip best suited to the task in hand
Once you have decided on your device the
practical work can begin
It may be that you start with a development board
And then move to a bespoke board

Or design the board based on your analysis of the


task it will be addressing

Some examples of PICs


8 pins - PIC12(L)F1571/2
Note:

Some pins have multiple labels

To slightly(!) more complex


ones

However

There will always be a few common things


Power (Vdd and Vss)
Input/Ouput ports
As the chips get bigger you get more
Different chips will have different devices integrated
into them
It is up to you, the programmer, to specify what you
need the pins to do

A reset MCLR
You may sacrifice this is the pin doubles up for a
function you require more

We can have circuits as simple


as

http://circuit-zone.com/ediy_blog/190/PIC12F675_Flashing_Blinking_LED.jpg

Your PIC board

Your board is a little more complex with a


number of peripherals built on the PCB

Tri-axial Analogue Accelerometer


Speaker
OLED Display (127x64 pixels)
ADC

To make use of these we need to do/know a


few things
Know what is connected to PINs on the chip
Configure the integrated device(s) / pins

Investigating your board

When working with development boards


such as the ones you have it is a good idea
to look at the schematics for the kit
This will allow us to see what is built in
How things are connected

You can find the schematics in the users


guide (on moodle)
Let us take a look at them and explain how they
describe the board

The overview

The Peripherals

These are links back


to the processor

The audio

And one more the


switches

Useful as we will be writing code to monitor them!

Note the names on the


chip RC2 & RA8
On the switches note
the line over the name
-> negative logic

But how do we use them?

Consider the switches, they are linked to


RC2 (Switch_S1) and RA8 (Switch_S2)

But what are RA8 and RC2?


They are Pins of Ports

But what is a port?


A port is a connection between the chip and the
outside world
It is to this that we connect devices or signals (if the pin
is say an ADC)

The most basic are simple digital ports that we can


Set the direction of (Input or Output)
Set or read the value on a port

How do we so do this?
The first task is to indicate how the pin is to
work (will it be an input or an output_
This is done using the TRIS (Tristate)
register for the port

Each port has its own one, TRISA, TRISB (for as


many/few ports as there are)
To specify a pin on the port is to be in INPUT we use a
1 (one)
For the pin to be an output we use 0 (zero)

This is best done by


example

Consider we have PORTA (an 8 bit port) and


we wish
RA0,1,2 to be an input
All other pins (RA1-RA7) to be output

We create a the binary representation as


RA7

RA6

RA5

RA4

RA3

RA2

RA1

RA0

128

64

32

16

So in binary we need to set the TRISA as


0b00000111 or 0x07 or 7

If using assembler (we are


not!)

One would set the register as


movlw
movwf

b0000111
TRISA

Note:
We would not need to define TRISA as the
selection of device would provide this to the
compiler

The good news


We are not using assembler!

So how do I do this in C

The xc16 compiler knows about the


various devices and pins on the chip via the
header file you include (the
device_number.h)
Feel free to look at this file BUT CHANGE
NOTHING!

This means that in C we can simply set the


register, by name, to a value e.g.
TRISA = 0x07;
TRISA = 0b0000111;

Once configured writing


out
We can make use of the port!
The (basic) ports act like memory

A value we write to them latches until we


change it
We see the value presented across the (input)
pins as a value

So, if we had set


TRISA = 0b00000000;

// All output

Then
PORTA = 0b10101010;
Latches alternate pins at 5v, 0v, 5v etc. (if
Vdd=5v)

Reading in
We can read the value across the pins and store this in
a suitable variable
So, if we had set

TRISA = 0b11111111; // All Input (binary notation)


TRISA = 0xff; // All Input (hex notation)
TRISA = 255; // All Input (decimal notation)

Then
Connect 5v (Vdd) to pins RA0,1,2,3

We would see this across the port as


00001111

So if we had (assuming VonA is an integer)


VonA = PORTA;
Then VonA would (if displayed) contain 15

But what about individual


pins?

If we wanted to (say) read only one pin we


could
Read the value on the port
Mask out the other bits (use an AND)
Look at the result

To change the output state of one pin


Read the value on the port
OR the relevant pin (turn on)
AND the relevant pin (turn off)

There is an easier way!

The pins too have names and we can access these


_TRISA8 = Tristate for pin 8 of port A
_RA0 = Pin 0 of Port A
_RA1 = Pin 1 of Port A

So to set a pin we just use


_RA3 = 1;
_RA3 = 0;

// Turn it on
// Turn it off

To read a single pin


A_Pin1 = RA1

// Assumes A_Pin1 is defined!

Note
The above are defined in code for ease of use (see below)
#define _TRISA0 TRISAbits.TRISA0
#define _RA0
PORTAbits.RA0

But what are these?

A reminder from C

You will remember we had structures


struct DataStuct
{
int a;
int b;
int c;
int d;
};
int main(void)
{
struct DataStuct DS;
DS.a = 1;
DS.b = 2;
return 0;
}

In this example we have four


separate variables within the
structure

The total size of the structure


is that of four integers.

An integer is (on a PC) 4 bytes


so 16 bytes in total

A new bit of C

Bitfield structures: we define variable sizes


in terms of bits (integer types ONLY)
struct DataStuct
{
int a:1; // 1 bit (0 or 1)
int b:2; // 2 bits (0,1,2,3)
int c:3; // 3 bits (0 to 7)
int d:2; // 2 bits (0,1,2,3)
};
int main(void)
{
struct DataStuct DS;
DS.a = 1;
DS.b = 2;
return 0;
}

In this example we have four


separate variables, all integers which
we can use as required

The USED size of each (and so range)


is defined by the number of BITS

In this example the TOTAL used size


is 1+2+3+2 = 8 bits = 1 Byte

It will take on the size of an integer as


this is base unit

We could use a CHAR

Bitfield structures: we define variable sizes


in terms of bits (integer types ONLY)
struct DataStuct
{
char a:1; // 1 bit (0 or 1)
char b:2; // 2 bits (0,1,2,3)
char c:3; // 3 bits (0 to 7)
char d:2; // 2 bits (0,1,2,3)
};
int main(void)
{
struct DataStuct DS;
DS.a = 1;
DS.b = 2;
return 0;
}

In this example we have four


separate variables, all CHARs which
we can use as required

The USED size of each (and so range)


is defined by the number of BITS

In this example the TOTAL used size


is
1+2+3+2 = 8 bits = 1 Byte = 1 char

It will take on the SAME size of an


char as this is base unit

UNIONS
union DataUnion
{
int a,b;
float c,d;
};

This is a technique in C
where we allow variables to
SHARE memory

int main(void)
{
union DataUnion DU;
DU.a = 1;
printf ("\nDU.a = %d ", DU.a);
printf ("\nDU.b = %d ", DU.b);
DU.b = 2;
printf ("\nDU.a = %d ", DU.a);
printf ("\nDU.b = %d ", DU.b);
return 0;
}

In this example we have


defined four separate
variables
The address of each is
however the SAME!

I.e. &a == &b == &c == &d

We change one, we affect


the others

UNIONS in action
union DataUnion
{
int a,b;
float c,d;
};
int main(void)
{
union DataUnion DU;
DU.a = 1;
printf ("\nDU.a = %d ",
printf ("\nDU.b = %d ",
DU.b = 2;
printf ("\nDU.a = %d ",
printf ("\nDU.b = %d ",
return 0;
}

DU.a);
DU.b);
DU.a);
DU.b);

Output (PC)

Why is he telling us this?


As you will remember, we control PICs (and
such devices) by setting register values.
A register may control a number of related
parameters, each perhaps needing a
different number of bits
The header for the chip defines each of
these using the same name
We then set these values as required

BUT: This was we need to set everything in one go

Consider

To set this we might use


T1CON = 0b101000001100110;
T1CON = 0x5066;
T1CON = 20582;
To change a bit, we need to know the current state and
then modify as required (using OR and XOR to set/clear
bits)

The Clever trick


We create a BITFIELD structure that
describes the register
We UNION this over the register address

The header file defines the name for us


struct {
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
};

:1;
TCS:1;
TSYNC:1;
:1;
TCKPS:2;
TGATE:1;
:6;
TSIDL:1;
:1;
TON:1;

We can then
Set the whole register in one
go
T1CON = 0x5066;

Set UNDIVIDUAL items as


required
T1CONbits.TCPKS = 3;
T1CONbits.TON = 0;
T1CONbits.TON = 1;

For more complex devices

As well as basic IO ports, PICs have many


other (often complex) devices
Timers
PWM modules
UARTS

All of which we configure through the use of


registers
Using the method detailed today!

And will talk more about next week!

For very complex things


We are often given pre-written code that provides us
with a number of functions we then make use of
Microchip provide a large number of such libraries

One such is the graphics library and it is that you will be


using this week

While it looks complicated if you read the user


guides on Moodle in conjunction with the sample
code provided you will soon get to grips with it
Enabling you to modify things and so make your own
applciation.

The sample code


This code has a number of samples showing
how the graphics functions are called
It includes

Displaying text on the screen


Some simple shapes
Show how the slider can be used

Your tasks
Are to use these to display information on the
screen (numbers)
To build a little egg timer

Next week (lecture & labs)

We dig deeper
Look how the CheckSwitchS1/2 functions work
Consider techniques including
Polling
Interrupts
Timers

And (alas)
I have to let you use global variables
But in a very controlled manner!

You might also like