Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

I2C method of programming

Status
Not open for further replies.

electroRF

Member
Hi,
I got PIC18F (master) and I2C GLCD (Slave).
I managed to draw shapes in the GLCD, meaning, the I2C works well.

Now, before moving on to do some complicate stuff, like drawing pictures, I'd like to settle on a method.

I got a few questions and I'd appreciate your guide lines.

1.
when master loads SSPBUF with a byte, it waits for an ACK from the slave via - while (ACKSTAT) (ACKSTAT is cleared when ACK is received, and set when not).

The problem is that code will be stuck there if no ack is received from slave.

How should it be done then?

And what should be done if ack is not received - should I send Stop bit and start all over again?

How much time should I wait for an ACK before calling that no ACK was received?

2.
When Master receives bytes from Slave, should it ACK each byte?
The Slave datasheet doesn't say anything about it, so I guess I should do some trial and error?

3.
You think that it's OK to work without interrupts, or if I want to get PRO, interrupts are better.

Thanks guys :)
 
Hi,
Thanks KISS!

I'm experiencing a problem with receiving data from Slave.

I manage to send "DO" command from the master PIC18F4520 to the Slave GLCD (for example, I manage to send the GLCD a command to draw a circle, and GLCD draws a circle indeed).

But, when I send a command to read FW version, and then set the RCEN bit in the Master, I keep waiting for the BF flag to be set, but it stays cleared.

Any idea why the byte is not sent from the Slave to the Master, while the Slave DOES manage to receive the command?

Thanks.
 
Thanks KISS
That seems like good stuff.
I'll read it up and see how I can modify the code accordingly to make it work.
 
Hi again,
I have a question please (after reading the great link you posted).

I'm trying to read the Firmware of the device.
For that I do:


1. Master Sets Start bit
2. Master Sends Address (7bit) + Write bit (=0) ... [ I also tried Read bit = 1)
3. Master sends Part 1 out of 2 of FW read command
4. Slave sends ACK
5. Master sends Part 2 out of 2 of FW read command
6. Slave sends ACK
7. Master Sets RCEN bit
8. Master waits for BF to be set - BUT BF is never set.

I'm stuck at step #8.

Do you see something i'm missing here, or mis-doing?

Thanks a lot.
 
Firstly, an oscilloscope is a big help. You could use a logic analyser, and the logic analyser on the PICkit2 would be a lot better than nothing.

Although the I[SUP]2[/SUP]C modules are really convenient when they work, if they don't it is very difficult to find what you are doing wrong. I started on I[SUP]2[/SUP]C with a bit-bash program and I can't imagine fault finding I[SUP]2[/SUP]C without a 'scope.

I've not understood exactly what you are trying to do, as if you can send data to the LCD, what else do you need?

Also, although I've worked with I[SUP]2[/SUP]C, I'm not familiar with the I2C GLCD. As far as I can tell, the data is received inside the I2C GLCD by a MCP23S17. I looked up the data sheet of that, which is at https://ww1.microchip.com/downloads/en/devicedoc/21952b.pdf, and the programming figure on page 7 of that seems to say that to read from the MCP23S17, you have to first write the address of what you are trying to read, and then restart, address the device again, this time with the read bit set, and then start reading.

The sequence looks like:-

send start
send device opcode with R/W clear (write)
send address of the register you want to read
send restart
send device opcode with R/W set (read)
read data
send stop (or I guess, just don't acknowledge) when you've seen enough data.

I hope this helps.
 
Hi dear mates.
Thanks a lot!

Diver
Firstly, an oscilloscope is a big help. You could use a logic analyser, and the logic analyser on the PICkit2 would be a lot better than nothing.
I got Pickit3, I wasn't familiar with its logic analyzer, i'll check it out! it sounds helpful for debugging!
I was actually looking for I2C debug tool in MPLAB X IDE (which I use) and haven't found one.

I've not understood exactly what you are trying to do, as if you can send data to the LCD, what else do you need?
Yes, I manage to have the LCD drawing stuff.
But there's information I'd like to read like if any / which buttons were pressed (it has a keypad).

https://www.electro-tech-online.com/custompdfs/2013/03/21952b-2.pdf, and the programming figure on page 7 of that seems to say that to read from the MCP23S17, you have to first write the address of what you are trying to read, and then restart, address the device again, this time with the read bit set, and then start reading.

The sequence looks like:-

send start
send device opcode with R/W clear (write)
send address of the register you want to read
send restart
send device opcode with R/W set (read)
read data
send stop (or I guess, just don't acknowledge) when you've seen enough data.

That datasheet is really helpful.
I got a question though.
What if the "register address" is actually two bytes - Prefix + Command (see picture attached).
GLCD_CMDs.jpg
If I want to read Firmware version - 0xFE 0x30 - what would the sequence look like?

Would it be:
send start (SEN=1)
send device opcode with R/W clear (write) (A7,A6,A5,A4,A3,A2,A1,0)
send Prefix (0xFE)
send restart (RSEN=1)
send Command (0x30)
send restart (RSEN=1)
send device opcode with R/W set (read) (A7,A6,A5,A4,A3,A2,A1,1)
read data (Do you need to set here RCEN bit to 1?)
send stop (or I guess, just don't acknowledge) when you've seen enough data. (NACK)




KISS
Thanks, I'm going to see how to use that logic analyzer for I2C debuggig.
 
One of the problems is that the names of the bytes change between different manufactures.

I don't think that you need to send a restart unless you are changing from reading to writing.

Can you post the datasheet where that table with the addresses came from?
 
One of the problems is that the names of the bytes change between different manufactures.

I don't think that you need to send a restart unless you are changing from reading to writing.

Can you post the datasheet where that table with the addresses came from?

Hi DIVER,
Thanks!

The datasheet of the GLCD is here

I wrote the below stream, however all I get from SSPBUF is 0x01.
Even when I set Cursor to 0x08, and then read cursor, I get 0x01.

This is the stream:

send start (SEN=1)
send device opcode with R/W clear (write) (A7,A6,A5,A4,A3,A2,A1,0)
send Prefix (0xFE)
send Command (0x30)
send restart (RSEN=1)
send device opcode with R/W set (read) (A7,A6,A5,A4,A3,A2,A1,1)
read data (RCEN = 1)
send stop (or I guess, just don't acknowledge) when you've seen enough data. (ACKDT = 1 [i.e. NACK], ACKEN = 1 [i.e. send ACKDT] )
send stop bit (PEN = 1)

Looks logical to you?
 
Last edited:
Hi Diver,
Thanks.

This is what Arduino does in order to read FW version:

unsigned int GLCDI2C::firmware(void){

unsigned int data = 0;
unsigned char number = 1;

Wire.beginTransmission(g_i2caddress);
Wire.write(GLCDI2C_COMMAND);
Wire.write(GLCDI2C_FIRM_VER);
Wire.endTransmission();
//delay(GLCDI2C_CMDDELAY);

// Connect to device and request byte
Wire.beginTransmission(g_i2caddress);
Wire.requestFrom(g_i2caddress, number);

if (Wire.available()) {
data = Wire.read();
}
return data;
}


It seems that it sends stop bit after sending Prefix and Command, and then start bit for sending again the Address?

Also, it doesn't seem to send stop bit at the end of the function.

Do you have your own PIC I2C Code, that perhaps I could take a look on the logic of things?
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top