I2C and PICC ... not working?

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

Moderators: Henry, Mods

craven
LCD?
Posts: 9
Joined: Mon Nov 08, 2004 8:23 pm

I2C and PICC ... not working?

Post by craven »

I have exchanged countless emails with Matrix Orbital (and in their defense they have responded many times and tried to help me). Thus far I can not get I2C to work with the following situation:

Using a LK/VK162-12
PICC (HI-TECH) 'C' compiler for microcontroller programming
Using a 16F84a microcontroller and a bit-banging I2C routine


MULTIPLE code chunks have been attempted.

Code supplied with the compiler did not work, but seemed to force garbage characters on the screen at times.

Code provided by M.O. did not produce any results.

My own code produced only garbage characters (thus why I went after other options)

I have tried both the default jumper settings (as sugested by MO) and the ones shown in the manual which suggest a change is needed.

I need a clear-cut PROVEN code example using PICC. If anyone out there has one I would greatly apreciate it. MO has been working with me for almost 2 months now to find a solution-no dice. Please help!

drwasilko
LCD?
Posts: 1
Joined: Mon Nov 08, 2004 8:51 pm
Location: Boise, ID

Post by drwasilko »

craven, I too am fumbling with getting I2C to work with a rev 1.3 LCD2041, and I too am running PICC. Any chance you can share some of your code snippets thus far? I'm particularly interested in the bit banging technique.

Mahalo!
Dave

craven
LCD?
Posts: 9
Joined: Mon Nov 08, 2004 8:23 pm

Post by craven »

Current cut... been goofing around with various techniques. This is actually the code from MO that was slightly modified--they wrote it in C so it needed some tweaking to compile in PICC.



bit DataOutBit;
bit DI;

static volatile bit SDAEn @ (unsigned)&TRISA*8+0;
static volatile bit SCLEn @ (unsigned)&TRISA*8+1;
static volatile bit SDA @ (unsigned)&PORTA*8+0;
static volatile bit SCL @ (unsigned)&PORTA*8+1;


// Master I2C implementation
// Master functions are done bit-wise


void MasterInit()
{
SCL = 0; // Set SDA, SCL low when not in tri-state
SDA = 0; // Set SDA, SCL low when not in tri-state
SCLEn = 1; // SCL and SDA are inputs
SDAEn = 1; // SCL and SDA are inputs
}

void StartI2C()
{
SDAEn = 1; //
SCLEn = 1;
SDA = 0; // Set SDA, SCL low when not in tri-state
SDAEn = 0; // SDA goes low during SCL high
DelayUs(5); // Timing adjustment, .6uS Fast mode, 4.7 standard mode
SCL = 0; // Set SDA, SCL low when not in tri-state
SCLEn = 0; // Start clock train
}

void StopM()
{
SDA = 0; // Set SDA, SCL low when not in tri-state
SDAEn = 0; // Return SDA to low
DelayUs(2); // modified assuming 2 ms
SCLEn = 1; // Set SCL high
DelayUs(5);
SDAEn = 1; // SDA goes from low to high during SCL high
}

void BitOut()
{
// int count;

if (DataOutBit)
SDAEn = 1; // Output bit 1
else
SDAEn = 0; // Output bit 0

DelayUs(2); // modified for us delay
SCLEn = 1; // Allow SCL to go high
DelayUs(5);
SCLEn = 0; // return Clock to low state
}

void BitIn()
{
SDAEn = 1; // Set SDA for input
DI = 0; // may also function as a delay!
SCLEn = 1; // Clock high
DelayUs(3);

if(SDA) // Read SDA pin
DI = 1; // for our returned data else leave it cleared
DelayUs(2);

SCLEn = 0; // Return SCL to low
}

void XmitM(char OutData)
{
int Count;
int SDA_DIR;

for(Count = 0; Count < 8; Count++)
{
// SDAEn = shift_left(&OutData,1,0);

SDA_DIR = ((OutData>>Count)&0x01);
if (SDA_DIR) { /* bit to send */
SDAEn=1;
}else{
SDAEn=0;
}

DelayUs(2);
SCLEn = 1; // Allow SCL to go high
DelayUs(5);
SCLEn = 0; // return Clock to low state
}

SDAEn = 1; // Set SDA for input
DelayUs(2);
SCLEn = 1; // Clock high
DelayUs(5);
SCLEn = 0; // Return SCL to low
}

void sender (char inChar)
{
XmitM(inChar);
}

void main()
{
char ADDY;
ADDY = 0x50;

MasterInit();
//XmitM(ADDY);
StartI2C();
XmitM(ADDY);
XmitM(0x48);
StopM();
DelayUs(10);
while(1){
// endless loop
}
}

craven
LCD?
Posts: 9
Joined: Mon Nov 08, 2004 8:23 pm

Post by craven »

Be aware this code isnt doing a *darn* thing tho...still trying to get it to produce some results. My old code was at least putting junk on the screen per each button press (using a 1 ms interrupt and some buttons interface on that one).

Miles
Matrix Orbital
Matrix Orbital
Posts: 1105
Joined: Mon Mar 04, 2002 4:00 pm

Post by Miles »

Please see the following link on how to bit bash for one of our units. Be advised that this is not a PICC, however the idea is the same...The code that Tom sent you was a part of a test script that we use here to test address and functionality. It may not be exactly what you are looking for, however it gives you the idea on how to bit bash.

http://www.lennard.net.nz/electronics/matrixlcd.html
Miles Y.
Head of Technical Support
Product Manager
Matrix Orbital

craven
LCD?
Posts: 9
Joined: Mon Nov 08, 2004 8:23 pm

Post by craven »

Using default jumper settings this produces absolutely no results. Clear screen failed, sending text failed. The only difference I found between your code's process and my current one is the lack of delays used. I tried removing my delays as well and it failed to produce any results.

I need a working example of PICC code using I2C. I dont care what 16f IC is used I will buy one to test. I am getting the feeling that the model I have simply doesnt work with I2C using the current jumper settings (or at all)

I have two of them and neither works with I2C but both work with serial communications just fine. Too bad I cant use serial.

craven
LCD?
Posts: 9
Joined: Mon Nov 08, 2004 8:23 pm

Post by craven »

Let's boil this down to the basics. Even this doesnt work. Any ideas?


#include <pic.h>
#include "delay.h"

static volatile bit SDA_TRI @ (unsigned)&TRISA*8+0;
static volatile bit SCL_TRI @ (unsigned)&TRISA*8+1;
static volatile bit SDA @ (unsigned)&PORTA*8+0;
static volatile bit SCL @ (unsigned)&PORTA*8+1;
static volatile bit Error_Ind @ (unsigned)&PORTA*8+3;

// Master I2C implementation
// Master functions are done bit-wise

void Send0()
{
SDA=0;
//DelayMs(1);
SCL=1;
//DelayMs(1);
SCL=0;
//DelayMs(1);
}
void Send1()
{
SDA=1;
//DelayMs(1);
SCL=1;
//DelayMs(1);
SCL=0;
//DelayMs(1);
}

void main(void)
{

__CONFIG(0x03FF1);

T0IE = 0; // disable timer interupts
GIE = 0; // disable all interupts

TRISA0 = 0; // make output I2C Data
TRISA1 = 0; // make output I2C Clock

TRISA3 = 0; // make output for error led

Error_Ind=0;

DelayMs(1000); // init time
DelayMs(1000); // init time
DelayMs(1000); // init time

// start I2C
SDA=1;
SCL=1;
SDA=0;
SCL=0;

// write the address of the slave
// 01010000 same as 0x50 or ?
Send0;
Send1;
Send0;
Send1;
Send0;
Send0;
Send0;
Send0;

/*
// write a command init string
// 11111110 same as 254 or 0xFE
Send1;
Send1;
Send1;
Send1;
Send1;
Send1;
Send1;
Send0;

// write a clear screen command
// 01011000 same as 88
Send0;
Send1;
Send0;
Send1;
Send1;
Send0;
Send0;
Send0;
*/
// 01000001 same as 0x41 and letter A
Send0;
Send1;
Send0;
Send0;
Send0;
Send0;
Send0;
Send1;

// stop I2C
SDA=0;
SCL=1;
SDA=1;

while(1){
// endless loop
Error_Ind=1;
}
}


Tried it with the comnted delays as well. No dice. No response at all.

Miles
Matrix Orbital
Matrix Orbital
Posts: 1105
Joined: Mon Mar 04, 2002 4:00 pm

Post by Miles »

I apologize for not noticing this earlier...the I2C protocol is 7-bit addressing...try this instead:

// write the address of the slave
// 10100000 same as A0
Send1;
Send0;
Send1;
Send0;
Send0;
Send0;
Send0;
Send0:
//essentially you use the first 7bits of the address followed by a 0(write) or 1(read), shifting the address over one...thus giving you A0...

For more information, please see the following link: http://homepages.which.net/~paul.hills/ ... CBody.html
Miles Y.
Head of Technical Support
Product Manager
Matrix Orbital

craven
LCD?
Posts: 9
Joined: Mon Nov 08, 2004 8:23 pm

Post by craven »

This is the latest code. Still no results.

#include <pic.h>
#include "delay.h"

static volatile bit SDA_TRI @ (unsigned)&TRISA*8+0;
static volatile bit SCL_TRI @ (unsigned)&TRISA*8+1;
static volatile bit SDA @ (unsigned)&PORTA*8+0;
static volatile bit SCL @ (unsigned)&PORTA*8+1;
static volatile bit Error_Ind @ (unsigned)&PORTA*8+3;

// Master I2C implementation
// Master functions are done bit-wise

void Send0(void)
{
SDA=0;
SCL=1;
//DelayMs(5);
SCL=0;
}
void Send1(void)
{
SDA=1;
SCL=1;
//DelayMs(5);
SCL=0;
}

void main(void)
{

__CONFIG(0x03FF1);

T0IE = 0; // disable timer interupts
GIE = 0; // disable all interupts

SDA_TRI = 0; // make output I2C Data
SCL_TRI = 0; // make output I2C Clock

TRISA3 = 0; // make output for error led

Error_Ind=0;

DelayMs(1000); // init time
DelayMs(1000); // init time
DelayMs(1000); // init time

// start I2C
SDA=1;
SCL=1;
SDA=0;
SCL=0;

// write the address of the slave
// 10100000 same as A0
Send1();
Send0();
Send1();
Send0();
Send0();
Send0();
Send0();
Send0();

/*
// write a command init string
// 11111110 same as 254 or 0xFE
Send1();
Send1();
Send1();
Send1();
Send1();
Send1();
Send1();
Send0();

// write a clear screen command
// 01011000 same as 88
Send0();
Send1();
Send0();
Send1();
Send1();
Send0();
Send0();
Send0();
*/
// 01000001 same as 0x41 and letter A
Send0();
Send1();
Send0();
Send0();
Send0();
Send0();
Send0();
Send1();

// stop I2C
SDA=0;
SCL=1;
SDA=1;

while(1){
// endless loop
Error_Ind=1;
}
}
Last edited by craven on Tue Nov 09, 2004 3:19 pm, edited 2 times in total.

Miles
Matrix Orbital
Matrix Orbital
Posts: 1105
Joined: Mon Mar 04, 2002 4:00 pm

Post by Miles »

What type of pull up resistors are you using?
Miles Y.
Head of Technical Support
Product Manager
Matrix Orbital

craven
LCD?
Posts: 9
Joined: Mon Nov 08, 2004 8:23 pm

Post by craven »

Tried 1k and 10k

Tom
Matrix Orbital
Matrix Orbital
Posts: 1030
Joined: Mon Jul 19, 2004 4:43 pm
Location: Calgary
Contact:

Post by Tom »

Try making a loop and cycling through every address. The address maybe something other that the default.

craven
LCD?
Posts: 9
Joined: Mon Nov 08, 2004 8:23 pm

Post by craven »

Code used to test all addresses. Failed to produce any results.


#include <pic.h>
#include "delay.h"

static volatile bit SDA_TRI @ (unsigned)&TRISA*8+0;
static volatile bit SCL_TRI @ (unsigned)&TRISA*8+1;
static volatile bit SDA @ (unsigned)&PORTA*8+0;
static volatile bit SCL @ (unsigned)&PORTA*8+1;
static volatile bit Error_Ind @ (unsigned)&PORTA*8+3;

// Master I2C implementation
// Master functions are done bit-wise

void SendBit(signed char BitToSend)
{
SDA=BitToSend;
SCL=1;
//DelayMs(5);
SCL=0;
}

SendByte(unsigned char byte)
{
signed char i;
signed char SDA_DIR;

for(i=0; i<8; i++)
{
SDA_DIR = ((byte>>i)&0x01);
if (SDA_DIR)
{
SendBit(1);
}else{
SendBit(0);
}
}
}

void main(void)
{
signed int Addresstest;
__CONFIG(0x03FF1);

T0IE = 0; // disable timer interupts
GIE = 0; // disable all interupts

SDA_TRI = 0; // make output I2C Data
SCL_TRI = 0; // make output I2C Clock

TRISA3 = 0; // make output for error led

Error_Ind=0;

DelayMs(1000); // init time
DelayMs(1000); // init time
DelayMs(1000); // init time


for(Addresstest=1; Addresstest<254; Addresstest++)
{

// start I2C
SDA=1;
SCL=1;
SDA=0;
SCL=0;

// write the address of the slave
SendByte(Addresstest);

// 01000001 same as 0x41 and letter A
SendByte(0x41);

// stop I2C
SDA=0;
SCL=1;
SDA=1;
}


while(1){
// endless loop
Error_Ind=1;
}
}

Miles
Matrix Orbital
Matrix Orbital
Posts: 1105
Joined: Mon Mar 04, 2002 4:00 pm

Post by Miles »

I have an I2C tester on our test bench...would you be willing to send it to me and I can verify that I can get it working here...if we can eliminate all possibilites, that would be a great start!! :)
Miles Y.
Head of Technical Support
Product Manager
Matrix Orbital

RussCA
LCD!
Posts: 13
Joined: Tue Nov 09, 2004 9:59 am
Location: Ontario, Canada

Post by RussCA »

I think there are at least four problems in the above I2C code:

1. Matrix Orbital defines what they call an "8-bit address" which is the standard I2C address shifted left one position. This means that if the address is 0x50, it must be sent unshifted.

2. The I2C protocol calls for data to be sent MSB first. The above code appears to be sending LSB first.

3. When data is sent over the I2C bus, the sender is expected to receive the receiver's ACK. The above code does not do this.

4. When data is received over the I2C bus, the receiver is expected to transmit an ACK. Again, the above code does not do this as far as I can see.

Here is my working I2C code:

Code: Select all

/*
 * Routines to drive a standard I2C bus.
 */


#include <stdio.h>
#include "\JKMicro\H\i2c.h"
#include "\JKMicro\H\Ports186.h"

  #define SCL     PORTA
  #define SCLBIT  0x00
  #define SDA     PORTB
  #define SDABIT  0x00

/*
 * I2C Routines derived from the pseudo code by V. Himpe,
 * and are likewise released into the Public Domain by:
 *
 * Russell W. Ranshaw
 *
 * For more information, visit:
 *  http://www.ping.be/~ping0751/i2cfaq/i2cindex.htm
 *
 */

/* 
 * I2Cinit is to be called immediately after power up.
 * This is normally the only I2C routine to be called 
 * directly by the application.
 */

void I2Cinit (void) {
	int n;

	I2Chighsda ();
	I2Clowscl ();

	for (n = 0; n < 3; n++) {
		I2Cstop ();
	}
}

void I2Cstart (void) {
	I2Chighscl ();
	I2Chighsda ();
	I2Clowsda ();
	I2Clowscl ();
	I2Chighsda ();
}


void I2Cstop (void) {
	I2Clowsda ();
	I2Clowscl ();
	I2Chighsda ();
}

int I2Cgetbyte(void)
{
	int i_byte = 0, n;

	SetInputPort (SDA);

	for (n=0; n<8; n++)
	{
		I2Chighscl();
		
		if (GetPortBit (SDA, SDABIT))
		{
			i_byte = (i_byte << 1) | 0x01; /* msbit first */
		}
		else
		{
			i_byte = i_byte << 1;
		}

		I2Clowscl();
	}


	I2Chighsda ();
	return(i_byte);
}

void I2Cputbyte(int o_byte)
{
	int n;

	for(n=0; n<8; n++)
	{
		if(o_byte&0x80)
		{
			I2Chighsda();
		}
		else
		{
			I2Clowsda();
		}

		I2Chighscl();
		I2Clowscl();
		o_byte = o_byte << 1;
	}

	I2Chighsda();
}


void I2Cgiveack(void)
{
	I2Clowsda(); 
	I2Chighscl();
	I2Clowscl();
	I2Chighsda();
}

void I2Cgetack (void) {
	int n;

	I2Chighsda ();
	I2Chighscl ();

	SetInputPort (SDA);

	/* Wait until Slave pulls SDA low */
	/* Note:  The pseudocode does not have the for loop.  
	 * It was added to prevent a lock up situation. 
	 *
	 * Actually, there should be more error checking and reporting
	 * in this code.  For example, this routine should indicate a
	 * missed ACK.
	 */

	for (n = 0; n < 100; n--) {
		if (GetPortBit (SDA, SDABIT) == 0)
			break;
	}

	I2Clowscl ();
	SetOutputPort (SDA);
}


void I2Chighsda(void)
{
	SetOutputPort (SDA);
	SetPortBit (SDA, SDABIT);
}

void I2Clowsda(void)
{
	SetOutputPort (SDA);
	ClearPortBit (SDA, SDABIT);
}

void I2Chighscl(void)
{
	SetOutputPort (SCL);
	SetPortBit (SCL, SCLBIT);
}

void I2Clowscl(void)
{
	SetOutputPort (SCL);
	ClearPortBit (SCL, SCLBIT);
}

/*
 * Routine to send an address on the I2C bus.  To indicate
 * adr is a 10-bit address, set the high-order bit (0x8000).
 */
void I2Csendadr (int adr, int rw) {
	I2Cstart ();

	if ((adr & 0x8000) != 0) {
		/* Send two MSBs of the ten bit address */
		I2Cputbyte (0xF0 | rw | ((adr > 8) & 0x06));
		I2Cgetack ();
		I2Cputbyte (adr & 0xFF);
	} else {
		I2Cputbyte (adr | rw);
	}

	I2Cgetack ();
}

/* Read num bytes from device adr into buf */
void I2Cread (int adr, int num, char *buf) {

	I2Csendadr (adr, 1);

	while (num-- > 0) {
		*buf++ = I2Cgetbyte ();

		if (num > 0) I2Cgiveack ();
	}

	I2Cstop ();
}


/* Write num bytes to device adr from buf */
void I2Cwrite (int adr, int num, char *buf) {
	I2Csendadr (adr, 0);

	while (num-- > 0) {
		I2Cputbyte (*buf++);
		I2Cgetack ();
	}

	I2Cstop ();
}


The low-level bit banging routines include a delay of about one microsecond.

My LK204-25 display arrived with the jumpers set for an address other than 0x50, and they had to be changed. Check your jumpers against the manual for your display. Not all displays are created equal!
Russ

Have you tried Renewable Energy yet?

Post Reply