Other Parts Discussed in Thread: CC2640R2F,
Hello,
I have a problem with I2C_transfer() communicating with a TMP116. The setup is a custom board with a CC2640R2F on it and i.a. a TMP116 connected via I2C at IOID_29/IOID_30.
The problem is similar to one that was already asked before in this forum but the solution hasn't been published in that thread unfortunately. Click here for related thread.
The code is basically the "i2ctmp" example from TIs SimpleLink example pack (C:\ti\simplelink_cc2640r2_sdk_5_30_00_03\examples\rtos\CC2640R2_LAUNCHXL\drivers\i2ctmp) but adapted into a TI-RTOS-task instead of POSIX-"pthread".
Strangely enough it works fine when calling it from pthread-context. But the rest of my project is structured with "tasks" so I don't really want to use that POSIX-threading.
Here is my code (I packed it all into one .c-file for this post here):
#define TMP116_REG 0x0000 #define TMP116_BP_ADDR 0x48 #define TMP116_LP_ADDR 0x49 // Read the temperature every 5 minutes (5min * 60 sec/min * 1000 milliseconds/sec) #define READ_TEMP_TIME 300000 #ifndef SENSORS_TASK_STACK_SIZE #define SENSORS_TASK_STACK_SIZE 640 #endif #ifndef SENSORS_TASK_PRIORITY #define SENSORS_TASK_PRIORITY 1 #endif /********************************************************************* * INCLUDES */ #include <xdc/runtime/System.h> #include <xdc/std.h> #include <stdint.h> #include <stddef.h> #include <ti/sysbios/knl/Task.h> #include <ti/sysbios/knl/Clock.h> #include <ti/drivers/I2C.h> #include "util.h" /********************************************************************* * GLOBAL VARIABLES */ // Task configuration Task_Struct sensorsTask; #if defined __TI_COMPILER_VERSION__ #pragma DATA_ALIGN(sensorsTaskStack, 8) #else #pragma data_alignment=8 #endif uint8_t sensorsTaskStack[SENSORS_TASK_STACK_SIZE]; // I2C vars I2C_Handle i2cHandle; I2C_Params i2cParams; I2C_Transaction i2cTransaction; uint16_t sample; uint16_t temperature; uint8_t txBuffer[1]; uint8_t rxBuffer[2]; // Clock Structs static Clock_Struct readTempClock; /********************************************************************* * LOCAL FUNCTIONS */ extern void Sensors_createTask(); static void Sensors_init(); static void Sensors_taskFxn(); static void Sensors_readTemp(); /********************************************************************* * @fn Sensors_createTask * * @brief Reserves stack and sets priority settings */ extern void Sensors_createTask() { Task_Params sensorsTaskParams; // Configure task Task_Params_init(&sensorsTaskParams); sensorsTaskParams.stack = sensorsTaskStack; sensorsTaskParams.stackSize = SENSORS_TASK_STACK_SIZE; sensorsTaskParams.priority = SENSORS_TASK_PRIORITY; Task_construct(&sensorsTask, Sensors_taskFxn, &sensorsTaskParams, NULL); } /********************************************************************* * @fn Sensors_taskFxn * * @brief Sensors-Manager. * Takes care of all sensors equipped with the Smartpen. * Until now just the temperature-sensor is implemented. */ static void Sensors_taskFxn() { // Initialize application Sensors_init(); } /********************************************************************* * @fn Sensors_init * * @brief Initializes all Sensor related things. * Temperature-sensor is using I2C to communicate. */ static void Sensors_init() { I2C_init(); I2C_Params_init(&i2cParams); i2cParams.bitRate = I2C_400kHz; i2cParams.transferMode = I2C_MODE_BLOCKING; // i2cParams.transferCallbackFxn = *Sensors_readTempCompleteCb; Util_constructClock(&readTempClock, Sensors_readTemp, 1, READ_TEMP_TIME, 1, 0); } /********************************************************************* * @fn Sensors_readTemp * * @brief reads the temperature */ static void Sensors_readTemp() { i2cHandle = I2C_open(0, &i2cParams); if (i2cHandle == NULL) { System_printf("Error Initializing I2C\n"); System_flush(); while (1) ; } else { System_printf("I2C Initialized!\n"); System_flush(); } /* Common I2C transaction setup */ i2cTransaction.writeBuf = txBuffer; i2cTransaction.writeCount = 1; i2cTransaction.readBuf = rxBuffer; i2cTransaction.readCount = 2; /* * Determine which I2C sensor is present. * We will prefer sensors in this order: TMP116 (on BoosterPacks), * TMP116 (on-board CC32XX LaunchPads), and last TMP006 * (on older CC32XX LaunchPads). */ /* Try TMP116 values */ txBuffer[0] = TMP116_REG; i2cTransaction.slaveAddress = TMP116_BP_ADDR; if (!I2C_transfer(i2cHandle, &i2cTransaction)) { System_printf("Not BP TMP116, trying LP TMP116\n"); System_flush(); i2cTransaction.slaveAddress = TMP116_LP_ADDR; if (!I2C_transfer(i2cHandle, &i2cTransaction)) { System_printf("Error. No TMP sensor found!\n"); System_flush(); while (1); } } /* Print which TMP is in use */ if (TMP116_REG == txBuffer[0]) { System_printf("Detected TMP116 sensor.\n"); System_flush(); } I2C_close(i2cHandle); System_printf("I2C closed!\n"); }
When calling Sensors_createTask() from main() it will initialize the task and call Sensors_init() when the BIOS has started. Then it will call Sensors_readTemp() through the clock-function initialized in Sensors_init().
In Sensors_readTemp() it will open up the I2C driver which succeeds but when trying to contact the TMP116 it fails.
A colleague of mine then connected an oscilloscope to SDA and SCL and found out that the problem is a missing STOP condition (thats where the related question thread comes in).
Its a really strange problem and maybe thats not a sensors forum problem but a SYS/BIOS-problem but I hope you can help me.
Kind regards