embedded - 每次 SPI 发送都会导致 MSP430 上接收到 0

标签 embedded microcontroller spi msp430 texas-instruments

我运行这个用于 SPI 通信的简化程序,在 TI MSP430FR5969 的相应启动板 MSP-EXP430FR5969 上运行,并在 CCS (Code Composer Studio) 中的 TX 之前和 RX 之后设置断点。断点带有注释标记。

我的启动板未连接到任何东西。 (一旦我弄清楚了这一点,我打算将其传递给其他一些设备以进行真正的通信。)

我预计不会收到任何数据,因为启动板未连接到任何东西。但每次发送我都会收到恰好一个零。从第一个 TX 断点开始,以交替顺序命中断点。

为什么我会收到数据?是因为我需要在某些引脚上启用上拉寄存器吗?我相信启动板本身使用 USCI“A”模块,因此我使用的“B”模块应该没有任何连接。

#include <msp430.h>

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;

    P1SEL0 &= ~BIT3; // UCB0STE
    P1SEL0 &= ~BIT6; // UCB0SIMO
    P1SEL0 &= ~BIT7; // UCB0SOMI
    P2SEL0 &= ~BIT2; // UCB0CLK

    P1SEL1 |= BIT3;  // UCB0STE
    P1SEL1 |= BIT6;  // UCB0SIMO
    P1SEL1 |= BIT7;  // UCB0SOMI
    P2SEL1 |= BIT2;  // UCB0CLK

    PM5CTL0 &= ~LOCKLPM5;

    CSCTL0_H = CSKEY_H;
    CSCTL1 &= ~DCORSEL;
    CSCTL1 = (CSCTL1 & ~0x000e) | DCOFSEL_0; // 1 MHz
    CSCTL3 |= DIVA__1 | DIVS__1 | DIVM__1; // clock dividers = 1
    CSCTL0_H = 0;

    UCB0CTLW0 |= UCSWRST;
    UCB0CTLW0 |= UCCKPH;
    UCB0CTLW0 |= UCCKPL;
    UCB0CTLW0 |= UCMSB;
    UCB0CTLW0 |= UCMST;
    UCB0CTLW0 |= UCMODE_2;
    UCB0CTLW0 |= UCSYNC;
    UCB0CTLW0 |= UCSSEL__SMCLK;
    UCB0CTLW0 |= UCSTEM;
    // UCB0STATW |= UCLISTEN; // OK, if enabled i receive what i send
    UCB0CTLW0 &= ~UCSWRST;

    UCB0IE |= UCRXIE;

    _enable_interrupts();

    _delay_cycles(100000);
    int send = 0;
    while (1) {
        while (!(UCB0IFG & UCTXIFG));
        UCB0TXBUF = send;  // BREAKPOINT 1
        send = (send + 1) % 100;
        _delay_cycles(100000);
    }

    return 0;
}

#pragma vector = USCI_B0_VECTOR
__interrupt void isr_usci_b0 (void) {
    static volatile int received = 0;
    switch (__even_in_range(UCB0IV, USCI_SPI_UCTXIFG)) {
    case USCI_NONE:
        break;
    case USCI_SPI_UCRXIFG:
        received = UCB0RXBUF;
        UCB0IFG &= ~UCRXIFG;  // BREAKPOINT 2
        _no_operation();
        break;
    case USCI_SPI_UCTXIFG:
        break;
    }
}

最佳答案

如果 MISO 和 MOSI 启用(当然,CLK 也启用),SPI 外设会执行两件事。假设在主模式操作下,它从 MOSI 线上的 TX 移位寄存器输出数据,同时从 MISO 线上将数据输入到 RX 移位寄存器。

在您的电路中,MISO 输入悬空,因为您没有启用上拉或下拉内部电阻。因此,观察 0x00 并不奇怪。如果您启用了上拉电阻,那么您会在接收缓冲区中看到 0xFF。

另一个经验法则: 如果您使用外设功能,则将 MSP430 的 GPIO 引脚配置为输出/输入。 (即 MOSI、CLK = 输出、MISO = SPI 主模式的输入)

回答评论中的问题:

MSP430 在列出的代码中配置为 SPI 主设备。我认为使用专用的 RX 中断服务例程没有什么意义,除非您希望 Controller 在将数据从 TX 缓冲区移位到移位寄存器和将数据从 RX 移位寄存器移位到 RX 缓冲区之间的时间内执行其他操作,即一个“字节”传输周期。您也可以像轮询 TX 中断一样轮询 RX 中断。但必须等待RX中断。

用户指南摘录:

The eUSCI initiates data transfer when data is moved to the transmit data buffer UCxTXBUF. The UCxTXBUF data is moved to the transmit (TX) shift register when the TX shift register is empty, initiating data transfer on UCxSIMO starting with either the MSB or LSB, depending on the UCMSB setting. Data on UCxSOMI is shifted into the receive shift register on the opposite clock edge. When the character is received, the receive data is moved from the receive (RX) shift register to the received data buffer UCxRXBUF and the receive interrupt flag UCRXIFG is set, indicating the RX/TX operation is complete. A set transmit interrupt flag, UCTXIFG, indicates that data has moved from UCxTXBUF to the TX shift register and UCxTXBUF is ready for new data. It does not indicate RX/TX completion. To receive data into the eUSCI in master mode, data must be written to UCxTXBUF, because receive and transmit operations operate concurrently.

客户端不会自行向MSP430发送数据。客户端设备可能需要一些时间来执行主设备刚刚发送的命令。通常是 SPI 闪存芯片的“删除闪存”命令。

在这种情况下,主设备(即 MSP430)必须轮询客户端设备以查看它是否有数据要发送/完成命令。这通常通过轮询客户端设备的状态寄存器(或通过使用专用 IRQ 中断)来完成。即客户端通过状态字节(或 IRQ 中断)发出“命令完成”/“数据可用性”信号。在这种情况下,主机可以从客户端读取数据。

乍一看,需要写入数据(虚拟字节)才能读取数据,这似乎相当违反直觉 - 也许也是您混淆的根源:)

也许阅读有关 SPI 客户端的内容可能会有所帮助。例如this SPI memory .

关于embedded - 每次 SPI 发送都会导致 MSP430 上接收到 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24966501/

相关文章:

linux - Snapdragon 810 上的启动配置 DIP 开关

c - 带 C 代码的 4 位 LCD

c - 为什么 Timer1 不在 PIC18 上计数?

embedded - STM32 SPI 慢速计算

c - STM32 : FatFs Library - f_mount

c - 日常机器是如何编程的?

embedded - 嵌入式代码示例的用例图

c - 解析循环缓冲区

c - c编程中两个ASCII值的相加

c - STM32F4 SPI问题