View previous topic :: View next topic |
Author |
Message |
Pyrofer
Joined: 13 Sep 2006 Posts: 16
|
9Bit SPI and inline asm |
Posted: Wed Sep 13, 2006 7:14 am |
|
|
Hi, I want to use 9bit spi to a device, but the hardware only does 8bit.
So, I am manualy toggling the pins with code like this,
Code: |
output_low(clockpin);
output_bit(datapin,address);
output_high(clockpin);
output_low(clockpin);
output_bit(datapin,data&&128);
output_high(clockpin);
output_low(clockpin);
output_bit(datapin,data&&64);
output_high(clockpin);
output_low(clockpin);
output_bit(datapin,data&&32);
output_high(clockpin);
etc
|
I would like to do one manual toggle, then use hardware spi but when I enable hardware SPI it stops me changing the pins manualy and nothing works.
My only solution left to speed things up for output is to make this an inline ASM function but I dont know asm.
Can anybody help? |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Wed Sep 13, 2006 8:00 am |
|
|
OK - silly question but what SPI device are you using that expects 9 bits? _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Pyrofer
Joined: 13 Sep 2006 Posts: 16
|
|
Posted: Wed Sep 13, 2006 8:00 am |
|
|
Nokia 6100 LCD.
No, i cant change the input mode to anything else. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
|
Pyrofer
Joined: 13 Sep 2006 Posts: 16
|
|
Posted: Wed Sep 13, 2006 9:09 am |
|
|
I cant get the SPI port to work as I need 9 bits.
If you can tell me how to make the hardware SPI port output 9bit I will leap up and down screaming eureka!
I have the port spare, and am in fact using the pics for my manual bashing.
How to get 9bit out of hardware spi port?
Pic 18F2620 |
|
|
Ttelmah Guest
|
|
Posted: Wed Sep 13, 2006 9:26 am |
|
|
You don't say what chip is involved, butyou can simply toggle out the extra bit.
The 'answer', is the 'SSPEN' bit. When the SSP is enabled (this bit set), it takes over control of the output on the SDO/SCK lines. However when this bit is cleared, you can control the lines.
Make #bit declaration and control this bit directly.
Remember to _leave_ the clock level, as you want it to be when you next change the line. So:
Code: |
SSPEN=0;
output_low(clockpin);
output_bit(datapin,extrabit);
output_high(clockpin);
delay_us(1);
output_low(clockpin);
SSPEN=1;
//Now use the SPI command to send the next 8 bits.
|
Best Wishes |
|
|
Pyrofer
Joined: 13 Sep 2006 Posts: 16
|
|
Posted: Wed Sep 13, 2006 9:51 am |
|
|
THANK YOU!!
Oh god that will save me so much trouble if it works. Ill compile it tonight and hopefully be jumping for joy as previously suggested.
The SPI mode is low to high, so the hardware SPI port leaves the pin HIGH
at the end of a write...
So i assume,
Code: |
SSPEN=0;
output_low(clockpin);
output_bit(datapin,extrabit);
output_high(clockpin);
SSPEN=1;
SPI_WRITE(data);
|
is ok? As the pin is left High by my code and that is the state the hardware SPI expects it to be in, pulled low at the start of the spi send and left high at the end of the spi routine.
I will experiment tonight and let you know, but i hold out high hopes! |
|
|
Pyrofer
Joined: 13 Sep 2006 Posts: 16
|
|
Posted: Wed Sep 13, 2006 5:28 pm |
|
|
Thank you. Dance done, all working. Hardware SPI now takes care of 8bits out of the 9. |
|
|
Marcoose
Joined: 09 Dec 2006 Posts: 5 Location: Ontario, Canada
|
|
Posted: Fri Mar 09, 2007 2:21 pm |
|
|
Sorry this is an old post, but I just found it and it was exactly what I needed! (for the same Nokia issue) Thanks so much for the great tip... gotta love using hardware when it's available! |
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Mon Dec 24, 2007 11:36 pm |
|
|
Hey all,
I am attempting to interface an 18F2550 with a Nokia 6610 LCD, which has (apparently) a Phillips PCF8833 controller. I've come to that conclusion since the connector is orange and the LCD also has those large gold-plated connectors. Anyway, I wrote some code of my own; it seems to be running properly in the MPLAB simulator (though I have to manually set the SSPSTAT.0 bit for it to continue execution). However when I try to interface the LCD (physically) it just doesn't work. Would someone be so kind as to point out if I've made any coding mistakes. Thanks.
Regards.
Rohit
PS: I hope the documentation is adequate. I'm using v4.038 of the compiler.
Code: |
// This is the prototype for a Nokia 6610
// 132*132 pixel colour LCD driver.
//
// Rohit de Sa
// 24Dec07
// ver1.0
#include <18F2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
// defines for pins
#define hard_cs pin_a1 //Chip select
#define hard_res pin_a2 //Reset
#define hard_clk pin_b1 //SPI clock
#define hard_sdo pin_c7 //SPI data out
// defines for constants
#define sleepout 0x11 //from datasheet
#define invon 0x21
#define colmod 0x3a
#define setcon 0x25
#define dispon 0x29
#define ramwr 0x2c
#define paset 0x2b
#define caset 0x2a
#bit SSPEN = 0xfc6.5
int1 command=0;
int1 data=1;
int i=0;
void write_command (int command)
{
SSPEN=0;
output_low(hard_clk);
delay_us(2);
output_low(hard_sdo);
delay_us(2);
output_high(hard_clk);
delay_us(2);
SSPEN=1;
spi_write(command);
delay_us(2);
}
void write_data (int data)
{
SSPEN=0;
output_low(hard_clk);
delay_us(2);
output_high(hard_sdo);
delay_us(2);
output_high(hard_clk);
delay_us(2);
SSPEN=1;
spi_write(data);
delay_us(2);
}
void main (void)
{
output_high(hard_cs); //initializing the LCD
output_high(hard_clk);
output_high(hard_sdo);
output_low(hard_res); //holding the LCD in reset
output_high(pin_a0); //pin connected to LCD backlight
setup_spi(spi_master|spi_h_to_l|spi_clk_div_64);
delay_ms(2); //are these delays necessary?
output_high(hard_res); //bringing LCD out of reset
delay_ms(2);
output_low(hard_cs); //enabling LCD
delay_us(2);
write_command(sleepout);
write_command(invon);
write_command(colmod);
write_data(0x03);
write_command(setcon);
write_data(0x10);
write_command(dispon);
write_command(paset);
write_data(0x00);
write_data(131);
write_command(caset);
write_data(0x00);
write_data(131);
write_command(ramwr); //shading part of the LCD white
for (i=0;i<255;i++)
{
write_data(0xff);
write_data(0xff);
write_data(0xff);
}
delay_us(2);
output_high(hard_cs); //deselecting the LCD
while (true)
{
}
}
|
|
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Tue Dec 25, 2007 12:44 am |
|
|
I just checked the code again.
In the definition/declarations there are two statements
Code: |
int1 command=0;
int1 data=1;
|
Those are residues from an older (now scrapped) version of the code. Though I have removed those lines, the LCD still doesnt work.
Rohit |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Dec 25, 2007 1:22 am |
|
|
Quote: | setup_spi(spi_master | spi_h_to_l | spi_clk_div_64);
However when I try to interface the LCD (physically) it just doesn't work.
|
You have selected SPI Mode 2. I can tell this from the code below:
Code: |
#define SPI_MODE_0_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1 (SPI_L_TO_H)
#define SPI_MODE_1_0 (SPI_H_TO_L)
#define SPI_MODE_1_1 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
|
Look at the timing diagrams for the four SPI modes, down at the
bottom of the following web page:
http://elm-chan.org/docs/spi_e.html
It shows that in Mode 2, SCLK idles at a high level and it samples
data on the falling edge.
Download the data sheet for the LCD controller:
http://www.nxp.com/acrobat_download/datasheets/PCF8833_1.pdf
Look at the SPI timing diagrams on pages 71 to 73. They show that
SCLK must idle at a low level, and sample data on the rising edge.
(The rising edge is shown to occur in the middle of the data cell).
So SPI mode 2 is not correct. It's actually using mode 0.
Look at this SPI mode timing diagram, or the other one above:
http://www.totalphase.com/support/articles/article03/#modes
This shows the timing for mode 0.
Then use SPI_MODE_0_0 constant from the #define statements above,
and put it in the middle of the setup_spi() statement. Add those four
#define statements to your program.
Also, you have code that initializes the SCLK line to a high level.
That needs to be fixed. And also, you have code that manually
clocks out one bit of data. That code is not correct. It needs to be
made more like Ttelmah's code. Change the data, then issue the
clock pulse. Then set the clock line to the idle state (a low level). |
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Tue Dec 25, 2007 6:44 am |
|
|
Thanks PCM Programmer. I made adjustments as you mentioned. The command sequence is similar to Ttelmah's. But it still is not working. Its the same as before - only the LCD backlight turns on. Is there something I've missed?
Code: |
#include <18F2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
// defines for pins
#define hard_cs pin_a1 //Chip select
#define hard_res pin_a2 //Reset
#define hard_clk pin_b1 //SPI clock
#define hard_sdo pin_c7 //SPI data out
// defines for constants
#define sleepout 0x11 //from datasheet PCF8833
#define invon 0x21
#define colmod 0x3a
#define setcon 0x25
#define dispon 0x29
#define ramwr 0x2c
#define paset 0x2b
#define caset 0x2a
#bit SSPEN = 0xfc6.5
int i=0;
void write_command (int command)
{
// output_low(hard_cs); //removed these because LCD gets deselected
// delay_us(1); //between data writes. Data gets corrupted
SSPEN=0; //due to this.
output_low(hard_sdo); //Setting bit 8 = 0 for commands
delay_us(1);
output_high(hard_clk);
delay_us(1);
output_low(hard_clk);
delay_us(1);
SSPEN=1;
spi_write(command);
delay_us(1);
// output_high(hard_cs);
}
void write_data (int data)
{
// output_low(hard_cs);
// delay_us(1);
SSPEN=0;
output_high(hard_sdo); //Setting bit 8 = 1 for data
delay_us(1);
output_high(hard_clk);
delay_us(1);
output_low(hard_clk);
delay_us(1);
SSPEN=1;
spi_write(data);
delay_us(1);
// output_high(hard_cs);
}
void main (void)
{
output_high(hard_cs); //initializing the LCD
output_low(hard_clk); //clock idle state in Mode0
output_high(hard_sdo);
output_low(hard_res); //holding the LCD in reset
setup_spi(spi_master|spi_l_to_h|spi_xmit_l_to_h|spi_clk_div_64);
delay_ms(2); //are these delays necessary?
output_high(hard_res); //bringing LCD out of reset
delay_ms(2);
output_high(pin_a0); //pin connected to LCD backlight
output_low(hard_cs); //enabling LCD
write_command(sleepout);
write_command(invon);
write_command(colmod);
write_data(0x03);
write_command(setcon);
write_data(0x20);
write_command(dispon);
write_command(paset);
write_data(0x00);
write_data(131);
write_command(caset);
write_data(0x00);
write_data(131);
write_command(ramwr); //shading part of the LCD white
for (i=0;i<255;i++)
{
write_data(0xff);
write_data(0xff);
write_data(0xff);
}
while (true)
{
}
}
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Tue Dec 25, 2007 8:12 am |
|
|
Code: | delay_ms(2); //are these delays necessary?
output_high(hard_res); //bringing LCD out of reset
delay_ms(2); | Check figure 50 of the PCF8833 datasheet. The first delay can be reduced to a minimum of 1.5us but because of power supply startup and other synchronisation issues I would keep it at a save 1ms.
The second delay is too short, according to the same figure 50 it can take the controller 5ms to finish the reset sequence.
Digital pins A1 and A2 are multiplexed with the A/D-converter and comparator modules. When either of these analog modules is activated the digital ports will be disabled. Most compiler versions do disable the analog modules but this behaviour has been known to change in between releases. I therefore never assume the compiler will do something for me and always explicitly setup the hardware modules the way I want them: Code: | setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_comparator(NC_NC_NC_NC); |
|
|
|
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Wed Dec 26, 2007 5:39 am |
|
|
Hey all,
No go. I've tried, and nothing seems to ge the LCD to respond. Maybe its the LCD itself. It was an old one from a friend's phone. I'll try to procure another LCD and see if that works. Will post if I'm successful.
Thanks guys, once again.
Regards.
Rohit |
|
|
|