360 |
Chapter 9 / The PIC Prototype |
|
|
start the program. We have plenty of I/O pins on the dsPIC30F2010 but we need to be careful how we implement our I2C and SPI communications interfaces. Both of these interfaces are implemented in the chip and have software wrappers that provide easy software access. The problem is that both of these hardware implementations use the same pins. To overcome this challenge we will implement and test each of these functions using the built-in simulator. We will then implement and test each function using the dsPICDEM 28 board. Once completed we will design our own board for implementing this version of the prototype.
The RS-232 Interface
The dsPIC has two RS-232 TTL interfaces built in. These interfaces do not have flow control but adding this feature is really pretty simple. In keeping with our original design, we will use one RS-232 TTL interface and add CTS/RTS handshake signals. This single interface will connect to the communication host via RS-232 (with the use of our transceiver from Chapter 7), Ethernet, and USB (using the 16C745). Rather than modify the dsPICDEM 28 board, we will simply test the serial, SPI, and I2C I/O and then make final design changes to our board.
To show the differences between the Microchip GNU-based compiler and the HI-TECH dsPICC compiler we will write a short test program using each for our serial I/O. Let’s begin by starting the MPLAB workbench by double-clicking the desktop icon. Once the program has started, select Project | Project Wizard, select the dsPIC30F2010 device, and press Next. The next screen allows you to select the toolset. We will start by selecting the MPLAB C30 compiler.
Note:
If you haven’t already done so, please download and install the trial version of the C30 compiler before continuing.
362 |
Chapter 9 / The PIC Prototype |
|
|
Listing 9-1
/***************************************************************************** uart_test - Test the alternate UART using the C30 "C" compiler toolsuite from Microchip. Copyright 2004 Oliver H. Bailey
written: 06/13/2004 - Oliver H. Bailey modified 12/16/2004 - Oliver H. Bailey
*****************************************************************************/
#define __dsPIC30F2010__ |
// Define Device Type |
#include <p30fxxxx.h> |
// Include Generic Header |
#include <uart.h> |
// Include UART Header |
char recBuf[80]; |
// Receive Buffer |
char * recData = recBuf; |
// Character Pointer to Receive Buffer |
void __attribute__((__interrupt__)) _U1TXInterrupt(void) |
// Uart 1 TX Interrupt Routine |
{ |
|
|
IFS0bits.U1TXIF = 0; |
// Clear Interrupt Flag |
} |
|
|
void __attribute__ ((__interrupt__)) _U1RXInterrupt(void) |
// UART 1 RX Interrupt Function |
{ |
|
|
IFS0bits.U1RXIF = 0; |
// Clear Interrupt Flag |
while (DataRdyUART1()) |
// While DataReady = True |
{ |
|
|
(*(recData)++) = ReadUART1(); |
// Next Buffer Position = Character |
} |
|
|
} |
|
|
int main(void) |
// Main Program |
{ |
|
|
char tstData[] = {"Hello from Embedded System\r\n\0"}; |
// Test Character Data String |
unsigned int baud; |
// Baud Rate |
unsigned int mode, dbgmode; |
// UART Mode |
unsigned int intmode; |
// UART Interrupt Mode |
unsigned int loop; |
// Loop Counter if Needed |
CloseUART1(); |
// Close UART for Saftey |
baud = 5; |
// 9.6K Baud @ 7.37 MHz |
ConfigIntUART1(UART_RX_INT_EN & UART_RX_INT_PR6 & // Enable RX Interrupt, Priority 6 |
UART_TX_INT_DIS & UART_TX_INT_PR2); |
// Disable TX Interrupt, Priority 2 |
364 |
Chapter 9 / The PIC Prototype |
|
|
Now let’s see how this same program would be written in dsPICC from HI-TECH software. The following program is written in dsPICC and does the same task as above.
Listing 9-2
#include |
<dspic.h> |
// |
dsPIC definitions |
#include |
<string.h> |
// |
Used for string functions |
// Alternate method of setting configuration bits. __CONFIG(FOSC, POSC & XTPLL4 & CLKSWDIS & FSCMDIS); __CONFIG(FWDT, WDTDIS);
__CONFIG(FBORPOR, PWRT16 & MCLREN & BORDIS); __CONFIG(FGS, GCPU & GWRU);
__CONFIG(FCOMM, PGEMU);
#define BAUD |
9600 |
// Baud Rate |
#define OSC |
7372800 |
// Oscillator Speed |
#define DIVIDER |
(((OSC/BAUD)/16)-1) |
// Calculation for bus speed |
char stmsg[]={"Hello From Embedded Systems\n\r\0"}; |
// Test String |
void main(void) |
|
// Start of main program |
{ |
|
|
|
unsigned int slen; int loop;
U1BRG = DIVIDER;
U1_UARTEN = 1;
U1_UTXEN = 1;
slen = strlen(stmsg);
for(loop = 0; (loop < slen); loop++){ U1TXREG = stmsg[loop];
};
while(1){ while(!U1_URXDA); while(!U1_TRMT); U1TXREG = U1RXREG;
};
};
//Length of stmsg
//Array Element Number
//UART BIT RATE BYTE VALUE
//Enable UART 1
//Enable TX 1
//Get String Length
//Loop through string
//Put Array Element in Transmit Register
//While there is no receive data
//and no transmit data
//Echo received data to transmit
366 |
Chapter 9 / The PIC Prototype |
|
|
void attribute_((interrupt)) SPI1Interrupt(void) // Interrupt declaration
{
IFS0bits.SPI1IF = 0; |
// Clear interrupt flag |
} |
|
int main(void) |
|
{ |
|
unsigned int SPIConfig; |
// SPI configuration bits |
unsigned int SPIStat; |
// SPI status configuration |
SPIConfig = FRAME_ENABLE_ON & |
// Turn on framing for DS2404 3-Wire |
FRAME_SYNC_OUTPUT & |
// SYNC OUPUT TO CLOCK |
ENABLE_SDO_PIN & |
// ENABLE Serial Data Out |
SPI_MODE16_OFF & |
// 8 BIT MODE |
SPI_SMP_ON & |
// Input Sample OFF |
SPI_CKE_OFF & |
// Clock EDGE Select OFF |
SLAVE_ENABLE_OFF & |
// Slave Mode OFF |
CLK_POL_ACTIVE_HIGH & |
// Clock Polarity Active HIGH |
MASTER_ENABLE_ON & |
// Enable MASTER |
SEC_PRESCAL_7_1 & |
// Secondary Prescaler |
PRI_PRESCAL_64_1; |
// Primary Prescaler |
SPIStat = SPI_ENABLE & |
// Enable SPI |
SPI_IDLE_CON & |
// Continue Operation when IDLE MODe |
|
// is Active |
SPI_RX_OVFLOW_CLR; |
// Clear Receive Overflow Bit |
CloseSPI1(); |
// Close SPI1 |
ConfigIntSPI1(SPI_INT_DIS & SPI_INT_PRI_7); |
// Configure SPI 1 Interrupt |
OpenSPI1(SPIConfig, SPIStat); |
// Open SPI 1 |
slen = strlen(tstData); |
// get length of tstData |
for(loop = 0; (loop < slen); loop++) |
// Output a character at a time |
{ |
|
putcSPI1((unsigned int) tstData[loop]); |
|
} |
|
putsSPI1(slen, (unsigned int *) &tstData[0]); // Output Entire String
368 |
Chapter 9 |
/ The PIC Prototype |
|
|
|
S1_MODE16 = 0; |
// 8 Bit Mode |
S1_SMP = 1; |
// Input sampled at end of clock cycle |
S1_CKE = 0; |
// Serial Output data changes on transition from idle to active clock |
S1_SSEN = 1; |
// Slave enable line will be handled automatically by module |
S1_CKP = 0; |
// Idle Clock State is Low |
S1_MSTEN = 1; |
// Enable Master Mode |
//Using the following prescaler values the data rate with the processor clock at 30 MHz
//will be 59 KHz
//See the dsPIC family reference guide for information on calculating SPI data rates.
S1_SPRE0 = 0; |
// Secondary prescale = 8:1 |
S1_SPRE1 = 0; |
|
S1_SPRE2 = 0; |
|
S1_PPRE0 = 0; |
|
// Primary Prescale = 64:1 |
|
S1_PPRE1 = 0; |
|
// Enable SPI in master mode |
|
S1_SPISIDL = 0; |
// Continue when Idle |
S1_SPIEN = 1; |
// Enable SPI 1 |
slen = strlen(stmsg); |
// Get String Length |
for(loop = 0; (loop < slen); loop++){ |
// Loop through string |
while(S1_SPITBF); |
// Wait for Transmit Buffer to Empty |
SPI1BUF = stmsg[loop]; |
// Put Array Element in Transmit Register |
}; |
|
}; |
|
The I2C Interface
The next communications interface we need to implement is the I2C interface. As you may recall this interface allows us to communicate with the LCD display. It’s a very important interface since the LCD handles all user I/O and alarm functions.
We’ve used the I/O pins allotted for I2C on the dsPIC for other purposes. Even so, I’ve written a generic I2C handler that can use any general-purpose pair of I/O pins. I’ve kept the naming conventions the same as the dsPIC peripheral library so the