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

dsPIC33 I2C Hardware Issue
Goto page Previous  1, 2, 3
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
temtronic



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

View user's profile Send private message

PostPosted: Tue Feb 19, 2019 9:47 am     Reply with quote

While I don't use DSPICs...
I was curious as 'tolerant' doesn't necessarily mean 'it will work', so I downloaded the datasheet as well as DS70330 (ref app note). I can't see anywhere that MicroChip says you can tie the bus to +5 while using a VDD of 3v3.
It'd be nice to have someone confirm this is allowed.
Baskar Veerappan



Joined: 17 Feb 2019
Posts: 9

View user's profile Send private message Send e-mail

PostPosted: Tue Feb 19, 2019 10:32 am     Reply with quote

Dear temtronic,

I am able to Write to slaves without any issues out only reading causes issues
creating a Bus Collision.
_________________
Regards
Baskar V
Baskar Veerappan



Joined: 17 Feb 2019
Posts: 9

View user's profile Send private message Send e-mail

Code
PostPosted: Tue Feb 19, 2019 10:35 am     Reply with quote

This is my code
Please Correct if anything is wrong

Code:


#define CLK_16MHZ
#define FCY      16010000 /*16.01 MHz*/

#ifndef CLK_16MHZ
#define FCY      69400000 /*69.4 MHz*/
#define CLK_138MHZ
#endif

#define MAXTASK (5u)
#define DS3231_RD         ((104u << 1u)|1u) /* RW Bit 1 */
#define DS3231_WR         (104u << 1u)  /* RW Bit 0 */

typedef enum { TASK0=0u,TASK1,TASK2,TASK3,TASK4} T_NO ;

typedef enum
{
   T_RUN,      /* Run the Task  */
   T_SUSPEND,   /* Wait For the event to Occur */
   T_STOP,      /* Stop the task. Enabled by user */
   T_WAIT      /* Wait For specific Period  */
}T_STATE ;

typedef struct
{
    T_NO TaskNo;
   T_STATE  TaskState;   
    Uint16 WaitTime ;
    void  (*Task)(void);
}SCHEDULER ;

typedef struct
{
   SCHEDULER *OsPtr  ;
   T_NO CurrentTask ;
   
}MAINTASK;

/********************************************************************************
* FUNCTION      :   I2C MASTER INITILIZATION
* ARGUMENT1     :   NONE
* RETURN TYPE   :   NONE
* NOTE          :   MASTER MODE
*            :   I2C BAUD RATE FORMULA : I2C1BRG = {[((1/FScl)-Delay)*Fcy]-2}
*            :   DELAY VARIES FROM 110nS to 130nS
* REFERENCE    :   MICROCHIP REFERENCE MANUAL : DS70330
********************************************************************************/
static void dsPIC33EP512GP502_I2C2MasterInit(void)
{
   TRISB      =  (BIT5|BIT6);       /* Inputs for I2C2 */
   I2C2CON      =   CLEAR ;          /*I2C2 Disabled */
#ifndef CLK_16MHZ /*Device Enters Full speed 70MIPS Approx */
   I2C2BRG    =   I2C_CLK_400KHz_AT_138MHz;
#endif
#ifdef CLK_16MHZ  /*Device Enters Low speed 16MIPS Approx */
   I2C2BRG    =   I2C_CLK_100KHz_AT_16MHz;
#endif
   I2C1ADD      =   CLEAR ;
   I2C1MSK      =   CLEAR ;
   I2C2CON      =   (BIT15|BIT13|BIT12|BIT8);
}
/********************************************************************************
* FUNCTION      :   SET I2C2 TIME OUT TIME
* ARGUMENT1     :   NONE
* RETURN TYPE   :   NONE
* NOTE          :   -/-
********************************************************************************/
void inline SetTimeoutTime(void)
{
#ifndef CLK_16MHZ /*Default Clock is 138 MHz*/
   I2C2.TimeOut   =   80000;/*Approx 2mS 70MIPS 0.001/Instrction Cycle14.4nS*/
#endif
#ifdef CLK_16MHZ /* Debug Clock is 16 MHz*/
   I2C2.TimeOut   =   17010;/*Approx 2mS 16MIPS 0.001/Instrction Cycle62.4nS*/
#endif    
}
/********************************************************************************
* FUNCTION      :   BUS IDLE  I2C2
* ARGUMENT1     :   NONE
* RETURN TYPE   :   BUS IDLE [1]  NOT IDLE [0]
* NOTE          :   -/-
********************************************************************************/
Flag BusIdle_I2C2(void)
{
   Flag ReturN = 0 ;
   ReturN =  (((I2C2STAT & (BIT14|BIT10|BIT7|BIT6)) == 0u) &&
           (( I2C2CON  & (BIT2|BIT1|BIT0)) == 0u)) ;
   return ReturN ;
}
/********************************************************************************
* FUNCTION      :   GENERATE ACK ON I2C2
* ARGUMENT1     :   ACK TYPE [0-ACK, 1-NACK]
* RETURN TYPE   :   NONE
* NOTE          :   -/-
********************************************************************************/
void PutAcknowledgeI2C2(Flag AckBit)
{
   I2C2CONbits.ACKDT   =   AckBit ;   
   I2C2CONbits.ACKEN   =   TRUE ;
}
/********************************************************************************
* FUNCTION      :   READ ACK FROM SLAVE ON I2C2 BUS
* ARGUMENT1     :   NONE
* RETURN TYPE   :   ACK TYPE [0-ACK, 1-NACK,2 ACK TIMEOUT ERROR]
* NOTE          :   -/-
********************************************************************************/
Uint08 GetAcknowledgeI2C2(void)
{
   if(I2C2.Sts == I2C_OK) {
   SetTimeoutTime();   
   while(I2C2.TimeOut != 0u) {
   if((BusIdle_I2C2() == TRUE) && (!I2C2STATbits.TBF)) {
   I2C2.Sts   =   I2C_OK ;
   return (I2C1STATbits.ACKSTAT);
   } else { I2C2.TimeOut -- ; }
   }
   return(I2C2.Sts=ACK_ERR) ;   
   }
   else { return(I2C2.Sts=ACK_ERR);}   
}
/********************************************************************************
* FUNCTION      :   INITIATE START,RESTART,STOP CONDITION ON I2C2 BUS
* ARGUMENT1     :   START,RESTART,STOP
* RETURN TYPE   :   NONE
* NOTE          :   -/-
********************************************************************************/
void dsPIC33EP512GP502_IIC2(STATE_IIC Action)
{
   if(I2C2.Sts != I2C_OK) {
   
   dsPIC33EP512GP502_I2C2MasterInit();
      
   } else { /* No Operation */ }
      
   SetTimeoutTime();   
   
   while(I2C2.TimeOut != 0u) {
      
   I2C2.Sts =    I2C_OK ;
   
   ((BusIdle_I2C2() == TRUE) ? ((Action == START) ? (I2C2CONbits.SEN = TRUE) :
      
   ((Action == RESTART) ? (I2C2CONbits.RSEN = TRUE):(I2C2CONbits.PEN = TRUE))):
      
   (I2C2.Sts  = BUS_NOT_IDLE) ) ;
      
   (I2C2.Sts  != BUS_NOT_IDLE) ? (I2C2.TimeOut = CLEAR) : (I2C2.TimeOut--) ;
   
   }
}
/********************************************************************************
* FUNCTION      :   WRITE TO I2C2 BUS
* ARGUMENT1     :   NONE
* RETURN TYPE   :   NONE
* NOTE          :   -/-
********************************************************************************/
void IIC2_Transmit(Uint08 DaTa)
{
   if(I2C2.Sts == I2C_OK) {
   SetTimeoutTime();   
   while(I2C2.TimeOut != 0u) {
   if(BusIdle_I2C2() == TRUE) {
   I2C2TRN      =   DaTa ; /*Shift Out*/
   I2C2.Sts   =   I2C_OK ;
   return ;
   }
   else {   I2C2.TimeOut -- ; }
   }
   I2C2.Sts   =   I2C_ERR;
   return ;   
   }
   else { /* Exit Without Operation */}
}
/********************************************************************************
* FUNCTION      :   READ FROM I2C2 BUS
* ARGUMENT1     :   NONE
* RETURN TYPE   :   READ DATA
* NOTE          :   -/-
********************************************************************************/
Uint08 IIC2_Recieve(void)
{
   Uint08 RxData = NULL ;
   if(I2C2.Sts == I2C_OK) {
   SetTimeoutTime();   
   while(I2C2.TimeOut != 0u) {
   if(I2C2STATbits.RBF == TRUE) {
   RxData      =   I2C2RCV; /*Shift In */
   I2C2.Sts   =   I2C_OK ;
   return RxData ;
   }
   else {   I2C2.TimeOut -- ; }
   }
   I2C2.Sts   =   I2C_ERR;
   return NULL ;   
   }
   else { return NULL ; /* Exit Without Operation */}
}
/********************************************************************************
* FUNCTION      :   READ TIME FROM DS3231 RTC CHIP
* ARGUMENT1     :   ADDRESS OF INTERNAL REGISTER TO BE READ
* RETURN TYPE   :   RTC READ VALUE
* NOTE          :   -/-
********************************************************************************/
Uint08 Read_DS3231(Uint08 Adrs )
{
   Uint08 RxD =0; Flag AckNow=1;
   AckNow = I2C2STATbits.ACKSTAT ;
   I2C2CONbits.RCEN = TRUE ;
   dsPIC33EP512GP502_IIC2(START);   
   IIC2_Transmit(DS3231_WR);
   IIC2_Transmit(Adrs); /*Internal Register Address */
   AckNow = (GetAcknowledgeI2C2() == ACK);
   dsPIC33EP512GP502_IIC2(RESTART);   
   IIC2_Transmit(DS3231_RD);/* Bus Collision Occurs Here Making SDA 0 for Ever*/
   RxD = IIC2_Recieve();
   PutAcknowledgeI2C2(NACK);
   dsPIC33EP512GP502_IIC2(STOP);   
   return RxD ;   
}
/********************************************************************************
* FUNCTION      :   SERIAL COMMUNICATIONS INIT
* ARGUMENT1     :   NONE
* RETURN TYPE   :   NONE
* NOTE          :   ALL TIMER SETTINGS
********************************************************************************/
static inline void dsPIC33EP512GP502_SerialCoM(void)
{
   dsPIC33EP512GP502_I2C2MasterInit();
   dsPIC33EP512GP502_UARTMaster();
}
/********************************************************************************
* FUNCTION      :   HARDWARE INITILIZATION 
* ARGUMENT1     :   NONE
* RETURN TYPE   :   NONE
* NOTE          :   NONE
********************************************************************************/
void dsPIC33EP512GP502_Hw_Initialization(void)
{
   dsPIC33EP512GP502_OscConfig();    /* Oscillator Configurations */
   dsPIC33EP512GP502_PMD();       /* PMD Configurations        */
   dsPIC33EP512GP502_IO_Setting();    /* IO Pin Configurations     */
   dsPIC33EP512GP502_Interrupts();    /* Interrupt Settings        */
   dsPIC33EP512GP502_Timers();       /* Timer Settings            */
   dsPIC33EP512GP502_SerialCoM();    /* Serial Communications     */
   dsPIC33EP512GP502_RemapingIO();    /* PPS- Remaping IO          */
}
/********************************************************************************
* FUNCTION      :   TASK STATE CONTROL   
* ARGUMENT1     :   TASK NUMBER
* ARGUMENT2     :   WAIT TIME [IF TASK STATE IS SET TO WAIT ELSE PASS 0]
* RETURN TYPE   :   NONE
* CATEGORY      :   TASK MANAGEMENT      
********************************************************************************/
void SetTaskState(T_NO TaskNo ,T_STATE StatE,Uint16 Time)
{
   Main.OsPtr[TaskNo].TaskState  = StatE ;
   Main.OsPtr[TaskNo].WaitTime   = Time ;
}
/********************************************************************************
* FUNCTION      :   TASK_INITIALIZATION TASK 
* ARGUMENT1     :   NONE
* RETURN TYPE   :   NONE
********************************************************************************/
void Task_Initialization(void)
{
   dsPIC33EP512GP502_Hw_Initialization();
   dsPIC33EP512GP502_Sw_Initialization(); /*Variables Initialization */
   Init_LCD_4bit();
   Print_LCD("Welcome Boss...",STRING,Line2); // Test Purpose
   Display_Auto_clear(2000,Line2+3,8); // Test Purpose Clear after 2 Seconds
   SetTaskState(TASK0,T_STOP,NULL);    // No More Further Execution
}
/********************************************************************************
* FUNCTION      :   500mS TASK 
* ARGUMENT1     :   NONE
* RETURN TYPE   :   NONE
********************************************************************************/
void Task_500mS(void)
{
   Uint16 Sec=0;
   Sec = Read_DS3231(0); // Read Seconds Register
   Print_LCD(&Sec,INTEGER2,Line3);
   SetTaskState(TASK1,T_WAIT,250u); /*250*2mS = 500mS*/
}
/********************************************************************************
* FUNCTION      :   MAIN
* ARGUMENT1     :   NOT REQUIRED
* RETURN TYPE   :   NONE
********************************************************************************/
int main(void)
{
   Uint08 TskNow ;

   SCHEDULER   TaskHandler[MAXTASK] = {
   { TASK0   ,   T_RUN         ,      0u  ,    Task_Initialization   },
   { TASK1   ,   T_RUN         ,      0u  ,    Task_500mS        },
   { TASK2   ,   T_RUN         ,      0u  ,    Task_1000mS        },
   { TASK3   ,   T_WAIT        ,      500u,    Task_DisplayHandler }, /* 1S Wait*/
   { TASK4   ,   T_STOP        ,      0u  ,    Task_AlarmHandler   }
   } ;
/*  Enabling for Global Access */
   Main.OsPtr = TaskHandler ;
/*  Run Time Task Handling */
   for(TskNow = 0; TskNow < MAXTASK; TskNow = ((TskNow+1u)%MAXTASK))
   {   
   if(TaskHandler[TskNow].TaskState == T_RUN) {   
   Main.CurrentTask = TaskHandler[TskNow].TaskNo;
   TaskHandler[TskNow].Task() ;
   }
   }
   return 0 ;
}


_________________
Regards
Baskar V
gaugeguy



Joined: 05 Apr 2011
Posts: 303

View user's profile Send private message

PostPosted: Tue Feb 19, 2019 10:44 am     Reply with quote

5V tolerant pins on PIC24 & PIC33 have the specs in the specific data sheet for that processor under electrical characteristics. This is typical of many:

Voltage on any general purpose digital or analog pin (not 5.5V tolerant) with respect to VSS: -0.3V to (VDD + 0.3V)

Voltage on any general purpose digital or analog pin (5.5V tolerant, including MCLR) with respect to VSS:
When VDD = 0V: -0.3V to +4.0V
When VDD > = 2.0V:. -0.3V to +6.0V

So I2C can be operated this way with 5V tolerant pins.
Baskar Veerappan



Joined: 17 Feb 2019
Posts: 9

View user's profile Send private message Send e-mail

PostPosted: Tue Feb 19, 2019 10:51 am     Reply with quote

Anybody Having Working I2C Code for dsPIC33EP512GP502

It will be very helpful if any one provide.
_________________
Regards
Baskar V
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Feb 19, 2019 10:54 am     Reply with quote

Your posted code is for a Microchip compiler, not CCS.
This is the CCS forum.
Baskar Veerappan



Joined: 17 Feb 2019
Posts: 9

View user's profile Send private message Send e-mail

PostPosted: Tue Feb 19, 2019 10:59 am     Reply with quote

Dear PCM Programmer,

Yup you are Right

But I have not used any inbuilt library code from XC16 compiler.
Smile
_________________
Regards
Baskar V
allenhuffman



Joined: 17 Jun 2019
Posts: 554
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Wed Apr 26, 2023 10:38 am     Reply with quote

daveh wrote:
So apparently when the hardware I2C module is enabled "input(i2c2_SDA)" will always read '0'. [Someone please correct me if I'm wrong]

So instead I'm using the following code which disables the hardware I2C before testing the pin:
Code:
#bit I2C2EN_BIT = 0x0216.15   // I2CEN bit to enable/disable hardware I2C module
#define i2c2_SDA PIN_B5


I2C2EN_BIT=0;                 // disable I2C2 Hardware Module
if(!input(i2c2_SDA)){         // SDA stuck low - Fault Condition
    output_drive(i2c2_SCL);   // set SCL as output
    while(!input(i2c2_SDA)){  // Toggle clock line till fault clears
       output_toggle(i2c2_SCL);
       delay_us(1);
    }
    output_float(i2c2_SCL);   // set SCL as input
}
I2C2EN_BIT=1;                 // enable I2C2 Hardware Module


Thanks for posting this, back then.

I just implemented a variation of this one several of our PIC24 boards today. I ran in to an issue where, after Build & Run from the CCS IDE, the board would start up and the I2C bus would be locked. It took a power cycle to get it working. I went searching to see about trying an I2C Bus Reset and found a reference to this post in another thread.

I left out the check for SDA, and just used i2c_init() to start/stop it, so mine was more like this:

Code:

// I2C configuration
#define I2C1_CLOCK              PIN_B8      // I2C1 clock
#define I2C1_DATA               PIN_B9      // I2C1 data

#define I2C_INTERNAL_BUS_SCL    I2C1_CLOCK
#define I2C_INTERNAL_BUS_SDA    I2C1_DATA

#use i2c (MASTER, FAST=400000, I2C1, stream=INTERNAL_BUS)

...

i2c_init (INTERNAL_BUS, 0);             // disable
output_drive(I2C_INTERNAL_BUS_SCL);     // set SCL as output
for (int idx=0; idx<20; idx++)
{
    output_toggle(I2C_INTERNAL_BUS_SCL); // send clock pulses
    delay_us(1);
}
output_float(I2C_INTERNAL_BUS_SCL);     // set SCL as input
i2c_init (INTERNAL_BUS);                // enable

_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Thu Apr 27, 2023 2:06 am     Reply with quote

If you use the NOINIT setting in the #USE I2C, then the bus is not
started at boot, so you can test the SDA pin and clock before starting the
bus:
Code:


#use i2c(I2C1, MASTER, FAST=320000, stream=I2CBUS, NOINIT)
//NOINIT to allow I2C bus hang to be cleared

      //I2C startup code
      while (input(SDA)==0)
      {
         //SDA is low. Bus may be hung
         //So need to try clocking SCL to release bus
         //SDA must be floated during this to avoid an ACK if
         //the bus releases
         output_float(SDA);
         for (temp8=0;temp8<9;temp8++)
         {
            output_low(SCL);
            delay_us(5);
            output_float(SCL);
            delay_us(5);
         } //9*100KHz clocks
         output_low(SDA);
         delay_us(10);
         output_float(SDA);
         //This technically generates a STOP.
      }
      i2c_init(I2CBUS,1); //Now physically initialise bus


This is how I init I2C. This is the defined sequence in the I2C spec to
release a hung bus.
allenhuffman



Joined: 17 Jun 2019
Posts: 554
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Thu Apr 27, 2023 5:45 pm     Reply with quote

Ttelmah wrote:
If you use the NOINIT setting in the #USE I2C, then the bus is not
started at boot, so you can test the SDA pin and clock before starting the
bus:
Code:

...
output_low(SCL);
delay_us(5);
output_float(SCL);
delay_us(5);



Thanks -- useful. Why using float/low versus high/low?
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Thu Apr 27, 2023 8:13 pm     Reply with quote

allenhuffman wrote:
Thanks -- useful. Why using float/low versus high/low?


He's just exactly mimicking what the peripheral does: actively pull the line low, then release - not drive high. That's what the pullups are there for.
Ttelmah



Joined: 11 Mar 2010
Posts: 19539

View user's profile Send private message

PostPosted: Fri Apr 28, 2023 12:44 am     Reply with quote

and remember that the whole point of I2C, is that it supports multiple
devices potentially pulling the lines 'low' at the same time, and can do this
because none ever _drive_ the lines high. If you drive a line high it only
takes another device to be pulling the line low, and you have potentially
damaging currents flowing... Sad
I2C relies on having historically 'open collector; drives. Low only. Drive
upwards is just the pull-up resistor, or an accelerator (which actively pulls
up, but only once the voltage is already rising).
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, 3
Page 3 of 3

 
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