# How to get a PIC32 SPI port working for transmitting data?

I am looking to get a SPI serial port running on a PIC32 (PIC32MX360F). can anyone point me to some good resources on how to do this so that a newbie can figure it out? I am using the PIC32 starter kit and have a PIC32 breakout board from Digi-Key.

This is the code that I have been using... I found it in the PIC32 family manual.

#include <p32xxxx.h>
int main(void){
int rData;
IEC0CLR=0x03800000; // disable all interrupts
SPI1CON = 0; // Stops and resets the SPI1.
rData=SPI1BUF; // clears the receive buffer
IFS0CLR=0x03800000; // clear any existing event
IPC5CLR=0x1f000000; // clear the priority
IPC5SET=0x0d000000; // Set IPL=3, Subpriority 1
IEC0SET=0x03800000; // Enable RX, TX and Error interrupts
SPI1BRG=207; // use FPB/4 clock frequency
SPI1STATCLR=0x40; // clear the Overflow
SPI1CON=0x8220; // SPI ON, 8 bits transfer, SMP=1, Master mode
// from now on, the device is ready to transmit and receive data
SPI1BUF='A'; // transmit an A character

while(1){
SPI1BUF= 'A'; // transmit an A character
while(i < 10000){i++;}
i = 0;
}
}


How do I set the baudrate? I am guessing it got something to do with SPI1BRG

EDIT:

Thanks to tcrosley I feel that I am getting closer to being able to communicate with my pic32. I changed SPI1BRG to 207. By my calculations this will set the baudrate to around 9600.

Fsck = Fpb/(2(SPIxBRG +1)) = 4MHZ/(2*(207+1))= 9615

I am trying to view the output on the picchip with HyperTerminal. The settings I am using are:

Baud: 9600
Data bits: 8
Parity: None
Stop bits: 1
Flow Control: None


The pins I am using are:

93 - connected to db9 3
95 - connected to db9 2


and db9 5 is connected to the boards ground...

I am now getting an output, which is nice, but unfortunately it is garbage. my output on HyperTerminal comes out as a bunch of hearts :S now I just feel like my pic32 is mocking me

• @Richard, pins 93 and 95 on J2 of your Starter Kit are indeed the SPI1 interface, but you cannot connect them to RS-232 per my comment in my answer below. Pins 88 and 90 of J2 are the RX and TX leads of the UART1 interface, BUT you cannot connect them directly to RS-232 either without using a level-shifter (which is absent from your board). You need a circuit like this: sparkfun.com/commerce/product_info.php?products_id=133 in between. Oct 7 '10 at 14:34
• @tcrosely, by level-shifter, do you mean to switch the voltages from 3.3 to 5 volts? Because if so, I have the device connected to an external power supply which I thought would do the job. Oct 7 '10 at 15:38
• @Richard, the issue is that your PC outputs RS-232 levels, and your PIC is using logic levels. RS-232 uses +- 3v to +- 12v, with a negative voltage representing the idle (marking), and a positive voltage representing the active (spacing) state. Your PIC's UART uses logic 1 (typically 3.3v) for idle (marking) and logic 0 (0v) for active (spacing). You need a circuit in between like the one linked to above to invert the logic and shift the levels. See "Voltage Levels" in this article: en.wikipedia.org/wiki/RS-232 Oct 7 '10 at 17:32
• @tcrosely, Once I figure out how these UART registers work I will Put it on a scope to see how the levels act. I will be honest I am a pic32 newbie.. but looking at the pin diagrams it does say that the U1RTS and U1TCTS pins are 5 volt tolerant... I know that doesn't say anything about how their level's are triggered. If not I will do as you suggested and change the level's via a few transistors Oct 7 '10 at 17:41
• @Richard, here is the schematic of the SparkFun level shifter: sparkfun.com/datasheets/Prototyping/RS232-Shifter-v2.pdf -- since the PIC can't generate a negative voltage for the marking state, the circuit stores negative voltage from the PC's TX line and uses that as the idle voltage for sending back to the PC. Also, TX/RX on this circuit are relative to the PC, so RX connects to the PIC's TX and vice versa. Oct 7 '10 at 18:52

This application note AN1277 describes how to interface a serial SRAM to a PIC32 microcontroller using the C32 Compiler. The page has a link to a zip file containing source code, which should have low level routines for reading and writing data via the SPI interface.

EDIT:

How do I set the baudrate? I am guessing it got something to do with SPI1BRG

I see that you have downloaded the "datasheet" for your processor (datasheet is a bit of a misnomer, it is 632 pages long), so I will be using page references from that.

The equation (on page 397) for the SPI clock frequency is

Fsck = Fpb / (2 * (SPI1BRG+1))

I believe the PIC32MX360F starts out with a internal FRC oscillator of 8 MHz, divided by 2 (due to the FRCDIV default value of 1 in OSCCON register, page 56), and since you are not making a changes in your code to OSCCON, the SYSCLK value will be 4 MHz.

Fpb is the Peripheral Bus Clock frequency. It is set up in PBDIV field of the OSCCON register, which in turn is initialized to the value of the FPBDIV field in the DEVCFG1 (boot configuration register), depicted on page 63. Assuming you haven't changed this, the default POR (power-on reset) value is binary 11, which means the Fpb is SYSCLK divided by 8.

Therefore Fpb = 4 MHz / 8 or 500 KHz.

If SPI1BRG = 1, as in your example, Fsck = Fpb / (2 * (1+1)) = Fpb / 4 = 500 KHz / 4 or 125 KHz.

If your SYSCLK differs from 4 MHz, then scale the Fpb accordingly.

Aren't embedded processors fun?

• lol loads of fun, I did find that application note, however I was unsure where Fpb came from. Thanks for clarifying that for me. I still am having trouble sending anything from the pic chip. I am using HyperTerminal on a pc to see if anything is transmitted. The settings I am using are 9600 baud, 8 data bits, parity none, stops bits 1, flow control none. I am newb to pic chips, so any help you can give would be great. Oct 7 '10 at 12:16
• @Richard, you are mixing up the SPI and UART. SPI is Serial Peripheral Interface and is designed for talking to chips that have an SPI interface with CS(chip select), SCK(clock), MOSI(master out/slave in) and MISO(master in/slave out) pins. HyperTerminal communicates via RS-232, which is implemented through the UART (Universal asynchronous Receiver/Transmitter) interface via level shifters on your PIC32 Starter Kit. I think you need to look at Chapter 19 in the datasheet, which describes the UART interface. Oct 7 '10 at 12:31
• I will have a look. Thanks for your help. I will post here once I give it a read. Oct 7 '10 at 13:05

It has a chapter called Synchronous Communication Using the SPI Modules and much more.

• I actually have access to that book already (I work at an university) I guess I will keep mucking with the chip to see what I can figure out... Oct 5 '10 at 17:53

What are you interfacing the SPI to? Whatever that is will have a datasheet that gives you the requirements for your SPI channel. So,

1. set up your TRIS register correctly,
2. properly enable the SPI channel,
3. set the levels of SI and SO and how they're phased with the SCLK. And you might need an enable (slave select). The datasheet of what your interfacing to will tell you that.

Use an oscope to double check that you're doing it correctly.

It is likely that your problem is that after sending the first "A" you are not reading SPI1BUF back to clear whatever the SPI "read" back. Recall that SPI works like a shift register; for every bit you push out you get a bit in. If you do not read the contents of SPI1BUF then likely you get an overun, and per section 17.2.6 of the data sheet, the device stops working until you clear SPIROV

• Two more things: you don' seem to be servicing the interrupts. If you have Tx and Rx inrerrupts you need to have an ISR that clears the interrupt flags. Also, the first time around I did not notice that you are trying to connect an SPI signal to a serial port in a PC. as tcrosley points out you can not do that directly. You need something like this maxim-ic.com/datasheet/index.mvp/id/2052 to change the protocol from a clocked SPI signal to an RS232. This is why even though you have the right baud rate you see garbage. Oct 9 '10 at 14:47

For starters:

1. Make sure you have your TRIS registers setup properly
2. Use a bus monitor or oscilloscope to see if the SPI signal timing is correct for the device you are trying to communicate with