很荣幸在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_time1000//1/system_jump_time = 1ms
/* Slave Address for I2C Slave */
#define SLAVE_ADDRESS_1 0x48
#define SLAVE_ADDRESS_2 0x49
#define NUM_OF_REC_BYTES10
#define I2C_DELAY50
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 outputGPIO_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上帖子解决了问题(具体的网页一时找不到了)。这里把驱动文件上传上来,可供大家参考。
i2c_driver.c
i2c_driver.h
gaoyang9992006:
多谢分享,干的漂亮。
gaoyang9992006:
回复 gaoyang9992006:
432有三套库函数:MSP432ware的,Keil版本的,还有simplelink版本的。
Susan Yang:
谢谢分享!
user5817386:
回复 gaoyang9992006:
Keil库版本有的好象simplelink版本都有。MSP432ware版本下载需要审核,下不了-_-!
Susan Yang:
回复 user5817386:
请问下载不了,有什么提示吗?
您是如何选择的呢?
user5300930:
代码实现比较清楚,最后也给了I2C的驱动,对于其他小伙伴用I2C驱动OLED或其他器件很方便。有干货,如果能再详细点就好了,将实现这个评测过程中遇到的问题和解决方法描述下,对于小伙伴少踩坑就更有帮助了。
user4637920:
这位同学直接贴上代码,show you the code,先赞一下。对重点用到的I2C接口的定义、原理说的比较清楚,最后给了I2C的驱动,对需要使用I2C的朋友是个帮助。感觉差点就是没有图文并茂,如果能把过程说的再多一点就好了。
user5284236:
很详细的一篇评测文章,代码比较多,最后也给了I2C的驱动文件,能给大家带来实际的帮助。
使用OLED显示验证了I2C器件的数据通信结果。投一票。
user5182684:
这篇分享结合了作者的其他模块,OLED屏和LSM6DSO传感器,主要使用I2C功能,代码也比较清晰,如果加上一些注释会更好,方便参考移植。但是呢,开发期间遇到了哪些问题,是怎样解决的并没有详细说明,我觉得这方面的可以详细点讲,避免其他人踩坑,加入了空闲的模块结合开发板实现各种功能是很好的试用,感谢分享!
user5817386:
回复 Susan Yang:
之前页面显示需要审核,没有下载按钮。我今天又试了一下,可以下载了。
TI中文支持网
