ZHCADM6 January 2024 MSPM0G1105 , MSPM0G1106 , MSPM0G1107 , MSPM0G1505 , MSPM0G1506 , MSPM0G1507 , MSPM0G3105 , MSPM0G3106 , MSPM0G3107 , MSPM0G3505 , MSPM0G3506 , MSPM0G3507 , MSPM0L1105 , MSPM0L1106 , MSPM0L1303 , MSPM0L1304 , MSPM0L1305 , MSPM0L1306 , MSPM0L1343 , MSPM0L1344 , MSPM0L1345 , MSPM0L1346
该子系统用作 BP-BASSSENSORSMKII BoosterPack™ 插件模块的接口。该模块具有温度和湿度传感器、霍尔效应传感器、环境光传感器、惯性测量单元和磁力计。该模块用于连接 TI LaunchPad™ 开发套件。该子系统使用 I2C 接口从这些传感器收集数据,并使用 UART 接口将数据传输出去。这有助于用户快速进入原型设计阶段并使用 MSPM0 和 BASSSENSORSMKII BoosterPack 模块进行试验。
MSPM0 使用 I2C 接口连接到 BP-BASSSENSORSMKII,使用 UART 接口传输处理后的数据。
使用的外设 | 说明 |
---|---|
I2C | 在代码中称为 I2C_INST |
UART | 在代码中称为 UART_0_INST |
DMA | 用于 UART TX |
GPIO | 这五个 GPIO 分别称为:HDC_V、DRV_V、OPT_V、INT1 和 INT2 |
ADC | 在代码中称为 ADC12_0_INST |
事件 | 用于将数据传输到 UART TX FIFO |
根据所需外设中所示的要求,本示例与下表所示的器件兼容。相应的 EVM 可用于原型设计。
兼容器件 | EVM |
---|---|
MSPM0Lxxxx | LP-MSPM0L1306 |
MSPM0Gxxxx | LP-MSPM0G3507 |
以下流程图简要展示了从传感器 BoosterPack 插件模块读取、收集、处理和传输数据所执行的软件步骤。
该应用利用 TI 系统配置工具 (SysConfig) 图形界面来生成器件外设的配置代码。使用图形界面配置器件外设可简化应用原型设计过程。
可以在 data_sensor_aggregator.c 文件的 main() 的开头找到 软件流程图 中所述内容的代码。
该应用首先设置 UART 和 I2C 传输的大小,然后分配内存来存储要传输的值。然后,它为最终的后处理测量分配内存,以便保存以通过 UART 进行传输。它还定义了一个用于记录 I2C 控制器状态的枚举。您可能需要调整某些数据包大小并更改您自己的实现中的某些数据存储。此外,建议为某些应用添加错误处理功能。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "ti_msp_dl_config.h"
/* Initializing functions */
void DataCollection(void);
void TxFunction(void);
void RxFunction(void);
void Transmit(void);
void UART_Console_write(const uint8_t *data, uint16_t size);
/* Earth's gravity in m/s^2 */
#define GRAVITY_EARTH (9.80665f)
/* Maximum size of TX packet */
#define I2C_TX_MAX_PACKET_SIZE (16)
/* Number of bytes to send to target device */
#define I2C_TX_PACKET_SIZE (3)
/* Maximum size of RX packet */
#define I2C_RX_MAX_PACKET_SIZE (16)
/* Number of bytes to received from target */
#define I2C_RX_PACKET_SIZE (16)
/*
* Number of bytes for UART packet size
* The packet will be transmitted by the UART.
* This example uses FIFOs with polling, and the maximum FIFO size is 4.
* Refer to interrupt examples to handle larger packets.
*/
#define UART_PACKET_SIZE (8)
uint8_t gSpace[] = "\r\n";
volatile bool gConsoleTxTransmitted;
volatile bool gConsoleTxDMATransmitted;
/* Data for UART to transmit */
uint8_t gTxData[UART_PACKET_SIZE];
/* Booleans for interrupts */
bool gCheckADC;
bool gDataReceived;
/* Variable to change the target address */
uint8_t gTargetAdd;
/* I2C variables for data collection */
float gHumidity, gTempHDC, gAmbient;
uint16_t gAmbientE, gAmbientR, gDRV;
uint16_t gMagX, gMagY, gMagZ, gGyrX, gGyrY, gGyrZ, gAccX, gAccY, gAccZ;
/* Data sent to the Target */
uint8_t gTxPacket[I2C_TX_MAX_PACKET_SIZE];
/* Counters for TX length and bytes sent */
uint32_t gTxLen, gTxCount;
/* Data received from Target */
uint8_t gRxPacket[I2C_RX_MAX_PACKET_SIZE];
/* Counters for TX length and bytes sent */
uint32_t gRxLen, gRxCount;
/* Indicates status of I2C */
enum I2cControllerStatus {
I2C_STATUS_IDLE = 0,
I2C_STATUS_TX_STARTED,
I2C_STATUS_TX_INPROGRESS,
I2C_STATUS_TX_COMPLETE,
I2C_STATUS_RX_STARTED,
I2C_STATUS_RX_INPROGRESS,
I2C_STATUS_RX_COMPLETE,
I2C_STATUS_ERROR,
} gI2cControllerStatus;
此应用中的 Main() 会初始化所有外围模块,然后在主循环中设备仅收集来自传感器的所有数据,并在处理后进行传输。
int main(void)
{
SYSCFG_DL_init();
NVIC_EnableIRQ(I2C_INST_INT_IRQN);
NVIC_EnableIRQ(ADC12_0_INST_INT_IRQN);
NVIC_EnableIRQ(UART_0_INST_INT_IRQN);
DL_SYSCTL_disableSleepOnExit(); while(1) {
DataCollection();
Transmit();
/* This delay is to the data is transmitted every few seconds */
delay_cycles(100000000);
}
}
下一个代码块包含所有中断服务例程。第一个是 I2C 例程,接下来是 ADC 例程,最后是 UART 例程。I2C 例程主要用于更新某些标志以及更新控制器状态变量。它还管理 TX 和 RX FIFO。ADC 中断服务例程会设置一个标志,以便主循环可以检查 ADC 值何时有效。UART 中断服务例程也只是设置标志来确认 UART 数据的有效性。
void I2C_INST_IRQHandler(void)
{
switch (DL_I2C_getPendingInterrupt(I2C_INST)) {
case DL_I2C_IIDX_CONTROLLER_RX_DONE:
gI2cControllerStatus = I2C_STATUS_RX_COMPLETE;
break;
case DL_I2C_IIDX_CONTROLLER_TX_DONE:
DL_I2C_disableInterrupt(
I2C_INST, DL_I2C_INTERRUPT_CONTROLLER_TXFIFO_TRIGGER);
gI2cControllerStatus = I2C_STATUS_TX_COMPLETE;
break;
case DL_I2C_IIDX_CONTROLLER_RXFIFO_TRIGGER:
gI2cControllerStatus = I2C_STATUS_RX_INPROGRESS;
/* Receive all bytes from target */
while (DL_I2C_isControllerRXFIFOEmpty(I2C_INST) != true) {
if (gRxCount < gRxLen) {
gRxPacket[gRxCount++] =
DL_I2C_receiveControllerData(I2C_INST);
} else {
/* Ignore and remove from FIFO if the buffer is full */
DL_I2C_receiveControllerData(I2C_INST);
}
}
break;
case DL_I2C_IIDX_CONTROLLER_TXFIFO_TRIGGER:
gI2cControllerStatus = I2C_STATUS_TX_INPROGRESS;
/* Fill TX FIFO with next bytes to send */
if (gTxCount < gTxLen) {
gTxCount += DL_I2C_fillControllerTXFIFO(
I2C_INST, &gTxPacket[gTxCount], gTxLen - gTxCount);
}
break;
/* Not used for this example */
case DL_I2C_IIDX_CONTROLLER_ARBITRATION_LOST:
case DL_I2C_IIDX_CONTROLLER_NACK:
if ((gI2cControllerStatus == I2C_STATUS_RX_STARTED) ||
(gI2cControllerStatus == I2C_STATUS_TX_STARTED)) {
/* NACK interrupt if I2C Target is disconnected */
gI2cControllerStatus = I2C_STATUS_ERROR;
}
case DL_I2C_IIDX_CONTROLLER_RXFIFO_FULL:
case DL_I2C_IIDX_CONTROLLER_TXFIFO_EMPTY:
case DL_I2C_IIDX_CONTROLLER_START:
case DL_I2C_IIDX_CONTROLLER_STOP:
case DL_I2C_IIDX_CONTROLLER_EVENT1_DMA_DONE:
case DL_I2C_IIDX_CONTROLLER_EVENT2_DMA_DONE:
default:
break;
}
}
void ADC12_0_INST_IRQHandler(void)
{
switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST)) {
case DL_ADC12_IIDX_MEM0_RESULT_LOADED:
gCheckADC = true;
break;
default:
break;
}
}
void UART_0_INST_IRQHandler(void)
{
switch (DL_UART_Main_getPendingInterrupt(UART_0_INST)) {
case DL_UART_MAIN_IIDX_EOT_DONE:
gConsoleTxTransmitted = true;
break;
case DL_UART_MAIN_IIDX_DMA_DONE_TX:
gConsoleTxDMATransmitted = true;
break;
default:
break;
}
}
该块会格式化数据,以使用 UART 接口发送。它以易于阅读的格式传递数据,以便在 UART 终端等设备上查看。在您自己的实现中,您可能希望更改正在传输的数据的格式。
/* This function formats and transmits all of the collected data over UART */
void Transmit(void)
{
int count = 1;
char buffer[20];
while (count < 14)
{
/* Formatting the name and converting int to string for transfer */
switch(count){
case 1:
gTxData[0] = 84;
gTxData[1] = 67;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%f", gTempHDC);
break;
case 2:
gTxData[0] = 72;
gTxData[1] = 37;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%f", gHumidity);
break;
case 3:
gTxData[0] = 65;
gTxData[1] = 109;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%f", gAmbient);
break;
case 4:
gTxData[0] = 77;
gTxData[1] = 120;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%i", gMagX);
break;
case 5:
gTxData[0] = 77;
gTxData[1] = 121;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%i", gMagY);
break;
case 6:
gTxData[0] = 77;
gTxData[1] = 122;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%i", gMagZ);
break;
case 7:
gTxData[0] = 71;
gTxData[1] = 120;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%i", gGyrX);
break;
case 8:
gTxData[0] = 71;
gTxData[1] = 121;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%i", gGyrY);
break;
case 9:
gTxData[0] = 71;
gTxData[1] = 122;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%i", gGyrZ);
break;
case 10:
gTxData[0] = 65;
gTxData[1] = 120;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%i", gAccX);
break;
case 11:
gTxData[0] = 65;
gTxData[1] = 121;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%i", gAccY);
break;
case 12:
gTxData[0] = 65;
gTxData[1] = 122;
gTxData[2] = 58;
gTxData[3] = 32;
sprintf(buffer, "%i", gAccZ);
break;
case 13:
gTxData[0] = 68;
gTxData[1] = 82;
gTxData[2] = 86;
gTxData[3] = 32;
sprintf(buffer, "%i", gDRV);
break;
}
count++;
/* Filling the UART transfer variable */
gTxData[4] = buffer[0];
gTxData[5] = buffer[1];
gTxData[6] = buffer[2];
gTxData[7] = buffer[3];
/* Optional delay to ensure UART TX is idle before starting transmission */
delay_cycles(160000);
UART_Console_write(&gTxData[0], 8);
UART_Console_write(&gSpace[0], sizeof(gSpace));
}
UART_Console_write(&gSpace[0], sizeof(gSpace));
}