This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP432P401R:连接 MSP432与 ADS1292时出现问题

Guru**** 2582405 points
Other Parts Discussed in Thread: ADS1292

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/696610/msp432p401r-problem-with-interfacing-msp432-with-ads1292

器件型号:MSP432P401R

我正在上传我希望与 ADS1292通信的 MSP432代码(原型中心电路板用于此目的)、原理图为 e2e.ti.com/.../pc_5F00_ads1292r_5F00_brk_5F00_v3.pdf

我已尽力编写代码、在 TI 提供的 MSP432 SDK 的帮助下、我尝试逐个启用 SPI、UART、很高兴它帮助我快速编写代码

但是、我发现通过 MSP432通过 SPI 访问 AD1292的寄存器时遇到了问题、每次我在调试模式下通过 SPI 读取电路板时、每一步都需要比所需的更多的延迟

这是我以 e2e.ti.com/.../6175.project.zip 的形式提供的完整代码包

如果在编译过程中找不到任何文件(由于包含路径),则会打开 build>变量并将 MSP lib 路径更改为 MSP lib 头文件所在的位置,否则必须下载这些文件(如果没有)

让我来展示一下代码流

UART 和 SPI 所连接的重要解串/引脚

*与 SPI 从器件数据回显代码示例配合使用。
*
* MSP432P401
* --------
* | |
* | |
* | |
* | P1.6|->数据输出(UCB0SIMO)
* | |
* | P1.7|<-数据输入(UCB0SOMI)
* | |
* | P1.5|->串行时钟输出(UCB0CLK)
*作者:Timothy Logan
/

#define ADS1292_DRDY_PORT GPIO_PORT_P2
#define ADS1292_DRDY_PIN GPIO_PIN3 //J4.34
#define ADS1292_CS_PORT GPIO_PORT_P5
#define ADS1292_CS_PIN GPIO_PIN1 //J4.33
#define ADS1292_START_PORT GPIO_PORT_P3
#define ADS1292_START_PIN GPIO_PIN5 //J4.32
#define ADS1292_PWDN_PORT GPIO_PORT_P3
#define ADS1292_PWDN_PIN GPIO_PIN7 //J4.31

/* SPI MasterConfig
= USCI_USCI_USCI 配置参数* USCI_Spi_USCI 配置

EUSCI_B_SPI_CLOCKSOURCE_SMCLK、 // SMCLK 时钟源
//3000000、 // SMCLK = DCO = 3MHz
1000000、 // SMCLK = DCO = 1MHz
50万、 // SPICLK = 500kHz
EUSCI_B_SPI_MSB_FIRST、 // MSB 优先
EUSCI_B_SPI_PHASE_DATA_Changed_ONFIRST_Captured_On_Next、//相位
EUSCI_B_SPI_CLOCKPOLARITY_INACTION_HIGH、//高极性
EUSCI_B_SPI_3引脚 // 3线 SPI 模式
};

/* UART 配置参数。 这些是配置参数
、*使 eUSCI 成为 UART 模块以115200波特率运行。 这些
*值是使用 TI 提供的在线计算器计算的*
网址
为:* software-dl.ti.com/.../index.html
*
/ const eUSCI_UART_Config uartConfig =
{
EUSCI_A_UART_CLOCKSOURCE_SMCLK、 // SMCLK 时钟源
13、 // BRDIV = 13
0、 // UCxBRF = 0
37、 // UCxBRS = 37
EUSCI_A_UART_NO_奇 偶校验、 //无奇偶校验
EUSCI_A_UART_MSB_FIRST、 // MSB 优先
EUSCI_A_UART_One_stop_bit、 //一个停止位
EUSCI_A_UART_MODE、 // UART 模式
EUSCI_A_UART_oversampling_BAUDRATE_generation //过采样
}; 

请注意、这些只是代码段、在上传项目的情况下、完整代码才会出现

初始化部分

int Setup_Initialization()
{

/*停止 WDT */
WDT_A_HOLDTimer();

/*初始化数据就绪和芯片选择引脚*/
GPIO_setAsInputPin (ADS1292_DRDY_PORT、ADS1292_DRDY_PIN);
GPIO_setAsOutputPin (ADS1292_CS_PORT、ADS1292_CS_PIN);
GPIO_setAsOutputPin (ADS1292_start_port、ADS1292_start_PIN);
GPIO_setAsOutputPin (ADS1292_PWDN_PORT、ADS1292_PWDN_PIN);

/*在 SPI 模式下选择 P1.5 P1.6和 P1.7 */
GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P1、
GPIO_PIN5 | GPIO_PIN6 | GPIO_PIN7、GPIO_PRIMARY_MODULE_FUNCTION);

/*在3线主控模式下配置 SPI */
SPI_initMaster (EUSCI_B0_BASE、&spiMasterConfig);

/*启用 SPI 模块*/
SPI_enableModule (USCI_B0_BASE);

/*启用中断*/
SPI_enableInterrupt (EUSCI_B0_BASE、EUSCI_B_SPI_Receive_interrupt);
INTERRUPT_enableInterrupt (INT_EUSCIB0);
interrupt_enableSlepOnIsrExit();

/*在 UART 模式下选择 P1.2和 P1.3并将 P1.0作为输出(LED)*/
GPIO_setPeripheralModuleFunctionInputPin (GPIO_PORT_P1、
GPIO_PIN2 | GPIO_PIN3、GPIO_PRIMARY_MODULE_FUNCTION);
GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0);
GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN0);

/*将 DCO 设置为24MHz (升级 Vcore)*/
FlashCtl_setWaitState (FLASH_BANK0、2);
FlashCtl_setWaitState (FLASH_BANK1、2);
PCM_setCoreVoltageLevel (PCM_VCORE1);
CS_setDCOCenteredFrequency (CS_DCO_FREQUENCY 24);

/*配置 UART 模块*/
UART_initModule (EUSCI_A0_BASE、uartConfig);

/*启用 UART 模块*/
UART_enableModule (USCI_A0_BASE);

/*启用中断*/
UART_enableInterrupt (EUSCI_A0_BASE、EUSCI_A_UART_Receive_interrupt);
INTERRUPT_enableInterrupt (INT_EUSCIA0);
interrupt_enableSlepOnIsrExit();

/*ADS 1292初始化*/
/*ADS1292复位*/
GPIO_setOutputHighOnPin (ADS1292_PWDN_PORT、ADS1292_PWDN_PIN);
延迟(100); //等待100毫秒
GPIO_setOutputLowOnPin (ADS1292_PWDN_PORT、ADS1292_PWDN_PIN);
延迟(100);
GPIO_setOutputHighOnPin (ADS1292_PWDN_PORT、ADS1292_PWDN_PIN);
延迟(100);
/*禁用启动*/
GPIO_setOutputLowOnPin (ADS1292_START_PORT、ADS1292_START_PIN);
延迟(20);
/*启用启动*/
GPIO_setOutputHighOnPin (ADS1292_START_PORT、ADS1292_START_PIN);
延迟(20);
/*硬停*/
GPIO_setOutputLowOnPin (ADS1292_START_PORT、ADS1292_START_PIN);
延迟(100);
/*发送命令数据开始*/
ads1292_SPI_Command_Data (开始);
/*软停止*/
ads1292_SPI_Command_Data (停止);
延迟(50);
/*停止连续读取数据*/
ads1292_SPI_Command_Data (SDATAC);
延迟(300);

ADs1292_Reg_Write (ADS1292_REG_CONFIG1、0x00); //将采样率设置为125SPS
延迟(10);
ADs1292_Reg_Write (ADS1292_REG_CONFIG2、0b10100000);//导联脱落补偿关闭、测试信号禁用
延迟(10);
ADs1292_ReG_Write (ADS1292_REG_LOFF、0b00010000); //lead-off 默认值
延迟(10);
ADs1292_Reg_Write (ADS1292_REG_CH1SET、0b01000000);//通道1启用、增益6、连接到中的电极
延迟(10);
ADs1292_ReG_Write (ADS1292_REG_CH2SET、0b01100000);//通道2启用、增益6、连接到中的电极
延迟(10);
ADs1292_Reg_Write (ADS1292_REG_RLDSENS、0b00101100);//RLD 设置:FMOD/16、RLD 启用、仅来自 Ch2的 RLD 输入
延迟(10);
ADs1292_Reg_Write (ADS1292_REG_LOFFSENS、0x00); //LOFF 设置:全部禁用
延迟(10);
//Skip 寄存器8、LOFF Settings 默认值
ads1292_Reg_Write (ADS1292_REG_RESP1、0b11110010); //呼吸:仅限 MOD/DEMOD,0相
延迟(10);
ads1292_Reg_Write (ADS1292_REG_RESP2、0b00000011); //Respiration:Calib Off、呼吸频率默认值
延迟(10);
/*停止连续读取数据*/
ads1292_SPI_Command_Data (RDATAC);
延迟(10);

/*启用启动*/
GPIO_setOutputHighOnPin (ADS1292_START_PORT、ADS1292_START_PIN);
延迟(20);
返回0;
} 

与 ADS1292通信

void ads1292_SPI_Command_Data (uint8_t 命令)
{

TXData =命令;
GPIO_setOutputLowOnPin (ADS1292_CS_PORT、ADS1292_CS_PIN);
延迟(2);
GPIO_setOutputHighOnPin (ADS1292_CS_PORT、 ADS1292_CS_PIN);
延迟(2);
GPIO_setOutputLowOnPin (ADS1292_CS_PORT、ADS1292_CS_PIN);
延迟(2);
//轮询以查看 TX 缓冲区是否就绪*/
while (!(SPI_getInterruptStatus (EUSCI_B0_BASE、EUSCI_B_SPI_Transmit_INTERRUPT)));

//将数据发送到从设备*/
SPI_transmitData (EUSCI_B0_BASE、TXData);

GPIO_setOutputHighOnPin (ADS1292_CS_PORT、ADS1292_CS_PIN);
delay

}(2);)
void ads1292_Reg_Write (uint8_t read_write_address、uint8_t data)
{
uint8_t dataToSend;
switch (read_write_address)
{
案例1:
数据= DATA &(uint8_t) 0x87;
中断;
案例2:
数据= DATA &(uint8_t) 0xFB;
数据|= 0x80;
中断;
案例3:
data = data &(uint8_t) 0xFD;
数据|= 0x10;
中断;
案例7:
数据= DATA &(uint8_t) 0x3F;
中断;
案例8:
数据= DATA &(uint8_t) 0x5F;
中断;
案例9:
数据|= 0x02;
中断;
案例10:
数据=数据& 0x87;
数据|= 0x01;
中断;
案例11:
数据=数据和0x0F;
中断;
默认值:
break;
}

//现在将寄存器地址和命令组合成一个字节:
dataToSend = Read_write_address | WREG;

GPIO_setOutputLowOnPin (ADS1292_CS_port、ADS1292_CS_PIN);
延迟(2);
GPIO_setOutInputOnPin (ADS1292_CS_PORT、 ADS1292_CS_PIN);
延迟(2);
GPIO_setOutputLowOnPin (ADS1292_CS_PORT、ADS1292_CS_PIN);
延迟(2);

//轮
询以查看 TX 缓冲区是否就绪*
(!(SPI_getInterruptStatus (EUSCI_B0_S));//





发送 SPI_BIST_0 (*);*发送 SPI_BIT_RUSCI_0);*中断*(*发送 SPI_BIT_RUSCI_B);*发送 SPI_BUSCI_RUSCI_0);*中断/*(*发送 SPI_BUSCI_RUSCI_RUST_RUSCI_B)
//将数据发送到从设备*/
SPI_transmitData (EUSCI_B0_BASE、0x00);

/*要写入的寄存器数*/
/*轮询以查看 TX 缓冲器是否就绪*/
while (!(SPI_getInterruptStatus (EUSCI_B0_BASE、EUSCI_B_SPI_Transmit_INTERRUPT))));
// while (* ADS1292_OutputData (SPI_get_2_ADS1292_S


);* USCI_S 输出到 ADS12_S 引脚12_S (USCI_S)
延迟(2);
}

最重要和有问题 的代码就是这样

void delay (const int msec)
{
volatile int i;
for (i=0;i 

通过 UART 发送接收到的数据的主循环

int main (void)
{
int i、j;
Setup_Initialization();
while (1)
{
IF (ads1292dataReceived == true)
{
J=0;
for (i=0;i<6;i+=3) //数据输出为(24个状态位+ 24位呼吸数据+ 24位 ECG 数据)
{

uecgtemp =(unsigned long)(((unsigned long) SPI_RX_buff [i+3]<< 16)|(unsigned long) SPI_RX_buff [i+4]<< 8)|(unsigned long) SPI_RX_buff [i+5]);
uecgtemp =(unsigned long)(uecgtemp << 8);
secgtemp =(带符号长整型)(uecgtemp);
secgtemp =(带符号长整型)(secgtemp >> 8);

s32DaqVals[j++]=secgtemp;
}

DataPacketHeader[0]= CES_CMDIF_PKT_START_1;//数据包头1:0x0A
DataPacketHeader[1]= CES_CMDIF_PKT_START_2;//数据包头2:0xFA
DataPacketHeader[2]=(uint8_t)(data_len); //数据长度
DataPacketHeader[3]=(uint8_t)(data_len>8);
DataPacketHeader[4]= CES_CMDIF_TYPE_DATA; //数据包类型:0x02 -数据0x01 -命令

DataPacketHeader[5]= s32DaqVals[1]; // 4字节 ECG 数据
DataPacketHeader[6]= s32DaqVals[1]>8;
DataPacketHeader[7]= s32DaqVals[1]>16;
DataPacketHeader[8]=s32DaqVals[1]>24;

DataPacketHeader[9]= s32DaqVals[0]; // 4字节呼吸数据
DataPacketHeader[10]= s32DaqVals[0]>8;
DataPacketHeader[11]= s32DaqVals[0]>16;
DataPacketHeader[12]=s32DaqVals[0]>24;

DataPacketHeader[13]= CES_CMDIF_TYPE_DATA;//数据包 footer1:0x00
DataPacketHeader[14]= CES_CMDIF_PKT_STOP;//数据包 footer2:0x0B

for (i=0;i<15;i++){
UART_transmitData (EUSCI_A0_BASE、DataPacketHeader[i]); //通过 USB 发送数据
}
ads1292dataReceived = false;
SPI_RX_缓冲 器计数= 0;
}
}

// PCM_gotoLPM0 ();
//__no_operation();
} 

SPI 中断处理程序

//
//
////这是 EUSCI_B0中断矢量服务例程。
////
*********
void EUSCIB0_IRQHandler (void)
{
uint32_t status = SPI_getEnabledInterruptStatus (EUSCI_B0_BASE);
volatile uint32_t jj;

SPI_clearInterruptFlag (EUSCI_B0_BASE、STATUS);

IF (STATUS 和 EUSCI_B_SPI_Receive_interrupt)
{

RXData = SPI_receiveData (EUSCI_B0_BASE);

SPI_RX_buff [SPI_RX_buff Count ++]= RXData;//将结果数据存储在数组中

IF (SPI_RX_缓冲 器计数> 8){
SPI_RX_缓冲 器计数= 0;
ads1292dataReceived = true;
}

/*从机处理信息的传输之间的延迟*/
for (jjj=0;jjj<50;jjj++);

}
}

 

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Shyam、
    指示"When debug mode"(在调试模式下)下对 ADS 器件的 SPI 读取速度较慢。 未连接到调试器时、代码是否正常工作? 此外、您是否能够将逻辑分析仪连接到 SPI 链路、以查看通信周期中的延迟发生在何处?
    -Bob L.
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    不幸的是,我的逻辑分析仪出现了问题,我正面临的正是,TX 数据的一步一步一步需要占用大量时间,
    在函数调用 ads1292_SPI_Command_Data 行17中、您可以传递数据
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    > interrupt_enableSlepOnIsrExit();

    首先删除此行。 您不需要此功能、它可能会导致类似您描述的症状。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    > SPI_transmitData (EUSCI_B0_BASE、TXData);
    > GPIO_setOutputHighOnPin (ADS1292_CS_PORT、ADS1292_CS_PIN);

    在升高/CS 之前、您需要等待字节被发送。 这可能现在(意外)起作用、但如果您加速处理器时钟、它将失败。 在这两行之间插入类似这样的内容:

    > while (EUSCI_B_SPI_isBusy (EUSCI_B0_BASE))/* empty*/;//在提升/CS 前等待最终字节完成
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    > SPI_clearInterruptFlag (EUSCI_B0_BASE、STATUS);

    删除此行。 这是不需要的、它会邀请一场可能会失去(不相关)状态的比赛。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    "让我来展示一下代码流"

    对于类似的情况、您需要先隔离问题。 我经常做的就是这样:

    1) 1)在一组访问例程之上写入一组特定于器件的例程。 例如、这些例程可以基于我链接到的模块在软件或硬件 SPI 基础上构建。 软件 SPI 的优势在于其简单性、因此您可以确保代码的 SPI 部分正常工作、并且您可以专注于器件方面的工作。

    2) 2)完成此操作后、将您的软件 SPI 例程交换为硬件 SPI 例程、然后您可以调试该部分代码。

    特定于器件的例程通常构建在从单字节传输到多字节传输...的层上,以便为代码提供模块化。 最终产品是一组特定于器件的.h/.c 文件、在本例中为 ads1292.h/.c、构建在 SPI_SW.h/.c 或 SPI_HW.h/.c 文件之上。

    完成此操作后、您可以将代码移植到将来可能编写的几乎任何代码中。 又称您当前的努力是一项投资、而不是一项费用。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的回复、

    我已将用于发送 START 的代码稍微更改为该代码

    void ads1292_SPI_Command_Data (uint8_t 命令)
    {
    
    TXData =命令;
    GPIO_setOutputLowOnPin (ADS1292_CS_PORT、ADS1292_CS_PIN);
    延迟(2);
    GPIO_setOutputHighOnPin (ADS1292_CS_PORT、 ADS1292_CS_PIN);
    延迟(2);
    GPIO_setOutputLowOnPin (ADS1292_CS_PORT、ADS1292_CS_PIN);
    延迟(2);
    //轮询以查看 TX 缓冲区是否就绪*/
    while (!(SPI_getInterruptStatus (EUSCI_B0_BASE、EUSCI_B_SPI_Transmit_INTERRUPT)));
    
    //将数据发送到从设备*/
    SPI_TransmitData (EUSCI_B0_BASE、TXData);
    
    while (EUSCI_B_SPI_isBusy (EUSCI_B0_BASE));ADS1292_GPIO_OUT_UST_Pin
    
    、ADS1292_UST_S 引脚
    延迟(2);
    
    }
    

    下面是我为这种传输观察到的信号序列,对我来说似乎没有什么不同,它们是否正常?

    如果该事务为 true、则它对停止、读取数据、写入寄存器等其他事务保持良好状态、  

    如何确认 ADS1292是否对我作出响应?

    我觉得一个单调的信号变低就能完成我的工作,所以我已经为它设置了一个池,我已经修改了代码的主要部分,就像这样

    int main (void)
    {
    int i、j;
    Setup_Initialization();
    while (1)
    {
    if (GPIO_getInputPinValue (ADS1292_DRDY_PORT、ADS1292_DRDY_PIN)= false)
    {
    READ_1292 = true;
    }
    
    IF (ads1292dataReceived == true)
    {
    J=0;
    for (i=0;i<6;i+=3) //数据输出为(24个状态位+ 24位呼吸数据+ 24位 ECG 数据)
    {
    
    uecgtemp =(unsigned long)(((unsigned long) SPI_RX_buff [i+3]<< 16)|(unsigned long) SPI_RX_buff [i+4]<< 8)|(unsigned long) SPI_RX_buff [i+5]);
    uecgtemp =(unsigned long)(uecgtemp << 8);
    secgtemp =(带符号长整型)(uecgtemp);
    secgtemp =(带符号长整型)(secgtemp >> 8);
    
    s32DaqVals[j++]=secgtemp;
    }
    
    DataPacketHeader[0]= CES_CMDIF_PKT_START_1;//数据包头1:0x0A
    DataPacketHeader[1]= CES_CMDIF_PKT_START_2;//数据包头2:0xFA
    DataPacketHeader[2]=(uint8_t)(data_len); //数据长度
    DataPacketHeader[3]=(uint8_t)(data_len>8);
    DataPacketHeader[4]= CES_CMDIF_TYPE_DATA; //数据包类型:0x02 -数据0x01 -命令
    
    DataPacketHeader[5]= s32DaqVals[1]; // 4字节 ECG 数据
    DataPacketHeader[6]= s32DaqVals[1]>8;
    DataPacketHeader[7]= s32DaqVals[1]>16;
    DataPacketHeader[8]=s32DaqVals[1]>24;
    
    DataPacketHeader[9]= s32DaqVals[0]; // 4字节呼吸数据
    DataPacketHeader[10]= s32DaqVals[0]>8;
    DataPacketHeader[11]= s32DaqVals[0]>16;
    DataPacketHeader[12]=s32DaqVals[0]>24;
    
    DataPacketHeader[13]= CES_CMDIF_TYPE_DATA;//数据包 footer1:0x00
    DataPacketHeader[14]= CES_CMDIF_PKT_STOP;//数据包 footer2:0x0B
    
    for (i=0;i<15;i++){
    UART_transmitData (EUSCI_A0_BASE、DataPacketHeader[i]); //通过 USB 发送数据
    }
    ads1292dataReceived = false;
    SPI_RX_缓冲 器计数= 0;
    }
    }
    
    // PCM_gotoLPM0 ();
    //__no_operation();
    }
    

    我感觉、我几乎接近读取数据、但在中间的一些位置、请耐心地指导我  

    PS:已附加完整项目

    e2e.ti.com/.../18062018.zip

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    你好 Daram

    考虑到系统时钟为24MHz、存在一个延迟环路2、延迟似乎过大。 现在、您将轮询 SPI 寄存器以确保寄存器的返回值不是0x0。 实际上、您能否将寄存器读入变量、以查看中断状态中的哪些位已设置。

    其次、而不是使用

    void delay (const int msec)

    volatile int i;
    for (i=0;i <msec;i++);
    //__delay_cycles (msec);


    为什么不这样做?

    空延迟(int msec)

    volatile int i;
    for (i=0;i <msec;i++);
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您好 Dharam、

    是否有此主题的更新?