element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Code Exchange
  • Technologies
  • More
Code Exchange
Forum Interfacing of SHT11 with PIC24f16KA102
  • Blog
  • Forum
  • Documents
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Code Exchange to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • State Suggested Answer
  • Replies 13 replies
  • Answers 2 answers
  • Subscribers 47 subscribers
  • Views 2209 views
  • Users 0 members are here
Related

Interfacing of SHT11 with PIC24f16KA102

Former Member
Former Member over 11 years ago

Hi,

I have written the c code for I2C for interfacing the SHT11(temp sensor) and PIC24F16KA102. but i m not getting the acknowledge from the SHT11 when i m writing through pic.  i m pasting my code here. plz let me know where i m doing wrong if possible. thanks

 

#include <stdint.h>

#include <xc.h>

#include "main.h"

 

#include <p24Fxxxx.h>

// ICD Pin Placement Select (EMUC/EMUD share PGC3/PGD3)

//_FICD(ICS_PGx1)

/*

* File:   main.c

* Author: jalpa

*

* Created on 7 February, 2014, 10:11 AM

*/

/*******************************************************************************************************************/

//Include section

 

/*******************************************************************************************************************/

#include "p24F16KA102.h"

 

#include "spi.h"

#include "i2c.h"

#include <timer.h>

 

 

 

/*******************************************************************************************************************/

//Define section

/*******************************************************************************************************************/

// for input use  PORTBbits.RB7  notation and for output pin use LATBbits.LATB2.

//#define CE LATBbits.LATB2    //pin-6  // CE output pin, PORTB bit 2

 

 

//#define SDA_pin LATBbits.LATB9    //pin-22// Clock output pin, PORTB bit 11

//#define SCL_pin LATBbits.LATB8

//

//#define SDA_dir TRISBbits.TRISB9

//#define SCL_dir TRISBbits.TRISB8

 

/*******************************************************************************************************************/

 

//Declaration of variable

/*******************************************************************************************************************/

unsigned char msb;

unsigned char lsb;

unsigned char status;

 

/*******************************************************************************************************************/

//Declaration of functions

 

/*******************************************************************************************************************/

void i2c_init();

void reset_i2c_bus();

void delay_us(unsigned short us);

void i2c_start();

void i2c_restart();

char i2c_send_byte(int data);

char i2c_read_byte();

 

 

//#define SCK_dir TRISBbits.TRISB8

 

 

 

/*******************************************************************************************************************/

//Main function

/*******************************************************************************************************************/

 

void main(void)

{

 

 

 

   // AD1PCFGbits.PCFG0=1;

   // AD1PCFGbits.PCFG1=1;

 

   AD1PCFG =0XFF;

   //SCK_dir=0;

  

   i2c_init();

   i2c_start();

   delay_us(2000);

   status = i2c_send_byte(0x03);

   delay_us(10000);

   msb= i2c_read_byte();

   lsb= i2c_read_byte();

   reset_i2c_bus();

 

 

 

   

 

}

 

 

 

 

 

void i2c_init()

{

    int temp;

    I2C1BRG = 157;

    I2C1CONbits.I2CEN = 0;

    I2C1CONbits.DISSLW = 1;

    I2C1CONbits.I2CEN= 1;

    temp = I2C1RCV;

    reset_i2c_bus();

 

}

 

void reset_i2c_bus()  // reset is used before and after a packet i sent through the bus (release both sda and scl)

{

 

    int x=0;

 

    I2C1CONbits.PEN= 1;

 

    while(I2C1CONbits.PEN)

    {

 

        delay_us(1);

        x++;

        if(x>20) break;

 

    }

 

    I2C1CONbits.RCEN=0;

    IFS1bits.MI2C1IF=0;

    I2C1STATbits.IWCOL=0;

    I2C1STATbits.BCL=0;

 

    delay_us(10);

   

}

 

void i2c_start(void)

{

   int x = 0;

   I2C1CONbits.ACKDT = 0;    //Reset any previous Ack

   delay_us(10);

   I2C1CONbits.SEN = 1;    //Initiate Start condition

   Nop();

 

   //the hardware will automatically clear Start Bit

   //wait for automatic clear before proceding

   while (I2C1CONbits.SEN)

   {

      delay_us(1);

      x++;

      if (x > 20)

      break;

   }

    delay_us(2);

}

 

 

void i2c_restart(void)

{

   int x = 0;

 

   I2C1CONbits.RSEN = 1;    //Initiate restart condition

   Nop();

 

   //the hardware will automatically clear restart bit

   //wait for automatic clear before proceding

   while (I2C1CONbits.RSEN)

   {

      delay_us(1);

      x++;

      if (x > 20)    break;

   }

 

   delay_us(2);

}

 

 

char i2c_send_byte(int data)

{

   int i;

 

   while (I2C1STATbits.TBF) { }

   IFS1bits.MI2C1IF = 0; // Clear Interrupt

   I2C1TRN = data; // load the outgoing data byte

 

   // wait for transmission

   for (i=0; i<500; i++)

   {

      if (!I2C1STATbits.TRSTAT) break;

      delay_us(1);

 

      }

      if (i == 500) {

      return(1);

   }

 

   // Check for NO_ACK from slave, abort if not found

   if (I2C1STATbits.ACKSTAT == 1)

   {

      reset_i2c_bus();   //error

      return(1);

   }

 

   delay_us(2);

   return(0);

}

 

char i2c_read_byte(void)    //does not reset bus!!!

{

   int i = 0;

   char data = 0;

 

   //set I2C module to receive

   I2C1CONbits.RCEN = 1;

 

   //if no response, break

   while (!I2C1STATbits.RBF)

   {

      i++;

      if (i > 2000) break;

   }

 

   //get data from I2CRCV register

   data = I2C1RCV;

 

   //set ACK to high

   I2C1CONbits.ACKEN = 1;

 

   //wait before exiting

   delay_us(10);

 

   //return data

   return data;

}

 

 

 

void delay_us(unsigned short us)

{

  unsigned short i;

 

  // TIMER1 Period = PR1 x 2 x Tosc x Prescale second

  // TIMER1 Period = 145 x 2 x 1/32000000 x 1 = 9 us // practically coming 12us

 

  PR1=145;                      // Maximum Counter

  T1CON=0x0000;            // TIMER1 Off, Prescale 1:1 using the internal clock

  for (i=0; i < us;i++) {

    TMR1=0;                     // Reset TIMER1 Counter

    IFS0bits.T1IF=0;            // Clear TIMER1 Interrupt Flag

    T1CONbits.TON=1;            // Turn On TIMER1

    while(IFS0bits.T1IF != 1);  // Wait until TMR1 > PR1 (Overflow)

    T1CONbits.TON=0;            // Turn Off TIMER1

  }

 

}

  • Sign in to reply
  • Cancel

Top Replies

  • Former Member
    Former Member over 11 years ago in reply to gihu +1
    Hi, thanks Actually i checked the the clock configuration earlier through as u said by LED blinking Code. and for FRCPLL and keeping CLKDIV=0x0000; i m getting Fcy=16MHz. I have checked it by putting different…
  • gihu
    0 gihu over 11 years ago

    Hi jalpa,

     

    I suppose that you are using MPLAB IDE plus XC16 complier, rigth?

    In your code you:

    #include "i2c.h",

     

    but you never use it, you are using own function declared and coded in your main.c, right?

    If you have chosen the PIC when create the project, you do not need to:

    #include <p24Fxxxx.h>

    After includes and defines, configuration bits are missing, (the configuration bits MPLAB utility is very usefull!!).

     

    I recommend you using the functions in i2c.h, like OpenI2C1(), CloseI2C1(), MasterWriteI2C1(), StartI2C1(), StopI2C1(), etc... the function to use will depend on the configuration of the bus when OpenI2C.

     

    I hope that helps,

    Miguel

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Reject Answer
    • Cancel
  • Former Member
    0 Former Member over 11 years ago in reply to gihu

    thanks for your reply. For configuration i have kept file so thats why is not included in this code. I will try the functions suggested by you, which are in built.  can u tell me what is the difference between hardware spi and software spi?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • gihu
    0 gihu over 11 years ago in reply to Former Member

    Normally, you use I2C by soft when you do not have a dedicated hardware for I2C, mainly when you use software to emulate such a dedicated hardware, the CPU has to deal with all the delay, timings, pooling, checking flags, whereas if you use dedicated hardware (with interruptions), CPU has just to configure the hardware just once, and let the hardware deals with most of this work, making lighter the workload of the CPU.

     

    I see you try to use a the dedicated registers and flags, so better use the functions given by XC.

     

    If you configure the hardware, and when write, you don't receive the slave ACK, check you have configured correctly the address mode and the SCL speed of the I2C, maybe the sensor is not receiving correctly what it is expecting.

     

    Hope that helps,

    Miguel

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • gihu
    0 gihu over 11 years ago in reply to Former Member

    Probably you have a very usefull help file, path could look like this C:\Program Files (x86)\Microchip\xc16\v1.21\docs\periph_libs\Microchip PIC24F Peripheral Library.chm.

    Where every function is explained.

     

    Maybe it is obvios, but do not forget the pull-up resistor in both lines SCL and SDA.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • Former Member
    0 Former Member over 11 years ago in reply to gihu

    hi,

     

    i have tried the following code from example of library. but still i m not getting ACK as 0 in I2C1STAT register when i debug the code and watching status of I2C1STAT register. i m pasting here code as well as configuration file data. i m using PIC24F16KA102 related board that is Microstick 3.3V. Pic works at 32MHZ so its Fcy is 16MHz and according to 100KHZ of SCL i have kept baud rate generator count as 157(refereed from data sheet of pic). plz let me know where i m doing wrong. thanks

     

    code:.........................

     

    #include "p24F16KA102.h"

     

    #include "spi.h"

    //#include "i2c.h"

    #include <timer.h>

    #define USE_AND_OR /* To enable AND_OR mask setting */

    #include<i2c.h>

     

    UINT8 I2C_RECV[15],I2C_TRANS[] = "MICROCHIP";

     

    //******************** Interrupt sevice rotuine for I2C1 Master ***************************

    void __attribute__((interrupt,no_auto_psv)) _MI2C1Interrupt(void)

    {

      MI2C1_Clear_Intr_Status_Bit;  //Clear Interrupt status of I2C1

    }

     

     

    int main(void)

    {

       UINT config1 = 0,i=0;

       UINT config2 = 0;

     

       /* Turn off I2C modules */

       CloseI2C1();    //Disbale I2C1 mdolue if enabled previously

     

     

    //************ I2C interrupt configuration ******************************************************

        ConfigIntI2C1(MI2C_INT_OFF);  //Disable I2C interrupt

     

    //***************** I2C1 configuration **********************************************************

    /**********************************************************************************************

    *

    *        I2C1 enabled

    *        continue I2C module in Idle mode

    *        IPMI mode not enabled

    *        I2CADD is 7-bit address

    *        Disable Slew Rate Control for 100KHz

    *        Enable SM bus specification

    *        Disable General call address

    *        Baud @ 8MHz = 39 into I2CxBRG

    **********************************************************************************************/

       config1 = (I2C_ON  | I2C_7BIT_ADD );

       //config2 = 39;

       config2 = 157;

       OpenI2C1(config1,config2);   //configure I2C1

     

       IdleI2C1();

       StartI2C1();

       while(I2C1CONbits.SEN );  //Wait till Start sequence is completed

       MI2C1_Clear_Intr_Status_Bit; //Clear interrupt flag

     

       MasterWriteI2C1(0x03);       //Write Slave address and set master for transmission

       while(I2C1STATbits.TBF);     //Wait till address is transmitted

       while(!IFS1bits.MI2C1IF);    //Wait for ninth clock cycle

       MI2C1_Clear_Intr_Status_Bit; //Clear interrupt flag

       while(I2C1STATbits.ACKSTAT);

     

        for(i=0;i<1000;i++);

       

    }

     

    configuration file data:............

     

    #include "system_config.h"

    // *****************************************************************************

    // *****************************************************************************

    // Section: Configuration Bits

    // *****************************************************************************

    // *****************************************************************************

     

    // FBS

    #pragma config BWRP = OFF               // Table Write Protect Boot (Boot segment may be written)

    #pragma config BSS = OFF                // Boot segment Protect (No boot program Flash segment)

     

    // FGS

    #pragma config GWRP = OFF               // General Segment Code Flash Write Protection bit (General segment may be written)

    #pragma config GCP = OFF                // General Segment Code Flash Code Protection bit (No protection)

     

    // FOSCSEL

    #pragma config FNOSC = FRCPLL           // Oscillator Select (Fast RC oscillator with divide-by-N with PLL module (FRCDIV+PLL))

    #pragma config IESO = OFF               // Internal External Switch Over bit (Internal External Switchover mode disabled (Two-Speed Start-up disabled))

     

    // FOSC

    #pragma config POSCMOD = NONE           // Primary Oscillator Configuration bits (Primary oscillator disabled)

    #pragma config OSCIOFNC = ON            // CLKO Enable Configuration bit (CLKO output disabled; pin functions as port I/O)

    #pragma config POSCFREQ = HS            // Primary Oscillator Frequency Range Configuration bits (Primary oscillator/external clock input frequency greater than 8 MHz)

    #pragma config SOSCSEL = SOSCHP         // SOSC Power Selection Configuration bits (Secondary oscillator configured for high-power operation)

    #pragma config FCKSM = CSDCMD           // Clock Switching and Monitor Selection (Both Clock Switching and Fail-safe Clock Monitor are disabled)

     

    // FWDT

    #pragma config WDTPS = PS32768          // Watchdog Timer Postscale Select bits (1:32,768)

    #pragma config FWPSA = PR128            // WDT Prescaler (WDT prescaler ratio of 1:128)

    #pragma config WINDIS = OFF             // Windowed Watchdog Timer Disable bit (Standard WDT selected; windowed WDT disabled)

    #pragma config FWDTEN = OFF             // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))

     

    // FPOR

    #pragma config BOREN = BOR2             // Brown-out Reset Enable bits (Brown-out Reset enabled only while device is active and disabled in Sleep; SBOREN bit disabled)

    #pragma config PWRTEN = OFF             // Power-up Timer Enable bit (PWRT disabled)

    #pragma config I2C1SEL = PRI            // Alternate I2C1 Pin Mapping bit (Default location for SCL1/SDA1 pins)

    #pragma config BORV = V27               // Brown-out Reset Voltage bits (Brown-out Reset set to Highest Voltage (2.7V))

    #pragma config MCLRE = ON               // MCLR Pin Enable bit (MCLR pin enabled; RA5 input pin disabled)

     

    // FICD

    #pragma config ICS = PGx1               // ICD Pin Placement Select bits (PGC1/PGD1 are used for programming and debugging the device)

     

    // FDS

    #pragma config DSWDTPS = DSWDTPSF       // Deep Sleep Watchdog Timer Postscale Select bits (1:2,147,483,648 (25.7 Days))

    #pragma config DSWDTOSC = LPRC          // DSWDT Reference Clock Select bit (DSWDT uses LPRC as reference clock)

    #pragma config RTCOSC = SOSC            // RTCC Reference Clock Select bit (RTCC uses SOSC as reference clock)

    #pragma config DSBOREN = ON             // Deep Sleep Zero-Power BOR Enable bit (Deep Sleep BOR enabled in Deep Sleep)

    #pragma config DSWDTEN = OFF            // Deep Sleep Watchdog Timer Enable bit (DSWDT disabled)

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • gihu
    0 gihu over 11 years ago in reply to Former Member

    Hi,

     

    About config bits... Not easy to ceck image.

    I think that if you select FRCDIV+PLL,you have Fosc = 8 MHz /2 (Postscaler default is /2) x4 (PLL) = 16 Mhz, so Fcy = 8 MHz.

    About the clock config, try with this configuration with a simple program switching on and off (for example 250ms on, 750ms off), an output with an LED, and see the blinking speed (1s for the example).

     

    Despite of this i do not think this is the problem of communication.

     

    When want to write the command, try:

         IdleI2C();          //Wait to complete

         StartI2C1();     //Send start bit

         IdleI2C1();

         MasterWriteI2C1(0x03)          //Slave Adress 000, Command 00011 Measure temp

         IdleI2C1();               //In this case Idel waits until transmition is done (8 bit + ACK)

     

    Just in this moiment you can check ACK status. Notice that it can be a little bit confusing:

    while(I2C1STATbits.ACKSTAT) means while(I2C1STATbits.ACKSTAT ==1) and when I2C1STATbits.ACKSTAT ==1 means not ACK.

     

    So, after MasterWrite...IdleI2C1(), if the sensor has received correctly the command, and send back the acknowledge, the I2C1STATbits.ACKSTAT must be '0'.

     

    I hope my explanation is not more confusing...

     

    Hope that helps,

     

    Miguel

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Reject Answer
    • Cancel
  • Former Member
    0 Former Member over 11 years ago in reply to gihu

    Hi, thanks

     

    Actually i checked the the clock configuration earlier through as u said by LED blinking Code. and for FRCPLL and keeping CLKDIV=0x0000; i m getting Fcy=16MHz. I have checked it by putting different value of PR1 for Timer.

     

    For ACK, u r correct that it should be 0, so what i understood is it will come out from the while loop only when the ACK is received. And for my code its not coming out of the while loop.

     

    is it not required to check that stop sequence is completed or not?  if i want to read the data after writing command which sequence of functions of library i have to follow?

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • gihu
    0 gihu over 11 years ago in reply to Former Member

    Hi,

     

    What I would do:

    -Previosly declare variable similar like this:

      

         (...)

         char data_high=0;

         char data_low=0;

         unsigned short data;

         (...)

     

    When reading the sensor:

    (previosly open and configured I2C with OpenI2C1()

         (...)

         IdleI2C1();

         StarI2C1();

         IdleI2C1();

         MasterWriteI2C1(0x03);

         IdleI2C1();

         if (I2C1STATbits.ACKSTAT ==1){

              // here you can put code for ack error

         }else{

              __delay_ms(80);     // this delay to let the sensor make the conversation, see SHT11 datasheet

              data_high = MasterReadI2C1();

              IdleI2C1();

              AckI2C1();

              IdleI2C1();

              data_low = MasterReadI2C1();

              IdleI2C1();

              NotAckI2C1();     //here not ack because I discard using CRC

              IdleI2C1();

         }

         StopI2C1();

         (...)

     

        image

    Sorry for any syntax error.

     

    Hope that helps,

    Miguel

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • Former Member
    0 Former Member over 11 years ago in reply to gihu

    Hi, thanks

     

    now i m getting acknowledge from slave after MasterWriteI2C1(0x03) but when it goes to delay function after checking ACKSTAT bit and confirming it is 0, i m getting the value of I2C1STAT register = 4009, which means transmit is in progress, so i have confusion about how come i can get ACKSTAT= 0 without completion of transfer. Can u tell me why we should use and at what place we should use IdleI2C1();  what is the actual purpose of it?  i have tried to understand from library but not able to get the exact picture of it.

     

    when i m trying to read from the slave (SHT11) i m not able to proceed ahead from data_low = MasterReadI2C1();, it stops at this point and then it cant go further for debugging. plz let me know where i m doing wrong.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • gihu
    0 gihu over 11 years ago in reply to Former Member

    Hi,

     

    About the IdleI2C1():

    image

     

    After a StartI2C1(); you can wait until start condition enable bit is clear.

    After a StopI2C1(); you can wait until stop condition enable bit is clear.

    After a MasterWriteI2C1(); you can wait until transmit status bit is clear.

    And so on.

    Or for all these functions I think you can use IdleI2C1() instead of checking their own flag.

     

    So, it seems you can get the data_high but not the data_low....Have you tried changing AckI2C1 by NotAckI2C1 and viceversa?

     

    Hope that helps,

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube