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.

MSP430F169 USART0 as SPI -> every byte is sent twice

Hi,

if I configure the USART0 as SPI using the following code, the sent byte is sent twice.


    // Init SPI
    P3DIR |= 0x0B; // P3DIR_0 = 1;  // STE0         
                   // P3DIR_1 = 1;  // SIMO0
                   // P3DIR_2 = 0;  // SOMI0 (D/S)
                   // P3DIR_3 = 1;  // ULCK0

    // Pin select function
    P3SEL |= 0x0E; // P3SEL_0 = 0;  // STEO0
                   // P3SEL_1 = 1;  // SIMO0
                   // P3SEL_2 = 1;  // SOMI0 (D/S)
                   // P3SEL_3 = 1;  // ULCK
                   
    P3OUT |= 0x01; // STE0 to high
    
    U0CTL = SWRST;                   // Initialize USART state machine while held in reset
    
    U0CTL  |= CHAR+SYNC+MM;          // SPI Mode, 8bit, Master mode
    U0TCTL  = CKPH+SSEL1+SSEL0+STC;  // 3pin Mode, clock->SMCLK, no CKPL (poliarity), no CKPH (phase)
    U0BR0   = 0x02;                  // UCLK/2
    U0BR1   = 0x00;
    UMCTL0  = 0x00;                  // no modulation (in spi mode don't used)
    
    ME1 |= USPIE0;                   // Enable SPI0
    
    U0CTL &= ~SWRST;                 // get USART out of reset state
    
    // dummy transmission
    P3OUT &= ~0x01; // STE0 to low
    
    U0TXBUF = 0xAA;
    while (!( IFG1 & UTXIFG0)); // Wait for TX to finish
    IFG1 &= ~UTXIFG0; // clear flag
    
    P3OUT |= 0x01; // STE0 to high

I see 2 identical bytes on the scope, the second comes about 5us after the first.

ACLK is 32,768 kHz

Does anyone know whats wrong here?

Best Regards,

Alex

  • Alexander Kiermayer said:
    0TXBUF = 0xAA;

    Hello. What first thing that comes to my mind, you misinterpret the double A in your output, did you check by sending some different hex like 0xF5.

  • Hi,

    ich checked some different bytes, but i clearly get 2 identical bytes (2 * 8bit)

  • Alexander Kiermayer said:
        // dummy transmission
        P3OUT &= ~0x01; // STE0 to low
        
        U0TXBUF = 0xAA;


        while (!( IFG1 & UTXIFG0)); // Wait for TX to finish

        U0TXBUF = 0xAA;

    while (!( IFG1 & UTXIFG0)); // Wait for TX to finish


        IFG1 &= ~UTXIFG0; // clear flag

    Start playgin around a little, try sendig 2 Bytes on purpose, what do you get then, 3 Bytes or 4? then you can at least suppose that you send your routine twice in a row...

  • I played a lot, but every single byte i want to send, gets sent twice, no matter how many bytes...

  • My expirience show, that a lot of times the user, in my case me : ) does the errors by programming.

    I always start a minimal working piece of code when debugging things I can simply never understand.

    So start with a example code of TIs see if it works, then start your own code, I do not see in what kind of routine you are sending your code, and what hardware you have connected or how you use your oscilloscope, so I cannot tell where the error might be.

    Simply start a new project and try to put only one TX out and only attach your osciloscope to that output wire nothing else, at least this should send only one Byte, or you are really misinterpreting the double A to 2 Bytes because both 4 bits look the same :P

  • this already is a minimal working piece:


    void main(void) {    
        
        /* disable watchdog and interrupts*/
        WDTCTL = WDTHOLD | WDTPW;
        _disable_interrupts();
        
        /* init clk sources */
        BCSCTL1 &= ~XT2OFF;        // enable high freq crystal (XT2 Bit must be cleared)
        BCSCTL2 = SELM_2 + DIVM_3; // select XT2 clock source / 8 for MCLK (8MHz crystal -> 1MHz MCLK)
        BCSCTL2 |= SELS + DIVS_3;  // select XT2 clock source / 8 for SMCLK (8MHz crystal -> 1MHz SMCLK)

        /* CODE FROM FIRST POST */

        while(1);

    }

    Also i only have the Scope connected and i know how to use it.

    I see 8 Clockcycles with the sent byte and 5us later there are 8 Clockcycles with the same byte, so in total 16 clockcycles and 2 identical bytes.

  • Ok, now to the same while sending 2 Bytes on purpose what do you see now.

  • i see 2 times 0xAA and then 2 times 0xF5

      // dummy transmission
        P3OUT &= ~0x01; // STE0 to low
        
        U0TXBUF = 0xAA;
        while (!( IFG1 & UTXIFG0)); // Wait for TX to finish
        IFG1 &= ~UTXIFG0; // clear flag
        
        
        U0TXBUF = 0xF5;
        while (!( IFG1 & UTXIFG0)); // Wait for TX to finish
        
        P3OUT |= 0x01; // STE0 to high

  • Hmm then my only guess would be: Do you have a slave device already attached? SPI always receives as it sends, so perhaps you build an echo device, which does a loop of your input signals.

    Next thing:

    Alexander Kiermayer said:
       IFG1 &= ~UTXIFG0; // clear flag

    In my code the IFG gets reset automatically, shouldnt be a problem, but as you already see a problem I would alternate a lot of things and try to get another result. also play around with different clock signals, as this can be done pretty easy in Software.

  • I have an Nokia 3310 LCD attached but when i send a byte to it to enable ONE pixel, it enable TWO pixel, so the second byte which i see is not the answer from the attaced spi device

  • Alexander Kiermayer said:
     U0TXBUF = 0xAA;
        while (!( IFG1 & UTXIFG0)); // Wait for TX to finish
        IFG1 &= ~UTXIFG0; // clear flag   
        P3OUT |= 0x01; // STE0 to high

    This won't work as expected. UTXIFG0 is set as soon as U0TXBUF is ready to take the nex tbyte - which is when the last byte has been moved intot he output shift register. So your code contines while the fist byte is still being sent and STE0 (Don't call it STE0, as it isn't STE0, it is CS for the slave. STE is an INPUT signal for 4-wire mode) is raised while the transfer hasn't finished yet.

    It's possible that manually clearing the UTXIFG0 bit fools the USART into thinking you wrote another byte into U0TXBUF, so the same byte is sent once more.
    This is just a guess. I never manually cleared this bit, and I never had problems like this with my SPI code.

    If you want to ensure that transmission is done, check the TXEPT bit. in U0TCTL.

    Alexander Kiermayer said:
        U0TCTL  = CKPH+SSEL1+SSEL0+STC;  // 3pin Mode, clock->SMCLK, no CKPL (poliarity), no CKPH (phase)

    MSP polarity is inverted to Motorola polarity, so for many (non-TI) slaves, CKPL needs to be set when their datasheet talks about 'normal' polarity.

    Alexander Kiermayer said:
    ACLK is 32,768 kHz

    You're using SMCLK for the USART, so did you have a particular reason for adding this info?

  • Hi,

    now i am checking the TXEPT instead of UTXIFG0 bit, and i removed the manual clearing of that flag, but the main issue is still present.

    After playing around with the clock sources,i finaly found the issue, but i don't know why this is not working.

    If i don't use the external high freq crystal for MCLK and SCLK clock source the "SPI double transmission"  does not happen, so everythings works fine.

    But i want to use the external high freq crystal, so does anyone know whats the problem?

    You find my CLK init code above

  • Alexander Kiermayer said:
       BCSCTL1 &= ~XT2OFF;        // enable high freq crystal (XT2 Bit must be cleared)
        BCSCTL2 = SELM_2 + DIVM_3; // select XT2 clock source / 8 for MCLK (8MHz crystal -> 1MHz MCLK)
        BCSCTL2 |= SELS + DIVS_3;  // select XT2 clock source / 8 for SMCLK (8MHz crystal -> 1MHz SMCLK)

    Perhaps this could be the issue; You first say BCSCTL2 euqals something and then you or it with others values, this should work as long as you really want to set the first thing and then add the other Bits, but perhaps this is not what you wanted, I dont know.

    But clearly there may be some errors in your HArdware around your HF crystal since it is not working with it attached.

  • Now i changed it to


        BCSCTL1 &= ~XT2OFF;
        BCSCTL2 = SELM_2 + DIVM_3 + SELS + DIVS_3;

    But it does not help.

    It is also no HW error, because it is a evaluation board and the crystal freq works fine for UART communication with the PC.

  • Ok, i found it.

    I have to check the OSCFault flag after enabling the crystal and wait for it to be cleared.

    After that i can chose the MCLK


      BCSCTL1 &= ~XT2OFF;                       // XT2= HF XTAL

      do
      {
      IFG1 &= ~OFIFG;                           // Clear OSCFault flag
      for (i = 0xFF; i > 0; i--);               // Time for flag to set
      }
      while ((IFG1 & OFIFG));                   // OSCFault flag still set?

      BCSCTL2 |= SELM_2;                        // MCLK= XT2 (safe)

    Best Regards

**Attention** This is a public forum