很荣幸在21IC论坛活动中获得一块MSP432P401R LanchPad。拿到开发板后,先搭建开发环境,MSP432P401R可在CCS、KEIL、IAR 3个IDE平台都可开发,这里选择了比较熟悉的KEIL。并对MSP432P401R的SDK进行熟悉。
刚好手头有一块带6轴LSM6DSO传感器的板子和一块0.96寸的OLED屏,两个都可通过I2C进行通讯。LSM6DSO传感器自带计步功能,既通过中断通知计步事件,也可以通过读取对应的寄存器获得。那就做一个计步功能,来测试MSP432P401R的I2C功能。
下图是I2C的框架图
MSP432P401R的I2C模块包括下列功能:
7位和10位设备寻址模式
启动、重启和停止
多主发射机/接收机模式
从接收机/发射机模式
支持高达100 Kbps的标准模式、高达400 Kbps的快速模式和高达1 Mbps的快速模式
主模式下可编程UCXCLK频率
专为低功耗设计
具有中断能力和自动停止断言的8位字节计数器
多达四个硬件从地址,每个都有自己的中断和DMA触发器
从机地址和地址接收中断的屏蔽寄存器
时钟低超时中断,以避免总线暂停
I2C模块的功能非常丰富。此次评测只使用I2C的基本功能。
硬件连接为SCL -- P1.7,SDA -- P1.6,gpio中断 -- P5.0。
/* DriverLib Includes */ #include <ti/devices/msp432p4xx/driverlib/driverlib.h> /* Standard Includes */ #include <stdint.h> #include <stdbool.h> #include "i2c_driver.h" #include "oled_i2c.h" #include "Lsm6dso.h" #define system_jump_time 1000 // 1/system_jump_time = 1ms /* Slave Address for I2C Slave */ #define SLAVE_ADDRESS_1 0x48 #define SLAVE_ADDRESS_2 0x49 #define NUM_OF_REC_BYTES 10 #define I2C_DELAY 50 uint32_t i, j; uint32_t pedometerCnt, pedometerCntOld = 0xffffffff; static uint8_t index, indexOld = 0xff; //一次滴答中断的tick数 uint32_t System_tick_num; static uint32_t delayCnt = 0xffffffff, delayTarget = 0; static uint8_t delayFinFlag = 0; static volatile uint8_t Lsm6dsoEventDetected = 0; uint8_t pedoFlag = 0; // void pedometerShow(void); void MCU_Init() { // Set P1.0 to output direction GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0); /* Configuring P1.1 as an input and enabling interrupts */ MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1); MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN1); MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1); MAP_Interrupt_enableInterrupt(INT_PORT1); /* Configuring P1.1 as an input and enabling interrupts */ MAP_GPIO_setAsInputPinWithPullDownResistor(GPIO_PORT_P5, GPIO_PIN0); MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, GPIO_PIN0); MAP_GPIO_enableInterrupt(GPIO_PORT_P5, GPIO_PIN0); MAP_Interrupt_enableInterrupt(INT_PORT5); /* Enabling SRAM Bank Retention */ MAP_SysCtl_enableSRAMBankRetention(SYSCTL_SRAM_BANK1); /* Enabling MASTER interrupts */ MAP_Interrupt_enableMaster(); } void SysTick_Init(void) { /* Setup SysTick Timer for 10ms interrupts */ System_tick_num = SystemCoreClock / system_jump_time; if (SysTick_Config(System_tick_num)) { // OLED_ShowStr(1, 3, "SysTick err", 2); // OLED_ON();//OLED唤醒 while (1); } } void delayMS(uint32_t num) { delayTarget = num; delayCnt = 0; delayFinFlag = 0; while(!delayFinFlag); } int main(void) { /* Disabling the Watchdog */ MAP_WDT_A_holdTimer(); MCU_Init(); SysTick_Init(); BSP_I2C_Init(); for(i = 0; i < 4; i++) { // Toggle P1.0 output GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0); delayMS(250); } OLED_Init(); if(0 == Lsm6dso_Init()) { OLED_ShowStr(0, 1, "PEDOMETER :", 1); } else { OLED_ShowStr(1, 3, "Lsm6dso err", 2); OLED_ON();//OLED唤醒 while(1); } pedometerCnt = 0; while(1) { if(Lsm6dsoEventDetected) { Lsm6dsoEventDetected = 0; if(RET_OK == Get_Lsm6dso_Event(&pedoFlag)) { pedoFlag = 0; pedometerCnt++; } } pedometerShow(); } } void SysTick_Handler(void) { if(delayCnt < delayTarget) { delayCnt++; if(delayCnt >= delayTarget) { delayFinFlag = 1; } } } void pedometerShow() { stOledShow currRow; uint32_t pedometerCntShow; if(pedometerCntOld == pedometerCnt) { return; } pedometerCntOld = pedometerCnt; pedometerCntShow = pedometerCnt; index = 0; currRow.str[MAX_ROW_STR_NUM] = 0x0; while(pedometerCntShow > 9) { index++; currRow.str[MAX_ROW_STR_NUM - index] = (pedometerCntShow % 10) + 0x30; pedometerCntShow /= 10; } index++; if(index > MAX_PEDOMETER_INDEX) { index = 1; currRow.str[MAX_ROW_STR_NUM - index] = 0x21; index++; currRow.str[MAX_ROW_STR_NUM - index] = 0x4c; index++; currRow.str[MAX_ROW_STR_NUM - index] = 0x6e; index++; currRow.str[MAX_ROW_STR_NUM - index] = 0x6e; index++; currRow.str[MAX_ROW_STR_NUM - index] = 0x41; } else { currRow.str[MAX_ROW_STR_NUM - index] = (pedometerCntShow % 10) + 0x30; } if(indexOld != index) { indexOld = index; currRow.x = 0; currRow.y = 2; OLED_Fill_Line(currRow.y, 0x0); OLED_Fill_Line(currRow.y+1, 0x0); OLED_Fill_Line(currRow.y+2, 0x0); OLED_Fill_Line(currRow.y+3, 0x0); } currRow.y = 3; currRow.TextSize = 4; currRow.x = (ROW_PIXEL - 16 * index) / 2; OLED_ShowStr(currRow.x, currRow.y, &currRow.str[MAX_ROW_STR_NUM - index], currRow.TextSize); } /* GPIO ISR */ void PORT1_IRQHandler(void) { uint32_t status; status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P1); MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, status); /* Toggling the output on the LED */ if(status & GPIO_PIN1) { // MAP_GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0); pedometerCnt = 0; } } /* GPIO ISR */ void PORT5_IRQHandler(void) { uint32_t status; status = MAP_GPIO_getEnabledInterruptStatus(GPIO_PORT_P5); MAP_GPIO_clearInterruptFlag(GPIO_PORT_P5, status); /* Toggling the output on the LED */ if(status & GPIO_PIN0) { // if(GPIO_INPUT_PIN_HIGH == GPIO_getInputPinValue(GPIO_PORT_P5, GPIO_PIN0)) { Lsm6dsoEventDetected = 1; } } }
I2C调试期间遇到了很多问题,也参考了E2E上帖子解决了问题(具体的网页一时找不到了)。这里把驱动文件上传上来,可供大家参考。
//***************************************************************************** // // Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // //**************************************************************************** //************************MODIFICATON INFORMATION***************************** //Modified from original source located at: // https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/472504/1701554#1701554 // //Modifed by Reid Kersey, CEO, Sniffer GPS - 7/19/2017 // sniffergps.com // reid@sniffergps.com // 678-209-2215 // //Updates: //6/7/2017 //Changed EUSCI_Bx_MODULE to EUSCI_Bx_BASE //Changed from using B1 to allowing use of any Bx Module //Added funciton description comments //7/19/2017 //removed slow speed bug on B2 and B3 //Feel free to contact me about modifications to this code or questions about usage, //however I am not the original author. Credit goes to DavidL https://e2e.ti.com/members/2005340 #include "msp432.h" #include "i2c_driver.h" //#include "driverlib.h" #include <ti/devices/msp432p4xx/driverlib/driverlib.h> //***************************************************************************** // // Definitions // //***************************************************************************** //***************************************************************************** // // Global Data // //***************************************************************************** volatile eUSCI_status ui8Status; uint8_t *pData; uint8_t ui8DummyRead; uint32_t g_ui32ByteCount; bool burstMode = false; //B0-3 configurations /* I2C Master Configuration Parameter */ //volatile eUSCI_I2C_MasterConfig i2cConfig_B0 = eUSCI_I2C_MasterConfig i2cConfig_B0 = { EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 0, EUSCI_B_I2C_SET_DATA_RATE_100KBPS, // Desired I2C Clock of 400khz 0, // No byte counter threshold EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD // Autostop }; //volatile eUSCI_I2C_MasterConfig i2cConfig_B1 = eUSCI_I2C_MasterConfig i2cConfig_B1 = { EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 0, EUSCI_B_I2C_SET_DATA_RATE_100KBPS, // Desired I2C Clock of 400khz 0, // No byte counter threshold EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD // Autostop }; //volatile eUSCI_I2C_MasterConfig i2cConfig_B2 = eUSCI_I2C_MasterConfig i2cConfig_B2 = { EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 0, EUSCI_B_I2C_SET_DATA_RATE_100KBPS, // Desired I2C Clock of 400khz 0, // No byte counter threshold EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD // Autostop }; //volatile eUSCI_I2C_MasterConfig i2cConfig_B3 = eUSCI_I2C_MasterConfig i2cConfig_B3 = { EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 0, EUSCI_B_I2C_SET_DATA_RATE_100KBPS, // Desired I2C Clock of 400khz 0, // No byte counter threshold EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD // Autostop }; //***************************************************************************** // // Imported Data // //***************************************************************************** //***************************************************************************** // // Constants // //***************************************************************************** //***************************************************************************** // // Function Prototypes // //***************************************************************************** /*********************************************************** Function: You MUST call this before doing any read or writes @param module the EUSCI module to use ex: EUSCI_B0_BASE */ void initI2C(int module) { /* I2C Clock Soruce Speed */ if(module == EUSCI_B0_BASE){ i2cConfig_B0.i2cClk = MAP_CS_getSMCLK(); GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION); /* Initializing I2C Master to SMCLK at 100kbs with autostop */ MAP_I2C_initMaster(EUSCI_B0_BASE, &i2cConfig_B0); }else if(module == EUSCI_B1_BASE){ i2cConfig_B1.i2cClk = MAP_CS_getSMCLK(); GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P6, GPIO_PIN5 | GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION); /* Initializing I2C Master to SMCLK at 100kbs with autostop */ MAP_I2C_initMaster(EUSCI_B1_BASE, &i2cConfig_B1); }else if(module == EUSCI_B2_BASE){ i2cConfig_B2.i2cClk = MAP_CS_getSMCLK(); GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P3, GPIO_PIN6 | GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION); /* Initializing I2C Master to SMCLK at 100kbs with autostop */ MAP_I2C_initMaster(EUSCI_B2_BASE, &i2cConfig_B2); }else if(module == EUSCI_B3_BASE){ i2cConfig_B3.i2cClk = MAP_CS_getSMCLK(); GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P6, GPIO_PIN6 | GPIO_PIN7, GPIO_SECONDARY_MODULE_FUNCTION); /* Initializing I2C Master to SMCLK at 100kbs with autostop */ MAP_I2C_initMaster(EUSCI_B3_BASE, &i2cConfig_B3); } } /*********************************************************** Function: @param module the EUSCI module to use ex: EUSCI_B0_BASE @param ui8Addr the 7 bit address of the module @param ui8Reg the register to write to @param Data a pointer to where the data to be written is stored @param ui32ByteCount the number of bytes to write @returns true if successful, false otherwise */ bool writeI2C(int module, uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount) { /* Wait until ready to write */ while (MAP_I2C_isBusBusy(module)); /* Assign Data to local Pointer */ pData = Data; /* Disable I2C module to make changes */ MAP_I2C_disableModule(module); /* Setup the number of bytes to transmit + 1 to account for the register byte */ if(module == EUSCI_B0_BASE){ i2cConfig_B0.byteCounterThreshold = ui8ByteCount + 1; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B0); }else if(module == EUSCI_B1_BASE){ i2cConfig_B1.byteCounterThreshold = ui8ByteCount + 1; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B1); }else if(module == EUSCI_B2_BASE){ i2cConfig_B2.byteCounterThreshold = ui8ByteCount + 1; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B2); }else if(module == EUSCI_B3_BASE){ i2cConfig_B3.byteCounterThreshold = ui8ByteCount + 1; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B3); }else{ return false; } /* Load device slave address */ MAP_I2C_setSlaveAddress(module, ui8Addr); /* Enable I2C Module to start operations */ MAP_I2C_enableModule(module); /* Enable master STOP, TX and NACK interrupts */ MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT + EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_TRANSMIT_INTERRUPT0); /* Set our local state to Busy */ ui8Status = eUSCI_BUSY; /* Send start bit and register */ MAP_I2C_masterSendMultiByteStart(module,ui8Reg); /* Enable master interrupt for the remaining data */ if(module == EUSCI_B0_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB0); }else if(module == EUSCI_B1_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB1); }else if(module == EUSCI_B2_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB2); }else if(module == EUSCI_B3_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB3); }else{ return false; } // NOW WAIT FOR DATA BYTES TO BE SENT while(ui8Status == eUSCI_BUSY) { #ifdef USE_LPM MAP_PCM_gotoLPM0(); #else __no_operation(); #endif } /* Disable interrupts */ MAP_I2C_disableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT + EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_TRANSMIT_INTERRUPT0); if(module == EUSCI_B0_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB0); }else if(module == EUSCI_B1_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB1); }else if(module == EUSCI_B2_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB2); }else if(module == EUSCI_B3_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB3); }else{ return false; } if(ui8Status == eUSCI_NACK) { return(false); } else { return(true); } } /*********************************************************** Function: @param module the EUSCI module to use ex: EUSCI_B0_BASE @param ui8Addr the 7 bit address of the module @param ui8Reg the register to read from @param Data a pointer to where to put the data @param ui32ByteCount the number of bytes to read @returns true if successful, false otherwise */ bool readI2C(int module, uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount) { /* Todo: Put a delay */ //todo reset if busy for long enough time /* Wait until ready */ while (MAP_I2C_isBusBusy(module)); /* Assign Data to local Pointer */ pData = Data; /* Disable I2C module to make changes */ MAP_I2C_disableModule(module); /* Setup the number of bytes to receive */ if(module == EUSCI_B0_BASE){ i2cConfig_B0.byteCounterThreshold = ui8ByteCount; i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B0); // i2cConfig_B0.byteCounterThreshold = ui8ByteCount; // i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP;//EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD;// // g_ui32ByteCount = ui8ByteCount; // burstMode = true; }else if(module == EUSCI_B1_BASE){ i2cConfig_B1.byteCounterThreshold = ui8ByteCount; i2cConfig_B1.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B1); }else if(module == EUSCI_B2_BASE){ i2cConfig_B2.byteCounterThreshold = ui8ByteCount; i2cConfig_B2.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B2); }else if(module == EUSCI_B3_BASE){ i2cConfig_B3.byteCounterThreshold = ui8ByteCount; i2cConfig_B3.autoSTOPGeneration = EUSCI_B_I2C_SEND_STOP_AUTOMATICALLY_ON_BYTECOUNT_THRESHOLD; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B3); }else{ return false; } /* Load device slave address */ MAP_I2C_setSlaveAddress(module, ui8Addr); /* Enable I2C Module to start operations */ MAP_I2C_enableModule(module); /* Enable master STOP and NACK interrupts */ MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT + EUSCI_B_I2C_NAK_INTERRUPT); /* Set our local state to Busy */ ui8Status = eUSCI_BUSY; /* Send start bit and register */ MAP_I2C_masterSendMultiByteStart(module,ui8Reg); /* Enable master interrupt for the remaining data */ if(module == EUSCI_B0_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB0); }else if(module == EUSCI_B1_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB1); }else if(module == EUSCI_B2_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB2); }else if(module == EUSCI_B3_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB3); }else{ return false; } /* NOTE: If the number of bytes to receive = 1, then as target register is being shifted * out during the write phase, UCBxTBCNT will be counted and will trigger STOP bit prematurely * If count is > 1, wait for the next TXBUF empty interrupt (just after reg value has been * shifted out * * If your code is getting stuck here, you probably called this function from an interrupt * DON'T DO THAT! */ while(ui8Status == eUSCI_BUSY) { if(MAP_I2C_getInterruptStatus(module, EUSCI_B_I2C_TRANSMIT_INTERRUPT0)) { ui8Status = eUSCI_IDLE; } } ui8Status = eUSCI_BUSY; /* Turn off TX and generate RE-Start */ MAP_I2C_masterReceiveStart(module); /* Enable RX interrupt */ MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); /* Wait for all data be received */ while(ui8Status == eUSCI_BUSY) { #ifdef USE_LPM MAP_PCM_gotoLPM0(); #else __no_operation(); #endif } /* Disable interrupts */ MAP_I2C_disableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT + EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_RECEIVE_INTERRUPT0); if(module == EUSCI_B0_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB0); }else if(module == EUSCI_B1_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB1); }else if(module == EUSCI_B2_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB2); }else if(module == EUSCI_B3_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB3); }else{ return false; } if(ui8Status == eUSCI_NACK) { return(false); } else { return(true); } } /*********************************************************** Function: @param module the EUSCI module to use ex: EUSCI_B0_BASE @param ui8Addr the 7 bit address of the module @param ui8Reg the register to read from @param Data a pointer to where to put the data @param ui32ByteCount the number of bytes to read @returns true if successful, false otherwise */ bool readBurstI2C(int module, uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint32_t ui32ByteCount) { /* Todo: Put a delay */ /* Wait until ready */ while (MAP_I2C_isBusBusy(module)); /* Assign Data to local Pointer */ pData = Data; /* Disable I2C module to make changes */ MAP_I2C_disableModule(module); /* Setup the number of bytes to receive */ if(module == EUSCI_B0_BASE){ i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; g_ui32ByteCount = ui32ByteCount; burstMode = true; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B0); }else if(module == EUSCI_B1_BASE){ i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; g_ui32ByteCount = ui32ByteCount; burstMode = true; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B1); }else if(module == EUSCI_B2_BASE){ i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; g_ui32ByteCount = ui32ByteCount; burstMode = true; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B2); }else if(module == EUSCI_B3_BASE){ i2cConfig_B0.autoSTOPGeneration = EUSCI_B_I2C_NO_AUTO_STOP; g_ui32ByteCount = ui32ByteCount; burstMode = true; MAP_I2C_initMaster(module, (const eUSCI_I2C_MasterConfig *)&i2cConfig_B3); }else{ return false; } /* Load device slave address */ MAP_I2C_setSlaveAddress(module, ui8Addr); /* Enable I2C Module to start operations */ MAP_I2C_enableModule(module); /* Enable master STOP and NACK interrupts */ MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT + EUSCI_B_I2C_NAK_INTERRUPT); /* Set our local state to Busy */ ui8Status = eUSCI_BUSY; /* Send start bit and register */ MAP_I2C_masterSendMultiByteStart(module,ui8Reg); /* Enable master interrupt for the remaining data */ if(module == EUSCI_B0_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB0); }else if(module == EUSCI_B1_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB1); }else if(module == EUSCI_B2_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB2); }else if(module == EUSCI_B3_BASE){ MAP_Interrupt_enableInterrupt(INT_EUSCIB3); }else{ return false; } /* NOTE: If the number of bytes to receive = 1, then as target register is being shifted * out during the write phase, UCBxTBCNT will be counted and will trigger STOP bit prematurely * If count is > 1, wait for the next TXBUF empty interrupt (just after reg value has been * shifted out * * If your code is getting stuck here, you probably called this function from an interrupt * DON'T DO THAT! */ while(ui8Status == eUSCI_BUSY) { if(MAP_I2C_getInterruptStatus(module, EUSCI_B_I2C_TRANSMIT_INTERRUPT0)) { ui8Status = eUSCI_IDLE; } } ui8Status = eUSCI_BUSY; /* Turn off TX and generate RE-Start */ MAP_I2C_masterReceiveStart(module); /* Enable RX interrupt */ MAP_I2C_enableInterrupt(module, EUSCI_B_I2C_RECEIVE_INTERRUPT0); /* Wait for all data be received */ while(ui8Status == eUSCI_BUSY) { #ifdef USE_LPM MAP_PCM_gotoLPM0(); #else __no_operation(); #endif } /* Disable interrupts */ MAP_I2C_disableInterrupt(module, EUSCI_B_I2C_STOP_INTERRUPT + EUSCI_B_I2C_NAK_INTERRUPT + EUSCI_B_I2C_RECEIVE_INTERRUPT0); if(module == EUSCI_B0_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB0); }else if(module == EUSCI_B1_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB1); }else if(module == EUSCI_B2_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB2); }else if(module == EUSCI_B3_BASE){ MAP_Interrupt_disableInterrupt(INT_EUSCIB3); }else{ return false; } if(ui8Status == eUSCI_NACK) { return(false); } else { return(true); } } /*********************************************************** Function: euscib0IntHandler */ void EUSCIB0_IRQHandler(void) { uint_fast16_t status; status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B0_BASE); MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, status); if (status & EUSCI_B_I2C_NAK_INTERRUPT) { /* Generate STOP when slave NACKS */ MAP_I2C_masterSendMultiByteStop(EUSCI_B0_BASE); /* Clear any pending TX interrupts */ MAP_I2C_clearInterruptFlag(EUSCI_B0_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0); /* Set our local state to NACK received */ ui8Status = eUSCI_NACK; } if (status & EUSCI_B_I2C_START_INTERRUPT) { /* Change our local state */ ui8Status = eUSCI_START; } if (status & EUSCI_B_I2C_STOP_INTERRUPT) { /* Change our local state */ ui8Status = eUSCI_STOP; } if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0) { /* RX data */ *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE); ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE); if (burstMode) { g_ui32ByteCount--; if (g_ui32ByteCount == 1) { burstMode = false; /* Generate STOP */ MAP_I2C_masterSendMultiByteStop(EUSCI_B0_BASE); } } } if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0) { /* Send the next data */ MAP_I2C_masterSendMultiByteNext(EUSCI_B0_BASE, *pData++); } #ifdef USE_LPM MAP_Interrupt_disableSleepOnIsrExit(); #endif } void EUSCIB1_IRQHandler(void) { uint_fast16_t status; status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B1_BASE); MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, status); if (status & EUSCI_B_I2C_NAK_INTERRUPT) { /* Generate STOP when slave NACKS */ MAP_I2C_masterSendMultiByteStop(EUSCI_B1_BASE); /* Clear any pending TX interrupts */ MAP_I2C_clearInterruptFlag(EUSCI_B1_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0); /* Set our local state to NACK received */ ui8Status = eUSCI_NACK; } if (status & EUSCI_B_I2C_START_INTERRUPT) { /* Change our local state */ ui8Status = eUSCI_START; } if (status & EUSCI_B_I2C_STOP_INTERRUPT) { /* Change our local state */ ui8Status = eUSCI_STOP; } if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0) { /* RX data */ *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE); ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B1_BASE); if (burstMode) { g_ui32ByteCount--; if (g_ui32ByteCount == 1) { burstMode = false; /* Generate STOP */ MAP_I2C_masterSendMultiByteStop(EUSCI_B1_BASE); } } } if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0) { /* Send the next data */ MAP_I2C_masterSendMultiByteNext(EUSCI_B1_BASE, *pData++); } #ifdef USE_LPM MAP_Interrupt_disableSleepOnIsrExit(); #endif } void EUSCIB2_IRQHandler(void) { uint_fast16_t status; status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B2_BASE); MAP_I2C_clearInterruptFlag(EUSCI_B2_BASE, status); if (status & EUSCI_B_I2C_NAK_INTERRUPT) { /* Generate STOP when slave NACKS */ MAP_I2C_masterSendMultiByteStop(EUSCI_B2_BASE); /* Clear any pending TX interrupts */ MAP_I2C_clearInterruptFlag(EUSCI_B2_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0); /* Set our local state to NACK received */ ui8Status = eUSCI_NACK; } if (status & EUSCI_B_I2C_START_INTERRUPT) { /* Change our local state */ ui8Status = eUSCI_START; } if (status & EUSCI_B_I2C_STOP_INTERRUPT) { /* Change our local state */ ui8Status = eUSCI_STOP; } if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0) { /* RX data */ *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B2_BASE); ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B2_BASE); if (burstMode) { g_ui32ByteCount--; if (g_ui32ByteCount == 1) { burstMode = false; /* Generate STOP */ MAP_I2C_masterSendMultiByteStop(EUSCI_B2_BASE); } } } if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0) { /* Send the next data */ MAP_I2C_masterSendMultiByteNext(EUSCI_B2_BASE, *pData++); } #ifdef USE_LPM MAP_Interrupt_disableSleepOnIsrExit(); #endif } void EUSCIB3_IRQHandler(void) { uint_fast16_t status; status = MAP_I2C_getEnabledInterruptStatus(EUSCI_B3_BASE); MAP_I2C_clearInterruptFlag(EUSCI_B3_BASE, status); if (status & EUSCI_B_I2C_NAK_INTERRUPT) { /* Generate STOP when slave NACKS */ MAP_I2C_masterSendMultiByteStop(EUSCI_B3_BASE); /* Clear any pending TX interrupts */ MAP_I2C_clearInterruptFlag(EUSCI_B3_BASE, EUSCI_B_I2C_TRANSMIT_INTERRUPT0); /* Set our local state to NACK received */ ui8Status = eUSCI_NACK; } if (status & EUSCI_B_I2C_START_INTERRUPT) { /* Change our local state */ ui8Status = eUSCI_START; } if (status & EUSCI_B_I2C_STOP_INTERRUPT) { /* Change our local state */ ui8Status = eUSCI_STOP; } if (status & EUSCI_B_I2C_RECEIVE_INTERRUPT0) { /* RX data */ *pData++ = MAP_I2C_masterReceiveMultiByteNext(EUSCI_B3_BASE); ui8DummyRead= MAP_I2C_masterReceiveMultiByteNext(EUSCI_B3_BASE); if (burstMode) { g_ui32ByteCount--; if (g_ui32ByteCount == 1) { burstMode = false; /* Generate STOP */ MAP_I2C_masterSendMultiByteStop(EUSCI_B3_BASE); } } } if (status & EUSCI_B_I2C_TRANSMIT_INTERRUPT0) { /* Send the next data */ MAP_I2C_masterSendMultiByteNext(EUSCI_B3_BASE, *pData++); } #ifdef USE_LPM MAP_Interrupt_disableSleepOnIsrExit(); #endif } void BSP_I2C_Init() { initI2C(EUSCI_B0_BASE); } bool BSP_I2C1_WriteReg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { if(writeI2C(EUSCI_B0_BASE, (DevAddr & 0xff), (Reg & 0xff), pData, (Length & 0xff))) { return 0; } return 1; } bool BSP_I2C1_ReadReg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) { if(readI2C(EUSCI_B0_BASE, (DevAddr & 0xff), (Reg & 0xff), pData, (Length & 0xff))) { return 0; } return 1; }