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

Hardware SPI
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Atarek



Joined: 07 Sep 2017
Posts: 9

View user's profile Send private message

Hardware SPI
PostPosted: Thu Sep 07, 2017 2:57 am     Reply with quote

Hi everyone,

I need advice in something,
I am trying to interface MFRC522 using hardware SPI. However, I fail every time. I thought to share the code, and maybe someone can help me.

The description from the MFRC522's datasheet states the following:

Quote:
from section 8.1.2,
Data on both MOSI and MISO lines must be stable on the rising edge of
the clock and can be changed on the falling edge,
Data is provided by the MFRC522 on the falling clock edge and is stable
during the rising clock edge,


Hence we can conclude that data transmission mode is Mode 0, right???

Now i use the following code in the main.h
Code:
#use SPI(MASTER, DO = PIN_C5, DI = PIN_C4, CLK = PIN_C3,MODE = 0, ENABLE = PIN_E2, BITS = 8, FORCE_HW)
#define PIN_CS   PIN_E2 //MFRC522 SPI chip select pin (NRSTPD)


and when i try to write to the MFRC522 i used the following code according to the device instructions:
Code:
   /*
   section 8.1.2.3
   The MSB of the first byte defines the mode used.
   To write data to the MFRC522 the MSB must be set to logic 0.
   Bits 6 to 1 define the address and LSB is set to logic 0;
   /*

   output_bit(PIN_CS, 0);
   spi_write(reg & 0x7E);
   spi_write(value);
   output_bit(PIN_CS, 1);


I hope someone will be able to help me.
Thank you in advance,

Atarek
Ttelmah



Joined: 11 Mar 2010
Posts: 19553

View user's profile Send private message

PostPosted: Thu Sep 07, 2017 3:26 am     Reply with quote

You are mixing two ways of using the SPI.

If you look at the manual for #use spi, you will see no mention of spi_write.
The command to use with #use spi, is spi_xfer.

spi_write is the older command for use with setup_spi. They are two _not mixable_ ways of using the spi.

You also need to read the reply (even when it is not used), otherwise the spi commands will return immediately, when the byte is transferred to the hardware.

Now you don't tell us your chip, but assuming your chip does have the hardware SPI on the pins you are using:
Code:

#USE SPI (SPI1, MODE=0, BITS=8, STREAM=MFRC)

//Then to send to it:
    int8 dummy;

    output_low(PIN_CS);
    dummy=spi_xfer(MFRC, reg & 0x7E);
    dummy=spi_xfer(value);
    output_high(PIN_CS);


The clock is shown as idling low, so yes this is mode 0.

Reading the returned byte, ensures the actual transfer has completed before you raise the CS.
Selecting the peripheral by name, forces the hardware pins to be used.
Atarek



Joined: 07 Sep 2017
Posts: 9

View user's profile Send private message

PostPosted: Thu Sep 07, 2017 6:38 am     Reply with quote

Thank you Ttelmah for your quick feedback,
but it seems that i have another problem. When i try to use the hardware SPI, the micro controller does not exit any routine that uses hardware SPI.

So that when i use the below code in the main.c
Code:
   MFRC522_init(); //function that uses SPI
   delay_ms(10);
   
   output_high(LEDB);
   output_high(LEDR);
   output_high(LEDG);
   delay_ms(50);
   output_low(LEDB);
   output_low(LEDR);
   output_low(LEDG);

the leds never blink.

By the way i am using 18F452.

Thanks in advance,
Atarek
Ttelmah



Joined: 11 Mar 2010
Posts: 19553

View user's profile Send private message

PostPosted: Thu Sep 07, 2017 7:16 am     Reply with quote

You really need to show us your init code.
Atarek



Joined: 07 Sep 2017
Posts: 9

View user's profile Send private message

PostPosted: Sun Sep 10, 2017 7:00 am     Reply with quote

here it is

Code:
void MFRC522_init(void)   //MFRC522 chip initialization
{
   MFRC522_writeReg(TModeReg, 0x8D);     
   MFRC522_writeReg(TPrescalerReg, 0x3E);
   MFRC522_writeReg(TReloadRegH, 0x00);
   MFRC522_writeReg(TReloadRegL, 0x30);   
   MFRC522_writeReg(TxASKReg, 0x40);   
   MFRC522_writeReg(ModeReg, 0x3D);   
   
   MFRC522_AntennaOn();
}


I tried Hardware SPI using
Code:
 spi_write(); spi_read();

The code works, but when i try to monitor the signal bus, it is not sending the same data, (the MRFC522 is not working).

By the way the code is based on the library used in the following link:
http://microcontrolandos.blogspot.com.eg/2014/02/pic-rfid-mfrc522.html

Are there some condititions where one cannot substitute software SPI (bit banging) for Hardware SPI, (maybe MSB first) ?


Regards
Atarek
temtronic



Joined: 01 Jul 2010
Posts: 9246
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sun Sep 10, 2017 7:40 am     Reply with quote

As far as I know the only 2 things are different between HW vs SW SPI

1) SW doesn't have _normally_ interrupt capabilty

2) speed, SW will be _normally_ slower

How the data gets sent to the SPI device depends upon how the programmer sets up the SPI code. A look at the listing, comparing HW vs SW SPI will show what's going on.

Jay
Atarek



Joined: 07 Sep 2017
Posts: 9

View user's profile Send private message

PostPosted: Sun Sep 10, 2017 7:57 am     Reply with quote

Hi Temtronic,

Thank you for the quick feedback,

the list file of the software SPI
    .................... SoftSPI_write(reg & 0x7E);
    0052: MOVF 65,W
    0054: ANDLW 7E
    0056: MOVWF 67
    0058: MOVWF 6D
    005A: RCALL 000E
    .................... SoftSPI_write(value);
    005C: MOVFF 66,6D
    0060: RCALL 000E


and for the hardware SPI
    .................... spi_write(reg & 0x7E);
    002E: MOVF 65,W
    0030: ANDLW 7E
    0032: MOVWF 67
    0034: MOVF FC9,W
    0036: MOVFF 67,FC9
    003A: BTFSS FC7.0
    003C: BRA 003A
    .................... spi_write(value);
    003E: MOVF FC9,W
    0040: MOVFF 66,FC9
    0044: BTFSS FC7.0
    0046: BRA 0044


They are different, how to make it work now?

Thanks in advance,
Atarek
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Sep 10, 2017 9:31 am     Reply with quote

Of course they are different. The software SPI uses a bit-banging routine
and the hardware SPI talks to the hardware SPI registers.

In the code below, you are doing something wrong. You have specified
a Chip Select signal with the ENABLE parameter in the #use spi() statement,
as shown in bold below:
Quote:
#use SPI(MASTER, DO = PIN_C5, DI = PIN_C4, CLK = PIN_C3,MODE = 0, ENABLE = PIN_E2, BITS = 8, FORCE_HW)

This ENABLE (chip select) signal operates on a per byte basis. But that's
not what you want for this driver.

The MFRC522 data sheet says:
Quote:
Remark:
The signal NSS must be LOW to be able to send several bytes in one
data stream
. To send more than one data stream NSS must be set
HIGH between the data streams.

NSS is their name for Slave Select. The 'N' means its active state is
a logic low level.


Delete the 'ENABLE = PIN_E2' setting from your #use spi() statement.
Then your #use spi() statement should look like this:
Code:
#use SPI(MASTER, DO = PIN_C5, DI = PIN_C4, CLK = PIN_C3, MODE = 0, BITS = 8, FORCE_HW)


In the code below, you are manually handling chip select, and you are
keeping it low for the 2-byte transmission. This is the correct way to do it:
Quote:

output_bit(PIN_CS, 0);
spi_write(reg & 0x7E);
spi_write(value);
output_bit(PIN_CS, 1);
Atarek



Joined: 07 Sep 2017
Posts: 9

View user's profile Send private message

PostPosted: Mon Sep 11, 2017 12:33 am     Reply with quote

HI PCM Programmer,

Thank you for the explanation,
but in the last section you mentioned the following

Quote:
In the code below, you are manually handling chip select, and you are
keeping it low for the 2-byte transmission. This is the correct way to do it:
Quote:

output_bit(PIN_CS, 0);
spi_write(reg & 0x7E);
spi_write(value);
output_bit(PIN_CS, 1);


Do you mean that this is the correct way to do it?

Thanks in advance,
Atarek
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 11, 2017 12:54 am     Reply with quote

Atarek wrote:

Do you mean that this is the correct way to do it?

To make sure that you understood, I put that exact statement in my post !
Here is my post again, with that line shown in bold:
Quote:

In the code below, you are manually handling chip select, and you are
keeping it low for the 2-byte transmission. This is the correct way to do it:

output_bit(PIN_CS, 0);
spi_write(reg & 0x7E);
spi_write(value);
output_bit(PIN_CS, 1);
Atarek



Joined: 07 Sep 2017
Posts: 9

View user's profile Send private message

PostPosted: Mon Sep 11, 2017 1:10 am     Reply with quote

PCM Programmer,

Thank you for your effort to make sure that i understand the concept,

according to what you said the correct answer is to make NSS logic high between the 2 byte transmission,
Code:

output_bit(PIN_CS, 0);
spi_write(reg & 0x7E);
output_bit(PIN_CS, 1);

output_bit(PIN_CS, 0);
spi_write(value);
output_bit(PIN_CS, 1);


Thanks in advance,

Atarek
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 11, 2017 2:07 am     Reply with quote

Atarek wrote:

output_bit(PIN_CS, 0);
spi_write(reg & 0x7E);
output_bit(PIN_CS, 1);

output_bit(PIN_CS, 0);
spi_write(value);
output_bit(PIN_CS, 1);


That is absolutely NOT what I said.

I'm done with this. I cannot talk to someone who does the opposite of
what I say. I'm sorry, I'm done.
Atarek



Joined: 07 Sep 2017
Posts: 9

View user's profile Send private message

PostPosted: Mon Sep 11, 2017 4:55 am     Reply with quote

Maybe this
Code:

spi_write(reg & 0x7E);
output_bit(PIN_CS, 1);
spi_write(value);


Regards,
Atarek
temtronic



Joined: 01 Jul 2010
Posts: 9246
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Sep 11, 2017 5:13 am     Reply with quote

What PCM P has said...
Quote:

In the code below, you are manually handling chip select, and you are
keeping it low for the 2-byte transmission. This is the correct way to do it:

output_bit(PIN_CS, 0);
spi_write(reg & 0x7E);
spi_write(value);
output_bit(PIN_CS, 1);


IS THE WAY TO DO IT !!!

I understand English is not everyone's first language, but the code segment that PCM P has posted for you DOES WORK.
No other code you've shown will work.

Hopefully you've got an oscilloscope to view the data stream. If not, save your coins and buy one. Even a 30 year old, 2 channel analog scope, will work fine for 99% of PIC projects. I know as that's what I use, daily.

PCM P's code works, I've seen it on my scope. Normally I don't take time to code/compile/test but his does work, so please use it as posted.

Something not mentioned is power supply levels. Most peripheral 'devices' are designed for 3 volts, and PICs are rated at 5 volts ,unless the 'L' version. The MFRC522 IS a 3 volt device, so what PIC are you using? It is critical information we need to know!! You cannot directly connect 3 V devices to 5V PICs and have them work !!

Jay
Atarek



Joined: 07 Sep 2017
Posts: 9

View user's profile Send private message

PostPosted: Mon Sep 11, 2017 6:37 am     Reply with quote

thank you temtronic for clarification,
forgive my igonorance,

I use the scope as you said, and here is the results
soft SPI
[img]https://drive.google.com/file/d/0By2rhMw0TAvNRWM0YmhkV1lKWDA/view[/img]

Hard SPI
[img]https://drive.google.com/file/d/0By2rhMw0TAvNY0ZCZ2E4MUs0Yms/view[/img]

please advise
Regards,

Atarek
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  Next
Page 1 of 2

 
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