Tank2005 Tank2005 -4 years ago 144
C Question

SPI signal translation between Arduino and PIC(8bit microcontroller)

I'm testing a SPI communication between Arduino UNO and PIC16F1(PC16F1827).

This is my wiring and source code:

MPLAB X IDE 3.55 / XC8 v1.4.1(Free)

#include <xc.h>

#pragma config FOSC = INTOSC // Inner clock
#pragma config WDTE = OFF // Watchdog timer
#pragma config PWRTE = OFF // Power-Up timer
#pragma config MCLRE = ON // MCLR pin
#pragma config CP = OFF // Code protection
#pragma config CPD = OFF // Memory protection
#pragma config BOREN = ON // Brown-out Reset
#pragma config CLKOUTEN = OFF // Outer clock
#pragma config IESO = OFF // Oscillator switchover
#pragma config FCMEN = OFF // Fail-Safe clockmonitor

#pragma config WRT = OFF // Power-up Timer
#pragma config PLLEN = ON // Use 4xPLL
#pragma config STVREN = OFF // Reset when stack error
#pragma config LVP = OFF // Low voltage program

#define _XTAL_FREQ 32000000 // 32MHz

void main(void)
// PIC initialization
OSCCON = 0b00110100; // Inner clock = 4Mhz

ANSELA = 0b00000000; // All RA are digital
TRISA = 0b00000001; // RA0 is input
PORTA = 0b00000000; // Initialize RA

// SPI initalization
SDO1SEL = 0; // RB2 sets to SDO pin
SSP1CON1 = 0b00100101; // Slave mode(Unuse SS)
SSP1STAT = 0b01000000; // Slave mode(Clock phase is LOW)

SSP1BUF = 0;

unsigned char read_data; // Current is dummy
unsigned char count = 255;
// Read byte from master
read_data = SSP1BUF;

// Write byte to master
if(count == 255) count = 0; else count++;
SSP1BUF = count;

Arduino IDE 1.8.1

#include <SPI.h>

void setup()

SPI.begin() ;
SPI.setBitOrder(MSBFIRST) ;
SPI.setDataMode(SPI_MODE1) ;

delay(1500) ;

void loop()
char msg[100];
byte i, n;

for (i = 0 ; i < 10 ; i++) {
n = SPI.transfer(i) ;

sprintf(msg, "%d/%d,", n, i);


Wiring image

My ideal is that Arduino receives the value of 0-255(I have ignored about frequency of SPI because it's a programming test). But SPI.transfer() returns a value of i(0-9).

I worry about where I should fix because there is little technical information of those IC on the web. Does someone know the good way?

Answer Source

I took a look at the PIC 16F1826 datasheet to check your connections.

The pin used to transmit out data from SPI1 , named SDO1, can be RA6 or RB2 (from datasheet, page 12 [Table 1-2]).

Given that you write 0 to SDO1SEL (it's already 0 on reset), SDO1 appears to be on RB2. In fact, you connected RB2 and not RA6.

But you don't clear the corresponding TRISB bit to make RB2 an output, as stated in page 236 (chapter 25.2.2). Your current program can not transmit data out of RB2/SDO1.

Maybe there are other errors too, probably in setting up registers. I advice to read carefully the datasheet and revise all your settings on the PIC side. Then, if you have still problems, update your question and I will update my answer (leave a comment to wake me). For example, I didn't check that your connection from RB2 goes to the right place of Arduino (I see it goes to pin 11, but I didn't check it is correct: like some compilers, I stop on the first error).

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download