0% found this document useful (0 votes)
48 views13 pages

Tailieuxanh Nigel Pic Tutorial Hardware 10 5422

Uploaded by

Nguyen HA
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
48 views13 pages

Tailieuxanh Nigel Pic Tutorial Hardware 10 5422

Uploaded by

Nguyen HA
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

value written as the 'Slave Address' for the chip.

Each chip on the bus must have a unique


address or problems are going to occur.

Although it's labelled as connecting to PortB, as with most of the boards, it can also be
connected to PortA if required.

This is the top view of the I2C EEPROM Board, it has 7 wire links.

The bottom of the I2C EEPROM Board, there are 7 track cuts, please note
that there are only 3 between the I/C pins, one isn't cut as it's used to ground
the WP pin.

These tutorials require the Main Board, the LCD Board, and various of the I2C Boards, as
written the tutorials use the LCD Board on PortA and the I2C Boards on PortB - although these
could easily be swapped over, as the I2C Boards don't use either of the two 'difficult' pins for
PortA, pins 4 and 5, as outputs. Download zipped tutorial files.

As with the LCD Tutorial, the idea is to implement a reusable set of I2C routines.

Rather than showing the routines on the page as with earlier tutorials (they are getting quite
lengthy now), I'm only going to store them in the pages download ZIP file so you will need to
download them. As the I2C tutorials use a number of different boards, each section is headed by
the I2C boards required in bold type.

I2C is a protocol designed by Philips Semiconductors, and is for communications between


I/C's over a two wire synchronous serial bus, devices are classed as either 'Master' or 'Slave', for
our purposes the Main Board processor is the 'Master', and any other devices are 'Slaves'. The
initial tutorials use a 24C04, a 512 byte EEPROM memory chip, commonly used for storing the
settings in modern TV's and VCR's, where they are used to store all the customer settings
(tuning, volume, brightness etc.) and the internal calibration values for the set, which are
normally accessed through a special 'service mode'. These chips provide non-volatile memory as
a series of 256 byte 'pages', so the 24C04 provides two 'pages' giving 512 bytes of memory. The
24C02 uses 'standard addressing', which gives the 256 byte page limit, other larger chips use
'extended addressing', giving a possible 16 bit address space, I've used a 24C256 which uses a 15
bit address space, giving 32,768 of memory space. To address these you require two bytes of
address data, the programs already include these (but commented out), I've uncommented them
for copies of the first two tutorials and called them 6_1a and 6_2a, if you want to use an
EEPROM larger than a 24C16 you will need to use these extended addressing versions.

I2C EEPROM Board


The first tutorial writes sequential numbers through one entire page of memory, and then
reads them back, 4 bytes at a time, displaying them on the LCD, separated by about half a
second between updates. The second tutorial demonstrates 'sequential writing', the first tutorial
uses 'byte writing' (which is why it displays 'Writing..' for a couple of seconds) - a write is fairly
slow to EEPROM, taking around 10mS to complete - 'sequential writing' allows you to store a
number of bytes in RAM inside the EEPROM chip (a maximum of 8 for the 24C04) and then
write them all to EEPROM with a single write delay. Tutorial 2 writes 4 bytes at once, to
demonstrate how this is done. The third tutorial is simply a cut-down version of the first, I've
included it as a useful tool, it simply reads one page of the EEPROM and displays it as tutorial 1
does - useful for checking the contents of an EEPROM. You can deal with the EEPROM write
delay in a couple of ways, firstly you can introduce a software delay, and this option is included
in the tutorials (but commented out), or you can keep checking until the chip is ready, this is the
method I've used in these tutorials, although if you want you can comment that line out and un-
comment the 'call delay10' line instead.

PIC Tutorial - I2C A2D Board

I2C A2D Board

This is the I2C A2D (Analogue to Digital converter) Board, it uses a Philips PCF8591P, which
is an I2C chip providing 4 analogue inputs, and 1 analogue output, all having 8 bit resolution.
There are actually very few support components required, I've chosen to use an external 2.5V
precision voltage reference, which feeds in at pin 14, but this could be simply connected to the
5V rail - though it would be less accurate. By using the 2.5V reference we set the range of the
conversion from 0-2.5V, however this can easily be scaled by feeding from a suitable attenuator.
Notice the circuit also shows an EEPROM, the idea being to give the option of storing samples
in it's non-volatile memory, and I'll be using a 24C256 to give 32,768 bytes of storage. Notice
both chips connect to the same port pins via the I2C bus - by having different chip addresses we
can address either one independently.

Although it's labelled as connecting to PortB, as with most of the boards, it can also be
connected to PortA if required.

This is the top view of the I2C A2D Board, there are 23 wire links.

The bottom of the I2C A2D Board, there are 26 track cuts.
PIC Tutorial - I2C Clock Board

I2C Clock Board

This is the I2C Clock Board, it uses a PCF8583P, which is a real time, battery backed,
CMOS I2C clock chip in an 8 pin DIL package. The actual chip I'm using here (as shown in the
picture) is labelled 'Intersil 7313', and came from a Grundig VS920 video recorder, but it's pin
compatible with the original Philips chip (which is what's actually listed on the circuit). Notice
that this chip only has one address line, so can only be mapped as either page 0, or page 1.

The circuit is very similar to the previous I2C EEPROM board, with a few additions, a
32KHz clock crystal and trimmer (using two of the previous address lines), an extra alarm
output complete with 12K pull-up resistor (connected to RB4), and components for the battery
backup circuit (D1 and D2 are isolating diodes). When the board is powered up the chip is
supplied with 5V through D1 (which drops 0.7V leaving 4.3V on the chip), D2 is reverse biased
and passes no current. When the board isn't powered, D2 passes current from the battery (only
around 2uA, giving a long battery life) to the chip, and D1 is reverse biased, isolated the rest of
the circuit. The 3V battery shown is a lithium disk type, and usually lasts around 5 years in the
Grundig VCR's that use this same chip. The trimmer is for setting the accuracy of the clock, and
if accurately adjusted should keep good time.

Although it's labelled as connecting to PortB, as with most of the boards, it can also be
connected to PortA if required.
This is the top view of the I2C Clock Board, it has 7 wire links.

The bottom of the I2C Clock Board, there are 13 track cuts.

I2C Clock Board, and I2C Switch Board


Now we move onto the I2C Clock board, basically we use exactly the same I2C routines, the
only difference being in the way we manipulate the data, we need to read the clock registers
from the chip (using a sequential read), apply a little processing, and then display them on the
LCD. Actually setting the clock is somewhat more complicated, and the biggest difference is the
routines for reading the switch board, and setting the clock chip values - which are then written
back to the chip with a sequential write. The four buttons used are (from left to right), 'Set', 'Up',
'Down', and 'Next' - in the initial display mode the only button which has an effect is the 'Set'
button, this jumps to the 'Clock Set' mode, and starts a flashing cursor on the tens of hours. From
this point all four buttons work, pressing 'Set' again will return to display mode, updating the
clock values (and zeroing the seconds). Pressing 'Up' will increase the value under the cursor,
and 'Down' will decrease the value, with '0' being the lower limit, and '9' being the upper one - I
don't currently take account of the different maximum values for particular digits (i.e. tens of
hours doesn't go higher than 2), but rely on setting them sensibly. The 'Next' button moves on to
the next digit, and if pressed while on the last digit (years units) will return to display mode, just
like pressing the 'Set' button. I also don't currently take any account of the correct years, the
PCF8583 only provides 0-3 for the years, with 0 being a leap year - extra software routines will
be required to do this, with the actual values stored in spare PCF8583 EEPROM memory, and
updated when the year changes (remembering that the year might change while the processor is
powered down, and the clock is running on it's back-up battery).
I2C A2D Board, and I2C Switch Board
Again, the A2D board uses the same basic I2C routines as before (but with a different chip
address for the PCF8591) as with the I2C Clock Board the differences come in the manipulation
of the data. As the board also includes an EEPROM socket this can be used to store samples
from the A2D chip - with a single 24C256 we can store up to 32,768 eight bit samples - this
introduces a slight 'snag', the 24C256 uses 'extended addressing', while the PCF8591 only uses
'standard addressing', however we can still use the same I2C routines by using a flag to tell the
routines which addressing mode to use, simply switching the flag for the different chips - this
flag switching becomes part of the reusable I2C routines.
PIC Tutorial Seven - RS232

RS232 Board

This is the RS232 board, it uses a MAX232 5V to RS232 converter chip, this converts the 0-
5V TTL levels at the PIC pins to the +12V/-12V levels used in RS232 links. As is common with
these devices it inverts the data during the conversion, the PIC USART hardware is designed to
take account of this - but for software serial communications you need to make sure that you
invert both the incoming and outgoing data bits.

The two closed links on the RC7 and RC6 lines are for connection to the 16F876 board (the
16F876 uses RC6 and RC7 for it's USART connection), and are the two top wire links shown on
the top view of the board below. The two open links on the RC1 and RC2 lines are for the
16F628 board (the 16F628 uses RB1 and RB2 for it's USART connection), and are the two top
track breaks shown on the bottom view of the board below.

So, for use with the 16F876 board fit the top two wire links, and cut the top two tracks
shown, for the 16F628 leave the top two links out, and don't cut the two top track breaks. This
only applies if you are using the hardware USART, for software serial communications you can
use any pins you like.

Although it's labelled as connecting to PortC for the 16F876 processor board (and is also
designed to connect to PortB for the 16F628 processor board), as with most of the boards, it can
also be connected to other ports if required, and if not using the hardware USART.
This is the top view of the RS232 Board, there are five wire links, the
three veropins at the bottom right are the connections to the 9 pin D socket.
As it's not too clear, pin one of the chip is at the left hand side of the board.

The bottom of the RS232 Board, it has fifteen track breaks, marked with
blue circles (as usual).

For these tutorials you require the Main Board, Main Board 2, LCD Board, Serial Board,
LED Board and switch board. Download zipped tutorial files, a number of examples for the
16F876 based Main Board 2 are provided, these have an 'a' at the end of the filename - the rest
are left for the user to convert as an exercise.

RS232 is an asynchronous serial communications protocol, widely used on computers.


Asynchronous means it doesn't have any separate synchronising clock signal, so it has to
synchronise itself to the incoming data - it does this by the use of 'START' and 'STOP' pulses.
The signal itself is slightly unusual for computers, as rather than the normal 0V to 5V range, it
uses +12V to -12V - this is done to improve reliability, and greatly increases the available range
it can work over - it isn't necessary to provide this exact voltage swing, and you can actually use
the PIC's 0V to 5V voltage swing with a couple of resistors to make a simple RS232 interface
which will usually work well, but isn't guaranteed to work with all serial ports. For this reason
I've designed the Serial Board to use the MAX232 chip, this is a chip specially designed to
interface between 5V logic levels and the +12V/-12V of RS232 - it generates the +12V/-12V
internally using capacitor charge pumps, and includes four converters, two transmit and two
receive, the Serial Board only makes use of one of each - the other two are clearly marked on the
circuit, and can be used for something else if required.

There are various data types and speeds used for RS232, I'm going to concentrate on the most
common type in use, known as 8N1 - the 8 signifies '8 Data Bits', the N signifies 'No Parity' (can
also be E 'Even Parity' or O 'Odd Parity'), the final 1 signifies '1 Stop Bit'. The total data sent
consists of 1 start bit, 8 data bits, and 1 stop bit - giving a total of 10 bits. For the speed, I'm
going to concentrate on 9600BPS (Bits Per Second), as each byte sent has 10 bits this means we
can transfer a maximum of 960 bytes of data per second - this is fairly fast, but pretty easy to do
in software, it's easily modified if you need faster or slower speeds, all you need to do is alter
the delay timings - but I find 9600BPS is a pretty good speed to use.

We now know that we will be sending or receiving 960 ten bit data bytes per second, from
that it's simple to calculate how long each bit is - simply divide 1 second by 9600 - this gives
104uS per bit. This value is crucial to successful RS232 communication, it doesn't have to be
exact as the stop pulse allows resynchronisation after each data byte, but it must be accurate
enough to maintain reading in the correct bit throughout each byte. The data is sent low bit first,
so the example in the diagrams below is sending '01001011 Binary', '4B Hex', '75 Decimal'.

OK, now we know all the details of the protocol we are using, I'll explain how we transmit a
byte:

1. The RS232 signal needs to be in the 'STOP CONDITION', at -12V, as the MAX232
inverts (a '1' is -12V and a '0' +12V) we need to make sure the PIC output pin is set
HIGH, this should be done in the initialisation section of the program - this pin should
always be high, EXCEPT when we are sending data, when it can be either high or low.
2. The RS232 line is now happily sat at -12V, and the receiving device is waiting for a
'START BIT', to generate this all we need to do is set the PIC output pin low, the
MAX232 inverts the signal and takes the RS232 line up to +12V. As we know that all
bits should be 104uS long we now delay 104uS, before we do anything else.
3. Now we can transmit the 8 data bytes, starting with the low bit, after each bit is set on the
output pin we again wait 104uS, so each bit is the correct length.
4. That only leaves the 'STOP BIT', for this we set the PIC output pin HIGH (as in section 1
above), and wait 104uS to give the correct bit length - now the 'STOP BIT' doesn't have
to be only 104uS long, it simply signifies the end of the data byte. If it is the last data
byte it could be a considerable time before another 'START BIT' is sent - this is shown in
the diagrams by the large gap between the end of the 'STOP BIT' (shown by the dotted
line) and the next 'START BIT'. If you are sending data as fast as possible the next
'START BIT' will start on that dotted line, immediately after the 104uS 'STOP BIT'.

This is an example of a
signal on an RS232 line,
initially it sits at -12V, known
as the 'STOP CONDITION',
this condition lasts until a
signal is sent. To send a signal
we first need to let the
receiving device know we are
starting to send data, to do this
we set the line to +12V, this is
called the 'START BIT' - the
receiving device is waiting for
this to happen, once it does it
then gets ready to read the next
9 bits of data (eight data bits
and one stop bit).
This is the identical signal
as it leaves (or enters) the PIC
pin, as the MAX232 inverts the
signal this looks to be inverted,
but is actually the correct way
up - RS232 logic levels are
inverted compared to normal
levels.
To receive a data byte is pretty straightforward as well:

1. Test the PIC input pin, and loop until it goes low, signifying the beginning of the
'START BIT'.
2. Now we wait just half a bit time (52uS) and check again to make sure it's still low - this
52uS delay means we are reading the 'START BIT' pretty well in the centre of the pulse,
where it should be the most reliable.
3. Following a successful 'START BIT' we can now read the data bits, as we are currently
in the centre of the 'START BIT' we can simply wait 104uS, which will take us to the
centre of the first data bit, then read the input pin again, remembering to invert the
polarity of the bit. We then read the next seven bits in the same way, waiting 104uS
before each one.
4. Lastly we need to account for the 'STOP BIT', again we wait 104uS for the centre of the
bit and could read the port pin if we wanted, if it isn't high there has obviously been an
error, but for simplicity we just exit the routine.
5. We now can transfer the received byte to where we wish, and either wait for another byte
or do something else.

Here are the actual serial routines we will be using, they consist of a number of small
subroutines, and require four data registers allocating:

• Xmit_Byte - this is used to store the transmitted byte (passed in W).


• Rcv_Byte - this is used for the received byte, and is copied to W on exiting the routine.
• Bit_Cntr - used to count the number of bits sent or received, set to 8 and decremented.
• Delay_Count - used in the two delay routines.

The routines themselves consist of three subroutines that are called, and two internal
subroutines, not normally called from elsewhere:

• SER_INIT - this is only ever called once, usually when the program first runs, as part of
the normal initialisation stages, it sets the input and output pins to the correct direction,
and sets the output pin to the correct polarity - high, so the RS232 line sets at -12V.
• XMIT_RS232 - this is the transmit routine, simply load the byte to be transmitted into
the W register and call this subroutine (CALL XMIT_RS232).
• Rcv_RS232 - this is the receive routine, when you call this is waits for a received byte,
there's no timeout, so it will wait for ever if it doesn't receive a byte. To use the
subroutine simply call it (CALL Rcv_RS232) and it returns the received byte in the W
register.
• Start_Delay - internal subroutine that delays 52uS, used by the Rcv_RS232 subroutine
to delay half a bit length.
• Bit_Delay - used by both the transmit and receive subroutines, to provide a 104uS (one
bit) delay.

;Serial routines
Xmit_Byte Equ 0x20 ;holds byte to xmit
Rcv_Byte Equ 0x21 ;holds received byte
Bit_Cntr Equ 0x22 ;bit counter for RS232
Delay_Count Equ 0x23 ;delay loop counter
SER_INIT
BSF STATUS, RP0 ;select bank 1
BCF TRISB, 6 ;set B6 as an output
BSF TRISB, 7 ;set B7 as an input
BCF STATUS, RP0 ;select bank 0
BSF PORTB, 6 ;set B6 high
RETURN

XMIT_RS232 MOVWF Xmit_Byte ;move W to Xmit_Byte


MOVLW 0x08 ;set 8 bits out
MOVWF Bit_Cntr
BCF PORTB, 6
CALL Bit_Delay
Ser_Loop RRF Xmit_Byte , f ;send one bit
BTFSS STATUS , C
BCF PORTB, 6
BTFSC STATUS , C
BSF PORTB, 6
CALL Bit_Delay
DECFSZ Bit_Cntr , f ;test if all done
GOTO Ser_Loop
BSF PORTB, 6
CALL Bit_Delay
RETURN

Rcv_RS232 BTFSC PORTB, 7 ;wait for start bit


GOTO Rcv_RS232
CALL Start_Delay ;do half bit time delay
BTFSC PORTB, 7 ;check still in start bit
GOTO Rcv_RS232
MOVLW 0x08 ;set up to read 8 bits
MOVWF Bit_Cntr
CLRF Rcv_Byte
Next_RcvBit CALL Bit_Delay
BTFSS PORTB, 7
BCF STATUS , C
BTFSC PORTB, 7
BSF STATUS , C
RRF Rcv_Byte , f
DECFSZ Bit_Cntr , f ;test if all done
GOTO Next_RcvBit
CALL Bit_Delay
MOVF Rcv_Byte, W
RETURN

Start_Delay MOVLW 0x0C


MOVWF Delay_Count
Start_Wait NOP
DECFSZ Delay_Count , f
GOTO Start_Wait
RETURN

Bit_Delay MOVLW 0x18


MOVWF Delay_Count
Bit_Wait NOP
DECFSZ Delay_Count , f
GOTO Bit_Wait
RETURN

The routines presented here use PortB pin 6 as the output, and PortB pin 7 as the input, they
are based on a 4MHz clock frequency. As it's all done in software you can easily change the port
and pin designations, and simply alter the delay timings for different clock speeds or baud rates.
Tutorial 7.1 - required hardware, Main Board and Serial Board.

This first sample program simply transmits a few ASCII characters out of the serial board, it
displays 'RS232'. In this example each character is individually loaded in to the W register and
the XMIT_RS232 subroutine is called.

Tutorial 7.2 - required hardware, Main Board and Serial Board.

This second sample program transmits two lines of text, the text is stored as a string
(terminated by '0x00') in the top page of memory, the two characters '0x0A' and '0x0D' in the
string are LF and CR to move the cursor to the start of the next line. The XMIT_RS232
subroutine is called repeatedly in the loop which reads the string.

Tutorial 7.3 - required hardware, Main Board, LCD Board and Serial Board.

This third sample program receives data one character at a time and displays it on the LCD
module. Please note that both this, and the next tutorial, can only handle one character at a time -
as there's no handshaking involved the routine on the PIC must finish whatever it has to before
the next character arrives - if a continuous stream of data is incoming it only has 52uS before the
next byte arrives, and this is too fast for the LCD to have finished displaying the previous
character. There are various ways of overcoming this - firstly, as long as you are typing the
characters on the keyboard there won't be a problem (you can't type fast enough), secondly you
could arrange for the transmitted protocol to have more than one stop bit (two stop bits would
give three times as long to display the characters, three stop bits would give five times as long,
and so on). Or you could buffer the characters in PIC data registers, this still wouldn't allow a
continuous data stream, but would probably do all that's required. (For a further possibility see
Tutorial 7.7a)

Tutorial 7.4 - required hardware, Main Board, LCD Board and Serial Board.

This fourth sample program receives data one character at a time, displays it on the LCD
module (as in 7.3) and then echo's the character back to the PC screen.

Tutorial 7.5 - required hardware, Main Board, LED Board and Serial Board.

This fifth sample program receives data one character at a time, displays it on the LED board
and then echo's the character back to the PC screen, the ports have been swapped around (PortA
now connects to the serial board, and PortB connects to the LED board, because pin A4 is an
open-collector output). This would make a nice simple way of providing eight switched outputs
controlled from a serial port.

Tutorial 7.6 - required hardware, Main Board, Switch Board and Serial Board.

This sixth sample program receives one data byte from the PC (any byte - just to initiate a
read), reads the switches connected to PortB, and sends the result back to the PC as a string of
eight 1's and 0's - B0 first, and B7 last - followed by CRLF. If you examine the code, the routine
for sending the PortB reading as a series of ASCII 1's and 0's is based on the XMIT_RS232
code, it reads the bits in turn in exactly the same way, only the action taken for each bit is
different. As the previous example makes a nice easy way of writing eight bits, this one makes a
nice easy way of reading eight bits.
Tutorial 7.7a - required hardware, Main Board 2, LCD Board and Serial Board.

This seventh sample program works exactly like Tutorial 7.4, but is based on the 16F876 at
20MHz, and uses the hardware USART rather than software emulation. As it uses hardware to
receive the serial data, this gives a lot more time for processing and displaying characters,
around 1mS or so. There isn't a 16F628 version of this tutorial yet as I have to change the serial
board connections over, as soon as this is done I'll post a 16F628 version as well - if you want to
do it, the values for the USART are SPBRG=25 and BRGH=1. 

You might also like