i2c with PICs MSSP and Hi-Tech PIC C

LK/ELK/VK/PK/OK/MX/GLK/EGLK/GVK/GLT Series

Moderators: Henry, Mods

Post Reply
jheiv
LCD!
Posts: 11
Joined: Mon Jul 24, 2006 9:56 am

i2c with PICs MSSP and Hi-Tech PIC C

Post by jheiv »

Code: Select all

#include <htc.h>

void delay(int);
void init(void);
void i2c_init(void);
void i2c_start(void);
void i2c_write(char);
void i2c_stop(void);
void i2c_wait(void);

void main(void)
{
	
	delay(600);
	init();
	i2c_init();
	
	SSPIF =		0;			//CLEAR INTERRUPT
	
	i2c_start();
	i2c_write(0x50);		//Load LCD Address
	i2c_write(0xFE);		//Load Command
	i2c_write(0x58);		//Load Clear
	RA0 =		1;	
	i2c_stop();
	
	while (1){
		i2c_start();

		i2c_write(0x50);
		//while(ACKSTAT == 1);
		i2c_write(0xFE);
		//while(ACKSTAT == 1);
		i2c_write(0x58);
		//while(ACKSTAT == 0);
		i2c_stop();

	}
}




void init(void){
	PORTA = 	0x00;

	PORTB = 	0x00;

	ADCON1 =	0x06;

	TRISA = 	0x00;
	TRISB = 	0x00;
	TRISC = 	0x00;
	

}

void i2c_init(void){
	/* SSPCON1 REGISTERS */
	SSPEN		= 1;	//Enables Serial Port Mode
	SSPM3		= 1;	/////////
	SSPM2		= 0;	//I2C Master Mode
	SSPM1		= 0;	//
	SSPM0		= 0;	////////

	/* SSPCON2 REGISTERS */
	SSPCON2     = 0x00;

	/* SSPSTAT REGISTERS */
	STAT_SMP 	= 1;	//Slew Rate Control Disabled
	STAT_CKE	= 0;	//SMBus Specific Inputs Disabled

	SSPADD		= 0x19;
}

void i2c_start(void){
	SEN = 1;			//Generate Start Condition
	i2c_wait();
}

void i2c_write(char byte){
	SSPBUF = byte;
	i2c_wait();	
}

void i2c_stop(void){
	PEN = 1;				//Generate Stop Condition
	i2c_wait();
}

void i2c_wait(void) {
	while ( SSPIF==0 );
	SSPIF = 0;
}
	

void delay(int pause){
	unsigned int i, j, k;
	
	unsigned int clock = 8;
	unsigned int cycle = 14;
	
	for(i = 0; i <= pause; i++){
	for(j = 0; j <= clock; j++){
	for(k = 0; k <= cycle; k++){
		asm("nop");
	}}}
}
I try this code, see great looking waveforms on the scope, running full 0 - 5 V but it looks as if the two devices (LCD and uC) are conflicting. The ack bit (9th) of the data bytes sent (0x50, 0xFE, 0x47) is only around 2.5 volts. With the LCD unplugged the ack bit reads 5V (since there is nothing there to pull it low signalling an ACK) I've tried 220 ohm, 1K, 10K, even 100K ohm line pull ups. Why would the data line on the 9th bit look like its inbetween a voltage divider... Any Ideas?

Also, on the 3rd byte, the first bit of the clock looks the same way (as if one device was pulling it low while the other holding it high) with a voltage around 2.2 - 2.5V. Any help would be great!

I'm using a PIC16F876A with onboard MSSP, and LCD-2041 and the Hi-Tech C ANSI compliant compiler.

-Jim

Raquel
Matrix Orbital
Matrix Orbital
Posts: 796
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Post by Raquel »

Hello Jim,

Thank you for posting on the forum.

I see that you assign SSPADD = 0x19;
Can you try this with SSPADD = 0x50:

Please let me know how it turns out.
Raquel Malinis
Design and Development
Matrix Orbital

jheiv
LCD!
Posts: 11
Joined: Mon Jul 24, 2006 9:56 am

Post by jheiv »

It looks like all that did was change the clock frequency to around 25kHz and clear up the 'half-level' that was present on the clock line. But not it looks like it connects a few bytes on the clock line, so instead of being 9 distinct cycles, its something like 27 then an extended high on the clock line, then 27 cycles, etc. The data line still has some half-levels and it looks like it lost it's accuracy. Instead of clocking out a recognizable byte pattern it clocks out what looks to be:

01010000H (0x50)
11111110H (0xFE)
101100010 (0x58)

.. all continuously.

The H's correspond to the half levels on the data line.

Any ideas?

jheiv
LCD!
Posts: 11
Joined: Mon Jul 24, 2006 9:56 am

Post by jheiv »

Even when I insert a pause between send commands -- like this:

Code: Select all

		i2c_start();
		delay(1);

		i2c_write(0x50); 
		delay(1);

		i2c_write(0xFE);
		delay(1);

		i2c_write(0x58);
		delay(1);

		i2c_stop();
		delay(1);
The scope still shows the half levels, with a spacing with both lines low of about 6-8x the single-byte duration

jheiv
LCD!
Posts: 11
Joined: Mon Jul 24, 2006 9:56 am

Post by jheiv »

I just swapped out the LCD display with another LCD-2041 -- no luck.

Raquel
Matrix Orbital
Matrix Orbital
Posts: 796
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Post by Raquel »

Hi Jim,

Can you please tell me what PCB rev LCD2041 you are connecting to? If you have a PCB 2.0, 0x50 is the default I2C address; but then if you have an older version, the I2C address depends on the setting of the RS232/I2C addr jumpers. It'll be best if you can post a picture.

Thank you.
Raquel Malinis
Design and Development
Matrix Orbital

jheiv
LCD!
Posts: 11
Joined: Mon Jul 24, 2006 9:56 am

Post by jheiv »

Both LCD2041 LCDs I'm using are PCB Rev 2.0.

If I don't specify the address, it's not specified anywhere else in the program...

I tried this program just now... still nothing.

Code: Select all

#include <htc.h>

void delay(int);
void init(void);
void i2c_init(void);
void i2c_start(void);
void i2c_write(char);
void i2c_stop(void);
void i2c_wait(void);

void main(void)
{
	unsigned int inc = 0;
	
	delay(600);
	init();
	i2c_init();
	
	SSPIF =		0;			//CLEAR INTERRUPT
	
	RA0 =		1;	

	i2c_start();
	i2c_write(0x50); 
	i2c_write(0xFE);
	i2c_write(0x58);
	i2c_stop();

	while (1){
		inc++;
		i2c_start();
		//delay(1);
		i2c_write(0x50); 
		//delay(1);
		i2c_write(inc);
		//delay(1);
		i2c_stop();
		delay(1);
	}
}




void init(void){
	PORTA = 	0x00;

	PORTB = 	0x00;

	ADCON1 =	0x06;

	TRISA = 	0x00;
	TRISB = 	0x00;
	TRISC = 	0x00;
	

}

void i2c_init(void){
	/* SSPCON1 REGISTERS */
	SSPEN		= 1;	//Enables Serial Port Mode
	SSPM3		= 1;	/////////
	SSPM2		= 0;	//I2C Master Mode
	SSPM1		= 0;	//
	SSPM0		= 0;	////////

	/* SSPCON2 REGISTERS */
	SSPCON2     = 0x00;

	/* SSPSTAT REGISTERS */
	STAT_SMP 	= 1;	//Slew Rate Control Disabled
	STAT_CKE	= 1;	//SMBus Specific Inputs Disabled

	//SSPADD			= 0x19;		//~75kHz
	//SSPADD			= 0x13;		//~100kHz
	//SSPADD			= 0x07;		//~400kHz
	SSPADD			= 0x50;
	
	
}

void i2c_start(void){
	SEN = 1;			//Generate Start Condition
	i2c_wait();
}

void i2c_write(char byte){
	SSPBUF = byte;
	i2c_wait();	
}

void i2c_stop(void){
	PEN = 1;				//Generate Stop Condition
	i2c_wait();
}

void i2c_wait(void) {
	while ( SSPIF==0 );
	SSPIF = 0;
}
	

void delay(int pause){
	unsigned int i, j, k;
	
	unsigned int clock = 8;
	unsigned int cycle = 14;
	
	for(i = 0; i <= pause; i++){
	for(j = 0; j <= clock; j++){
	for(k = 0; k <= cycle; k++){
		asm("nop");
	}}}
}

Any idea why the acknowledge bit would only be pulled down to half height?

Raquel
Matrix Orbital
Matrix Orbital
Posts: 796
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Post by Raquel »

Hi Jim,

I checked the datasheet for the PIC16F876A, you will need to set RA3 and RA4 to inputs. That is one reason that I can think of why the LCD can not pull the SDA line low to acknowledge.

Please let me know how it turns out.
Raquel Malinis
Design and Development
Matrix Orbital

jheiv
LCD!
Posts: 11
Joined: Mon Jul 24, 2006 9:56 am

Post by jheiv »

I did as you said... and added the following lines to my code after my initial TRISC = 0x00...

Code: Select all

	TRISC3 = 1;
	TRISC4 = 1;

It works great! Thanks again for your time. If anyone is needs code that uses the hardware MSSP peripheral on a PIC this code works now!

Thanks again.
-Jim

Raquel
Matrix Orbital
Matrix Orbital
Posts: 796
Joined: Thu Aug 19, 2004 3:37 pm
Location: MO Office

Post by Raquel »

Hi Jim,

I am glad that things are working now.

Best Regards,
Raquel Malinis
Design and Development
Matrix Orbital

tedlarson
LCD?
Posts: 3
Joined: Wed Aug 06, 2008 6:23 pm

Post by tedlarson »

jheiv wrote:It works great! Thanks again for your time. If anyone is needs code that uses the hardware MSSP peripheral on a PIC this code works now!

Thanks again.
-Jim
Were you ever able to get the i2c_read to work? Or only writing to the display.

-Ted

Clark
Matrix Orbital
Matrix Orbital
Posts: 881
Joined: Fri Aug 17, 2007 10:58 am
Location: Matrix Orbital
Contact:

Post by Clark »

Hi Ted,

Not sure if you'll get an answer from Jim or not, but I'll be more than happy to help you work out the read issue on your original post.

~Troy
Troy Clark
Design & Development
Matrix Orbital

JeffMac
LCD?
Posts: 1
Joined: Mon Oct 09, 2017 3:25 am

Re:

Post by JeffMac »

tedlarson wrote:
Wed Aug 06, 2008 7:28 pm
jheiv wrote:It works great! Thanks again for your time. If anyone is needs code that uses the hardware MSSP peripheral on a PIC this code works now!

Thanks again.
-Jim
Were you ever able to get the i2c_read to work? Or only writing to the display.

-Ted
Hey Ted did you get it working?

Clark
Matrix Orbital
Matrix Orbital
Posts: 881
Joined: Fri Aug 17, 2007 10:58 am
Location: Matrix Orbital
Contact:

Re: i2c with PICs MSSP and Hi-Tech PIC C

Post by Clark »

Hi Jeff,

I understand you are also working with I2C, and have some questions regarding reading. I don't see a read function in Jim's code, and this is an older post so we may not get a direct response. However, if you can post your own read function we can certainly look into any issues you may be having.

Cheers,
Troy
Troy Clark
Design & Development
Matrix Orbital

Post Reply