Chapter 8 - Communication

Download Report

Transcript Chapter 8 - Communication

Chapter 8
Communication
Introduction to serial
communication interfaces.
Examples of use of the SPI module
Synchronous Serial Interfaces
Di Jasio - Programming 32-bit Microcontrollers in C
SPI bus
Di Jasio - Programming 32-bit Microcontrollers in C
Asynchronous Serial Interfaces
Di Jasio - Programming 32-bit Microcontrollers in C
Serial Interfaces Side by Side
Di Jasio - Programming 32-bit Microcontrollers in C
SPI module
figure 17-1 (DS61143)
Di Jasio - Programming 32-bit Microcontrollers in C
SPIxCON
Di Jasio - Programming 32-bit Microcontrollers in C
SPI module basic setup
// configuration bit settings, Fcy=72MHz, Fpb=9MHz
#pragma config POSCMOD=XT, FNOSC=PRIPLL
#pragma config FPLLIDIV=DIV_2, FPLLMUL=MUL_18, FPLLODIV=DIV_1
#pragma config FPBDIV=DIV_8, FWDTEN=OFF, CP=OFF, BWP=OFF
#define SPI_BAUD
15
// Fpb/(2 * (15+1)) = 1:32
Provides a clock of 9MHz / 32 = ~ 280kHz
// peripheral configurations
#define SPI_CONF 0x8120 // SPI on, 8-bit master,CKE=1,CKP=0
Di Jasio - Programming 32-bit Microcontrollers in C
Reading and Writing
// I/O definitions
#define CSEE
#define TCSEE
_RD12
_TRISD12
// 1. init the SPI peripheral
TCSEE = 0;
//
CSEE = 1;
//
SPI2CON = SPI_CONF;
//
SPI2SPI2BRG = SPI_BAUD;
//
// select line for EEPROM
// tris control for CSEE pin
make SSEE pin output
de-select the EEPROM
select mode and enable
select clock speed
// send one byte of data and receive
int writeSPI2( int i)
{
SPI2BUF = i;
//
while( !SPI2STATbits.SPIRBF); //
return SPI2BUF;
//
}//writeSPI2
Di Jasio - Programming 32-bit Microcontrollers in C
one back at the same time
write to buffer for TX
wait for transfer complete
read the received value
Serial EEPROM Commands
// 25LC256 Serial EEPROM commands
#define SEE_WRSR
1
// write status register
#define SEE_WRITE
2
// write command
#define SEE_READ
3
// read command
#define SEE_WDI
4
// write disable
#define SEE_STAT
5
// read status register
#define SEE_WEN
6
// write enable
Di Jasio - Programming 32-bit Microcontrollers in C
Serial EEPROM Status Register
25LC256 Status register detail (DS21822)
Di Jasio - Programming 32-bit Microcontrollers in C
Writing Data to the EEPROM
// send a Write command
CSEE = 0;
// select the Serial EEPROM
writeSPI2( SEE_WRITE);
// send command, ignore data
writeSPI2( ADDR_MSB);
// send MSB of memory address
writeSPI2( ADDR_LSB);
// send LSB of memory address
writeSPI2( data);
// send the actual data
// send more data here to perform a page write
CSEE = 1;
// start actual EEPROM write
cycle
Di Jasio - Programming 32-bit Microcontrollers in C
Reading EEPROM Data
// send a Read command
CSEE = 0;
writeSPI2( SEE_READ);
writeSPI2( ADDR_MSB);
writeSPI2( ADDR_LSB);
//
//
//
//
data = writeSPI2( 0);
// send dummy, read data
select the Serial EEPROM
send command, ignore data
send MSB of memory address
send LSB of memory address
// read more data here sequentially incrementing the address
...
// terminate the read sequence
CSEE = 1;
// and return to low power
Di Jasio - Programming 32-bit Microcontrollers in C
32-bit Serial EEPROM Lib
/*
** SEE Access Library
*/
#include "p32xxxx.h"
#include "see.h"
// I/O definitions
#define CSEE
_RD12
#define TCSEE
_TRISD12
// select line for Serial EEPROM
// tris control for CSEE pin
// peripheral configurations
#define SPI_CONF
0x8120 // SPI on, 8-bit master,CKE=1,CKP=0
#define SPI_BAUD
15
// clock divider Fpb/(2 * (15+1))
// 25LC256 Serial EEPROM commands
#define SEE_WRSR
1
// write status register
#define SEE_WRITE
2
// write command
#define SEE_READ
3
// read command
#define SEE_WDI
4
// write disable
#define SEE_STAT
5
// read status register
#define SEE_WEN
6
// write enable
// send one byte of data and receive
int writeSPI2( int i)
{
SPI2BUF = i;
//
while( !SPI2STATbits.SPIRBF); //
return SPI2BUF;
//
}//writeSPI2
Di Jasio - Programming 32-bit Microcontrollers in C
void initSEE( void)
{
// init the SPI2 peripheral
CSEE = 1;
TCSEE = 0;
SPI2CON = SPI_CONF;
SPI2BRG = SPI_BAUD;
}// initSEE
//
//
//
//
one back at the same time
write to buffer for TX
wait for transfer complete
read the received value
de-select the Serial EEPROM
make SSEE pin output
enable the peripheral
select clock speed
32-bit Serial EEPROM Lib (cont.)
int readStatus( void)
{
// Check the Serial EEPROM status register
int i;
CSEE = 0;
// select the Serial EEPROM
writeSPI2( SEE_STAT);
// send a READ STATUS COMMAND
i = writeSPI2( 0);
// send/receive
CSEE = 1;
// deselect terminate command
return i;
} // readStatus
int readSEE( int address)
{ // read a 32-bit value starting at an even address
int i;
// wait until any work in progress is completed
while ( readStatus() & 0x1);// check WIP
// perform a 32-bit read sequence, four byte sequential read
CSEE = 0;
// select the Serial EEPROM
writeSPI2( SEE_READ);
// read command
writeSPI2( address >>8);
// address MSB first
writeSPI2( address & 0xfc); // address LSB (word aligned)
i = writeSPI2( 0);
// send dummy, read msb
i = (i<<8)+ writeSPI2( 0); // send dummy, read lsb
i = (i<<8)+ writeSPI2( 0); // send dummy, read lsb
i = (i<<8)+ writeSPI2( 0); // send dummy, read lsb
CSEE = 1;
return ( i);
}// readSEE
Di Jasio - Programming 32-bit Microcontrollers in C
32-bit Serial EEPROM Lib (cont.)
void writeEnable( void)
{
// send a Write Enable
CSEE = 0;
writeSPI2( SEE_WEN);
CSEE = 1;
}// writeEnable
command
// select the Serial EEPROM
// write enable command
// deselect to complete the command
void writeSEE( int address, int data)
{ // write a 32-bit value starting at an even address
// wait until any work in progress is completed
while ( readStatus() & 0x1) // check the WIP flag
// Set the Write Enable Latch
writeEnable();
// perform
CSEE = 0;
writeSPI2(
writeSPI2(
writeSPI2(
writeSPI2(
writeSPI2(
writeSPI2(
writeSPI2(
CSEE = 1;
}// writeSEE
a 32-bit write sequence (4 byte page write)
// select the Serial EEPROM
SEE_WRITE);
// write command
address>>8);
// address MSB first
address & 0xfc); // address LSB (word aligned)
data >>24);
// send msb
data >>16);
// send msb
data >>8);
// send msb
data);
// send lsb
Di Jasio - Programming 32-bit Microcontrollers in C
Tips and Tricks
If you store important data in an external non volatile memory (SEE), you
might want to put some additional safety measures in place (both
hardware and software). From a hardware perspective make sure that:
• Adequate power supply decoupling (capacitor) is provided close to the
device.
• A pull up resistor (10k Ohm) is provided on the Chip Select line, to avoid
floating during the microcontroller power up and reset.
• An additional pull down resistor (10k Ohm) can be provided on the SCK
clock line to avoid clocking of the peripheral during power up when the
PIC32 I/Os might be floating (tri-state).
• Verify clean and fast power-up and down slopes are provided to the
microcontroller to guarantee reliable Power-On Reset (POR) operation.
If necessary add an external voltage supervisor (see MCP809 devices
for example).
Di Jasio - Programming 32-bit Microcontrollers in C
Tips and Tricks
A number of software methods can then be employed to prevent even the most
remote possibility that a program bug or the proverbial cosmic ray might trigger the
write routine. Here are some suggestions:
•Avoid reading and especially updating the SEE content right after power up. Allow
a few milliseconds for the power supply to stabilize (this is going to be heavily
application dependent).
•Add a software write-enable flag, and demand that the calling application set the
flag before calling the write routine, possibly after verifying some application
specific entry condition.
•Add a stack level counter; each function in the stack of calls implemented by the
library should increment the counter upon entry and decrement it on exit. The write
routine should refuse to perform if the counter is not at the expected level.
•Some users refuse to use the SEE memory locations corresponding to the first
address (0x0000) and/or the last address (0xffff) believing they could be statistically
more likely to be subject to corruption.
•More seriously, store two copies of each essential piece of data, performing two
separate calls to the write routine. If each copy contains a checksum or simply by
comparison, when reading it back, it will be easy to identify a memory corruption
problem and possibly recover.
Di Jasio - Programming 32-bit Microcontrollers in C