View previous topic :: View next topic |
Author |
Message |
Fabri
Joined: 22 Aug 2005 Posts: 275
|
PIC16F690 and I2c master |
Posted: Mon Aug 08, 2011 3:47 am |
|
|
Hi to all,
I'm working around eeprom 2408 with PIC16F690. I already use it with slave I2c bus but now I need to use it as master.
I can't write and read data from eeprom and before analyze all bus signal with oscilloscope I decided to ask you help and more information.
I'm using ccs V3.249, does it support master function of PIC16F690 ?
in datasheet i read about limit of SSP in master application.
The driver used for eeprom is standard 2408.C.
my i2c bus configutation is:
Quote: |
#use i2c(master, sda=EEPROM_SDA, scl=EEPROM_SCL,force_hw,SLOW=100000)
|
Thanks for help,
Regards,
Fabri |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Mon Aug 08, 2011 6:22 am |
|
|
Get rid of force_hw.
Use force_sw instead.
The 16F690, _does not support I2C master mode on it's SSP hardware_. The compiler will happily perform software I2C, but you are currently trying to force it to use the hardware, which does not support this.
Look at section 13.11 of the data sheet. Modes supported:
Code: |
Four mode selection bits (SSPCON<3:0>)
allow one of the following I2C modes to be selected:
• I2C Slave mode (7-bit address)
• I2C Slave mode (10-bit address)
• I2C Slave mode (7-bit address), with Start and
Stop bit interrupts enabled to support Firmware
Master mode
• I2C Slave mode (10-bit address), with Start and
Stop bit interrupts enabled to support Firmware
Master mode
• I2C Start and Stop bit interrupts enabled to
support Firmware Master mode; Slave is idle
|
Note the lack of _any_ master modes.
Best Wishes |
|
|
Fabri
Joined: 22 Aug 2005 Posts: 275
|
|
Posted: Fri Aug 12, 2011 7:25 am |
|
|
Thanks Ttelmah for suggestion but it still doesn't work....
I tried with:
Code: |
#use i2c(master, sda=PIN_B4, scl=PIN_B6,force_sw)
|
does it enough for PIC16F690 software I2c bus?
The software stay in loop in routine ext_eeprom_ready(). It seems there's no ack from eeprom.
Some year ago I wrote code for PIC16F876A and 24C32 and I haven't any kind of problem....
Thanks for suggestions,
Fabri |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Fri Aug 12, 2011 8:04 am |
|
|
The software I2C routines generally run fine (assuming you haven't got something like a very early V4 compiler). 3.249 is OK.
I'd be triple checking:
1) Pin configuration - you have turned _off_ the ADC on pin B4.
2) Connections.
3) Pull up resistors.
4) Address of the EEPROM. - have you got the right pins pulled up/down.
Best Wishes |
|
|
epalite
Joined: 06 Apr 2008 Posts: 16
|
|
Posted: Wed Sep 07, 2011 10:29 pm |
|
|
Fabri wrote: |
Code: |
#use i2c(master, sda=PIN_B4, scl=PIN_B6,force_sw)
|
does it enough for PIC16F690 software I2c bus?
The software stay in loop in routine ext_eeprom_ready(). It seems there's no ack from eeprom.
Some year ago I wrote code for PIC16F876A and 24C32 and I haven't any kind of problem....
|
As you are implementing a firmware based master, you have to note if F690 will be fast enough to service the I2C. If you run F690 at 8MHz, you might only be able to effectively drive a bus clock SCL at 50kHz considering all your bus and error handling and processing. A scope capture of what went wrong would be useful. Hope that helps! |
|
|
zasi80
Joined: 03 Oct 2011 Posts: 4 Location: London
|
|
Posted: Tue Oct 04, 2011 3:12 pm |
|
|
Hi
I was fighting with I2C and my PIC16f690 for 3 days (I'm beginner), and finally made it work !!! I used EEPROM AT24C512B. I've done simulation and physical circuit however when I swapped EEPROM AT24C512B for 24AA08 in my simulation it didn't work so there must be something about that memory (I didn't go through datasheet). Hope it will help.
Code: |
#include<16f690.h>
#fuses NOWDT, NOPROTECT, NOBROWNOUT, PUT, NOMCLR, INTRC_IO
#use delay(clock=4000000)
#use rs232(baud=4800, xmit=pin_b7, rcv=pin_b6) // to see results on display
#use i2c (master ,sda=PIN_c1,scl=PIN_c2, stream=z )
//---------------------------
void main()
{
int n, byte111=0;
delay_ms(1000);
putc(254); //for LCD
putc(1);
delay_ms(10);
i2c_start();
i2c_write(0b10100000); //device address + last bit 0 to write / 1 to read
i2c_write(0); //eeprom address high (8 bits - some bits don't care depending on memory size)
i2c_write(0); //eeprom address low (8 bits)
i2c_write('4'); //after this instruction address in EEPROM is incremented internally - no need to do in PIC
i2c_write('5');
i2c_write('6');
i2c_stop();
delay_ms(10); //delays needed for correct write to eeprom (time depends on memory)
//when writing in memory pages (=<64bytes) only one delay at the end is enough
for(n=0;n<3;n++) //reads 3 times the same byte
{
i2c_start();
i2c_write(0b10100000); //dummy write required to clock in address
i2c_write(0x00);
i2c_write(1); //read address 1
i2c_start();
i2c_write(0b10100001);
byte111=i2c_read(z,0); //don't acknowledge if it is last byte in memory page (or random read)
i2c_stop(); //to be able to set NO ACKNOWLEDGE stream must get a name in #use i2c (corrected - name is not necessary)
// here stream named "z"
putc(byte111);
}
printf(" Done");
}
|
Last edited by zasi80 on Wed Oct 05, 2011 12:00 am; edited 3 times in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Oct 04, 2011 3:29 pm |
|
|
Code: |
// don't acknowledge if it is last byte in memory page (or random read)
// to be able to set NO ACKNOWLEDGE stream must get a name in
//#use i2c here stream named "z"
byte111=i2c_read(z,0);
|
Are you saying that you must put the 'stream' parameter in the #use i2c()
statement, and that you must specify the stream to be allowed to do a
NACK ? I've never seen this to be true.
It should do a NACK if you do this (no streams specified or used):
Code: |
#use i2c (master, sda=PIN_C1, scl=PIN_C2)
byte111=i2c_read(0);
|
If that doesn't work, post your CCS compiler version.
Also, CCS has the same basic code, except it's written as driver routines,
in this file:
Quote: | c:\program files\picc\drivers\24512.c |
|
|
|
zasi80
Joined: 03 Oct 2011 Posts: 4 Location: London
|
|
Posted: Tue Oct 04, 2011 11:54 pm |
|
|
Sorry, my mistake
byte111=i2c_read(0); does the same. |
|
|
|