我的 SPI 配置/编程有什么问题?

问题描述 投票:0回答:1

我正在尝试让 2 个 MCU 使用单向 SPI 进行通信,即主设备发送到从设备。在我测试 BF 标志设置的点写入输出缓冲区后,主代码似乎被阻止。

我使用 2 个 PIC16F1503 MCU,其中一个配置为主机,另一个配置为从机。 电路如下图所示。Circuit diagram

除了 MSSP 模块细节之外,两个处理器的配置相同

  • 内部振荡器16MHz
  • 所有引脚设置为数字
  • RC2 为输出,驱动红色 LED

Master 的 SPI 配置为

SPI_init:
    clrf    INTCON        ; Disable all interrupts
    banksel    TRISC
    
    ; set alternative SDO pin
    banksel    APFCON
    bsf        APFCON, APFCON_SDOSEL_POSN  ; SDO function is on RA4
    
    ; complete the rest of SPI setup but don't enable just yet
    banksel    SSP1STAT
    movlw       01000000B
           ;0-------    SMP input data sampled at end of data o/p time
           ;-1------    CKE xmit occurs on transition from active to idle clock
           ;--xxxxxx    I2C only
    movwf       SSP1STAT
    
    ; set SDO function to alternative RA4 pin
    banksel    APFCON
    bsf        APFCON, APFCON_SDOSEL_POSN  ; SDO function is on RA4
    
    ; set the SPI mode and clock speed
    movlw       00110010B
               ;0-------    WCOL write collision bit - no collision
               ;-0------    SSPOV receive overflow indicator bit - no OF
               ;--1-----    SPEN enable synchronous serial port
               ;---1----    CKP clock polarity, idle state for clock is high
               ;----0010    SPI Master mode, Fosc/64
    movwf       SSP1CON1
    
    ; set SS high
    banksel    LATC
    bsf        LATC, LATC_LATC3_POSN
    
    call    stabilisationWait
    
    return

从机的 SPI 配置是

SPI_init:
    clrf    INTCON      ; Disable all interrupts
    banksel TRISC
    
    ; set alternative SDO pin, even though we won't be sending any data
    banksel APFCON
    bsf     APFCON, APFCON_SDOSEL_POSN  ; SDO function is on RA4
    
    ; complete the rest of SPI setup but don't enable just yet
    banksel SSP1STAT
    movlw       01000000B
               ;0-------    SMP input data sampled at end of data o/p time
               ;-1------    CKE xmit occurs on transition from active to idle clock
               ;--xxxxxx    I2C only
    movwf       SSP1STAT
    
    ; set SDO function to alternative RA4 pin
    banksel APFCON
    bsf     APFCON, APFCON_SDOSEL_POSN  ; SDO function is on RA4
    
    movlw       00110001B
               ;0-------    WCOL write collision bit - no collision
               ;-0------    SSPOV receive overflow indicator bit - no OF
               ;--0-----    SPEN disable synchronous serial port
               ;---1----    CKP clock polarity, idle state for clock is high
               ;----0100    SPI Slave mode, SS enabled
    movwf       SSP1CON1

    ; now wait for the SS line to go high, meaning SPI master is ready
    banksel PORTC
    btfss   PORTC, PORTC_RC3_POSN

    goto    $-1

    ; now enable SPI
    banksel SSP1CON1
    bsf     SSP1CON1, SSP1CON1_SSPEN_POSN   ; enable SPI
    
    call    stabilisationWait
    return

在主设备中有一个循环,我将一个字节写入 SPI,如下所示。

loop:
    movlw   2
    call    flashLED
    call    SPI_write
    call    delay5s
    goto    loop
     
SPI_write:
    movlw   10101010B
    
    ; pull SS low
;    banksel    LATC
;    bcf    LATC, LATC_LATC3_POSN
    
    ; write the value to SPI transmit buffer
    banksel SSP1BUF
    movwf   SSP1BUF
    
    ; wait till BF flag goes high
    banksel SSP1STAT
    btfss   SSP1STAT, SSP1STAT_BF_POSN
    goto    $-1

    ; clear the BF flag by reading SSP1BUF
    banksel SSP1BUF
    movf    SSP1BUF, w
   
    ; set SS high
;    banksel    LATC
;    bsf        LATC, LATC_LATC3_POSN

    return

当我运行此程序时,LED 闪烁两次(符合预期),然后程序“挂起”。唯一的阻塞代码是等待 BF 标志变高。

您还会从注释的代码中注意到,我不清楚是否需要显式地操作SS线,或者这是否是由MSSP模块完成的(我怀疑是后者) - 我已经尝试了带/不带的代码SS线设置,问题依然存在。

由于 SPI 没有明确的 ACK,我相信 Slave 代码可能不相关,但是,Slave 中的处理循环在这里供参考。

loop:
    ; wait for buffer full flag
    movlw   1
    call    flashLED
    
    btfss   SSP1STAT, SSP1STAT_BF_POSN 
    goto    $-1
    
    ; read the value from the receive buffer
    banksel SSP1BUF
    movf    SSP1BUF, w
    movwf   bufferValue
    
    goto    loop

FWIW,我已成功将 PIC16F1503 配置为驱动 DAC (MCP4091) 的主设备 - 这是单向交互,效果很好。但是,它是用 C 语言编写的,当我将其“翻译”为 ASM 时,它不再起作用。我认为如果我“拥有”主组件和服务器组件,调试会更容易,这就是我将此配置放在一起的原因。

此外,延迟例程工作正常。我已经使用它们很多年了,没有任何问题。

希望有人能够发现我哪里出错了。

pic spi
1个回答
0
投票

根据数据表的以下部分:

数据发送/接收期间对 SSPxBUF 寄存器的任何写入都将被忽略,并且 SSPxCON1 寄存器的写冲突检测位 WCOL 将被置 1。用户软件必须清零 WCOL 位才能成功完成以下对 SSPxBUF 寄存器的写入。

所以在忙等待接收之前,必须确保数据已发送,这样才能得到从机的响应。如果您想在 CPU 忙于等待 BF 标志之前知道移位寄存器是否可用于传输,则需要添加更多代码。

这是 SPI_write 函数的稍微修改版本:

spi1_write:
    ; wait till transmit buffer to be available if needed
    banksel SSP1STAT ; Make sure you are in the SSP registers bank
    btfss   SSP1STAT, SSP1STAT_BF_POSN ; Make sure there is nothing received in the buffer
    goto    spi1_send ; Buffer is available for transmission
    movf    SSP1BUF, W ; There is a received data waiting for handling
    movwf   ssp1_rx_data ; <- should declare this variable. store the data if needed
spi1_send:
    bcf     SSP1CON1, SSP1CON1_WCOL_POSN ; Clear the write collision flag before writing to the buffer
    movwf   SSP1BUF ; Write the data first
    btfsc   SSP1CON1, SSP1CON1_WCOL_POSN ; Then check whether a write collision has occured
    goto    spi1_write ; The shift register is still busy, keep checking until the data has been sent
    ; Now that the data has sent successfully, wait till BF flag goes high
spi1_wait_response:
    btfss   SSP1STAT, SSP1STAT_BF_POSN
    goto    spi1_wait_response

    ; clear the BF flag by reading SSP1BUF
    banksel SSP1BUF
    movf    SSP1BUF, w
    return

尝试一下代码,看看是否对您有帮助。

然而,另一方面,delay5s 电话对我来说看起来很可疑。你测试过这个功能吗?也许程序流程挂在那个延迟函数中?

© www.soinside.com 2019 - 2024. All rights reserved.