View previous topic :: View next topic |
Author |
Message |
doug_h
Joined: 26 Feb 2004 Posts: 11
|
Mysterious SPI right shift problem |
Posted: Tue Mar 02, 2004 12:53 am |
|
|
I'm having a problem with the spi_read / spi_write functions. I have a simple test program that writes to the configuration registers on the MCP2515 CAN controller and then reads back the values. The problem is the values I'm reading back have been right shifted one position. What am I doing wrong here???
Here's the output of the code:
Code: |
CAN CFG TEST
Resetting the MCP2515
Reading registers...
CANSTAT = 40
CANCTRL = 43
CNF1 = 80
CNF2 = 00
CNF3 = 00
Writing status registers...
Setting CNF1 = 90
Setting CNF2 = 92
Setting CNF3 = 84
Reading back status registers...
CANSTAT = 00
CANCTRL = 00
CNF1 = 48
CNF2 = 49
CNF3 = 42
Running... |
And here's the source code:
Code: | #include <16F876A.h>
#device ICD=TRUE
#fuses HS,NOLVP,NOWDT,PUT
#use delay(clock=8000000)
#use rs232(DEBUGGER)
#define CAN_DO_DEBUG TRUE
//define the SPI control pins for PIC16F876A 28 PDIP
#define MCP2515_CS PIN_B5
#define MCP2515_RESET_PIN PIN_A0
#define READCMD 0x03
#define WRITECMD 0x02
#include <mcp2515.c>
#define LED1 PIN_A0
int rreg;
void ResetMCP2515(void)
{
output_high(MCP2515_CS);
output_low(MCP2515_RESET_PIN);
delay_us(10);
output_high(MCP2515_RESET_PIN);
}
int ReadRegister(int regaddr)
{
output_low(MCP2515_CS);
spi_write(READCMD);
spi_write(regaddr);
rreg = spi_read(0);
output_high(MCP2515_CS);
return(rreg);
}
void WriteRegister(int regaddr, int regvalue)
{
output_low(MCP2515_CS);
spi_write(WRITECMD);
spi_write(regaddr);
spi_write(regvalue);
output_high(MCP2515_CS);
}
void ConfigureMCP2515(void)
{
int cnfr1 = 0x90;
int cnfr2 = 0x92;
int cnfr3 = 0x84;
can_debug("Setting CNF1 = %2x\n", cnfr1);
can_debug("Setting CNF2 = %2x\n", cnfr2);
can_debug("Setting CNF3 = %2x\n", cnfr3);
WriteRegister(CANCTRL, 0x80); //set to config mode
WriteRegister(CNF1, cnfr1);
WriteRegister(CNF2, cnfr2);
WriteRegister(CNF3, cnfr3);
WriteRegister(CANCTRL, 0x00); //reset to normal mode
}
void main()
{
can_debug("\n\nCAN CFG TEST\n");
setup_spi(spi_master | spi_h_to_l);
can_debug("\nResetting the MCP2515\n");
ResetMCP2515();
can_debug("\nReading registers...\n");
can_debug("CANSTAT = %2x\n", ReadRegister(CANSTAT));
can_debug("CANCTRL = %2x\n", ReadRegister(CANCTRL));
can_debug("CNF1 = %2x\n", ReadRegister(CNF1));
can_debug("CNF2 = %2x\n", ReadRegister(CNF2));
can_debug("CNF3 = %2x\n", ReadRegister(CNF3));
can_debug("\nWriting status registers...\n");
ConfigureMCP2515();
can_debug("\r\nReading back status registers...\n");
can_debug("CANSTAT = %2x\n", ReadRegister(CANSTAT));
can_debug("CANCTRL = %2x\n", ReadRegister(CANCTRL));
can_debug("CNF1 = %2x\n", ReadRegister(CNF1));
can_debug("CNF2 = %2x\n", ReadRegister(CNF2));
can_debug("CNF3 = %2x\n", ReadRegister(CNF3));
can_debug("\nRunning...");
while(TRUE) //blink the LED so we know we're running
{
output_low(LED1);
delay_ms(500);
output_high(LED1);
delay_ms(500);
}
}
|
Thanks in advance for any help you can give me.
Best regards,
Doug |
|
|
mpfj
Joined: 09 Sep 2003 Posts: 95 Location: UK
|
|
Posted: Tue Mar 02, 2004 7:16 am |
|
|
Just a quick thought ... might the SPI clock be upside down ? This might clock the data at the wrong point (possibly just after it has changed) ... |
|
|
Charlie U
Joined: 09 Sep 2003 Posts: 183 Location: Somewhere under water in the Great Lakes
|
|
|
doug_h
Joined: 26 Feb 2004 Posts: 11
|
|
Posted: Tue Mar 02, 2004 9:59 am |
|
|
I tried changing the setup_spi() to use the spi_l_to_h flag to invert the clock, but now I get nothing back from the MCP2515. Is there another way to implement the clock change you suggested? |
|
|
mpfj
Joined: 09 Sep 2003 Posts: 95 Location: UK
|
|
Posted: Tue Mar 02, 2004 10:13 am |
|
|
Actually there are 4 SPI modes ... 00, 01, 10 and 11
As you already know, the clock can be idle high / active low, or idle low / active high. However, the data sample / change point can also change ... it can be on either the rising or falling edge of the clock !!
Check the Microchip datasheets for the bits CKE (ClocK Edge) and CKP ((ClocK Polarity) ...
Unfortunately CCS don't directly support all 4 modes via the setup_spi() function. You'll either have to set the bits manaully, or look at this forum link ...
http://www.ccsinfo.com/forum/viewtopic.php?t=8747&highlight=spi+modes |
|
|
doug_h
Joined: 26 Feb 2004 Posts: 11
|
|
Posted: Tue Mar 02, 2004 10:33 am |
|
|
Aha! This could indeed be the problem - I'll give it a try and report back.
Thanks |
|
|
doug_h
Joined: 26 Feb 2004 Posts: 11
|
|
Posted: Tue Mar 02, 2004 2:57 pm |
|
|
Problem solved!
I changed the SPI setup code from this:
Code: |
setup_spi(SPI_MASTER | SPI_H_TO_L);
|
To this:
Code: |
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_XMIT_L_TO_H);
|
And now everything is working.
Thanks a bunch guys! |
|
|
Guest
|
|
Posted: Sat Mar 15, 2008 5:20 am |
|
|
Hi
Does someone know how ideological scheme looks to this programme inserted by doug_h ? |
|
|
|