|
|
View previous topic :: View next topic |
Author |
Message |
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Feb 19, 2019 9:47 am |
|
|
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
|
|
Posted: Tue Feb 19, 2019 10:32 am |
|
|
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
|
Code |
Posted: Tue Feb 19, 2019 10:35 am |
|
|
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
|
|
Posted: Tue Feb 19, 2019 10:44 am |
|
|
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
|
|
Posted: Tue Feb 19, 2019 10:51 am |
|
|
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
|
|
Posted: Tue Feb 19, 2019 10:54 am |
|
|
Your posted code is for a Microchip compiler, not CCS.
This is the CCS forum. |
|
|
Baskar Veerappan
Joined: 17 Feb 2019 Posts: 9
|
|
Posted: Tue Feb 19, 2019 10:59 am |
|
|
Dear PCM Programmer,
Yup you are Right
But I have not used any inbuilt library code from XC16 compiler.
_________________ Regards
Baskar V |
|
|
allenhuffman
Joined: 17 Jun 2019 Posts: 554 Location: Des Moines, Iowa, USA
|
|
Posted: Wed Apr 26, 2023 10:38 am |
|
|
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
|
|
Posted: Thu Apr 27, 2023 2:06 am |
|
|
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
|
|
Posted: Thu Apr 27, 2023 5:45 pm |
|
|
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
|
|
Posted: Thu Apr 27, 2023 8:13 pm |
|
|
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
|
|
Posted: Fri Apr 28, 2023 12:44 am |
|
|
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...
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). |
|
|
|
|
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
|