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.

[参考译文] RTOS/MSP430F5438A:SPI代码问题... UCB1RXBUF始终为零

Guru**** 2595800 points


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

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/666930/rtos-msp430f5438a-spi-code-problem-ucb1rxbuf-always-zero

部件号:MSP430F5438A

工具/软件:TI-RTOS

我在为MSP430编写SPI代码以与闪存芯片通信时遇到问题。

我尝试编写轮询例程和中断ISR,结果是相同的。  无论我尝试什么,UCB1RXBUF始终为零。

以下是我的init例程:

void hal SPI初始化(void)
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//下面是所有相关的IO引脚:
// FLASH_SS 3.6 UCB1STE/CS# (低有效)
// FLASH_MOSI 3.7 UCB1SIMO/SI
// 闪烁_错误 5.4 UCB1SOMI/SO
// FLASH_SCLK 5.5 UCB1CLK/SCK

P3DIR || FLASH_SS; // WFP 3.6 FLASH_SS是一个输出引脚
P3OUT |= FLASH_SS; //活动低电平,(禁用)

//设置MOSI (WFP 3.7),Miso (WFP 5.4),SCLK (WFP 5.5)的特殊模式
GPIO_setAsPeripheralModuleFunctionOutputPin (GPIO端口P3,FLASH_MOSI);
GPIO_setAsPeripheralModuleFunctionInputPin (GPIO端口P5,FLASH_miso);
GPIO_setAsPeripheralModuleFunctionOutputPin (GPIO端口P5,FLASH_SCLK);

//在主模式下初始化SPI
USI_B_SPI_initMasterParam参数={0};
param.selectClockSource = USI_B_SPI_CLOCKSOURCE_SMCLK;
Param.clockSourceFrequency = UCS_getSMCLK();
param.desiredSpiClock = 100万;
Param.msbFirst = USI_B_SPI_MSB_FIRST;
Param.clockPhase = USI_B_SPI_PHASE DATA_Captured_ONFIRST_changed_on_next;
Param.clockPolarity = USI_B_SPI_CLOCKPOLARITY_INACILY_LOW; //或USI_B_SPI_CLOCKPOLARITY_INACILY_HIGH;
布尔RC = USI_B_SPI_initMaster(USCI_B1_base,&param);
断言(rc == status_success);

//启用SPI模块
USI_B_SPI_ENABLE (USI_B1_BASE);

//禁用中断
USI_B_SPI_clearInterrupt (USI_B1_BASE,
USI_B_SPI_receive中断|USI_B_SPI_Transmit_interrupt);
USI_B_SPI_DisableInterrupt (USI_B1_BASE,
USI_B_SPI_Receive_interrup|USI_B_SPI_Transmit_interrupt);
}

接下来是SPI_TRANSFER例程:

void hal_spi_transfer(.
uINT8_t *txbuf,uint8_t *rxbuf,size_t txlen,uint8_t flags)
{
IF (标志和SPI_CS_ENABLE)
flash_ss_active();

//启动第一个字节传输
对于(; txlen;--txrxlen){

UINT8_t Tbyte = txbuf ? *txbuf++:0;

// USCI_B_SPI_TRICATEData(USCI_B1_BASE,Tbyte);
UCB1TXBUF = Tbyte;
UCB1IFG &=~UCRXIFG; // Clear RXIFG as Transmit (将RXIFG清除为传输)始终设置RX标记

//等待直到接收到RX字节
同时(!(UCB1IFG和UCRXIFG))
;

UINT8_t rbyte = UCB1RXBUF; // USI_B_SPI_receiveData(USCI_B1_base);

IF (rambuf !=空)
*rxbuf++= rbyte;
}

IF (标志和SPI_CS_DISABLE)
flash_ss_inactive();
} 

调用此例程时,仅读取零。

在逻辑分析器上,我可以看到数据在SPI总线上是正确的。   在以下示例中,我们发送flash_readid命令(hex 9F),然后读取芯片配置信息的0x56字节:

   HAL_SPI_SEND_BYTE (FLASH_READIDSPI_CS_ENABLE);
   HAL_SPI_TRANSFER (NULL,FLASH_CFI,FLASH_CFI,SPI_CS_DISABLE的大小);

在逻辑分析器上,我们可以看到所有SPI数据:

我们可以在蓝线(探测器6)上看到闪存芯片收到了命令并正在返回CFI数据。   我可以放大并检查数据,它是绝对正确的。

我还在CPU引脚(引脚51)上放置了示波器探头,结果相同。  电压水平看起来正常 (3V左右)。

但是,'flash_CFI[]'阵列始终为零。

是否可能是我的硬件损坏,SPI接收器不工作?

-Allan Schwartz

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

    为了进一步澄清这个问题,我刚刚在SPI_TRANSFER内部环路的3个关键点对代码进行了闪存测试信号:

    void hal_spi_transfer(.
    uINT8_t *txbuf,uint8_t *rxbuf,size_t txlen,uint8_t flags)
    {
    断言(txrxlen > 0);
    
    IF (标志和SPI_CS_ENABLE)
    flash_ss_active();
    
    //启动第一个字节传输
    对于(; txlen;--txrxlen){
    
    UINT8_t Tbyte = 0;
    IF (txbuf != NULL)
    Tbyte =*txbuf++;
    
    // USCI_B_SPI_TRICATEData(USCI_B1_BASE,Tbyte);
    green_LEDs_on();green_LEDs_off();
    UCB1TXBUF = Tbyte;
    UCB1IFG &=~UCRXIFG; // Clear RXIFG as Transmit (将RXIFG清除为传输)始终设置RX标记
    while ((UCB1IFG和UCTXIFG)== 0)
    ;
    blue_led_on(); blue_led_off();
    
    //等待直到接收到RX字节
    同时(!(UCB1IFG和UCRXIFG))
    ;
    
    Red_LED_on();Red_LED_off();
    UINT8_t rbyte = UCB1RXBUF; // USI_B_SPI_receiveData(USCI_B1_base);
    
    IF (rambuf !=空)
    *rxbuf++= rbyte;
    }
    
    IF (标志和SPI_CS_DISABLE)
    flash_ss_inactive();
    }
    

    因此,绿色LED指示灯在TXBUF填充之前闪烁。  当TXBUF可用时,蓝色LED会闪烁,因为它已传输到内部移位寄存器。  当RXIFG被确认时,红色LED闪烁,表示RXBUF已就绪。   以下是逻辑分析器上的外观(请注意,所有信号都标在左侧):

    (仅放大传输的前三个字节)

    正时标记A1标记了TXBUF的写入位置。   和正时标记A2标记读取RXBUF的位置。   它看起来是正确的时间。   但是,RXBUF始终为零。

    有人有什么想法吗?

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

    您好,Allan:

    感谢您提供有关您观察到的问题的详细信息。 您的代码似乎正在正确读取和写入USI_B1寄存器。 在从UCB1RXBUF读取并查看rbyte值时,是否可以使用调试器来放置断点?

    我还看到DriverLib API指南提到MSP430F5xx/6xx不支持GPIO_setAsPeripheralModuleFunctionInputPin和GPIO_setAsPeripheralModuleFunctionOutputPin函数的功能模式:

    http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSP430_Driver_Library/latest/exports/driverlib/msp430_driverlib_2_91_03_00/doc/MSP430F5xx_6xx/html/group__gpio__api.html#gaedffb91ddac0949fcbb73fbc3636b62a</s>3636

    您是否可以尝试直接对GPIO寄存器进行编程以确保正确设置SOMI引脚。 以下代码应该可以实现这一目的:

    P3SEL || BIT7; //将WFP 3.7 设置为UCB1SIMO功能
    P5SEL |= BIT4 + BIT5;//将WFP 5.4 和WFP 5.4 分别设置为UCB1SOMI和UCB1CLK功能 

    此致,  
    Caleb Overbay

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

    谢谢你Caleb。  我设置了一个断点。 我还总结了从RXBUF读取的所有字节数。  (零)。  我还尝试直接使用P3SEL和P5SEL。  但所有的想法都很好。

    但是,我最近的实验是最有趣的。

    我将我的代码重写为'bit-banger',以防微控制器上的SPI硬件出现故障(可能是RXBUF移位寄存器没有时钟或其它东西)。 而比特班格版本也不起作用!

    现在,如果无法接收任何I/O输入,我怀疑引脚51 (端口5 BIT4)上的驱动程序已熔断。 为了测试这一理论,我刚刚从闪存跳线到另一个MSP430输入引脚—WFP 1.0 ,它在我的主板上有一个TP。 我用SPI_miso端口的这个变化重新编译了,当然也使用了'big banger'版本,它第一次工作。  下面是我的逻辑分析器对那个时刻的把握:

    我的控制台窗口:
    00:13:06 |在flash_read_id中
    00:13:06 | init_flash:型号3031,v 1.3 ,大小= 0x400万
    SPI_sigma 5e FLASH_CFI:01 02 20 4D  00 80 30 31  82 ff ff ff ff ff
    00:13:16>  
    这是对Flash的完美解读。 此SPI的位挂版本比使用SPI硬件慢很多倍,但似乎工作正常!
    因此,我已经中断了这款MSP430端口5.4。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    为了完整起见,我将包含SPI_TRANSFER函数的工作版本,然后将此标记为"已解决"。

    void hal_spi_transfer(.
    uINT8_t *txptr,uint8_t *rxptr,size_t txlen,uint8_t flags)
    {
    断言(txrxlen > 0);
    
    #if bit_Bang
    P3SEL &=~FLASH_MOSI;
    P3DIR || FLASH_MOSI;
    P5SEL &=~(FLASH_miso + FLASH_SCLK);
    P5DIR || FLASH_SCLK;
    //错误是问题...
    // P5DIR &=~flash_miso;
    P1DIR &= BIT0;
    #else
    P3SEL || FLASH_MOSI;
    P5SEL || flash_miso + flash_sclk;
    #endif
    IF (标志和SPI_CS_ENABLE)
    flash_ss_active();
    
    //启动第一个字节传输
    对于(; txlen;--txrxlen){
    
    UINT8_t Tbyte = 0;
    IF (txptr !=空)
    Tbyte =*txptr ++;
    
    // USCI_B_SPI_TRICATEData(USCI_B1_BASE,Tbyte);
    green_LEDs_on();green_LEDs_off();
    #if bit_Bang
    UINT8_t Txbuf = Tbyte;
    UINT8_t Rxbuf = 0;
    uINT8_t i = 9;
    同时(--i){
    IF (Txbuf和0x80)
    P3OUT |= FLASH_MOSI;
    否则
    P3OUT &=~FLASH_MOSI;
    P5OUT |= FLASH_SCLK;
    Txbuf <= 1;
    _nop(); _nop(); _nop(); _nop();
    _nop(); _nop(); _nop(); _nop();
    Rxbuf <<= 1;
    // rxbuf ||((P5IN和FLASH_miso)>>4);
    Rxbuf |= P1IN和BIT0;
    P5OUT >=~FLASH_SCLK;
    }
    Red_LED_on();Red_LED_off();
    UINT8_t rbyte = Rxbuf;
    #else
    UCB1TXBUF = Tbyte;
    UCB1IFG &=~UCRXIFG; // Clear RXIFG as Transmit (将RXIFG清除为传输)始终设置RX标记
    while ((UCB1IFG和UCTXIFG)== 0)
    ;
    blue_led_on(); blue_led_off();
    
    //等待直到接收到RX字节
    同时(!(UCB1IFG和UCRXIFG))
    ;
    
    Red_LED_on();Red_LED_off();
    UINT8_t rbyte = UCB1RXBUF; // USI_B_SPI_receiveData(USCI_B1_base);
    #endif
    SPI_sigma == rbyte;
    
    IF (rxptr !=空)
    *rxptr++= rbyte;
    }
    
    IF (标志和SPI_CS_DISABLE)
    flash_ss_inactive();
    }
    

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

    感谢您提供解决方案。 听起来您正在使用的MSP430可能已因某种原因而损坏。 如果您有任何其他相关问题,请告诉我。 同时,我也会在我的终端上结束这一主题。

    此致,
    Caleb Overbay