很荣幸在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;
}





