This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C123G LaunchPad and l3gd20h sensor

Other Parts Discussed in Thread: EK-TM4C123GXL

Hi,

I am using EK-TM4C123GXL LaunchPad and i try to use your sensorlibrary. I have done some labs from "Getting Started with the Tiva™ TM4C123G LaunchPad Workshop" in Code Composer Studio 5.4.0.00091.I have finished lab 12 properly and was able to communicate with Putty and to send some data. I use itoa function for sending integers. Everything was working and i could see what i expected on Putty

Now i am trying to use your sensorlib (l3gd20h) to communicate with my sensor "Pololu MinIMU-9 v2 Gyro, Accelerometer, and Compass (L3GD20 and LSM303DLHC Carrier)". ( http://www.pololu.com/product/1268 ).

Unfortunately it is not working at all. Sensor is good and checked ( i can communicate with it using AVR launchpad with atmega32). Propably i am not able to use sesnorlib properly. When run my program in debbuger and play it step by step. It goes to the first step in main loop which is:

SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

and then i can only press suspend and it jumps to infinite loop in FaultISR. No source available for "0xfffffff8".

As i comment everything connected to sensorlib it is working good. Can anybody help me with this problem, and explain how to properly use your sensorlib. I linked it to my project.  

Project was created according to your launchpad workshop lab 12.

Before initialization there is something like this in your example in sensorlib user guide

// Initialize the L3GD20H. This code assumes that the I2C master instance has already been initialized.

Maybe i don't know how to do this initialization. I tried to do it and below is my C code.


Here is my C code: 

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"

//for i2a_my(i)
#include <stdlib.h>
#include <stdio.h>
#include <cstdio>


//for sensorlib
#include "sensorlib/hw_l3gd20h.h"
#include "sensorlib/i2cm_drv.h"
#include "sensorlib/l3gd20h.h"

//for i2c
#include "inc/hw_i2c.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/debug.h"
#include "driverlib/i2c.h"
#include "driverlib/interrupt.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"

#include "utils/uartstdio.h"


//
// A boolean that is set when a L3GD20H command has completed.
//
volatile bool g_bl3gd20hDone;

void
l3gd20hCallback(void *pvCallbackData, uint_fast8_t ui8Status)
{
	//
	// See if an error occurred.
	//
	if(ui8Status != I2CM_STATUS_SUCCESS)
	{
		//
		// An error occurred, so handle it here if required.
		//
	}
	//
	// Indicate that the L3GD20H transaction has completed.
	//
	g_bl3gd20hDone = true;
}


//***************itoa_my(i)*****************88
int a=-3;
char str[25];
#define INT_DIGITS 19           /* enough for 64 bit integer */

char *itoa_my(i)
int i;
{
	/* Room for INT_DIGITS digits, - and '\0' */
	static char buf[INT_DIGITS + 2];
	char *p = buf + INT_DIGITS + 1; /* points to terminating '\0' */
	if (i >= 0) {
		do {
			*--p = '0' + (i % 10);
			i /= 10;
		} while (i != 0);
		return p;
	}
	else {                  /* i < 0 */
		do {
			*--p = '0' - (i % 10);
			i /= 10;
		} while (i != 0);
		*--p = '-';
	}
	return p;
}
//*************************************************************************************

//***********UART for sending integer as ASCII **************
void USART_vSendBuffer(char *dane)
{
	int i = 0;
	while(dane[i]!=0) { UARTCharPut(UART0_BASE, dane[i]); //SysCtlDelay((SysCtlClockGet() / (1000 * 3))*15);
	i++; }
}
//***********************************************************

//UART interrupt handler
void UARTIntHandler(void)
{
	uint32_t ui32Status;

	ui32Status = UARTIntStatus(UART0_BASE, true); //get interrupt status

	UARTIntClear(UART0_BASE, ui32Status); //clear the asserted interrupts

	while(UARTCharsAvail(UART0_BASE)) //loop while there are chars
	{
		UARTCharPutNonBlocking(UART0_BASE, UARTCharGetNonBlocking(UART0_BASE)); //echo character
		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, GPIO_PIN_2); //blink LED
		SysCtlDelay(SysCtlClockGet() / (1000 * 3)); //delay ~1 msec
		GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_2, 0); //turn off LED
	}
}


int main(void) {

	//Set up the system clock
	SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

	//Enable the UART0 and GPIOA peripherals (the UART pins are on GPIO Port A)
	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

	//Configure the pins for the receiver and transmitter using GPIOPinConfigure
	GPIOPinConfigure(GPIO_PA0_U0RX);
	GPIOPinConfigure(GPIO_PA1_U0TX);
	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); //enable GPIO port for LED
	GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_2); //enable pin for LED PF2

	//Initialize the parameters for the UART: 115200, 8-1-N
	UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
			(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

	IntMasterEnable(); //enable processor interrupts
	IntEnable(INT_UART0); //enable the UART interrupt
	UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT); //only enable RX and TX interrupts



	//*********************************************************88
	//I2c initialization         - probably WRONG :(
	//

    //
    // The I2C0 peripheral must be enabled before use.
    //
	SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);

	//
	// For this example I2C0 is used with PortB[3:2].  The actual port and
	// pins used may be different on your part, consult the data sheet for
	// more information.  GPIO port B needs to be enabled so these pins can
	// be used.
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);

	//
	// Configure the pin muxing for I2C0 functions on port B2 and B3.
	// This step is not necessary if your part does not support pin muxing.
	//
	GPIOPinConfigure(GPIO_PB2_I2C0SCL);
	GPIOPinConfigure(GPIO_PB3_I2C0SDA);

    //
    // Select the I2C function for these pins.  This function will also
    // configure the GPIO pins pins for I2C operation, setting them to
    // open-drain operation with weak pull-ups.  Consult the data sheet
    // to see which functions are allocated per pin.
    //
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);

    //
    // Enable and initialize the I2C0 master module.  Use the system clock for
    // the I2C0 module.  The last parameter sets the I2C data transfer rate.
    // If false the data rate is set to 100kbps and if true the data rate will
    // be set to 400kbps.  For this example we will use a data rate of 100kbps.
    //
    I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
    //**************************************************************


	//********************* SENSOR *********************
	float fGyro[3];
	tI2CMInstance sI2CInst;
	tL3GD20H sl3gd20h;
	//
	// Initialize the L3GD20H. This code assumes that the I2C master instance
	// has already been initialized.
	//
	g_bl3gd20hDone = false;
	L3GD20HInit(&sl3gd20h, &sI2CInst, 0x68, l3gd20hCallback, 0);
	while(!g_bl3gd20hDone)
	{
	}
	//
	// Configure the L3GD20H for 500 deg/sec sensitivity
	//
	g_bl3gd20hDone = false;
	L3GD20HReadModifyWrite(&sl3gd20h, L3GD20H_O_CTRL4,
			~L3GD20H_CTRL4_FS_M,
			L3GD20H_CTRL4_FS_500DPS, l3gd20hCallback,
			0);
	while(!g_bl3gd20hDone)
	{
	}
	//
	// Loop forever reading data from the L3GD20H. Typically, this process
	// would be done in the background, but for the purposes of this example,
	// it is shown in an infinite loop.
	//
	while(1)
	{
		//
		// Request another reading from the L3GD20H.
		//
		g_bl3gd20hDone = false;
		L3GD20HDataRead(&sl3gd20h, l3gd20hCallback, 0);
		while(!g_bl3gd20hDone)
		{
		}
		//
		// Get the new gyroscope readings.
		//
		L3GD20HDataGyroGetFloat(&sl3gd20h, &fGyro[0], &fGyro[1], &fGyro[2]);
		//
		// Do something with the new gyroscope readings.
		//
		USART_vSendBuffer("\n\r");
		USART_vSendBuffer("Anything;  ");
		//USART_vSendBuffer(itoa_my(fGyro[0]));


	}



	//Use simple “UARTCharPut()” calls to create a prompt.
	/* UARTCharPut(UART0_BASE, 'E');
    UARTCharPut(UART0_BASE, 'n');
    UARTCharPut(UART0_BASE, 't');
    UARTCharPut(UART0_BASE, 'e');
    UARTCharPut(UART0_BASE, 'r');
    UARTCharPut(UART0_BASE, ' ');
    UARTCharPut(UART0_BASE, 'T');
    UARTCharPut(UART0_BASE, 'e');
    UARTCharPut(UART0_BASE, 'x');
    UARTCharPut(UART0_BASE, 't');
    UARTCharPut(UART0_BASE, ':');
    UARTCharPut(UART0_BASE, ' ');
	 */

	//USART_vSendBuffer("\n\r");
	//USART_vSendBuffer(itoa_my(a));
	//USART_vSendBuffer("kk123  ;  ");
	//An infinite loop. In this loop, if there is a character in the receiver, it is read, and then written to
	//the transmitter. This echos what you type in the terminal window.
	//while (1)
	//{
	//if (UARTCharsAvail(UART0_BASE)) UARTCharPut(UART0_BASE, UARTCharGet(UART0_BASE));
	//}

}

  • Hello Michal,

    Do check the NVIC_FAULTSTAT and NVIC_FAULTADDR registers. These contain why the fault occurred and also tell what address causes the fault to occur.

    Regards

    Amit

  • Hi,

    Thanks for your quick response.

    I checked registers in NVIC_FAULT_STAT and there are ones on:
    NVIC_FAULT_STAT_BFARV
    NVIC_FAULT_STAT_BSTKE

    NVIC_FAULT_ADDRESS:   00011111111111111111111011100000

    BUT, digging through your forum i have found similar post to mine. I added one initialization.
    I2CMInit(&g_psInst, 0x6B, INT_I2C0, 0xff, 0xff, 80000000);     and declared g_osInst.

    Now i can step in debbuger until i reach this initialzation:
    L3GD20HInit(&sl3gd20h, &sI2CInst, 0x6B, l3gd20hCallback, 0);

    I checked registers again in NVIC_FAULT_STAT and there are ones on: 
    NVIC_FAULT_STAT_BFARV
    NVIC_FAULT_STAT_BSTKE
    NVIC_FAULT_STAT_PRECISE

    NVIC_FAULT_ADDRESS:   00011111111111111111111111101000

  • Can anybody help me and explain what faults in those registers mean ? And how to use your sensorlibrary properly ;/ ?

  • Hi Michal

    I am working on it. If someone from the community has already a working code, they may post any time...

    Regards

    Amit

  • Hello Michal,

    Can you please send the following info

    1. The CCS Project zip for me to go through the sequences?

    2. Connection of the L3GD20H sensor to the TM4C? Are you using I2C-0 and have the Pull Up Installed on the sensor board?

    Regards

    Amit

  • Hi Amit,

    Answering your questions:

    Ad.1
    5684.2014_06_17_i2c_test.rar

    Here is my new project, which i have made today. It is not working, but there is no such an error like it was before. Now it is working until it reaches while loop waiting for g_bl3gd20hDone to be true after l3gd20Hinit. It is propably not connectting with sensor at all. After L3GD20HInit function it does not change g_bl3gd20hDone to true in callback function. 
    Maybe i missed something in initialization. It would be great if you could look at this project and see what i could have missed.

    Ad.2
    I am using I2C-0 and my sensor is on the something like this: http://www.pololu.com/product/1268 
    I have connected
    SCL -> PB2
    SDA -> PB3
    GND -> GND on J3
    VIN -> +3.3V on J1.
    But as i have read in board's documentation (A minimum of four connections are necessary to use the MinIMU-9 v2: VIN, GND, SCL, and SDA. VIN should be connected to a 2.5-5.5 V source, GND to 0 volts, and SCL and SDA should be connected to an I²C bus operating at the same logic level as VIN. (Alternatively, if you are using the board with a 3.3 V system, you can leave VIN disconnected and bypass the built-in regulator by connecting 3.3 V directly to VDD.)  i tried to connect VDD to 3.3V on J1 and it is also not working. 

    As i mentioned before, sensor is working fine. I am sure of that, because i can communicate using my ATB evaluation board with atmega32 and everything works ok there. I did even communicate vie UART with TM4C123G and send those measurements, but i would like to communicate with sensor using your library and your Lanuchpad. I am stuck now and i don't want to use atmega only to communicate with sensor, beacuse i am not able to communicate with it on TM4C.

    Please help me :)

    Regards,
    Michał Szewc.

  • I2C does require pull-up resistors to work, which usually reside on the master (MCU) side. Are they there ?

    Have you tried to attach a scope or logic analyzer on the I2C bus ?  How far does it come ?

  • Hello f.m.

    The sensor board has 4.7K Pull Up. That should be OK. But indeed it is a good point to scope to the I2C Bus.

    Hello Michal,

    Also I am reviewing the code, and may be the issue is in the code.

        I2CMInit(&g_psInst, GYRO, INT_I2C0, 0xff, 0xff, 80000000);
    should be

        I2CMInit(&g_psInst, I2C0_BASE, INT_I2C0, 0xff, 0xff, 80000000);

    Regards

    Amit

  • Hi f.m. ,

    As Amit has written, there are pull-up resistors on the sensor board so it should work and it does work but on atmega.

    Amit,

    I have changed the code as you mentioned. (I2CMInit(&g_psInst, I2C0_BASE, INT_I2C0, 0xff, 0xff, 80000000);)

    Unfortunately it didn't help. I tried to scope the i2c bus (i am not sure if i do it correctly. i connected gnd to gnd on my scope, and tried to scope the SDA line but nothing happens there (or i can't see it)).

    Program is still in the while loop after L3GD20HInit waiting for the g_bl3gd20hDone to be true. When i try to omit callback functions it is not working as well. I tried different GYRO addresses (6A, 6B, D4, D6).

    I think that i2c transmission hasn't started like the initialization and configuration of the bus is wrong.

    Regards,

    Michał. 

  • Hello Michal,

    I have ordered my sensor board (would take a few days). As for the Scope, do make sure that the trigger level is set correctly to the channel and voltage scale and that the scope is kept in RUN mode. I would be able to get back with some quantitative data on I2C Transaction starting (w/o a sensor board and only pull up) by tomorrow.

    As f.m. did raise a valid point (and based on another debug) you can use a multimeter to check that the SCL and SDA is indeed high.

    Regards

    Amit

  • Hello Michal,

    There were more issues than I thought. Anyways I fixed them and have attached the updated files that you would need to use.

    After making the changes, I see I2C Commands on the I2C Bus for accessing the device (I do not have the device so it NAK's).

    //*****************************************************************************
    //
    // startup_ccs.c - Startup code for use with TI's Code Composer Studio.
    //
    // Copyright (c) 2012-2013 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.0.1.11577 of the EK-TM4C123GXL Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include "inc/hw_nvic.h"
    #include "inc/hw_types.h"
    
    //*****************************************************************************
    //
    // Forward declaration of the default fault handlers.
    //
    //*****************************************************************************
    void ResetISR(void);
    static void NmiSR(void);
    static void FaultISR(void);
    static void IntDefaultHandler(void);
    
    //*****************************************************************************
    //
    // External declaration for the reset handler that is to be called when the
    // processor is started
    //
    //*****************************************************************************
    extern void _c_int00(void);
    extern void l3gd20hInterruptHandler(void);
    
    //*****************************************************************************
    //
    // Linker variable that marks the top of the stack.
    //
    //*****************************************************************************
    extern uint32_t __STACK_TOP;
    
    //*****************************************************************************
    //
    // The vector table.  Note that the proper constructs must be placed on this to
    // ensure that it ends up at physical address 0x0000.0000 or at the start of
    // the program if located at a start address other than 0.
    //
    //*****************************************************************************
    #pragma DATA_SECTION(g_pfnVectors, ".intvecs")
    void (* const g_pfnVectors[])(void) =
    {
        (void (*)(void))((uint32_t)&__STACK_TOP),
                                                // The initial stack pointer
        ResetISR,                               // The reset handler
        NmiSR,                                  // The NMI handler
        FaultISR,                               // The hard fault handler
        IntDefaultHandler,                      // The MPU fault handler
        IntDefaultHandler,                      // The bus fault handler
        IntDefaultHandler,                      // The usage fault handler
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // SVCall handler
        IntDefaultHandler,                      // Debug monitor handler
        0,                                      // Reserved
        IntDefaultHandler,                      // The PendSV handler
        IntDefaultHandler,                      // The SysTick handler
        IntDefaultHandler,                      // GPIO Port A
        IntDefaultHandler,                      // GPIO Port B
        IntDefaultHandler,                      // GPIO Port C
        IntDefaultHandler,                      // GPIO Port D
        IntDefaultHandler,                      // GPIO Port E
        IntDefaultHandler,                      // UART0 Rx and Tx
        IntDefaultHandler,                      // UART1 Rx and Tx
        IntDefaultHandler,                      // SSI0 Rx and Tx
        l3gd20hInterruptHandler,                      // I2C0 Master and Slave
        IntDefaultHandler,                      // PWM Fault
        IntDefaultHandler,                      // PWM Generator 0
        IntDefaultHandler,                      // PWM Generator 1
        IntDefaultHandler,                      // PWM Generator 2
        IntDefaultHandler,                      // Quadrature Encoder 0
        IntDefaultHandler,                      // ADC Sequence 0
        IntDefaultHandler,                      // ADC Sequence 1
        IntDefaultHandler,                      // ADC Sequence 2
        IntDefaultHandler,                      // ADC Sequence 3
        IntDefaultHandler,                      // Watchdog timer
        IntDefaultHandler,                      // Timer 0 subtimer A
        IntDefaultHandler,                      // Timer 0 subtimer B
        IntDefaultHandler,                      // Timer 1 subtimer A
        IntDefaultHandler,                      // Timer 1 subtimer B
        IntDefaultHandler,                      // Timer 2 subtimer A
        IntDefaultHandler,                      // Timer 2 subtimer B
        IntDefaultHandler,                      // Analog Comparator 0
        IntDefaultHandler,                      // Analog Comparator 1
        IntDefaultHandler,                      // Analog Comparator 2
        IntDefaultHandler,                      // System Control (PLL, OSC, BO)
        IntDefaultHandler,                      // FLASH Control
        IntDefaultHandler,                      // GPIO Port F
        IntDefaultHandler,                      // GPIO Port G
        IntDefaultHandler,                      // GPIO Port H
        IntDefaultHandler,                      // UART2 Rx and Tx
        IntDefaultHandler,                      // SSI1 Rx and Tx
        IntDefaultHandler,                      // Timer 3 subtimer A
        IntDefaultHandler,                      // Timer 3 subtimer B
        IntDefaultHandler,                      // I2C1 Master and Slave
        IntDefaultHandler,                      // Quadrature Encoder 1
        IntDefaultHandler,                      // CAN0
        IntDefaultHandler,                      // CAN1
        IntDefaultHandler,                      // CAN2
        0,                                      // Reserved
        IntDefaultHandler,                      // Hibernate
        IntDefaultHandler,                      // USB0
        IntDefaultHandler,                      // PWM Generator 3
        IntDefaultHandler,                      // uDMA Software Transfer
        IntDefaultHandler,                      // uDMA Error
        IntDefaultHandler,                      // ADC1 Sequence 0
        IntDefaultHandler,                      // ADC1 Sequence 1
        IntDefaultHandler,                      // ADC1 Sequence 2
        IntDefaultHandler,                      // ADC1 Sequence 3
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // GPIO Port J
        IntDefaultHandler,                      // GPIO Port K
        IntDefaultHandler,                      // GPIO Port L
        IntDefaultHandler,                      // SSI2 Rx and Tx
        IntDefaultHandler,                      // SSI3 Rx and Tx
        IntDefaultHandler,                      // UART3 Rx and Tx
        IntDefaultHandler,                      // UART4 Rx and Tx
        IntDefaultHandler,                      // UART5 Rx and Tx
        IntDefaultHandler,                      // UART6 Rx and Tx
        IntDefaultHandler,                      // UART7 Rx and Tx
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // I2C2 Master and Slave
        IntDefaultHandler,                      // I2C3 Master and Slave
        IntDefaultHandler,                      // Timer 4 subtimer A
        IntDefaultHandler,                      // Timer 4 subtimer B
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // Timer 5 subtimer A
        IntDefaultHandler,                      // Timer 5 subtimer B
        IntDefaultHandler,                      // Wide Timer 0 subtimer A
        IntDefaultHandler,                      // Wide Timer 0 subtimer B
        IntDefaultHandler,                      // Wide Timer 1 subtimer A
        IntDefaultHandler,                      // Wide Timer 1 subtimer B
        IntDefaultHandler,                      // Wide Timer 2 subtimer A
        IntDefaultHandler,                      // Wide Timer 2 subtimer B
        IntDefaultHandler,                      // Wide Timer 3 subtimer A
        IntDefaultHandler,                      // Wide Timer 3 subtimer B
        IntDefaultHandler,                      // Wide Timer 4 subtimer A
        IntDefaultHandler,                      // Wide Timer 4 subtimer B
        IntDefaultHandler,                      // Wide Timer 5 subtimer A
        IntDefaultHandler,                      // Wide Timer 5 subtimer B
        IntDefaultHandler,                      // FPU
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // I2C4 Master and Slave
        IntDefaultHandler,                      // I2C5 Master and Slave
        IntDefaultHandler,                      // GPIO Port M
        IntDefaultHandler,                      // GPIO Port N
        IntDefaultHandler,                      // Quadrature Encoder 2
        0,                                      // Reserved
        0,                                      // Reserved
        IntDefaultHandler,                      // GPIO Port P (Summary or P0)
        IntDefaultHandler,                      // GPIO Port P1
        IntDefaultHandler,                      // GPIO Port P2
        IntDefaultHandler,                      // GPIO Port P3
        IntDefaultHandler,                      // GPIO Port P4
        IntDefaultHandler,                      // GPIO Port P5
        IntDefaultHandler,                      // GPIO Port P6
        IntDefaultHandler,                      // GPIO Port P7
        IntDefaultHandler,                      // GPIO Port Q (Summary or Q0)
        IntDefaultHandler,                      // GPIO Port Q1
        IntDefaultHandler,                      // GPIO Port Q2
        IntDefaultHandler,                      // GPIO Port Q3
        IntDefaultHandler,                      // GPIO Port Q4
        IntDefaultHandler,                      // GPIO Port Q5
        IntDefaultHandler,                      // GPIO Port Q6
        IntDefaultHandler,                      // GPIO Port Q7
        IntDefaultHandler,                      // GPIO Port R
        IntDefaultHandler,                      // GPIO Port S
        IntDefaultHandler,                      // PWM 1 Generator 0
        IntDefaultHandler,                      // PWM 1 Generator 1
        IntDefaultHandler,                      // PWM 1 Generator 2
        IntDefaultHandler,                      // PWM 1 Generator 3
        IntDefaultHandler                       // PWM 1 Fault
    };
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor first starts execution
    // following a reset event.  Only the absolutely necessary set is performed,
    // after which the application supplied entry() routine is called.  Any fancy
    // actions (such as making decisions based on the reset cause register, and
    // resetting the bits in that register) are left solely in the hands of the
    // application.
    //
    //*****************************************************************************
    void
    ResetISR(void)
    {
        //
        // Jump to the CCS C initialization routine.  This will enable the
        // floating-point unit as well, so that does not need to be done here.
        //
        __asm("    .global _c_int00\n"
              "    b.w     _c_int00");
    }
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives a NMI.  This
    // simply enters an infinite loop, preserving the system state for examination
    // by a debugger.
    //
    //*****************************************************************************
    static void
    NmiSR(void)
    {
        //
        // Enter an infinite loop.
        //
        while(1)
        {
        }
    }
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives a fault
    // interrupt.  This simply enters an infinite loop, preserving the system state
    // for examination by a debugger.
    //
    //*****************************************************************************
    static void
    FaultISR(void)
    {
        //
        // Enter an infinite loop.
        //
        while(1)
        {
        }
    }
    
    //*****************************************************************************
    //
    // This is the code that gets called when the processor receives an unexpected
    // interrupt.  This simply enters an infinite loop, preserving the system state
    // for examination by a debugger.
    //
    //*****************************************************************************
    static void
    IntDefaultHandler(void)
    {
        //
        // Go into an infinite loop.
        //
        while(1)
        {
        }
    }
    

    //*****************************************************************************
    //
    // hello.c - Simple hello world example.
    //
    // Copyright (c) 2012-2013 Texas Instruments Incorporated.  All rights reserved.
    // Software License Agreement
    // 
    // Texas Instruments (TI) is supplying this software for use solely and
    // exclusively on TI's microcontroller products. The software is owned by
    // TI and/or its suppliers, and is protected under applicable copyright
    // laws. You may not combine this software with "viral" open-source
    // software in order to form a larger program.
    // 
    // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
    // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
    // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
    // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
    // DAMAGES, FOR ANY REASON WHATSOEVER.
    // 
    // This is part of revision 2.0.1.11577 of the EK-TM4C123GXL Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_memmap.h"
    #include "inc/hw_types.h"
    #include "driverlib/debug.h"
    #include "driverlib/fpu.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "utils/uartstdio.h"
    
    //for sensorlib
    #include "sensorlib/hw_l3gd20h.h"
    #include "sensorlib/i2cm_drv.h"
    #include "sensorlib/l3gd20h.h"
    
    //for i2c
    #include "inc/hw_i2c.h"
    #include "inc/hw_ints.h"
    #include <stdlib.h>
    #include "driverlib/i2c.h"
    
    //**********************Gyro addresses*********************
    //#define GYRO 0x6A
    #define GYRO 0x6B       //possible working address
    //#define GYRO 0xD4
    //#define GYRO 0xD6
    
    //******************************i2c************************
    tI2CMInstance g_psInst;
    //
    // A boolean that is set when a L3GD20H command has completed.
    //
    volatile bool g_bl3gd20hDone;
    
    void
    l3gd20hInterruptHandler(void)
    {
        //
        // Pass through to the I2CM interrupt handler provided by sensor library.
        // This is required to be at application level so that I2CMIntHandler can
        // receive the instance structure pointer as an argument.
        //
        I2CMIntHandler(&g_psInst);
    }
    void l3gd20hCallback (void *pvCallbackData, uint_fast8_t ui8Status)
    {
    	//
    	// See if an error occurred.
    	//
    	if(ui8Status != I2CM_STATUS_SUCCESS)
    	{
    		//
    		// An error occurred, so handle it here if required.
    		//
    	}
    	//
    	// Indicate that the L3GD20H transaction has completed.
    	//
    	g_bl3gd20hDone = true;
    }
    
    
    
    
    
    unsigned char odczyt;
    char bufor[36];
    
    
    
    //********************* SENSOR *********************
    float fGyro[3];
    uint8_t iGyro[6];
    int ciGyro[3];
    uint8_t Gyroreg[3];
    tL3GD20H sl3gd20h;
    
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // Configure the UART and its pins.  This must be called before UARTprintf().
    //
    //*****************************************************************************
    void
    ConfigureUART(void)
    {
        //
        // Enable the GPIO Peripheral used by the UART.
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        //uart1
        //ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
        //
        // Enable UART0
        //
        ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        //uart1
        //ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1);
    
        //
        // Configure GPIO Pins for UART mode.
        //
        ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
        ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
        ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        //uart1
        //ROM_GPIOPinConfigure(GPIO_PB0_U1RX);
        //ROM_GPIOPinConfigure(GPIO_PB1_U1TX);
        //ROM_GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //
        // Use the internal 16MHz oscillator as the UART clock source.
        //
        UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
        //uart1
        //UARTClockSourceSet(UART1_BASE, UART_CLOCK_PIOSC);
    
    }
    
    void ConfigureI2C(void)
    {
    	//*********************************************************
    	//I2c initialization         - probably WRONG :(
    	//
    
    	//
    	// The I2C0 peripheral must be enabled before use.
    	//
    	SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C0);
    	SysCtlPeripheralReset(SYSCTL_PERIPH_I2C0);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    
    	//
    	// For this example I2C0 is used with PortB[3:2].  The actual port and
    	// pins used may be different on your part, consult the data sheet for
    	// more information.  GPIO port B needs to be enabled so these pins can
    	// be used.
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    
    	//
    	// Configure the pin muxing for I2C0 functions on port B2 and B3.
    	// This step is not necessary if your part does not support pin muxing.
    	//
    	GPIOPinConfigure(GPIO_PB2_I2C0SCL);
    	GPIOPinConfigure(GPIO_PB3_I2C0SDA);
    
    	//
    	// Select the I2C function for these pins.  This function will also
    	// configure the GPIO pins pins for I2C operation, setting them to
    	// open-drain operation with weak pull-ups.  Consult the data sheet
    	// to see which functions are allocated per pin.
    	//
    	GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    	GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    
    	//
    	// Enable and initialize the I2C0 master module.  Use the system clock for
    	// the I2C0 module.  The last parameter sets the I2C data transfer rate.
    	// If false the data rate is set to 100kbps and if true the data rate will
    	// be set to 400kbps.  For this example we will use a data rate of 100kbps.
    	//
    
    	//I2CMasterInitExpClk(I2C0_BASE, SysCtlClockGet(), false);
    
    	I2CMInit(&g_psInst, I2C0_BASE, INT_I2C0, 0xff, 0xff, 80000000);
    }
    
    
    int
    main(void)
    {
        //volatile uint32_t ui32Loop;
    
        //
        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        ROM_FPULazyStackingEnable();
        //
        // Set the clocking to run directly from the crystal.
        //
        ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ |
                           SYSCTL_OSC_MAIN);
        //
        // Initialize the UART.
        //
        ConfigureUART();
        ConfigureI2C();
        UARTStdioConfig(0, 115200, 16000000);
        UARTprintf("Hello, world!\n");
    
        //
        // Initialize the L3GD20H. This code assumes that the I2C master instance
        // has already been initialized.
        //
        g_bl3gd20hDone = false;
        L3GD20HInit(&sl3gd20h, &g_psInst, GYRO, l3gd20hCallback, 0);
        while(!g_bl3gd20hDone)
        {
        }
    
        //
        // Configure the L3GD20H for 500 deg/sec sensitivity
        //
        g_bl3gd20hDone = false;
        L3GD20HReadModifyWrite(&sl3gd20h, L3GD20H_O_CTRL4,~L3GD20H_CTRL4_FS_M,L3GD20H_CTRL4_FS_500DPS, l3gd20hCallback,0);
        while(!g_bl3gd20hDone)
        {
        }
        //
        // Loop forever reading data from the L3GD20H. Typically, this process
        // would be done in the background, but for the purposes of this example,
        // it is shown in an infinite loop.
        //
        while(1)
        {
        	//
        	// Request another reading from the L3GD20H.
        	//
        	g_bl3gd20hDone = false;
        	L3GD20HDataRead(&sl3gd20h, l3gd20hCallback, 0);
    
    
        	while(!g_bl3gd20hDone)
        	{
        	}
        	//
        	// Get the new gyroscope readings.
        	//
    /*
        	Gyroreg[0]= 0x4F;
        	L3GD20HWrite(&sl3gd20h, 0x20, &Gyroreg[0], 1, NULL,0);
        	L3GD20HRead(&sl3gd20h, 0x28, &iGyro[0], 2, NULL,0);
        	L3GD20HRead(&sl3gd20h, 0x2A, &iGyro[+2], 2, NULL,0);
        	L3GD20HRead(&sl3gd20h, 0x2C, &iGyro[+2], 2, NULL,0);
    
        	ciGyro[0]=iGyro[1]<<8 | iGyro[0];
        	ciGyro[1]=iGyro[3]<<8 | iGyro[2];
        	ciGyro[2]=iGyro[5]<<8 | iGyro[4];*/
    
    
        	L3GD20HDataGyroGetFloat(&sl3gd20h, &fGyro[0], &fGyro[1], &fGyro[2]);
        	//L3GD20HDataGyroGetRaw(&sl3gd20h, &iGyro[0], &iGyro[1], &iGyro[2]);
    
        	UARTprintf("Gx: %d   Gy: %d   Gz: %d \n",fGyro[0],fGyro[1],fGyro[2]);
        	//UARTprintf("Done!\n");
    
    
        }
    
    }
    

    Regards

    Amit

  • Hi Amit,

    Thanks a lot for your advices. I have uploaded changes to my project and now i can see on the scope that i2c bus is working and it is trying to communicate with the sensor. I still do not have any proper data, (i get zeros or strange numbers) but now i am going to try with different addresses or different registers. i have to check if your library is working.

    Thanks again, because now i am sure that i2c bus is ok.

    Regards,

    Michał.

  •   I still do not have any proper data, (i get zeros or strange numbers) but now i am going to try with different addresses or different registers. i have to check if your library is working.

    Check the acknowledge bit of the first byte in every transfer, which is the slave addressing. If this bit is not low, the address is probably incorrect.

    BTW, I2C device addresses are often not stated very clear in datasheets. This (standard) addresses are 7 bit, with the LSB implicitely used for read/write differentiation. So sometimes you need to shift the stated device address left by one bit, sometimes not.

  • Hi f.m,

    As I expected the proped address is 0xB6 and i get data from the sensor. I still have some doubts wheter your library is good. First of all you have to wake up sensor (it is not done in the example). Here it is:
    L3GD20HReadModifyWrite(&sl3gd20h, L3GD20H_O_CTRL1,0xFF,0x8F, l3gd20hCallback,0);

    I have also changed the bit-mask in next function (i think your's is wrong).

    L3GD20HReadModifyWrite(&sl3gd20h, L3GD20H_O_CTRL4,0x1F,L3GD20H_CTRL4_FS_245DPS, l3gd20hCallback,0);

    That helped me. 

    I am not sure that when i use the L3GD20HReadModifyWrite function to change the scale in ctrl reg 4, does the function change the ui8NewGyroFsSel in the tL3GD20H structure. It is important when i use the L3GD20HDataGyroGetFloat function.

    Amit or anyone, whenever you will find some time you can answer the questions i asked above.

    As for now i will try to get raw data and convert it by myselft.

    Thank you guys for your support, i have data and i can deal with it.

    Regards,

    Michał.

  • Hello Michal,

    As for the address for the Slave, there seems to be some confusion w.r.t to what the datasheet of the device mentions the SA /s what you have mentioned as 0xB6. So what si that you have defined GYRO as?

    I am not sure why do you mention that bit-mask is wrong? The bit mask is a parameter to the function and needs to be updated based on what the read-modify-write has to do.

    Regards

    Amit

  • According to the datasheet of the L3GD20 sensor:

    The Slave ADdress (SAD) associated with the L3GD20 is 110101xb. The SDO pin can be used to modify the less significant bit of the device address. If the SDO pin is connected to voltage supply, LSb is ‘1’ (address 1101011b). Otherwise, if the SDO pin is connected to ground, the LSb value is ‘0’ (address 1101010b). This solution allows to connect and address two different gyroscopes to the same I2C bus.

    So 0b1101011 = 0x6B    and this is the only address that is working for me.

    I said that the bit mask is wrong because i had copied some of your's example in sensorlib-UG. There is a function:
    L3GD20HReadModifyWrite(&sl3gd20h, L3GD20H_O_CTRL4,~L3GD20H_CTRL4_FS_M, L3GD20H_CTRL4_FS_500DPS, l3gd20hCallback,0); 

    L3GD20H_CTRL4_FS_M = 0x30  - ->  ~L3GD20H_CTRL4_FS_M   =  0x0F
    L3GD20H_CTRL4_FS_500DPS = 0x10

    As i understand it, the bit mask is "ANDED" with the value you want to change in sensor's register.
    0x10 & 0x0F is 0 so it has no sense for me. But maybe i don't understand how it should work ;/

    Regards,

    Michał.

  • Hello Michal

    OK. In your last post you mentioned that the SA was mentioned as 0xB6. this clarifies

    The bit mask has to be created as per what the requirement of the RMW is. It can be sometimes confusing.

    Regards

    Amit