 |
 |
View previous topic :: View next topic |
Author |
Message |
SkeeterHawk
Joined: 16 Oct 2010 Posts: 36 Location: Florissant, CO
|
Buffer for spi_xfer? |
Posted: Thu Mar 27, 2025 5:13 pm |
|
|
Hello again, fellow programmers.
I have been trying to utilize the SPI hardware on the PIC on my current project because I have varying data sizes, and a bunch of peripherals to talk to quickly.
Both the Master and the Slave are PIC18F57Q84
My issue is with my Slave. When I am writing data to it, the register gets populated just fine as seen on the debugger, but when I go to read that data back to my Master, it transmits the address of the register that I am trying to read. There is obviously a buffer that I need to clear as it is completely disregarding the Data component of my spi_xfer statement. Here is my initialization code for this port:
Code: | #pin_select SS1IN=PIN_D0
#pin_select SDO1=PIN_C2
#pin_select SCK1IN=PIN_C3
#pin_select SDI1=PIN_C4
#use spi (STREAM = SPI, SLAVE, SPI1, ENABLE=PIN_D0, MODE=3) |
And here is the code that is sending or receiving data:
Code: | void CheckPumpCommunication(void)
{
int8 AddressIn, // Register to hold the address byte that the Pump Master is sending
MaskedAddress; // We mask the R/W bit, and then use this register for the basic address
if(input(PumpMaster_CS)) // Check to see if the Pump Master is asserting our Chip Select input, and if it is high (not asserted) return back to the calling program
{
return; // Nope, no chip select here, so head on back
}
AddressIn = spi_xfer(SPI, 0x00, 8); // Load the address register with the data that is on the SPI bus so we can see where we go from here
MaskedAddress = (AddressIn & (0xFF ^ Bit_SPI_Mask_Read)); // Mask the MSB of the address to nullify the R/W bit so we can see what the root address is
switch(MaskedAddress)
{
case 1: // There is no case "0" because that is the present/not-preent bit that is kept local to the Main Pump Board, so we are starting with the Valve Set Point byte
if ((AddressIn & Bit_SPI_Mask_Read) > 0) // Check to see if the MSB is set, meaning that this is a Read operation
{
spi_xfer(SPI, Reg_ValveSP, 8); // Send the current valve setpoint over to the Pump Master Module
}
else // If the MSBit is not set, this must be a Write operation
{
Reg_ValveSP = spi_xfer(SPI, 0x00, 8); // Read the register that the Pump Master wants to write to the current valve setpoint
SetUpValves(); // Call the routine to set the valves to the current state
}
break; |
So, the MSB is my "Read" bit and the whole address is one byte. When I write this register, I am sending 0x01, and when reading I am sending 0x81. When writing, the register gets written perfectly, but every time I read on any register, it only reads back the address of the register, so if I read 0x01, it will output 0x81 to the Master...which is the address for the Read command for that register. If I read a 16-bit register, there is still an 8-bit address, so it comes out with the address as the MSByte and zeros as the remaining two nybbles. I have tried to write a HEX number to the Master and the address is still sent. I removed my references to the data size and stream name, and it still didn't work with just the data component.
If I was writing this in assembly, I would know where to go by clearing the Buffer Full Flag and making sure that the Buffer had the right data, but I am not sure where to go from here with the spi_xfer command? I didn't see in the documentation that it has the ability to "echo" the previous command.
I am using compiler version 5.114. _________________ Life is too short to only write code in assembly... |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19763
|
|
Posted: Fri Mar 28, 2025 7:58 am |
|
|
You have a fundamental misunderstanding of the difference between slave
select, and enable.
In SPI, on a slave, the slave select line is a signal that needs to go true
before a transaction to say that the slave hardware should be selected on
this device. The enable line is a line operated on a per byte basis to
synchronise the transferred bytes. You are trying to use the slave select
line as an enable. |
|
 |
SkeeterHawk
Joined: 16 Oct 2010 Posts: 36 Location: Florissant, CO
|
|
Posted: Fri Mar 28, 2025 11:42 am |
|
|
Quote: | You have a fundamental misunderstanding of the difference between slave
select, and enable.
|
You are absolutely right, Ttelmah. I have been reading the forum like a crazy person and this post (https://www.ccsinfo.com/forum/viewtopic.php?t=60199&highlight=spi) made me think that I had to assign the Enable to the same pin as the SS.
I am assuming that I don't need the Enable line then, but pardon my ignorance, I am not understanding how a framing signal for a byte would cause the buffer to echo the last command. Thanks so much for your patience! _________________ Life is too short to only write code in assembly... |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19763
|
|
Posted: Sat Mar 29, 2025 11:50 pm |
|
|
What you need is the line you are sending as a chip select, going to the
slave select on the slave (logical). Don't setup enable in the #use.
Have a read of section 36.4.2 and onwards in the data sheet. Particularly
the diagram about SS (though this shows SS going high, and it's default
configuration is to go low). The polarity is controlled by the SSP bit.
Now for #use spa, CCS don't mention the slave select. For setup_spi
it is an option. However they do default to enabling the SSET bit which
means that if it is setup with pin select it will work.
There is one annoyance though. The data sheet says that the default for
the SSP polarity bit is '1', which means the select will be active low.
For some (unknown) reason CCS set this to 0, so the select becomes
active high. To use the more normal active low chip select, you have to
add:
Code: |
#bit SSP=getenv("SSP1CON1").2
//Then at the start of your main:
SSP=1;
|
This then gives the active low select.
I've suggested to CCS, that they add support for this with polarity
control, and also to handle the option for a hardware select output
that this chip implements. |
|
 |
|
|
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
|