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.

USCI_B0 SPI Master that sends data chunks from any buffer (assembler)



My routine that uses TX- IRQ to send chunks of data without main-routine intervention.(not fully tested)
Most examples uses hard-wait-loop to send each character, though not too bad as SPI rate is normally set high.
 
My example snippets below does
with the use of a macro point to a memory location you want to start to send from and how many bytes.
and also flag 1 = partial data don't pull CSn high as more data is coming.
2 = stayawake, main routine will not wait (sleep) for this SPI chunk to be completely sent before going on.
 
MISO pin P1.6  have it's pull-up resistor set as some IC floats when it's enable/CS is off.
There are 3 ways to start a SPI transfer, move first byte to UCB0TXBUF, enable IRQ or set IRQ Flag.
I use the later in my routine
You would need to add some timer or button press etc to initiate the main routine.
 
 
This code below you could point to a header in ram and then a larger chunk in flash and send together.
You could probably dedicate R15 to R12 to SPI routine and not use Ram for pointers, if wanted.
I will add spi_read next, most IC are asynchronous and you send 0s to start reading after you first wrote some bytes
#include  "msp430G2553.h"

spiCSpin        EQU  1<<4        ; ChipSelect_n is on Px.4
spiCSport       EQU  P1OUT       ; ChipSelect_n is on P1.x
SpiBufSize      EQU  64

spi_send macro text,len,flag       
      bic.b   #spiCSpin,&spiCSport          ; set CS active low 
      mov.w   #text,&spi_pnt                ; 16bit pointer
      mov.b   #len,&spi_len                 ; send xx bytes        
      if _args == 2                         ; was no flag value included? 
        mov.b   #0,&spi_flag                ; set flags to 0 as non was included
        bis.b   #UCB0TXIFG,&IFG2            ; set IRQ flag so SPI starts
        bis.w   #LPM3+GIE,SR                ; CPU off, enable interrupts then to sleep 
        exitm  
      endif 
      mov.b   #flag,&spi_flag               ; set flags (like partial data, stayawake etc)  
      bis.b   #UCB0TXIFG,&IFG2              ; set IRQ flag so SPI starts
      if flag &BIT1 == BIT1                 ; test BIT1 (stayawake flag)                       
        exitm 
      endif 
        bis.w   #LPM3+GIE,SR                ; CPU off, enable interrupts then to sleep    
      endm     
;***********************************************************************************      
            ORG     0200h       ; start of ram on all devices            
spi_buffer  ds8     SpiBufSize  ; reserve default 64bytes
spi_len     ds8     1           ; reserve 1 byte for lenght counter
spi_flag    ds8     1           ; 2= sleep 
EVEN
spi_pnt     ds16    1           ; 16bit spi buffer pointer

            ORG     0E000h      ; start of flash ram for a 8k device  

main        mov.w   #0x300,SP               ; Initialize stackpointer (on 256 ram)
            mov.w   #WDTPW+WDTHOLD,&WDTCTL  ; Stop WDT
            mov.b   &CALBC1_1MHZ,&BCSCTL1   ; Set DCO to factory calibrate 1MHz  
            mov.b   &CALDCO_1MHZ,&DCOCTL
            bis.b   #1<<0,&P1DIR            ; P1.0 LED as output             
            bic.b   #1<<0,&P1OUT            ; P1.0 LED off
            
            bis.b   #UCSWRST,&UCB0CTL1      ; Set UCSWRST (USCI Software Reset)
            bis.b   #UCMSB+UCMST+UCSYNC,&UCB0CTL0 ; 3-pin, 8-bit SPI master
            bis.b   #UCSSEL_2,&UCB0CTL1     ; Use SMCLK
            bis.b   #08h,&UCB0BR0           ; and divide it by 8
            clr.b   &UCB0BR1                ; the lower rate register 
            bis.b   #BIT5+BIT6+BIT7,&P1SEL  ; P1.x set as SPI pins (manual page 49)
            bis.b   #BIT5+BIT6+BIT7,&P1SEL2 ; P1.x set as SPI pins       
            bis.b   #1<<6,&P1REN            ; P1.6 (MISO) Pull Resistor
            bis.b   #1<<6,&P1OUT            ; P1.6 Make it pull-up 
            bic.b   #UCSWRST,&UCB0CTL1      ; Initialize USCI state machine
            bis.b   #UCB0TXIE,&IE2          ; Enable USCI_B0 TX interrupt     
               
            
            
mainloop    bis.w   #LPM3+GIE,SR            ; CPU off, enable interrupts then got to deep sleep
                                            ; your code below to run if CPU comes back on
            xor.b   #1<<0,&P1OUT            ; P1.0 LED on/off
            spi_send spi_buffer, 12, 1      ; macro to start a SPI TX_Irq transfer, partial_data,sleep
            spi_send flashdata,200,2        ; SPI TX_Irq transfer, last part,no sleep            
            jmp     mainloop                ; go back to sleep

flashdata  ds8 200                          ; just an example


;-------------------------------------------------------------------------------           
USCIAB0TX_ISR;          Shared A0 & B0 Transmit
            bit.b   #UCB0TXIFG, &IFG2       ; USCI_B0 Transmit Interrupt?
            jnz     USCIB0_TX_ISR           ; jmp if is was B0

USCIA0_TX_ISR
            ; A write to UCA0TXBUF would also clear UCA0TXIFG
            bic.b   #UCA0TXIFG,&IFG2        ; Clear IRQ flag if not done above
            RETI            
            
USCIB0_TX_ISR
            sub.b   #1,&spi_len
            jz      spibuffdone
            mov.w   &spi_pnt,R14
            mov.b   @R14,&UCB0TXBUF         ; iniate transmit of byte
            add.w   #1,&spi_pnt             ; move up to next byte
            reti    
spibuffdone 
            bic.b   #UCB0TXIFG,&IFG2        ; Clear IRQ flag
            bit.b   #BIT0,&spi_flag         ; Partial_data flag set?
            jnz     keepCSlow
USCIbusy    bit.b   #UCBUSY,&UCB0STAT       ; wait for the last byte to transmit            
            jnz     USCIbusy
            bis.b   #spiCSpin,&spiCSport    ; set high as active low
keepCSlow   bit.b   #BIT1,&spi_flag         ; stayawake flag was used?
            jz      spiwakeup               ; jmp if it was not
            reti                            ; leave it as it was
spiwakeup   bic.w   #LPM3,0(SP)             ; Exit LPM3 on reti = run main prog   
            reti

;-------------------------------------------------------------------------------
;                  blank isr routines 
USCIAB0RX_ISR
NMI_ISR  
WDT_ISR
            reti
;-------------------------------------------------------------------------------
;           Interrupt Vectors
;-------------------------------------------------------------------------------
  COMMON  INTVEC             ; Interrupt Vector base 0xFFE0
  ORG   USCIAB0TX_VECTOR    /* 0xFFEC USCI A0/B0 Transmit */
  DW    USCIAB0TX_ISR
  ORG   USCIAB0RX_VECTOR    /* 0xFFEE USCI A0/B0 Receive */
  DW    USCIAB0RX_ISR
  ORG   NMI_VECTOR          /* 0xFFFC Non-maskable */
  DW    NMI_ISR
  ORG   RESET_VECTOR        /* 0xFFFE Reset [Highest Priority] */
  DW    main
  END

**Attention** This is a public forum