CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

PIC 16F886 SPI CONFIGURATION
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Armando



Joined: 02 May 2013
Posts: 16
Location: Venezuela

View user's profile Send private message

PIC 16F886 SPI CONFIGURATION
PostPosted: Thu May 02, 2013 1:34 pm     Reply with quote

Hello everybody!


Right now I'm working on a project with PIC16F886 which need to communicate with other devices via SPI. For this, I am working with the CCS compiler and doing these configurations with the PIC Wizard.

The PIC16F886 should work as MASTER and the speed of the SPI SCK pin must be 2 MHz.


The configuration that I have done until now is:

General Options:

- Oscillator Frequency: 8 MHz (PIC speed)
- Internal RC Osc (Using the PIC's internal oscillator)
- Power Up Timer
- Master Clear pin Enabled (To use the hardware reset)

SPI Options:

- Port Count: 1 SPI # 1
- Use SPI1 hardware (To use the SPi hardware )
- Enable Pin: A1 (Using port A1 as Slave Select)
- Master (PIC's Role)
- Mode 0 (Idle 0, Sample Rises)
- Bits 8
- Enable Active: Low
- First Bit: MSB


To set the frequency of the SCK pin, I have understood that you use the Timing box, which can be put in Baud or Clock Times. My first question is: If I want to set the SCK pin to 2 MHz, and select the option "Baud", what value should I put there so that the frequency of the SCK go to 2 Mhz? What is relation Baud-SCK frequency? also has some relation to the FOSC? I've seen some formulas on the web regarding these calculations, and the datasheet too, but to be honest, it's the first time I set the SPI of any PIC and I am very confused with this.

Another question I have: What do you think so far what I have setup? Am I right till now? Am I ignoring some configuration or some detail of RLS?



Greetings and thanks in advance!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 02, 2013 2:29 pm     Reply with quote

Quote:

If I want to set the SCK pin to 2 MHz, and select the option "Baud", what
value should I put there so that the frequency of the SCK go to 2 Mhz ?

The 16F886 data sheet says:
Quote:

13.3.3 MASTER MODE

In Master mode, the SPI clock rate (bit rate)
is user programmable to be one of the following:

•FOSC/4 (or TCY)
•FOSC/16 (or 4 • TCY)
•FOSC/64 (or 16 • TCY)
• Timer2 output/2

This allows a maximum data rate (at 40 MHz) of 10.00 Mbps.

The SPI clock frequency is set by these bits in the SSPCON register:
Quote:

REGISTER 13-2: SSPCON: SSP CONTROL REGISTER 1

bit 3-0 SSPM<3:0>: Synchronous Serial Port Mode Select bits
0000 = SPI Master mode, clock = FOSC/4
0001 = SPI Master mode, clock = FOSC/16
0010 = SPI Master mode, clock = FOSC/64


Next, make a test program:
Code:

#include <16F886.H>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=8M)
#use spi(Master, SPI1, Mode=0, baud=2000000)

//==========================================
void main()
{
int8 temp;

temp = spi_xfer(0x00);

while(1);
}


Then compile it and find the value that the compiler puts into SSPCON:
Code:
.................... void main()
.................... {
002C:  MOVLW  71
002D:  BSF    STATUS.RP0
002E:  MOVWF  OSCCON
002F:  MOVF   OSCCON,W
0030:  MOVLW  FF
0031:  BCF    STATUS.RP0
0032:  MOVWF  @TRIS_C
0033:  BCF    SSPCON.SSPEN
0034:  MOVLW  40
0035:  BSF    STATUS.RP0
0036:  MOVWF  SSPSTAT
0037:  MOVLW  20
0038:  BCF    STATUS.RP0
0039:  MOVWF  SSPCON  // SSPCON = 0x20

It puts 0x20 into SSPCON. So bits 0-3 are set to all 0's. This means
FOSC/4 is used as the divisor. Therefore 8 MHz / 4 = 2 MHz SPI clock.
That's how to solve this type of problem.
Armando



Joined: 02 May 2013
Posts: 16
Location: Venezuela

View user's profile Send private message

PostPosted: Thu May 02, 2013 2:39 pm     Reply with quote

Thank you so much PCM programmer for your quickly reply!



I can see the value that the compiler puts into SSPCON in "C/ASM List" buttom right?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 02, 2013 4:33 pm     Reply with quote

I don't have the CCS IDE. But if that menu brings up the .LST file,
then that's what you want.
Armando



Joined: 02 May 2013
Posts: 16
Location: Venezuela

View user's profile Send private message

PostPosted: Thu May 02, 2013 7:02 pm     Reply with quote

Yes, it brings the .LST file. Thank you so much again for your help.


One last thing. I'm trying to understand spi_xfer functionality. In older versions of CCS, it used spi_write and spi_read to make spi transfers.

Now, in CCS datasheet shows this example about using this:

Example:

int i = 34;
spi_xfer(i);
// transfers the number 34 via SPI

It's clear to me...

int trans = 34, res;
res = spi_xfer(trans);
// transfers the number 34 via SPI
// also reads the number coming in from SPI



Now, they init "trans=34", and send it by spi and "res" get the value read (incoming on DI) by SPI right?

1)How i could make an single read without sending anything first?

2) How I can send an value (for example 0x0C) to an slave address(for example any number... 0x01). I would like to send in the first 8 clock cycles the address (0x01) and in the next 8 clock cycles the value for that address , in this case 0x0C.

I can do this with only one _spi_xfer? or i need to do:

spi_xfer(0x01)
spi_xfer(0x0C) // Also, I'm not sure if with spi_xfer i need to do a read before to send the second byte (0x0C). I'm asking this because i read in a Microchip document that SPI need to make (ALWAYS ) an read before sending a new byte via SPI. Or i just need to take it care if I'm building my own soft in i.e assembler?




Thanks in advance!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu May 02, 2013 9:32 pm     Reply with quote

Quote:
I need to communicate with other devices via SPI.

Tell us the part numbers of these devices.
Armando



Joined: 02 May 2013
Posts: 16
Location: Venezuela

View user's profile Send private message

PostPosted: Thu May 02, 2013 10:04 pm     Reply with quote

Oh, I'm sorry. Is an TRF7970A.

Is an multiprotocol Fully Integrated 13,56 MHz RFID/NFC IC.

I want to make it work ONLY as an NFC Card-Tag Emulator.

To do that i need:

1) Initialize SPI with SS by using Direct Command 0x03 -> 0x83 (Software Initialization) (see Table 5-18 of the TRF7970A data sheet).

2) Idle TRF7970A by using 0x00 -> 0x80 (Idle) (see Table 5-18 of the TRF7970A data sheet).

3) Write registers to configure TRF7970A for desired mode (ISO14443B in this example):

Register // Value // Notes

0x09 // 0x01 // SYS_CLK and MOD
0x01 // 0x25 // NFC Card Emulation, Type B
0x0B // 0x01 // Regulator, could be set to 0x87 (Auto)
0x0A // 0x3C // RX Special Settings for ISO14443B
0x18 // 0x07 // FC Target Detection Level
0x17 // 0x80123456 // Example NFCID/PUPI
0x16 // 0x03 // NFC Low Field Detection Level
0x02 // 0x02 // ISO14443B TX Options
0x00 // 0x21 // Chip Status Control

4) Reset the FIFO with Direct Command 0x0F -> 0x8F.
5) Disable/enable receivers with Direct Commands 0x16 -> 0x96 and 0x17 -> 0x97.

And after this, TRF7970A should be configured as an ISO14443B transponder with a NFCID/PUPI of 0x8012345616,
waiting for field to be presented and commands issued.


See TRF7970A IC Communication Interface (Pag. 29) and Direct Command from MCU to Reader (Page 53).
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri May 03, 2013 1:27 pm     Reply with quote

Here are two simple routines, based on the timing diagram oscilloscope
photos shown in the TRF7970A data sheet. This code just demonstrates
how to code two routines. It is not a demo of how to initialize the chip.
Code:

#include <16F886.H>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=8M)
#use spi(Master, SPI1, Mode=0, bits=8, baud=2000000)

#define TRF7970A_SS  PIN_C0

//-----------------------------------
// Figure 5-7. Single Address Register Write.

void trf7970a_write_reg(int8 reg, int8 data)
{
output_low(TRF7970A_SS);
spi_xfer(reg);
spi_xfer(data);
output_high(TRF7970A_SS);
}

//-----------------------------------
// Figure 5-8. Single Address Register Read.

int8 trf7970a_read_reg(int8 reg)
{
int8 retval;

output_low(TRF7970A_SS);
spi_xfer(reg);
retval = spi_xfer(0x00);
output_high(TRF7970A_SS);

return(retval);
}


//======================================
void main(void)
{
output_high(TRF7970A_SS);
delay_ms(100);


trf7970a_write_reg(0x01, 0x08);  // 0x08 = ISO14443A standard

while(1);
}
 
Armando



Joined: 02 May 2013
Posts: 16
Location: Venezuela

View user's profile Send private message

PostPosted: Fri May 03, 2013 5:45 pm     Reply with quote

Hi PCM!

I am totally grateful to you.. Thank you so much and I'm glad that there are still people who kindly help those that are starting programming and learning about electronic.

Tomorrow I'll just make the entire code using this 2 routines (They look so good). After this, I'll post this to show the final code. Also, next tuesday I'll be testing the hardware and software in College's Laboratory. I'll keep you informed of the results of these tests.

And again, thank you!

Armando! Very Happy
Armando



Joined: 02 May 2013
Posts: 16
Location: Venezuela

View user's profile Send private message

PostPosted: Sun May 12, 2013 5:47 pm     Reply with quote

Hi again PCM!

This week, I was testing the code for the TRF7970A's IC and I have 3 questions for you.

I tested 2 codes that I copy below:

FIRST CODE (From your previous code):

Code:

#include <16F886.H>
#fuses INTRC_IO, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=8M)
#use spi(Master, SPI1, Mode=0, bits=8, baud=2000000)

#define TRF7970A_SS  PIN_B5
#define ENABLEPIN  PIN_B4

//-----------------------------------
// Figure 5-7. Single Address Register Write.

void trf7970a_write_reg(int8 reg, int8 data)
{
output_low(TRF7970A_SS);
spi_xfer(reg);
spi_xfer(data);
output_high(TRF7970A_SS);
}

//-----------------------------------
// Figure 5-8. Single Address Register Read.

int8 trf7970a_read_reg(int8 reg)
{
int8 retval;

output_low(TRF7970A_SS);
spi_xfer(reg);
retval = spi_xfer(0x00);
output_high(TRF7970A_SS);

return(retval);
}

//======================================

void main(void)
{
.
   output_high(TRF7970A_SS);
   output_high(ENABLEPIN);
   delay_ms(100);

   output_low(TRF7970A_SS);
   spi_xfer(0x83);
   output_high(TRF7970A_SS);

   output_low(TRF7970A_SS);
   spi_xfer(0x80);
   output_high(TRF7970A_SS);
   
   trf7970a_write_reg(0x09, 0x01); //SYS_CLK and MOD
   trf7970a_write_reg(0x01, 0x25); //NFC Card Emulation, Type B)
   trf7970a_write_reg(0x0B, 0x01); //Regulator, could be set to 0x87 (Auto)
   trf7970a_write_reg(0x0A, 0x3C); //Rx Special Settiong for ISO14443B
   trf7970a_write_reg(0x18, 0x07); //NFC Target Detection Level
   trf7970a_write_reg(0x17, 0x80123456); // Example NFCID/PUPI
   trf7970a_write_reg(0x16, 0x03); //NFC Low Field Detection Level
   trf7970a_write_reg(0x02, 0x02); //ISO14442B Tx Options
   trf7970a_write_reg(0x00, 0x21); //Chip Status Control
   
   output_low(TRF7970A_SS);
   spi_xfer(0x8F);
   output_high(TRF7970A_SS);
   
   output_low(TRF7970A_SS);
   spi_xfer(0x96);
   output_high(TRF7970A_SS);
   
   output_low(TRF7970A_SS);
   spi_xfer(0x97);
   output_high(TRF7970A_SS);
   
   //TRF7970A is now configured as an ISO13444B with an
   //NFCID/PUPI 0x80123456, waiting for field to be presented.

while(1);
}



AND SECOND CODE (Using Pic Wizard):

Code:


#include <PruebaTagEmulacion.h>
#USE SPI (MASTER, SPI1, BAUD=2000000, MODE=0, BITS=8, ENABLE_ACTIVE=0, STREAM=SPI_1, MSB_FIRST)


//-----------------------------------
// Figure 5-7. Single Address Register Write.

void trf7970a_write_reg(int8 reg, int8 data)
{
output_low(TRF7970A_SS);
spi_xfer(reg);
spi_xfer(data);
output_high(TRF7970A_SS);
}

//-----------------------------------
// Figure 5-8. Single Address Register Read.

int8 trf7970a_read_reg(int8 reg)
{
int8 retval;

output_low(TRF7970A_SS);
spi_xfer(reg);
retval = spi_xfer(0x00);
output_high(TRF7970A_SS);

return(retval);
}


//======================================

void main()
{
 
   output_high(TRF7970A_SS);
   output_high(ENABLEPIN);
   delay_ms(100);

   output_low(TRF7970A_SS);
   spi_xfer(0x83);
   output_high(TRF7970A_SS);
   
   output_low(TRF7970A_SS);
   spi_xfer(0x80);
   output_high(TRF7970A_SS);
   
   trf7970a_write_reg(0x09, 0x01); //SYS_CLK and MOD
   trf7970a_write_reg(0x01, 0x25); //NFC Card Emulation, Type B)
   trf7970a_write_reg(0x0B, 0x01); //Regulator, could be set to 0x87 (Auto)
   trf7970a_write_reg(0x0A, 0x3C); //Rx Special Settiong for ISO14443B
   trf7970a_write_reg(0x18, 0x07); //NFC Target Detection Level
   trf7970a_write_reg(0x17, 0x80123456); // Example NFCID/PUPI
   trf7970a_write_reg(0x16, 0x03); //NFC Low Field Detection Level
   trf7970a_write_reg(0x02, 0x02); //ISO14442B Tx Options
   trf7970a_write_reg(0x00, 0x21); //Chip Status Control
   
   output_low(TRF7970A_SS);
   spi_xfer(0x8F);
   output_high(TRF7970A_SS);
   
   output_low(TRF7970A_SS);
   spi_xfer(0x96);
   output_high(TRF7970A_SS);
   
   output_low(TRF7970A_SS);
   spi_xfer(0x97);
   output_high(TRF7970A_SS);
   
   //TRF7970A is now configured as ISO14443B TAG, with an
   //NFCID/PUPI  0x80123456, waiting field to be presented.
 
  while(1);


Here's the thing: BOTH CODES SHOULD DO THE SAME WORK, but when I check SS Signal at Oscilloscope, IN THE FIRST PROGRAM SS IS HIGH (5V) that is good (Because the last code instruction sets SS high). But when I check the SS signal with the second code its 0v (that's wrong because last instruction is SS-HIGH).

First Question: What I'm doing wrong in the second code? its something about SPI configuration( SPI_ENABLE=0) ?

Second Question: PIC sends the clock signal (SPI CLK - 2Mhz) only while It's sending/reading data from the SPI? I'm asking this because when I transmit only 1 byte, I cant see the SPI CLk signal on Oscilloscope, but when I transmit infinite bytes, i can see perfectly the 2Mhz Waveform.


Third Question: In the first code, the MSB is transmited first right? Is not need to set the first bit to be transmitted as the second code?

Thanks in advance.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 12, 2013 7:13 pm     Reply with quote

Before I answer your questions, I need to know your compiler version.
It's given at the top of the .LST file, in your project directory.
Example of compiler versions:
http://www.ccsinfo.com/devices.php?page=versioninfo
Armando



Joined: 02 May 2013
Posts: 16
Location: Venezuela

View user's profile Send private message

PostPosted: Sun May 12, 2013 7:23 pm     Reply with quote

CCS PCM C Compiler, Version 4.140d, 1 10-may-13 16:57
Compiler operating in Evaluation Mode
Armando



Joined: 02 May 2013
Posts: 16
Location: Venezuela

View user's profile Send private message

PostPosted: Tue May 28, 2013 9:04 am     Reply with quote

Hello there? Sad


Any help/hint?


Thanks in advance
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue May 28, 2013 10:41 am     Reply with quote

Sorry, I forgot about your post. If no one else answers, I will work on
it sometime later today. (Maybe very late).
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue May 28, 2013 2:19 pm     Reply with quote

I compiled both your programs in v4.141 as I don't have 4.140 installed on my computer anymore. In this version both the programs give an identical list file. You can check this yourself when you look up the list file in your project directory (*.lst) and compare these versions with a compare tool (I like the open source WinMerge tool).

Quote:
First Question: What I'm doing wrong in the second code? its something about SPI configuration( SPI_ENABLE=0) ?
No this isn't a problem. You can delete this parameter as it only has effect when used in combination with the 'enable pin' parameter (ENABLE=PIN_XX), you don't have this parameter.

Quote:
Second Question: PIC sends the clock signal (SPI CLK - 2Mhz) only while It's sending/reading data from the SPI? I'm asking this because when I transmit only 1 byte, I cant see the SPI CLk signal on Oscilloscope, but when I transmit infinite bytes, i can see perfectly the 2Mhz Waveform.
That is how SPI works. You only get a clock when the master is transmitting data. This is also the reason that when reading from a slave the master has to send data as well (often the slave doesn't care what the data from the master is).

Quote:
Third Question: In the first code, the MSB is transmited first right? Is not need to set the first bit to be transmitted as the second code?
The first program is using the hardware SPI and the hardware can only transmit MSB first. For the same reason it doesn't matter in your second program if you specify MSB or leave it out (it is the default).

Perhaps the reason for failure is in the file PruebaTagEmulacion.h, you didn't post it so I used the contents of the first program.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group