|
|
View previous topic :: View next topic |
Author |
Message |
aressa Guest
|
PIC16F877 as I2C Slave |
Posted: Tue Nov 05, 2002 2:34 pm |
|
|
I am attempting to set up a PIC16F877 as an I2C Slave device. The more I read from these boards and linked articles I have a feeling I am fighting a losing battle. This is pretty much my only option as that is the way my hardware was designed.
__First the specs__
Rabbit 2000 Series Processor as Master
PIC16F877 / PLCC44 as Slave
PCM 3.094
MPLAB 5.62.00 -> ICE2000
FACTS:
The Rabbit2000 communicates flawlessly with two other off-the-shelf slave devices (a RAM and a EEPROM) so I know that it is not the source of any issues. But when I try to address the PIC I do not get an ACK all the time, in fact I get an ACK only about once every few seconds. The PIC is set up to do just a simple “flash lights” on interrupt.
I have used an o-scope to verify all of the behavior.
I am not currently using a watchdog, and when I did test that it made no difference (there is not a lockup condition currently).
PROBLEM:
The PIC flashes lights with each cycle of my "i2c test" routine, but only pulls down ACK about every two seconds. It has never ACKed the second byte in the case that it ACKed the first.
I’d like to set up the PIC as a reliable slave device, but am unsure if that is possible at this point.
Any idea what I am doing wrong or advice on how to proceed? Thanks in advance.
Andrew
-------============ TRIMMED CODE =================--------
** MASTER (Not a PIC) **
int test_i2c()
{
auto unsigned char cnt;
auto short int err;
LS_putc('*');
if (err=i2c_startw_tx())
{
i2c_stop_tx();
sprintf(msgBuffer, "too long stretching\r\n"); LS_puts(msgBuffer);
}
else if (err=i2c_write_char(0xE0))
{
i2c_stop_tx();
sprintf(msgBuffer, "no ack on slave\r\n"); LS_puts(msgBuffer);
}
else if (err=i2c_write_char(0x0A))
{
i2c_stop_tx();
sprintf(msgBuffer, "no ack on command\r\n"); LS_puts(msgBuffer);
}
i2c_stop_tx();
return 0;
}
** SLAVE PIC16F877 **
#include <16F877.h>
#fuses HS,WDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
#use delay(clock=20000000)
#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xE0, FORCE_HW)
#INT_SSP
void ssp_interupt ()
{
byte incoming;
if (i2c_poll() == FALSE) {
output_D(0xF0);
}
else {
i2c_read(1);
output_D(0x0F);
}
delay_ms(15);
output_d(0x00);
}
void main ()
{
enable_interrupts(GLOBAL);
enable_interrupts(INT_SSP);
while (TRUE) {}
}
___________________________
This message was ported from CCS's old forum
Original Post ID: 8575 |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
Re: PIC16F877 as I2C Slave |
Posted: Tue Nov 05, 2002 3:23 pm |
|
|
My advice is to throw away CCS's functions. Read the datasheet on the PIC and do it yourself. It is not hard and you have the ability to change the software. I use them in slave mode without any problems. In fact, in our design, 17 of them can be on the same bus.
Regards,
Mark
:=I am attempting to set up a PIC16F877 as an I2C Slave device. The more I read from these boards and linked articles I have a feeling I am fighting a losing battle. This is pretty much my only option as that is the way my hardware was designed.
:=
:=__First the specs__
:=Rabbit 2000 Series Processor as Master
:=PIC16F877 / PLCC44 as Slave
:=PCM 3.094
:=MPLAB 5.62.00 -> ICE2000
:=
:=FACTS:
:=The Rabbit2000 communicates flawlessly with two other off-the-shelf slave devices (a RAM and a EEPROM) so I know that it is not the source of any issues. But when I try to address the PIC I do not get an ACK all the time, in fact I get an ACK only about once every few seconds. The PIC is set up to do just a simple “flash lights” on interrupt.
:=I have used an o-scope to verify all of the behavior.
:=I am not currently using a watchdog, and when I did test that it made no difference (there is not a lockup condition currently).
:=
:=PROBLEM:
:=The PIC flashes lights with each cycle of my "i2c test" routine, but only pulls down ACK about every two seconds. It has never ACKed the second byte in the case that it ACKed the first.
:=I’d like to set up the PIC as a reliable slave device, but am unsure if that is possible at this point.
:=
:=
:=Any idea what I am doing wrong or advice on how to proceed? Thanks in advance.
:=
:=Andrew
:=
:=-------============ TRIMMED CODE =================--------
:=** MASTER (Not a PIC) **
:=int test_i2c()
:={
:=auto unsigned char cnt;
:=auto short int err;
:=LS_putc('*');
:=if (err=i2c_startw_tx())
:={
:=i2c_stop_tx();
:=sprintf(msgBuffer, "too long stretching\r\n"); LS_puts(msgBuffer);
:=}
:=else if (err=i2c_write_char(0xE0))
:={
:=i2c_stop_tx();
:=sprintf(msgBuffer, "no ack on slave\r\n"); LS_puts(msgBuffer);
:=}
:=else if (err=i2c_write_char(0x0A))
:={
:=i2c_stop_tx();
:=sprintf(msgBuffer, "no ack on command\r\n"); LS_puts(msgBuffer);
:=}
:=i2c_stop_tx();
:=return 0;
:=}
:=
:=
:=** SLAVE PIC16F877 **
:=#include <16F877.h>
:=#fuses HS,WDT,NOPROTECT,NOLVP,PUT,NOBROWNOUT
:=#use delay(clock=20000000)
:=#use i2c(SLAVE, SDA=PIN_C4, SCL=PIN_C3, address=0xE0, FORCE_HW)
:=
:=#INT_SSP
:=void ssp_interupt ()
:={
:= byte incoming;
:=
:= if (i2c_poll() == FALSE) {
:= output_D(0xF0);
:= }
:= else {
:= i2c_read(1);
:= output_D(0x0F);
:= }
:= delay_ms(15);
:= output_d(0x00);
:=}
:=
:=
:=void main ()
:={
:=
:= enable_interrupts(GLOBAL);
:= enable_interrupts(INT_SSP);
:=
:= while (TRUE) {}
:=}
___________________________
This message was ported from CCS's old forum
Original Post ID: 8577 |
|
|
Thomas Blake Guest
|
Re: PIC16F877 as I2C Slave |
Posted: Tue Nov 05, 2002 3:27 pm |
|
|
<font face="Courier New" size=-1>I agree that the F87x (I use an F873) as an I2C slave is pretty feeble. I followed the asm sample in PIC AN734, and (after a few corrections in the example code) it worked but only at a low link rate ... about 40kb/s max. This was OK for the project. The problem, of course, is that you have to lower the rate on your Rabbit., as the slave has nothing to do with the link rate. If you're using CCSC with the F87x as master it's just as well to dash off a few macros to access and mask SSPCON (0x14) and SSPSTAT(0x91).
PS >> Mark, I only saw you post after mine was up ... throwing away CCSC is basically what I would advocate if it weren't for client requirements. AN734 is the best guide.</font>
___________________________
This message was ported from CCS's old forum
Original Post ID: 8579 |
|
|
aressa Guest
|
Re: PIC16F877 as I2C Slave |
Posted: Tue Nov 05, 2002 5:36 pm |
|
|
:=My advice is to throw away CCS's functions. Read the datasheet on the PIC and do it yourself. It is not hard and you have the ability to change the software. I use them in slave mode without any problems. In fact, in our design, 17 of them can be on the same bus.
:=Regards,
:=Mark
Hmmm... thanks. Do you know of any available source code that has already merged the ASM into a "nice" C front-end? I have very little experience with ASM and all of my (other) code is currently in C.
I'm also worried about the ACK being generated by the hardware anyway. I started reading through the TechNote and it specifically said that the hardware generates the ACK on the address read, or am I reading something wrong? I guess I need to understand the ASM a bit more.
Just a bit frustrated at this point.
Thanks.
___________________________
This message was ported from CCS's old forum
Original Post ID: 8586 |
|
|
Kenny
Joined: 07 Sep 2003 Posts: 173 Location: Australia
|
Re: PIC16F877 as I2C Slave |
Posted: Tue Nov 05, 2002 7:40 pm |
|
|
:=:=My advice is to throw away CCS's functions. Read the datasheet on the PIC and do it yourself. It is not hard and you have the ability to change the software. I use them in slave mode without any problems. In fact, in our design, 17 of them can be on the same bus.
:=:=Regards,
:=:=Mark
:=
:=Hmmm... thanks. Do you know of any available source code that has already merged the ASM into a "nice" C front-end? I have very little experience with ASM and all of my (other) code is currently in C.
There's a C version of AN734 at:
<a href="http://www.pic-c.com/forum/general/posts/7662.html" TARGET="_blank">http://www.pic-c.com/forum/general/posts/7662.html</a>
Regards
Kenny
:=
:=I'm also worried about the ACK being generated by the hardware anyway. I started reading through the TechNote and it specifically said that the hardware generates the ACK on the address read, or am I reading something wrong? I guess I need to understand the ASM a bit more.
:=
:=Just a bit frustrated at this point.
:=
:=Thanks.
___________________________
This message was ported from CCS's old forum
Original Post ID: 8587 |
|
|
Thomas Blake Guest
|
Re: PIC16F877 as I2C Slave |
Posted: Wed Nov 06, 2002 1:19 pm |
|
|
:=There's a C version of AN734
I did a double-take when I saw that!! It's almost identical to the way I translated it at first. Thanks for the confidence boost! Do you actually have this working at the "slow" speed of 100kb/s? I could only ever get about half that with AN734, although to be fair I am using a slow system clock ... video subcarrier frequency, about 3.58 MHz.
___________________________
This message was ported from CCS's old forum
Original Post ID: 8619 |
|
|
Kenny
Joined: 07 Sep 2003 Posts: 173 Location: Australia
|
Re: PIC16F877 as I2C Slave |
Posted: Wed Nov 06, 2002 5:45 pm |
|
|
<font face="Courier New" size=-1>:=:=There's a C version of AN734
:=
:=I did a double-take when I saw that!! It's almost identical to the way I translated it at first. Thanks for the confidence boost! Do you actually have this working at the "slow" speed of 100kb/s? I could only ever get about half that with AN734, although to be fair I am using a slow system clock ... video subcarrier frequency, about 3.58 MHz.
Glad that you too had success with the translation into C.
My version is asm-ish but readable and easily modified for a particular application I think.
Yes, the i2c clock speed is 100kb/s. I don't see any problem with your system clock of 3.58MHz on the master. Since i2c clocking is done by the master, the slave system clock speed is only relevant re overall throughput.
On the master, the SSPADD register contains the reload value for the BRG Down Counter (on the slave it contains the device i2c address instead).
The clock for the baud rate generator (BRG Down Counter) is Fosc/4. (the minimum reload value would be 1 so 400kHz system clock would be the minimum, of course all other processing would be slowed down too much in this case).
BTW The 1k pullups shown in the CCS manual are incorrect. PCM Programmer has posted excellent comments and links recently on this forum. 2k2 is within spec. and still gives a strong pullup.
Regards
Kenny
</font>
___________________________
This message was ported from CCS's old forum
Original Post ID: 8637 |
|
|
Tommy Guest
|
Re: PIC16F877 as I2C Slave--Sample code attached |
Posted: Fri Nov 29, 2002 12:56 am |
|
|
:=:=My advice is to throw away CCS's functions. Read the datasheet on the PIC and do it yourself. It is not hard and you have the ability to change the software. I use them in slave mode without any problems. In fact, in our design, 17 of them can be on the same bus.
:=:=Regards,
:=:=Mark
:=
:=Hmmm... thanks. Do you know of any available source code that has already merged the ASM into a "nice" C front-end? I have very little experience with ASM and all of my (other) code is currently in C.
:=
:=I'm also worried about the ACK being generated by the hardware anyway. I started reading through the TechNote and it specifically said that the hardware generates the ACK on the address read, or am I reading something wrong? I guess I need to understand the ASM a bit more.
:=
:=Just a bit frustrated at this point.
:=
:=Thanks.
Hello, aressa:
Here's an UNTESTED sample, assy. lang. function that might help you. The program's comments, and the PIC18CXX8 datasheet should help you understand what's happening.
Caution: This function is based on MicroChip examples and might have bugs. However, I plan to use it in my project.
Feel free to e-mail me questions if you have any.
Best regards,
Tom
;; File: i2cRead.asm
;; Reads one byte from i2c Slave
;;
;; Rev. History:
;;
;;
;; Assumptions:
;; i2cSTART and i2cSlaveATTN (R/_W bit cleared), has successfully executed)
;; Targeted slave is now "awake" expecting a read from it
;;
;; Input:
;;
;; Output: RDDAT holds rec'd byte from slave
;;
;; Processor: PIC18C658
;;
;
i2cRead CODE
movlw i2cSTATUS ; Flag we're reading
iorlw i2cRDDAT
movwf i2cSTATUS
;
bcf PIR1, SSPIF ; Clear intr. flag
bsf SSPCON2, RCEN ; Enable recv. mode
call initTMR0 ; Reset and start the timer
btfss PIR1, SSPIF ; Wait 'till MSSP intr. (time-out or done reading)
goto $-2 ;
bcf T0CON, TMR0ON ; Stop the timer
;
; ACK Rec’d data:
bsf SSPCON2, ACKDT
bsf SSPCON2, ACKEN
;
call initTMR0 ; Reset and start the timer
btfsc SSPCON2, ACKEN ; Has MSSP ACKed yet?
goto $-2 ; No, keep checking
bcf T0CON, TMR0ON ; Yes, stop the timer
;
movff SSPBUF, i2cDATA ; Save byte we just read
;
movlw i2cSTATUS ; Flag we're done reading
xorlw i2cRDDAT
movwf i2cSTATUS
return
___________________________
This message was ported from CCS's old forum
Original Post ID: 9614 |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|