|
|
View previous topic :: View next topic |
Author |
Message |
Armando
Joined: 02 May 2013 Posts: 16 Location: Venezuela
|
PIC 16F886 SPI CONFIGURATION |
Posted: Thu May 02, 2013 1:34 pm |
|
|
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
|
|
Posted: Thu May 02, 2013 2:29 pm |
|
|
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
|
|
Posted: Thu May 02, 2013 2:39 pm |
|
|
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
|
|
Posted: Thu May 02, 2013 4:33 pm |
|
|
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
|
|
Posted: Thu May 02, 2013 7:02 pm |
|
|
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
|
|
Posted: Thu May 02, 2013 9:32 pm |
|
|
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
|
|
Posted: Thu May 02, 2013 10:04 pm |
|
|
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
|
|
Posted: Fri May 03, 2013 1:27 pm |
|
|
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
|
|
Posted: Fri May 03, 2013 5:45 pm |
|
|
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! |
|
|
Armando
Joined: 02 May 2013 Posts: 16 Location: Venezuela
|
|
Posted: Sun May 12, 2013 5:47 pm |
|
|
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
|
|
|
Armando
Joined: 02 May 2013 Posts: 16 Location: Venezuela
|
|
Posted: Sun May 12, 2013 7:23 pm |
|
|
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
|
|
Posted: Tue May 28, 2013 9:04 am |
|
|
Hello there?
Any help/hint?
Thanks in advance |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 28, 2013 10:41 am |
|
|
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
|
|
Posted: Tue May 28, 2013 2:19 pm |
|
|
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. |
|
|
|
|
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
|