CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

I2C on PIC12F1840 does not work on 3.3V
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 21, 2017 5:29 am     Reply with quote

This whole thread is running blind because you have not posted a test
program that shows the problem. It might be that we could look at your
i2c slave code and spot the problem right away. You also have not
posted your compiler version.

It should be possible to put together a minimalist test program that
shows your problem, and post it, along with your compiler version.
The program must have all #fuses, etc., and be compilable without errors.
Futterama



Joined: 17 Oct 2005
Posts: 98

View user's profile Send private message

PostPosted: Tue Feb 21, 2017 2:03 pm     Reply with quote

Test program with compiler 5.042:

test.h
Code:
#include <12F1840.h>

#FUSES NOWRT         // Program memory not write protected
#FUSES INTRC_IO      // Internal RC Osc, no CLKOUT
#fuses NOWDT          //No Watch Dog Timer
#fuses PUT            //Power Up Timer
#fuses NOMCLR         //Master Clear pin used for I/O
#fuses PROTECT        //Code protected from reads
#fuses NOCPD          //No EE protection
#fuses NOBROWNOUT     //No brownout reset
#fuses NOCLKOUT       //I/O function on OSC2
#fuses NOIESO         //Internal External Switch Over mode disabled
#fuses NOFCMEN        //Fail-safe clock monitor disabled
#fuses WRT            //Program Memory Write Protected
#fuses NOSTVREN       //Stack full/underflow will not cause reset
#fuses NODEBUG        //No Debug mode for ICD
#fuses NOLVP          //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O

#use delay(internal=32MHz)

#use i2c(SLAVE, I2C1, ADDRESS=0x18, FORCE_HW)

#use fast_io(a)


test.c
Code:
#include <test.h>

int8 I2C_bufferindex = 0;
int8 I2C_buffer[16] = {0x0C, 0x00, 1, 'T', 'e', 's', 't', ' ', 'I', '2', 'C', ' ', 'P', 'I', 'C', 0};

#INT_SSP
void SSP_isr(void)
{
   int8 I2C_state, I2C_address;
   
   I2C_state = i2c_isr_state(); // Get state
   if(I2C_state == 0x80) // Address match with R/W bit set
   {
      I2C_address = i2c_read(2); // Read from I2C and don't release the clock
   }
   if(I2C_state > 0x7F) // Slave needs to write data
   {
      i2c_write(I2C_buffer[I2C_bufferindex]); // Write data
      I2C_bufferindex++; // Increment buffer index
   }
   if(I2C_state == 0x90) // Last data byte has been written
   {
      I2C_bufferindex = 0; // Reset buffer index
   }
}

void main()
{
   set_tris_a(0b11101111);
   
   enable_interrupts(INT_SSP);
   enable_interrupts(GLOBAL);

   while(TRUE)
   {
   }
}


Code:
      Memory usage:   ROM=4%      RAM=11% - 18%
      0 Errors,  0 Warnings.
Build Successful.


The master device starts by enumerating the bus and the PIC needs to answer back twice. If it does, the master device will poll it continuously after that. The data is 16 bytes and the text in the data is displayed on the master device system.

I checked my notes from the other forum, and what I found was that with the 10k pull-up master (Cypress MCU), things worked OK, but when I switched to the 1k1 pull-up master (STM MCU), things got bad. I can replicate this by adding 1k pull-ups when using the 10k pull-up master.

I have scope shots of the 10k pull-up master with no additional pull-ups and then with 1k pull-ups added (running 16MHz clock).

At 16MHz the PIC runs fine with the added 1k pull-ups and 3.3V VDD. At 32MHz, it will not reply to the masters enumeration with the 1k pull-ups, but if I remove those, is will answer. Unfortunately, I can't really remove them from the STM device which has the built-in 1k1 pull-ups.

Cypress 10k pull-up device with no additional pull-up:
http://drive.google.com/uc?export=view&id=0B-a5yG3Hqo3BZ2tTQnpueTZ4TVE

Cypress 10k pull-up device with additional 1k pull-up:
http://drive.google.com/uc?export=view&id=0B-a5yG3Hqo3BRWtIWC1Uc19PRjA
temtronic



Joined: 01 Jul 2010
Posts: 9269
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Feb 21, 2017 3:15 pm     Reply with quote

this...
At 16MHz the PIC runs fine with the added 1k pull-ups and 3.3V VDD
...seems to be a reasonable solution.

When I look at the 2 scope shots, the one without the 1k pullups is 'terrible'. Aside from the 'lazy' leading edge, there's some mysterious 'blips' on the data line....

Without having that PIC to play with, I don't know why it doesn't run at 32MHz for you properly. I would suggest using a 2nd PIC to emulate the 'device'. One huge problem is not knowing what really ' inside' that device and how it does work.There are 4 or 5 possible 'solutions' based on what's presented, which 'fits' best depends on your time and pocketbook.


Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19587

View user's profile Send private message

PostPosted: Wed Feb 22, 2017 2:16 am     Reply with quote

The waveforms with the 10K pull-ups are out of spec.
Problem #1.

Then the handling is 'short cutting' standard I2C. The standard for an I2C read transaction, is:

start
send write address
write register address
restart
send read address
read byte(s)
stop

Instead the transaction is assuming that the read address will reset itself.
Now if everything remains perfectly synchronised this is fair, but as done, will go out of sync if anything unexpected is seen on the bus. This is 'why' the bus has start and stop transactions and these should be used to synchronise the transaction. The glitches visible are extremely worrying, and may well trigger unexpected states...
Then there is a problem that as written, if the bus sees an unexpected 'start' that is not followed by an address match 'write start', the chip will become hung. Remember the chip will see _all_ start transactions on the bus. This is why it _must_ read the address byte that follows, whatever direction is selected.
Finally the code needs to reset the CKP. There is an issue that is particularly prone to happen when the processor is running fast, that the reset done immediately after a write, may not work. It's documented in about four chip errata, but actually seems to apply to all PIC's (I've reported it on about three where it was not a listed erratum...).
The address also needs to be static.
Then there is no attempt to handle the possible error states. With the glitches seen, these need to be handled...

As a general comment also, don't enable protection till _after_ you have finished debugging.
Doing so, wastes lives on the chip memory. With this disabled, and the programmer set to only erase as needed, only the parts of the code you change have to be erased. With protection enabled _every_ cell in the memory has to be erased, even to change just one byte. Result lives being used up....

So:

1) More pull-up needed.
2)
Code:

#bit CKP=getenv("BIT:CKP")
#bit WCOL=getenv("BIT:WCOL")
#bit SSPOV=getenv("BIT:SSPOV")

#INT_SSP
void SSP_isr(void)
{
   int8 I2C_state, dummy;
   static int8 I2C_address; //must be static
   //first handle possible errors
   if (WCOL)
      WCOL=FALSE; //write collision - should be impossible
   if (SSPOV)
   {
      //overflow no read was done
      dummy=I2C_read();
      SSPOV=FALSE;
      return; //break out, since byte will be bad.
   }
   
   I2C_state = i2c_isr_state(); // Get state
   if (i2c_state<0x7F)
      dummy=i2c__read(); //dummy read in unexpected state
   if(I2C_state == 0x80) // Address match with R/W bit set
   {
      I2C_address = i2c_read(2);
      // Read from I2C and don't release the clock
      I2C_bufferindex = 0; // Use this to reset buffer index 'in case'     
   }
   if(I2C_state > 0x7F) // Slave needs to write data
   {
      i2c_write(I2C_buffer[I2C_bufferindex]); // Write data
      I2C_bufferindex++; // Increment buffer index
      //Now need to ensure clock releases
      CKP=TRUE;
   }
   if(I2C_state == 0x90) // Last data byte has been written
   {
      I2C_bufferindex = 0; // Reset buffer index
   }
}

This should handle all potential bus states.

I suspect that with the increase in sampling frequency when the clock goes faster, the PIC is seeing some of the glitches as legitimate states, and possibly entering the ISR in perhaps state 0. This is then not reading the buffer, which will then result in SSPOV being set, and the peripheral becoming hung....
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
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