SPI

OK I’ve struggled with this one long enough. There must be something obvious that I am missing.

What I think I am doing is:

Set up the SPI register for 16 bit operation

Load the SPI counter with the value 16

Store the word to be transmitted in the USI Shift Register

Set the USIWRST bit to 0 to start data transfer

Set the ~Select line to the UART to 0

Turn on the green LED to indicate that the prom has got this far

Test the USIIFG flag for completion of the transmission.

The green light comes on and there it sits. The select flag is low. I do not know if an initial 16 clock pulses were generated, but the USIIFLG never came on.

;*******************************************************************************
;   MSP430F2012 SPI Interface
;
;Initial test of the UART interface
;
;Read a $ character from the PC and turn on the LED
;
;
;
;
;
;
;    MSP430F2012                                      MAX3100 UART
;  -----------------                                           -------------------
; |1  Vcc        XIN|<- 13 <- 10 MHz Osc          |                       |
; |                      |                                        |                       |
; |14 Gnd           |                                         |                       |
; |                 |                                             |                       | 
; |             P1.0|  2 -->LED                            |                       |
;               P1.1|  3 -->Rudder Servo              |                       | 
;               P1.2|  4 -->                                  |                       |
;               P2.7|  12 ->                                  |
;                      |                                           |
;               P1.4|<-6 <-- Uart Ready<--------5  |
;               P1.5|  7 --> SPI Clock--------->3    |
;               P1.6|  8 --> SPI Out----------->1     |
;               P1.7|<-9 --- SPI In<------------2     |
;               P1.3|  5 --> UART select------->4    |
;
;
;   Tom Harper
;   Socorro,NM   
;   1 Sep 06
;   Built with IAR Embedded Workbench Version: 3.40A
;*******************************************************************************
#include  "msp430x20x3.h"

;Initial set up routines for test only - normally in initialization routine
;-----------------------------------------------------------------------------
            ORG     0F800h

RESET         mov.w   #0280h,SP               ; Initialize stackpointer
StopWDT     mov.w   #WDTPW+WDTHOLD,&WDTCTL  ; Stop watchdog timer
SetupP1       mov.b   #050h,&P1OUT            ; Clear output reg
                   bis.b   #050h,&P1REN            ; Enable all pull up resistors                                          
                   bis.b   #06Fh,&P1DIR            ; Set Direction P1.4, P1.7 Inputs
                   bis.b   #0h,&P1SEL              ; Set port for I/O   


;----------------------------------------------------------------------------
;   Application Routine
;----------------------------------------------------------------------------
;Setup for UART

AppsLp:     mov.w   #0C00Bh, R4             ; Configuration word for UART
                call        #SetupUSI
                call        #Xmt
                call        #UARTLp
                jmp        AppsLp
            
;----------------------------------------------------------------------
;  Universal Serial Interface Transmit Character
;------------------------------------------------------------------------------

Xmt          mov.w   R4,07Ch                 ; Load data word into USISR

;To initiate data transfer the P1.3 output pin is set to 0 and held there
;for the period of the data transfer. The command word and data byte are 
;latched into the UART on the subsequent rising edge of P1.3.
   
                 bic.b   #01h, 078h              ; USISWRST=0
                 bic.b   #004h,&P1OUT            ; Start SPI data exchange
                 bis.b   #01h, &P1OUT            ; Turn on green LED
SPIlp:        bit.b   #01h, 079h              ; Loop until transfer complete
                 jnc     SPIlp
                 bis.b   #001h, 078h             ; USIWRST=1 Stop transfer
                 bis.b   #004h,&P1OUT            ; Raise ~UARt SELECT line
                 bic.b   #01h, &P1OUT            ; Turn off green LED
                 ret
            
;----------------------------------------------------------------------------            
;Setup for SPI - 16 bits



                       

SetupUSI:   bis.b      #03h, 078h
                  mov.b   #0EBh, 078h                ; Configure Control 0
                  mov.b   #048h,07Ah                 ; Configure clock
                  mov.b   #050, 07Bh                  ; 16 bit counter & reg
                  bis.b     #004h,&P1OUT             ; Make sure ~UART select is hi          
                  ret
                        
            
; Universal Serial Interface Recieve Character
;------------------------------------------------------------------------------
Rcv:
                 mov.b   &USISRL,R4              ; Save RX'ed char
                 ret                                        ; Exit 
;------------------------------------------------------------------------------
; Wait for UART READY
;------------------------------------------------------------------------------

UARTLp      bit.b   #010h, 020h             ; Is ready line =0? P1.4
                 jnc     UARTLp                    ; No - stay in loop
                 ret           
            
;------------------------------------------------------------------------------
;           Interrupt Vectors Used MSP430x20x2/3
;------------------------------------------------------------------------------
            ORG     0FFFEh                   ; MSP430 RESET Vector
            DW       RESET                   ;
            
            END

In the cold light of dawn things looked different. I must have had my nose too close to the soldering iron yesterday. Bad fumes.

There are four things required to start the SPI clock:

USIPE5 - of Control Reg 0 = 1 (Bit 5 of address 078h)

USIMST - of Control Reg 0 = 1(Bit 3 of address 078h)

USISRST - of Control Reg 0 = 0 (Bit 0 of address 078h)

USIIFG - of Control Reg 1 = 0 (Bit 0 of address 079h)

So now the clock runs within the select gate on the UART. But there are 18 clock pulses instead of 16. Hmmm…back to the bench.

I’m using the MSP430f2012. The Data Sheet lists the USI as a byte peripheral. However the USI Shift Register (07Ch - 07Dh) is a 16 bit register. Only the lo order byte is listed in the Data Sheet. But, if the control bit is set in the clock control register the assembler will allow the register to be set as a word register.

In operation the 16 bit counter allows 16 clock bits. The shift register only shifts out 8 data bits. The upper byte is ignored. Looks like you have to stop midway and reload the shift register.

Anybody experienced with this?

That seems to be the problem. You have to set it up for eight bits and load the register twice. My debug code is:

;----------------------------------------------------------------------
;  Universal Serial Interface Transmit Word
;------------------------------------------------------------------------------


; To initiate data transfer the P1.3 output pin is set to 0 and held there
; for the period of the data transfer. The low order byte of the USI shift
; register is loaded first with the hi order byte of the output data and 
; then with the low order byte of the output data. Sixteen clock pulses are
; generated. When complete the P1.3 output goes high. This routine is for
; oscilloscope observation so a delay is used to separate the data bursts.

Xmt:        mov.b   #0AAh,07Ch              ; Load data word into USISR
            bis.b   #028h, 07Bh             ; Set bit counter & count=8
            bic.b   #008h,&P1OUT            ; Start SPI data exchange
            bic.b   #01h, 078h              ; USISWRST=0
            bic.b   #01h, 079h              ; Reset flag to start clock
SPIlp:      bit.b   #01h, 079h              ; Loop until byte transfer complete
            jz      SPIlp                   ; Continue when Flag=1
            bis.b   #01h, 078h              ; USISWRST=1
            mov.b   #0AAh,07Ch              ; Load data word into USISR
            bis.b   #028h, 07Bh             ; Set bit counter & count=8
            bic.b   #01h, 078h              ; USISWRST=0
            bic.b   #01h, 079h              ; Reset flag to start clock
SPIlp2:     bit.b   #01h, 079h              ; Loop until byte transfer complete
            jz      SPIlp2
            bis.b   #01h, 078h              ; USISWRST=1
            bis.b   #008h,&P1OUT            ; Raise ~UARt SELECT line
            call    #Delay
            jmp     Xmt
            
 Delay:     mov.w   #0FFh, R15
 Dcnt:      dec.w   R15
            jnz     Dcnt
            ret
;----------------------------------------------------------------------------

I assume there are redundancies in the code. I welcome comments.