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.

[参考译文] LP-MSP430FR2476:SPI 接收

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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1040183/lp-msp430fr2476-spi-receive

器件型号:LP-MSP430FR2476

我正在尝试根据 off eusci_a_spi_ex1master.c 文件设置 SPI 主器件事务。 该文件显示了如何启用 SPI RX 中断、但它也会检查 TX 中断是否已被明确启用。 Tx 中断是如何工作的?  我不理解如何设置 SPI RX ISR。 RX ISR 在第五个事务之后触发、 我可以获得一个要停止的断点。 但是、

RXData = EUSCI_A_SPI_receiveData (EUSCI_A1_BASE);显示 RXData 的值为0。 我手头没有示波器、我不明白为什么数据没有显示?

谢谢、

Priya

/*
*初始化 EUSCI A1上的 SPI 外设
*
空 init_spi_peripheral()

//初始化主设备
EUSCI_A_SPI_initMasterParam param ={0};
param.selectClockSource = EUSCI_A_SPI_CLOCKSOURCE_SMCLK;
param.clockSourceFrequency = CS_getSMCLK();
param.desiredSpiClock = 1000000;
param.msbFirst = UCMSB;
param.clockPhase = UCCKPH;
param.clockPolarity = 0;
param.spiMode = EUSCI_A_SPI_3引脚;
EUSCI_A_SPI_initMaster (EUSCI_A1_base、&param);

EUSCI_A_SPI_ENABLE (EUSCI_A1_BASE);

void CheckUSCI_A1_TxReady (void){
//USCI_A1 TX 缓冲器准备好了吗?
while (!eUSCI_A_SPI_getInterruptStatus (eUSCI_A1_base、
EUSCI_A_SPI_Transmit 中断);

void MaximUARTDaisyChainInitStart (void){

daisyChainInit = 1;

//USCI_A1 TX 缓冲器准备好了吗?
CheckUSCI_A1_TxReady ();
//向从器件发送数据
对于(I = 0;I < 2;I++)
eUSCI_A_SPI_transmitData (eUSCI_A1_base、DCInit_transaction1[i]);
TXData++;

CheckUSCI_A1_TxReady ();
//启用 Rx 中断标志
对于(I = 0;I < 2;I++)
eUSCI_A_SPI_transmitData (eUSCI_A1_base、DCInit_transaction2[i]);
TXData++;

CheckUSCI_A1_TxReady ();
//清除接收缓冲区
eUSCI_A_SPI_transmitData (eUSCI_A1_base、DCInit_transaction3);
TXData++;

CheckUSCI_A1_TxReady ();
//唤醒 UART 从设备
对于(I = 0;I < 2;I++)
eUSCI_A_SPI_transmitData (eUSCI_A1_base、DCInit_transaction4[i]);
TXData++;

CheckUSCI_A1_TxReady ();
//等待所有 UART 从设备唤醒
eUSCI_A_SPI_transmitData (eUSCI_A1_base、DCInit_transaction5);

  

int main (空)

WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器

init_gpio();//设置 IO 引脚
init_clock();//将系统时钟设置为16MHz (在 MSP430上)

//设置外设现在已设置 GPIO 和时钟
init_spi_peripheral();// Init Maxim SPI 外围设备

//清除接收中断标志
EUSCI_A_SPI_clearInterrupt (EUSCI_A1_base、
EUSCI_A_SPI_Receive_interrupt
);

//启用 USCI_A1 RX 中断
EUSCI_A_SPI_enableInterrupt (EUSCI_A1_BASE、
EUSCI_A_SPI_Receive_interrupt);

//等待从器件初始化
_DELAY_CYCLES (100);

TXData = 0x1;//保留 TX 数据

MaximUART菊花 链 InitStart();

_bis_SR_register (LPM0_bits + GIE);// CPU 关闭、启用中断
_NO_OPERATION ();//保持在 LPM0中


返回0;

#if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
#pragma vector=USCI_A1_vector
_interrupt
#Elif defined (_GNU_)
__attribute__((中断(USCI_A1_vector))
#endif
空 USCI_A1_ISR (空)

IF (USCI_SPI_UCRXIFG){

RXData = EUSCI_A_SPI_receiveData (EUSCI_A1_BASE);

if (daisyChainInit = 1 &&(TXData = 0x5)){
if (RXData = 0x21){
TXData++;

//从机处理信息的传输之间的延迟
_DELAY_CYCLES (40);

PS:我知道接收器可与评估板交易的评估 GUI 配合使用。 这是关于 MSP430 SPI 的问题、我没有正确关闭。

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

    您好、Priya、

    有关 TX 中断如何工作的问题、请参阅用户指南的第23.3.3节"主模式"、其中讨论了 eUSCI_A SPI 模块、并解释了数据传输的发生方式以及 TX 和 RX 中断所扮演的角色[链接]。

    我还会将 ISR 更改为遵循 eusci_a_spi_ex1master.c 的格式(使用 switch 语句)。 查看用户指南中的示例代码和几个示例(UART 的"UCAxIV 软件示例"和 I2C 的"UCBxIV 软件示例")、似乎应该以这种方式写入用于串行通信的 ISR。

    谢谢、

    王国新

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="49640" URL"~/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1040183/lp-msp430fr2476-spi-receive "] if (USCI_SPI_UCRXIFG){[/quot]

    是一个简单的常量、因此始终为 true。 它旨在用作状态寄存器的位掩码。 执行该操作或使用 IV 寄存器。

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

    感谢您的回复。 我找到了正确的 MSP430用户指南 slau445I、并且正在正确设置 SPI。 在接下来的2-3天内、我应该了解这一点。 我将保持该线程打开、直到那时。

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

    我需要更多有关设置 SPI 在中断时传输的帮助。 以下是我今天尝试的方法:

    需要将 EUSCI_A1_BASE 设置为 SPI 主器件
    2.从器件在 SPI 模式0 (CPOL=0、CPHA=0)上工作。 SPI 主器件设置是否正确?
    从器件需要一个4引脚 SPI 主器件。 此语句是否会使 CS 变为低电平有效? 这是在初始化 SPI 外设时完成的。
    P3SEL1 |= BIT1;//打开 SPI CS
    4.我正在尝试在 SPI TX 中断上向从器件发送消息。 据我了解、只要 TX 缓冲区准备好发送另一个字节、就会触发 TX 中断。 如何启动该第一个 SPI 传输并使其持续运行? 从器件将在事务9结束时发回一个 GPIO 中断。 使用此代码、我不会获得任何 SPI 发送中断、即使是第一个中断也是如此。

    下周我将得到一个示波器。 但我不确定我是否正确使用了 SPI。

    静态 uint8_t TXData = 0;

    typedef 结构{
    uint8_t len;
    uint8_t *数据;
    } SPI_MaximTrans_t;

    SPI_MaximTrans_t DCInit_事务[15];


    uint8_t i = 0;

    /**
    *根据 IO 引脚的配置初始化所有 IO 引脚
    *
    静态空 init_gpio (void){
    //将所有 GPIO 引脚设置为输出低电平以防止输入悬空并降低功耗
    GPIO_setOutputLowOnPin (GPIO_PORT_P1、GPIO_PIN_All8);
    GPIO_setOutputLowOnPin (GPIO_PORT_P2、GPIO_PIN_All8);
    GPIO_setOutputLowOnPin (GPIO_PORT_P3、GPIO_PIN_All8);
    GPIO_setOutputLowOnPin (GPIO_PORT_P4、GPIO_PIN_All8);
    GPIO_setOutputLowOnPin (GPIO_PORT_P5、GPIO_PIN_All8);
    GPIO_setOutputLowOnPin (GPIO_PORT_P6、GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);

    GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN_All8);
    GPIO_setAsOutputPin (GPIO_PORT_P2、GPIO_PIN_All8);
    GPIO_setAsOutputPin (GPIO_PORT_P3、GPIO_PIN_All8);
    GPIO_setAsOutputPin (GPIO_PORT_P4、GPIO_PIN_All8);
    GPIO_setAsOutputPin (GPIO_PORT_P5、GPIO_PIN_All8);
    GPIO_setAsOutputPin (GPIO_PORT_P6、GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);

    /*
    *初始化 EUSCI A1上的 SPI 外设
    *
    空 init_spi_peripheral()

    //初始化主设备
    EUSCI_A_SPI_initMasterParam param ={0};
    param.selectClockSource = EUSCI_A_SPI_CLOCKSOURCE_SMCLK;
    param.clockSourceFrequency = CS_getSMCLK();
    param.desiredSpiClock = 1000000;
    param.msbFirst = UCMSB;
    param.clockPhase = 0;
    param.clockPolarity = EUSCI_A_SPI_CLOCKPOLARITY_INACT_LOW;
    param.spiMode = EUSCI_A_SPI_4PIN_UCxSTE_ACTIVE_LOW;
    EUSCI_A_SPI_initMaster (EUSCI_A1_base、&param);

    EUSCI_A_SPI_ENABLE (EUSCI_A1_BASE);

    //为 SPI 总线启用 TX 和 RX 中断。
    UCA1IE |=(UCRXIE | UCTXIE);
    P3SEL1 |= BIT1;//打开 SPI CS


    void SetUpTransactions (void){
    //启用保持活动模式
    DCInit_transactions [0].Len = 2;
    DCInit_事务[0].Data[0]= 0x10;
    DCInit_事务[0].Data[1]= 0x5;

    //启用 Rx 中断标志
    DCInit_transactions [1].Len = 2;
    DCInit_transactions [1].Data[0]= 0x4;
    DCInit_transactions [1].Data[1]= 0x88;

    //清除接收缓冲区
    DCInit_transactions [2].Len = 1;
    DCInit_transactions [2].Data[0]= 0xe0;

    //唤醒 UART 从设备
    DCInit_translations[3].len = 2;
    DCInit_transactions [3].Data[0]= 0xe0;
    DCInit_transactions [3].Data[1]= 0x30;

    //等待所有 UART 从设备唤醒
    DCInit_translations[4].len = 1;
    DCInit_transactions [4].Data[0]= 0x01;

    // UART 从器件唤醒周期结束
    DCInit_translations[5].len = 2;
    DCInit_transactions [5]。Data[0]= 0x0E;
    DCInit_transactions [5]。Data[1]= 0x10;

    //等待收到空消息
    DCInit_transactions [6].Len = 1;
    DCInit_transactions [6]。Data[0]= 0x01;

    //清除发送缓冲区
    DCInit_translations[7].len = 1;
    DCInit_transactions [7]。Data[0]= 0x20;

    //清除接收缓冲区
    DCInit_transactions [8].Len = 1;
    DCInit_事务[8].Data[0]= 0xe0;


    /**
    * main.c
    *
    int main (空)

    WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器

    //设置 XT1的外部频率
    cs_setExternalClockSource (32768);

    //选择 XT1作为没有分频器的 SMCLK 的时钟源
    CS_initClockSignal (CS_SMCLK、CS_XT1CLK_select、CS_Clock_divider);

    //Start XT1、无超时
    CS_TurnOnXT1 (CS_XT1_DRIVE_0);

    init_gpio();//设置 IO 引脚


    //将 P1.0设置为输出方向
    GPIO_setAsOutputPin (GPIO_PORT_P1、GPIO_PIN0);
    GPIO_setAsInputPinWithPullUp电 阻器(GPIO_PORT_P4、GPIO_PIN2);
    GPIO_enableInterrupt (GPIO_PORT_P4、GPIO_PIN2);
    GPIO_selectInterruptEdge (GPIO_PORT_P4、GPIO_PIN2、GPIO_HIGH_TO_LOW_TRANSITION);
    GPIO_clearInterrupt (GPIO_PORT_P4、GPIO_PIN2);

    SetUpTransactions();
    TXData = 0x0;//保留事务编号

    //设置外设现在已设置 GPIO 和时钟
    init_spi_peripheral();// Init Maxim SPI 外围设备

    //USCI_A0 TX 缓冲器准备好了吗?
    while (!EUSCI_A_SPI_getInterruptStatus (EUSCI_A0_BASE、
    EUSCI_A_SPI_Transmit 中断);

    //向从器件发送数据
    EUSCI_A_SPI_transmitData (EUSCI_A0_BASE、DCInit_事务[TXData].Data[0]);

    i++;

    //等待从器件初始化
    _DELAY_CYCLES (100);


    //USCI_A0 TX 缓冲器准备好了吗?
    while (!eUSCI_A_SPI_getInterruptStatus (eUSCI_A1_base、
    EUSCI_A_SPI_Transmit 中断);

    _bis_SR_register (LPM0_bits + GIE);// CPU 关闭、启用中断
    _NO_OPERATION ();//保持在 LPM0中


    返回0;

    //
    //
    //这是 port2_vector 中断矢量服务例程
    //
    //
    #if defined (__TI_Compiler_version__)|| Defined (__IAR_systems_ICC__)
    #pragma vector=Port4_vector
    _interrupt
    #Elif defined (_GNU_)
    __attribute__((interrupt (port2_vector)))
    #endif
    void P4_ISR (void)

    GPIO_clearInterrupt (GPIO_PORT_P4、GPIO_PIN2);
    //切换 P1.0输出
    GPIO_toggleOutputOnPin (GPIO_PORT_P1、GPIO_PIN0);


    /
    * EUSCI_A1_ISR ()
    *
    *此中断用于 SPI 中断(UCA1)。
    秘书长的报告 /
    #pragma vector = USCI_A1_vector
    _interrupt void EUSCI_A1_ISR (void)

    // SPI TX 中断?
    IF (UCA1IFG 和 UCTXIFG)

    while (i < DCInit_事务[TXData].Len){
    EUSCI_A_SPI_transmitData (EUSCI_A1_base、DCInit_事务[TXData].Data[i]);
    i++;

    if (i == DCInit_translations[TXData].Len){
    UCA1IE &=~UCTXIE;
    I = 0;
    TXData++;

    /*将要发送的新字节放入 TX 缓冲区。
    *这可以防止我们填充额外的字节。
    ***** /

    /*禁用 TX 中断。 最后一个字节开始
    *已发送、请禁用 TX 中断。 如果未完成此操作、
    * ISR 将在时间间隔内重复调用
    * UCA1TXBUF 为空的时间和接收的时间
    *字节在 UCA1RXBUF 中可用。
    ***** /


    如果(TXData = 8)

    //重置 EUSCIA1 (这将禁用 RX 和 TX 中断。
    UCA1CTLW0 |= UCSWRST;

    /*将 SPI 芯片选择输入转换为常规输入引脚,因此
    *主程序可以检查 SPI CS 之前是否有效
    *重新启用 SPI 总线。 对于 GPIO 和、P1SEL1保持为0
    * SPI 功能。
    ***** /
    P3SEL1 &=~BIT1;


    /*如果 RX 和 TX 均已完成、请关闭 SPI 接口。
    *主程序在完成后将其重新打开
    *处理邮件。
    ***** /


    _DELAY_CYCLES (40);

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

    P3SEL 将该引脚配置为用作 SPI 从器件。 它是输入、而不是输出。 对于 CS 信号、只需使用您选择的常规 GPIO 即可。

    TXIFG 在复位期间被置位、所以我必须假定驱动程序库被清零、否则一旦你置位 TXIE、中断就会发生。 您可以自行设置、以启动传输过程。 (UCA1IFG |= UCTXIFG;)

    启动一个中断驱动的串行传输总是很复杂的。 关闭它。 有时、您可以通过禁用发送中断将其关闭、而启动中断将启用它。 这是我通常对 MSP430执行的操作。

    哦、请使用插入代码功能、以便您的代码显示在可滚动子窗口中、而不是仅在和上运行。

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

    SPI TX 中断现在被触发。 但是、我的某些事务值的长度为16位- X88、xe0。 如何使用 EUSCI_SPI_transmitData 函数发送此消息?

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

    while (i < DCInit_transactions[TXData].Len){
      EUSCI_A_SPI_transmitData(EUSCI_A1_BASE, DCInit_transactions[TXData].Data[i]);
      i++;
    }

    通常、每个 TXIFG 只允许您向 TXBUF 发送一个字节。 我想您只需删除 while ():

       EUSCI_A_SPI_transmitData(EUSCI_A1_BASE, DCInit_transactions[TXData].Data[i]);
       i++;

    ----------

    if (TXData == 8)
    {
       UCA1CTLW0 |= UCSWRST;
       P3SEL1 &= ~BIT1;
    }

    这可能 会在发送最后一个 Tx 字节之前使/CS 无效。 等待 SPI 不再忙(不会花费太长的时间):

    if (TXData == 8)
    {
       while (UCA1STATW & UCBUSY)/*EMPTY*/;  // Wait for last byte to complete
       UCA1CTLW0 |= UCSWRST;
       P3SEL1 &= ~BIT1;
    }

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

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    
    #include <driverlib.h>
    #include <msp430.h> 
    #include "clock~.h"                 // Clock configurations
    
    
    static uint8_t TXData = 0;
    
    typedef struct {
        uint8_t     Len;
        uint16_t    Data[5];
    } spi_MaximTrans_t;
    
    static spi_MaximTrans_t DCInit_transactions[15];
    
    
    uint8_t i = 0;
    
    /**
     *  Initialize system clocks
     */
    static void init_clock(void) {
        // Configure one FRAM waitstate as required by the device datasheet for MCLK
        // operation beyond 8MHz _before_ configuring the clock system.
        FRAMCtl_configureWaitStateControl(FRAMCTL_ACCESS_TIME_CYCLES_1);
    
        //Set DCO FLL reference = REFO
        CS_initClockSignal(CS_FLLREF, CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
        //Set ACLK = REFO
        CS_initClockSignal(CS_ACLK,   CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
    
        CS_initFLLParam param = {0};
        //Set Ratio/Desired MCLK Frequency, initialize DCO, save trim values
        CS_initFLLCalculateTrim(CS_MCLK_DESIRED_FREQUENCY_IN_KHZ, CS_MCLK_FLLREF_RATIO, &param);
    
        //Set MCLK = REFO
        CS_initClockSignal(CS_MCLK,   CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
        //Set SMCLK = DCO
        CS_initClockSignal(CS_SMCLK,  CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);
    
        //Clear all OSC fault flag
        CS_clearAllOscFlagsWithTimeout(1000);
    }
    
    /**
     *  Initialize all of the IO pins per their configuration
     */
    static void init_gpio(void) {
        // Set all GPIO pins to output low to prevent floating input and reduce power consumption
        GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN0|GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5|GPIO_PIN6|GPIO_PIN7);
        GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
    
        GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
    
        GPIO_setAsOutputPin(   GPIO_PORT_P1, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P2, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P3, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P4, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P5, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
    }
    
    /*
     * Initialize the SPI peripheral on EUSCI A1
     */
    void init_spi_peripheral()
    {
        //Initialize Master
            EUSCI_A_SPI_initMasterParam param = {0};
            param.selectClockSource = EUSCI_A_SPI_CLOCKSOURCE_SMCLK;
            param.clockSourceFrequency = CS_getSMCLK();
            param.desiredSpiClock = 1000000;
            param.msbFirst = UCMSB;
            param.clockPhase = 0;
            param.clockPolarity = EUSCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
            param.spiMode = EUSCI_A_SPI_4PIN_UCxSTE_ACTIVE_LOW;
            EUSCI_A_SPI_initMaster(EUSCI_A1_BASE, &param);
    
            EUSCI_A_SPI_enable(EUSCI_A1_BASE);
    
            // Enable the TX and RX interrupts for the SPI bus.
            UCA1IE |= (UCRXIE | UCTXIE);
    
    }
    
    
    void SetUpTransactions(void){
        //Enable keep alive mode
        DCInit_transactions[0].Len = 2;
        DCInit_transactions[0].Data[0] = 0x10;
        DCInit_transactions[0].Data[1] = 0x5;
    
        //Enable Rx Interrupt flags
        DCInit_transactions[1].Len = 2;
        DCInit_transactions[1].Data[0] = 0x4;
        DCInit_transactions[1].Data[1] = 0x88;
    
        //Clear receive buffer
        DCInit_transactions[2].Len = 1;
        DCInit_transactions[2].Data[0] = 0xe0;
    
        //Wakeup UART slave devices
        DCInit_transactions[3].Len = 2;
        DCInit_transactions[3].Data[0] = 0xe0;
        DCInit_transactions[3].Data[1] = 0x30;
    
        //Wait for all UART slave devices to wake up
        DCInit_transactions[4].Len = 1;
        DCInit_transactions[4].Data[0] = 0x01;
    
        //End of UART slave device wake-up period
        DCInit_transactions[5].Len = 2;
        DCInit_transactions[5].Data[0] = 0x0e;
        DCInit_transactions[5].Data[1] = 0x10;
    
        //Wait for null message to be received
        DCInit_transactions[6].Len = 1;
        DCInit_transactions[6].Data[0] = 0x01;
    
        //Clear transmit buffer
        DCInit_transactions[7].Len = 1;
        DCInit_transactions[7].Data[0] = 0x20;
    
        //Clear receive buffer
        DCInit_transactions[8].Len = 1;
        DCInit_transactions[8].Data[0] = 0xe0;
    
    }
    
    
    /**
     * main.c
     */
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	
    
        init_clock();
        init_gpio();                                    // Set up IO pins
    
    
        // Set P1.0 to output direction
    
        GPIO_setAsOutputPin (GPIO_PORT_P1, GPIO_PIN0);
        GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P4, GPIO_PIN2);
        GPIO_enableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
        GPIO_selectInterruptEdge (GPIO_PORT_P4, GPIO_PIN2, GPIO_HIGH_TO_LOW_TRANSITION);
        GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    
        SetUpTransactions();
        TXData = 0x0;                             // Holds transaction number
    
    
    
        // Setup peripheral(s) now that gpio and clocks are setup
        init_spi_peripheral();                      // Init Maxim spi peripheral
        //Wait for slave to initialize
            __delay_cycles(100);
    
        GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN1);        //Maxim chip select low
        UCA1IFG |= UCTXIFG;
    
    
    
        __bis_SR_register(LPM0_bits + GIE);      // CPU off, enable interrupts
        __no_operation();                       // Remain in LPM0
    
    
    	return 0;
    }
    
    //******************************************************************************
    //
    //This is the PORT2_VECTOR interrupt vector service routine
    //
    //******************************************************************************
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=PORT4_VECTOR
    __interrupt
    #elif defined(__GNUC__)
    __attribute__((interrupt(PORT2_VECTOR)))
    #endif
    void P4_ISR (void)
    {
        GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
        // Toggle P1.0 output
        GPIO_toggleOutputOnPin (GPIO_PORT_P1, GPIO_PIN0);
    }
    
    
    /****************************************************************************
     * EUSCI_A1_isr()
     *
     * This interrupt is used for SPI interrupts (UCA1).
     ****************************************************************************/
    #pragma vector = EUSCI_A1_VECTOR
    __interrupt void EUSCI_A1_isr(void)
    {
        // SPI TX interrupt?
        if (UCA1IFG & UCTXIFG)
        {
    
            EUSCI_A_SPI_transmitData(EUSCI_A1_BASE, DCInit_transactions[TXData].Data[i]);
            i++;
    
            if (i == DCInit_transactions[TXData].Len){
                UCA1IE &= ~UCTXIE;
                i = 0;
                TXData = TXData+1;
                if (TXData == 9) {
                    while (UCA1STATW & UCBUSY);     //wait for the last byte to transmit
                              // Reset EUSCIA1 (this disables RX & TX interrupts.
                    UCA1CTLW0 |= UCSWRST;
    
                          /* Turn the SPI Chip Select input into a regular input pin so the
                           * main program can check that the SPI CS is not asserted before
                           * re-enabling the SPI bus.  P1SEL1 remains 0 for both the GPIO and
                           * SPI functionality. *****/
    
                    GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
                 }
            }
            if (TXData < 9)
                UCA1IFG |= UCTXIFG;
    
            /* Put a new byte to send into the TX buffer.
             * This prevents us from stuffing an extra byte.
             *****/
    
                /* Disable the TX interrupt.  Since the last byte of the message
                 * has been sent, disable the TX interrupt.  If this is not done,
                 * the ISR will be repeatedly invoked between the time that the
                 * time that the UCA1TXBUF is empty and the time that the receive
                 * byte is available in UCA1RXBUF.
                 *****/
    
    
    
         }
    
    
        /* If both the RX & TX have completed, turn off the SPI interface.
         * The main program will turn it back on after it is finished
         * processing the message.
         *****/
    
    
        __delay_cycles(40);
    }
    
    
    

    感谢您的回复。 我的当前代码粘贴到此帖子。 我对以下交易感到关切:

    DCInit_transactions [1].Data[1]= 0x88;

    EUSCI_A_SPI_transmitData (EUSCI_A1_base、DCInit_事务[TXData].Data[i]);

    EUSCI_A_SPI_transmitData 需要8位数据、而0x88是16位。  

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

    常量0x88只有8位长。 浏览您的程序时、我看不到任何超过8位的此类常量。

    如果您的器件希望这些8位常量在总线上作为16位值发送、最简单的方法可能是将 Len 字段加倍并显式插入高位0x00字节。 (有关字节排序、请查看器件数据表。)

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

    是的、没有超过8位的内容、我感到困惑。 由于某种原因、SPI 事务尚未正常工作。

    我将在本周末获得一个示波器。 我将使用示波器进一步进行故障排除并返回。 我将保持该线程打开、直到那时。

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

    您如何判断交易不起作用?  您的程序是否挂起? 或者器件的工作状态是否未达到预期? (是的、对于这样的情况、示波器非常方便。)

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

    我希望 SPI 外设板上的 LED 在唤醒结束时亮起。 当我使用他们的评估 GUI 时会发生这种情况。 我需要查看示波器信号以了解正在发生的情况。

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

    我得到了示波器。 此时、我仅查看 LP SPI 输出信号。 我没有连接任何从器件。 我需要在   配置 GPIO 的末尾添加 PMM_unlockLPM5()。 只有在这之后、我才能看到 CS 转换为正确的值。 但是、我在示波器上看不到 SPI 时钟。 这是为什么? 我随附了我的当前代码供您参考、自我上一篇文章以来、它没有发生太大变化。

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    
    #include <driverlib.h>
    #include <msp430.h> 
    #include "clock~.h"                 // Clock configurations
    
    
    static uint8_t TXData = 0;
    
    typedef struct {
        uint8_t     Len;
        uint8_t    Data[5];
    } spi_MaximTrans_t;
    
    static spi_MaximTrans_t DCInit_transactions[15];
    
    
    uint8_t SPI_TX_index = 0;
    
    /**
     *  Initialize system clocks
     */
    static void init_clock(void) {
        // Configure one FRAM waitstate as required by the device datasheet for MCLK
        // operation beyond 8MHz _before_ configuring the clock system.
        FRAMCtl_configureWaitStateControl(FRAMCTL_ACCESS_TIME_CYCLES_1);
    
        //Set DCO FLL reference = REFO
        CS_initClockSignal(CS_FLLREF, CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
        //Set ACLK = REFO
        CS_initClockSignal(CS_ACLK,   CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
    
        CS_initFLLParam param = {0};
        //Set Ratio/Desired MCLK Frequency, initialize DCO, save trim values
        CS_initFLLCalculateTrim(CS_MCLK_DESIRED_FREQUENCY_IN_KHZ, CS_MCLK_FLLREF_RATIO, &param);
    
        //Set MCLK = REFO
        CS_initClockSignal(CS_MCLK,   CS_REFOCLK_SELECT,   CS_CLOCK_DIVIDER_1);
        //Set SMCLK = DCO
        CS_initClockSignal(CS_SMCLK,  CS_DCOCLKDIV_SELECT, CS_CLOCK_DIVIDER_1);
    
        //Clear all OSC fault flag
        CS_clearAllOscFlagsWithTimeout(1000);
    }
    
    /**
     *  Initialize all of the IO pins per their configuration
     */
    static void init_gpio(void) {
        // Set all GPIO pins to output low to prevent floating input and reduce power consumption
        GPIO_setOutputLowOnPin(GPIO_PORT_P1, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P4, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P5, GPIO_PIN_ALL8);
        GPIO_setOutputLowOnPin(GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
    
    
    
    
    
        GPIO_setAsOutputPin(   GPIO_PORT_P1, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P2, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P3, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P4, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P5, GPIO_PIN_ALL8);
        GPIO_setAsOutputPin(   GPIO_PORT_P6, GPIO_PIN0 | GPIO_PIN1 | GPIO_PIN2);
    
    
    
    }
    
    /*
     * Initialize the SPI peripheral on EUSCI A1
     */
    void init_spi_peripheral()
    {
        //Initialize Master
            EUSCI_A_SPI_initMasterParam param = {0};
            param.selectClockSource = EUSCI_A_SPI_CLOCKSOURCE_SMCLK;
            param.clockSourceFrequency = CS_getSMCLK();
            param.desiredSpiClock = 1000000;
            param.msbFirst = UCMSB;
            param.clockPhase = 0;
            param.clockPolarity = EUSCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW;
            param.spiMode = EUSCI_A_SPI_4PIN_UCxSTE_ACTIVE_LOW;
            EUSCI_A_SPI_initMaster(EUSCI_A1_BASE, &param);
    
            EUSCI_A_SPI_enable(EUSCI_A1_BASE);
    
            // Enable the TX and RX interrupts for the SPI bus.
            EUSCI_A_SPI_enableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_TRANSMIT_INTERRUPT);
            EUSCI_A_SPI_enableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_RECEIVE_INTERRUPT);
    
    }
    
    
    void SetUpTransactions(void){
        //Enable keep alive mode
        DCInit_transactions[0].Len = 2;
        DCInit_transactions[0].Data[0] = 0x10;
        DCInit_transactions[0].Data[1] = 0x5;
    
        //Enable Rx Interrupt flags
        DCInit_transactions[1].Len = 2;
        DCInit_transactions[1].Data[0] = 0x4;
        DCInit_transactions[1].Data[1] = 0x88;
    
        //Clear receive buffer
        DCInit_transactions[2].Len = 1;
        DCInit_transactions[2].Data[0] = 0xe0;
    
        //Wakeup UART slave devices
        DCInit_transactions[3].Len = 2;
        DCInit_transactions[3].Data[0] = 0xe0;
        DCInit_transactions[3].Data[1] = 0x30;
    
        //Wait for all UART slave devices to wake up
        DCInit_transactions[4].Len = 1;
        DCInit_transactions[4].Data[0] = 0x01;
    
        //End of UART slave device wake-up period
        DCInit_transactions[5].Len = 2;
        DCInit_transactions[5].Data[0] = 0x0e;
        DCInit_transactions[5].Data[1] = 0x10;
    
        //Wait for null message to be received
        DCInit_transactions[6].Len = 1;
        DCInit_transactions[6].Data[0] = 0x01;
    
        //Clear transmit buffer
        DCInit_transactions[7].Len = 1;
        DCInit_transactions[7].Data[0] = 0x20;
    
        //Clear receive buffer
        DCInit_transactions[8].Len = 1;
        DCInit_transactions[8].Data[0] = 0xe0;
    
    }
    
    
    /**
     * main.c
     */
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	
    
        init_clock();
        init_gpio();                                    // Set up IO pins
    
        GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
    
        // Configure SPI Pins for UCA1CLK, UCA1TXD/UCA1SIMO and UCA1RXD/UCA1SOMI
        /*
        * Select Port 2
        * Set Pin 4, Pin 5 and Pin 6 to input Secondary Module Function
        */
        GPIO_setAsPeripheralModuleFunctionInputPin(
            GPIO_PORT_P2,
            GPIO_PIN4 + GPIO_PIN5 + GPIO_PIN6,
            GPIO_PRIMARY_MODULE_FUNCTION
        );
    
        // Set P1.0 to output direction
    
        GPIO_setAsOutputPin (GPIO_PORT_P1, GPIO_PIN0);
        GPIO_setAsInputPinWithPullUpResistor (GPIO_PORT_P4, GPIO_PIN2);
        GPIO_enableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
        GPIO_selectInterruptEdge (GPIO_PORT_P4, GPIO_PIN2, GPIO_HIGH_TO_LOW_TRANSITION);
        GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    
        PMM_unlockLPM5();
    
        SetUpTransactions();
        TXData = 0x0;                             // Holds transaction number
    
    
        // Setup peripheral(s) now that gpio and clocks are setup
        init_spi_peripheral();                      // Init Maxim spi peripheral
        //Wait for slave to initialize
            __delay_cycles(100);
    
        GPIO_setOutputLowOnPin(GPIO_PORT_P3, GPIO_PIN1);        //Maxim chip select low
        UCA1IFG |= UCTXIFG;
    
    
    
        __bis_SR_register(LPM0_bits + GIE);      // CPU off, enable interrupts
        __no_operation();                       // Remain in LPM0
    
    
    	return 0;
    }
    
    //******************************************************************************
    //
    //This is the PORT2_VECTOR interrupt vector service routine
    //
    //******************************************************************************
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=PORT4_VECTOR
    __interrupt
    #elif defined(__GNUC__)
    __attribute__((interrupt(PORT2_VECTOR)))
    #endif
    void P4_ISR (void)
    {
        GPIO_setOutputHighOnPin(GPIO_PORT_P3, GPIO_PIN1);
        GPIO_clearInterrupt (GPIO_PORT_P4, GPIO_PIN2);
        // Toggle P1.0 output
        GPIO_toggleOutputOnPin (GPIO_PORT_P1, GPIO_PIN0);
    
        GPIO_disableInterrupt (GPIO_PORT_P4, GPIO_PIN2);
    }
    
    
    /****************************************************************************
     * EUSCI_A1_isr()
     *
     * This interrupt is used for SPI interrupts (UCA1).
     ****************************************************************************/
    #pragma vector = EUSCI_A1_VECTOR
    __interrupt void EUSCI_A1_isr(void)
    {
        // SPI TX interrupt?
        if (UCA1IFG & UCTXIFG)
        {
    
            EUSCI_A_SPI_transmitData(EUSCI_A1_BASE, DCInit_transactions[TXData].Data[SPI_TX_index]);
            SPI_TX_index++;
    
            if (SPI_TX_index == DCInit_transactions[TXData].Len){
                EUSCI_A_SPI_disableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_TRANSMIT_INTERRUPT);
                SPI_TX_index = 0;
                TXData = TXData+1;
                if (TXData == 9) {
                    while (UCA1STATW & UCBUSY);     //wait for the last byte to transmit
                              // Reset EUSCIA1 (this disables RX & TX interrupts.
                    EUSCI_A_SPI_disableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_TRANSMIT_INTERRUPT);
                    EUSCI_A_SPI_disableInterrupt(EUSCI_A1_BASE, EUSCI_A_SPI_RECEIVE_INTERRUPT);
    
                          /* Turn the SPI Chip Select input into a regular input pin so the
                           * main program can check that the SPI CS is not asserted before
                           * re-enabling the SPI bus.  P1SEL1 remains 0 for both the GPIO and
                           * SPI functionality. *****/
    
    
                 }
            }
            if (TXData < 9)
                UCA1IFG |= UCTXIFG;
    
            /* Put a new byte to send into the TX buffer.
             * This prevents us from stuffing an extra byte.
             *****/
    
                /* Disable the TX interrupt.  Since the last byte of the message
                 * has been sent, disable the TX interrupt.  If this is not done,
                 * the ISR will be repeatedly invoked between the time that the
                 * time that the UCA1TXBUF is empty and the time that the receive
                 * byte is available in UCA1RXBUF.
                 *****/
    
    
    
         }
    
    
        /* If both the RX & TX have completed, turn off the SPI interface.
         * The main program will turn it back on after it is finished
         * processing the message.
         *****/
    
    }
    
    
    

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

    >param.spiMode = EUSCI_A_SPI_4PIN_UCxSTE_ACTIVE_LOW;

    由于您不使用 STE 引脚、因此这会在每个字节上生成 UCFE [参考用户指南(SLAU445I)第23.3.1]节。 这就是您看不到任何时钟的原因。 请改用:

    >param.spiMode = eUSCI_A_SPI_3pin; // 3引脚模式--我们处理/CS

    ------------

    >IF (TXData < 9)
    > UCA1IFG |= UCTXIFG;

    您不应在此处人为触发 TXIFG、因为该字节(很可能)尚未发送。 只需删除这些行。

    ------------

    > if (SPI_TX_INDEX = DCInit_事务[TXData].Len){
    >  EUSCI_A_SPI_DisableInterrupt (EUSCI_A1_base、EUSCI_A_SPI_Transmit 中断);

    这会在第一个块之后禁用 TXIE、这太不方便了。 只需删除第二行。 (它将在下面的几行中、在正确的时间完成。)

    ------------

    > EUSCI_A_SPI_enableInterrupt (EUSCI_A1_base、EUSCI_A_SPI_receive_interrupt);

    您不使用 RXIFG、因此不应启用它。 只需删除此行。

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

    这大大改进了 SPI 信号。 在从器件初始化期间、我可能仍需要等待其中一个事务。 我将更仔细地查看外设寄存器。 感谢你的帮助。