lpcware

Lpc1768 - i2c 0

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by teslabox on Thu Mar 22 07:44:14 MST 2012
Hello everyone,

I try to connect to the LIS3DH accelerometer thru the I2C bus.
In the LIS3DH datasheet there is written that it has the I2C digital output (16 bits resolution).
First I initialized I2C for set clock timing at Standard Drive Speed Mode (100 kbps) but there is no clock signal on the SCL0 line (all the time is the high level) - I checked it by oscilloscope.
Below I send my C code:

    LPC_SC->PCONP         |= (1<<7);        // wlaczenie zasilania i sygnalu zegarowego dla kontrolera magistrali I2C 0

    LPC_PINCON->PINSEL0 &=~(1<<22);        // ustawienie wyprowadzenia P0.27 jako GPIO
    LPC_PINCON->PINSEL0 &=~(1<<23);        // ustawienie wyprowadzenia P0.27 jako GPIO
    LPC_PINCON->PINSEL0 &=~(1<<24);        // ustawienie wyprowadzenia P0.28 jako GPIO
    LPC_PINCON->PINSEL0 &=~(1<<25);        // ustawienie wyprowadzenia P0.28 jako GPIO

    // prze&#322;&#261;czenie funkcji wyprowadze&#324; z GPIO na SDA0 dla I2C 0
    LPC_PINCON->PINSEL0 |= (1<<22);        // ustawienie wyprowadzenia P0.27 jako SDA0
    LPC_PINCON->PINSEL0 &=~(1<<23);        // ustawienie wyprowadzenia P0.27 jako SDA0
    LPC_PINCON->PINSEL0 |= (1<<24);        // ustawienie wyprowadzenia P0.28 jako SCL0
    LPC_PINCON->PINSEL0 &=~(1<<25);        // ustawienie wyprowadzenia P0.28 jako SCL0

    LPC_SC->PCLKSEL0     &=~(1<<14);        // w&#322;&#261;czenie sygna&#322;u zegarowego dla kontrolera I2C; bity 14 i 15 PCLK_I2C0
    LPC_SC->PCLKSEL0     &=~(1<<15);        // w&#322;&#261;czenie sygna&#322;u zegarowego dla kontrolera I2C; bity 14 i 15 PCLK_I2C0
                                            /* warto&#347;ci: 00 - PCLK UART0 = CCLK/4
                                             *           01 - PCLK UART0 = CCLK
                                             *           10 - PCLK UART0 = CCLK/2
                                             *           11 - PCLK UART0 = CCLK/8
                                             * gdzie:    x  - bit starszy (np. z pary bitów PCLK_I2C0 to bit 15)
                                             *               x - bit m&#322;odszy (np. z pary bitów PCLK_I2C0 to bit 14)
                                             */
       NVIC_EnableIRQ(I2C0_IRQn);            // w&#322;&#261;czenie generowania przerwa&#324; od kontrolera magistrali I2C 0

       LPC_I2C0->I2CONSET         |= (1<<5)|(1<<6);    // bit STA: START flag sending, bit I2CEN: I2C interface enable -> MASTER MODE
       LPC_PINCON->I2CPADCFG     &=~(1<<0)|(1<<1)|(1<<2)|(1<<3); // Standard Drive Mode (pr&#281;dkosc na 100 kbps)

       // zmienne pomocnicze

           // zmienne przechowuj&#261;ce warto&#347;&#263;i zegarów
           uint32_t MainOscFreq     = 0;    // czestotliwo&#347;&#263; taktowania g&#322;ównego oscylatora "XTAL" - kwarcu zewn&#281;trznego
           uint32_t PLL0Freq         = 0;    // cz&#281;&#347;totliwo&#347;&#263; taktowania na wyj&#347;ciu p&#281;tli PLL0
           uint32_t CoreFreq         = 0;    // cz&#281;stotliwo&#347;&#263; taktowania rdzenia procesora ARM
           uint32_t APB0Freq         = 0;    // cz&#281;&#347;totliwo&#347;&#263; taktowania magistrali APB0 (do której pod&#322;&#261;czony jest UART0 i UART1)

           // zmienne przechowuj&#261;ce warto&#347;ci dzielników preslalerów poszczególnych cz&#281;stotliwo&#347;ci taktownia

           // zmienne przechowuj&#261;ce warto&#347;&#263; dzielnika i mno&#380;nika w p&#281;tli PLL0
           uint16_t PLL0Div         = 0;    // dzielnik N w p&#281;tli PLL0
           uint16_t PLL0Mult         = 0;    // mno&#380;nik  M w p&#281;tli PLL0

           // zmienna przechowuj&#261;ca warto&#347;&#263; dzielnika cz&#281;stotliwo&#347;ci taktowania rdzenia procesora ARM
           uint8_t CoreDiv            = 0;     // dzielnik cz&#281;stotliwo&#347;ci p&#281;tli PLL0 dla taktowania rdzenia procesora ARM

           // zmienna przechowuj&#261;ca warto&#347;&#263; dzielnika cz&#281;stotliwo&#347;ci taktowania magistrali systemowej APB0 (Advanced Peripherial Bus)
           uint8_t APB0Div         = 0;    // dzielnik magistrali APB0 dla kontrolerów UART0 i UART1 (ta sama warto&#347;&#263;)

       // obliczenie cz&#281;stotliwo&#347;ci poszczególnych zegarów

           // warto&#347;&#263; czestotliwo&#347;ci taktowania g&#322;ównego oscylatora "XTAL" - kwarcu zewn&#281;trznego
           MainOscFreq = 12000000;

           // warto&#347;&#263; cz&#281;&#347;totliwo&#347;ci na wyj&#347;ciu p&#281;tli PLL0
           PLL0Mult = (((LPC_SC->PLL0CFG)       & 0x00007FFF) + 1);    // warto&#347;&#263; mno&#380;nika  p&#281;tli PLL0 bity 0 -14 MSEL0: M-1; maska 0000 0000 0000 0111 1111 1111 1111 (15 bitów)
           PLL0Div  = (((LPC_SC->PLL0CFG >> 16) & 0x000000FF) + 1);    // warto&#347;&#263; dzielnika p&#281;tli PLL0 bity 16-23 NSEL0: N-1; maska 0000 0000 0000 0000 0000 1111 1111 (8 bitów)
                                                                       // i wcze&#347;niej przesuniecie bitowe o 16 bitów w prawo
           PLL0Freq = (2 * PLL0Mult * MainOscFreq) / (PLL0Div);        // wzór ze str. 41 dokumentacji

           // warto&#347;&#263; cz&#281;stotliwo&#347;ci taktowaniardzenia procesora ARM
           CoreDiv  = (LPC_SC->CCLKCFG) + 1;                            // warto&#347;&#263; dzielnika cz&#281;stotliwo&#347;ci p&#281;tli PLL0 dla taktowania rdzenia procesora ARM
           CoreFreq = PLL0Freq/CoreDiv;                                // warto&#347;&#263; cz&#281;stotliwo&#347;ci taktowania rdzenia procesora ARM

           // warto&#347;&#263; cz&#281;&#347;totliwo&#347;ci taktowania magistrali APB0 (do której pod&#322;&#261;czony jest CAN1 i CAN2)
           APB0Div  = ((LPC_SC->PCLKSEL0 >> 6) & 0x00000003);            // dzielnik magistrali APB0 dla kontrolera magistrali UART0 bity 6 i 7 PCLK_UART0
                                                                       // maska 0000 0000 0000 0000 0000 0000 0000 0011 i wcze&#347;niej przesuniecie bitowe o 6 bitów w prawo
               if (APB0Div == 0x00)        // dzielnik = 4;
               {
                   APB0Freq = CoreFreq/4;
               }
               else if (APB0Div == 0x01)        // dzielnik = 1;
               {
                   APB0Freq = CoreFreq/1;
               }
               else if (APB0Div == 0x02)        // dzielnik = 2;
               {
                   APB0Freq = CoreFreq/2;
               }
               else if (APB0Div == 0x03)        // dzielnik = 8;
               {
                   APB0Freq = CoreFreq/8;
               }

               LPC_I2C0->I2SCLH = (APB0Freq/100000)/2;    // 100000 - 100 kpbs (Standard I2C Drive Speed Mode)
               LPC_I2C0->I2SCLL = (APB0Freq/100000)/2; // 100000 - 100 kpbs (Standard I2C Drive Speed Mode)
               // divider is 2; it gives I2C period Duty Cycle = 50 % at 100 kbps speed

Outcomes