|
|
View previous topic :: View next topic |
Author |
Message |
jitun
Joined: 25 Mar 2009 Posts: 5
|
Hardware SPI not working in PIC18F4550 |
Posted: Wed May 27, 2009 1:14 pm |
|
|
I am trying to interface the Nokia 6610 color LCD with a pic18F4550. I can do everything with the LCD by using software spi i.e. bit banging but when I try to do the same using hardware SPI nothing happens at all. Here is the code that i am talking about
Code: |
void nokia_write_dorc(char bytefornokia) // serial write data or command subroutine
{
char caa;
for (caa=8;caa>0;caa--) {
output_low(SCK);
//delay_us(2);
if ((bytefornokia&0x80)==0){output_low(SDO);}
else {output_high(SDO);}
output_high(SCK);
bytefornokia=bytefornokia<<1;
}
} |
The above code snippet uses software SPI(bit banging SPI) but when I tries to use the following the LCD is not working
Code: |
void nokia_write_dorc(char bytefornokia) // serial write data or command subroutine
{
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16);
output_low (SDO);
//output_high (SCK);
//delay_cycles(2);
SSPEN = 1;
spi_write(bytefornokia);
//setup_spi(FALSE);
SSPEN = 0;
} |
I have tried all the clock frequencies in place of "SPI_CLK_DIV_16". I have even tried using timer2 at the same place but it was all in vain. I even tried using the #use SPI but still nothing happened. I tried to compile the code in two different version of CCS compilers (3.249 and 4.038) but still could not make it work. Can anybody please tell me what am i doing wrong that is preventing me from using the hardware SPI In place of the software(bit banging) SPI mode. I have set
#bit SSPEN = 0xFC6.5
The waveforms looks perfectly nice in Proteus simulation also the SPI debugger shows that the correct SPI data is being sent but when I implement it in the actual hardware it is not working. Please help. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 27, 2009 2:57 pm |
|
|
Quote: | setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_16); | Your software SPI code appears to be using SPI mode 0.
The SCLK idles low and the positive clock edge occurs in the center of
the data cell.
http://www.totalphase.com/support/kb/10045/#modes
http://elm-chan.org/docs/spi_e.html
Your setup_spi() statement is using the wrong mode. It's using mode 1.
Put the following #define statements above main(), and put SPI_MODE_0
in place of the middle parameter in your setup_spi() statement.
Code: | #define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H) |
Also, the SDO pin on the 18F4550 is multiplexed with the UART's Rx pin.
Do you have a #use rs232 statement that specifies the hardware UART
pins ? That could be the problem. You can't use the hardware UART
if you are using hardware SPI. |
|
|
Ttelmah Guest
|
|
Posted: Wed May 27, 2009 3:05 pm |
|
|
Start with telling us the clock rate of the chip.
Then, don't reprogram the SPI in the routine. Set it once at the start of your code, then don't fiddle again. Changing settings, (and manually overriding the SDO), could result in unwanted edges being generated.
You want CKE=1, and CKP=0, to generate the rising clock edge, after the data bit is sent, duplicating what your software does. This needs the SPI_XMIT_L_TO_H value added to your SPI setup.
This is probably the main problem.
Best Wishes |
|
|
jitun
Joined: 25 Mar 2009 Posts: 5
|
|
Posted: Wed May 27, 2009 10:46 pm |
|
|
@PCM programmer
I have tried using "SPI_XMIT_L_TO_H" but it still didn't work. However I still tried it again now and it didn't work. I am not using the UART.
@Ttelmah
I am using a 20MHz crystal with the HS fuse set. The following is the fuse and clock configuration
Code: | #fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,CPUDIV1,VREGEN
#use delay(clock=20000000) |
Since the Nokia color LCD uses 9 bit spi I have to manually override the SDO pin to generate the 9th bit. Have a look at the code
Code: | void nokia_write_dorc(char bytefornokia) // serial write data or command subroutine
{
/*char caa; //Software SPI working fine
for (caa=8;caa>0;caa--) {
output_low(SCK);
//delay_us(2);
if ((bytefornokia&0x80)==0){output_low(SDO);}
else {output_high(SDO);}
output_high(SCK);
bytefornokia=bytefornokia<<1;
}*/
output_low (SDO); //Hardware SPI never works
output_low (SCK);
SSPEN = 1;
spi_write(bytefornokia);
//while(!spi_data_is_in())
SSPEN = 0;
}
void gclcd_cmd(int8 cmd)
{
SSPEN = 0; // turn off hardware SPI allowing us direct access to SPI in/out pins
output_low (SCK);
delay_cycles(1);
output_low(CS); // enable chip
output_low (SDO); // output low on data out (9th bit low = command)
output_high (SCK);
nokia_write_dorc(cmd);
delay_cycles(1);
output_high(CS); // disable
}
// It sends data to the gclcd
void gclcd_data(int8 data)
{
SSPEN = 0; // turn off hardware SPI allowing us direct access to SPI in/out pins
output_low (SCK);
delay_cycles(1);
output_low(CS); // enable chip
output_high (SDO); // output high on data out (9th bit high = data)
output_high (SCK);
nokia_write_dorc(data);
delay_cycles(1);
output_high(CS); // disable
} |
As I said earlier using SPI_XMIT_L_TO_H also didn't work.
Please do reply. |
|
|
Ttelmah Guest
|
|
Posted: Thu May 28, 2009 2:22 am |
|
|
My comment about stop fiddling with the SPI pins, still applies. You risk generating extra clock edges, and if you do, it won't work.
Now, 20MHz, implies that the SPI will generate clocks at 5MHz, 1.25MHz, or 312500Hz from the standard clock. Your 'soft' code, will probably take about 20 instructions to test each single bit, three for each bit set/reset (three in each loop), and perhaps another ten for the arithmetic and loop. Probably something in the order of 40+ instructions for the loop. Probably even slightly more than this. Less than 1/3rd the rate of your slowest SPI setting. Now you say you have tried using timer2, but not what rate you programmed. So, try:
setup_timer_2(T2_DIV_BY_2,25,1);
This will give a SPI clock of 50KHz (timer2/2), which will be in the same order of speed as the software solution.
Have one SPI setup, just selecting SPI_MODE_0, from PCM's defines (much the safest way of setting up the SPI, to get the settings right), so:
setup_spi(SPI_MASTER|SPI_MODE_0|SPI_CLK_T2);
And get rid completely of changing the SDI/SDI pins. The _hardware_ sets the clock low as soon as the SPI port is setup. You don't need to touch the lines again.
Best Wishes |
|
|
jitun
Joined: 25 Mar 2009 Posts: 5
|
|
Posted: Thu May 28, 2009 11:29 am |
|
|
it worked with this setting
Code: |
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);
|
But it needs a delay of minimum 25us after each SPI_write()? Why? and how can i make it work without the delay? |
|
|
|
|
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
|