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.

Interface trouble

Other Parts Discussed in Thread: MSP430F5438A

Hello All,

I'm currently trying to interface my MSP430F5438A with an external Dot Matrix IC (HCMS-2903), just to display a number. The IC doesn't have any sort of UART/SPI/I2C module on it. What would be the best way to communicate with it? It reads data serially through one of its ports and I need to set its two 8bit control registers before sending it the data to display. I tried using the TX pin of a UART module with it but I think its confuses the start/stop bits for data bits and latches the wrong data (hard to tell, don't have a logic analyzer just a scope).

Thanks for any help you may be able to offer.

-Will

  • William Giasson said:
    What would be the best way to communicate with it?

    SPI peripheral. Thing is that SPI mode of msp430 USCI does not mean that it can't be used just for synchronous (clocked) bitstream transmission of arbitrary length. For instance it can be used to load SIPO register such as 74hc164 which definitely is not SPI slave chip.

    You shall read datasheet of display controller carefully. Hint: see "Write Cycle Diagram", understand how to use register select pin.

  • @llmars

    Thanks for the suggestion, when I looked over the SPI module before I thought  that it needed to interface with an IC that had a SPI module like with UART. But after actually reading through the section in the user manual again it looks like it'll work nicely with the little displays I have.

    But one thing I don't understand is how it can transmit bit-streams of arbitrary length. In the user manual and in the description of the UCAxCTL0 register it says that it can be enabled for either 7 or 8 bit data transmission. How then would you transmit a different length? Just keep loading them in the the TX buffer?

    And lastly would 4 wire mode really be necessary if the connection is just between 1 master and 1 slave? (trying to conserve IO)

    -Will

  • William Giasson said:
    How then would you transmit a different length? Just keep loading them in the the TX buffer?


    More or less. Devices with a simple serieal shift register (nto a full-featured SPI) usually have a select line too. When the select is released, the last n bits shifted in are counter. So just ensure that any superfluous bits of an n*8 bit transfer are sent out first.
    Of course if you e.g. have to send 48 bits for 8 rows of 6 bit, you can send them as 6*8 bit and have to reorder them before sending. The SPI signal output is just a bitstream. But it is always a multipkle of 8 bits. (On MSPs with USI moduel, not USCI, the number of bits to send can be adjusted between 1 and 16 bit per output operation)

    William Giasson said:
    And lastly would 4 wire mode really be necessary if the connection is just between 1 master and 1 slave? (trying to conserve IO)

    Indeed, 4-wire mode isn't necessary. However, you will likely still need a 4th wire to signal the slave the beginning and (more important) end of a transfer, so it will copy the last n received bits form its shift register into its state machine.

  • @Jens-Michael Gross

    That makes a lot of sense, I figured that it would have to be some sort of multiple of 8, your explanation made it a lot more clear as to what was actually going on in the device. As for using a fourth wire to tell the device when to start/stop the transfer, I figured this out when I went to actually program it; I just ended up using one of the GPIO pins. 

    @Anyone

    So I loaded the firmware onto the uC and I noticed that I was getting a constant flicker on the two GPIO pins I was using to control the device (one to signal the start/stop of the data transfer and another to switch between the displays control registers and its Dot Matrix). Every 30-40 ms the pins toggle for 800 us, e.g. after being configured one of the pins stays low but instead goes high (3.3 V) for about 1 ms every 35 ms, the other  pin is the same but reversed states with the same period.

    Any ideas why???

    -Will

  • William Giasson said:
    Any ideas why???

    Your coude could tell. My crystal ball won't :) Without knowing your code, it can be virtually anything. For example the watchdog that keeps resetting the MSP as it isn't triggered in time.

  • @Jens-Michael Gross

    Yea that might help, here yea go:

    FYI : CE is Chip Enable on the device, it is active low.

    void main(void)
    {  
      // Need 5 Wires to communicate with display
      //    *Data in (SPI: SIMO)
      //    *RS [register select] (GPIO port)
      //    *CLK (SPI: UCxCLK)
      //    *CE [Chip Enable] (SPI: UCxSTE if 4 wire mode, GPIO port if 3 wire mode)
      //    *RESET (GPIO port)
      
      
      WDTCTL = WDTPW + WDTHOLD;                                    // Disable Watchdog Timer
      
      
      /*Setting GPIO ports for use on the chip*/
      
      P1DIR |= BIT0 + BIT1 + BIT2;                               // RS, CE, and RESET
      P1OUT &= ~(BIT0 + BIT1 + BIT2);  // Initializing GPIO ports to 0
      
      /*Multiplexing port 3 pins to be used for SPI*/
      
      P3SEL |= BIT0 + BIT3 + BIT4 + BIT5;                       // Module A0 : CLK, STE, SIMO, and SOMI
      P3DIR |= BIT0 + BIT3 + BIT4;                                // CLK, STE, and SIMO set to output
      P3DIR &= ~BIT5;                                                 // SOMI set to input (might not be used, if so set back to GPIO later)
      
      /*SPI register configuration*/
      
      UCA0CTL1 |= UCSWRST + UCSSEL_2;                                          // Enables the UC registers for software reset, and selects SMCLK as the module source
      UCA0CTL0 |= UCMSB + UCMST + UCSYNC;          // Data transmits MSB first (required for display), sets the module as the master, and enables synchronous mode
      UCA0BR0 |= 0x01;                                                     // Sets the bit clock prescaler (int to divide the clock source by for the timer), defined as: UCAxBR0 + UCAxBR1 x 256
      UCA0BR1 &= 0x00;                                              // with this setup:  prescaler = 0x01 + 0x00 x 256 = 1 , thusly UCA0CLK = SMCLK
      UCA0CTL1 &= ~UCSWRST;                                          // Latches all register setting into place and enable the module to transmit data
       
      /*Loading the displays control registers*/
      
      P1OUT |= BIT0;                                                            //RS High, selects control register as the destination for serial data entry
      P1OUT &= ~BIT1;                                                        //CE Low, allows data to be written to a register, to be latched on the on first low clock after it returns to logic high
      
      UCA0TXBUF |= 0x6F;                                             //0 1 10 1111, Control word 0 is selected, sleep mode disabled, peak currect set to ~4mA, and set at full brightness
      P1OUT |= BIT1;                                                    //CE high to latch the data to control register 0
     
      __delay_cycles(100);  // Delay for control register to settle
      
      P1OUT &= ~BIT1;                                 //CE set to low for next transmisson
      UCA0TXBUF |= 0x82;                       //1 0 0 00 0 1 0, Control word 1 is selected, Bits 6-2 reserved must set low, external oscillator prescaller set to 1
      P1OUT |= BIT1;                                       //CE high to latch the data to control register 1
      
      __delay_cycles(100);                             // Delay for control register to settle
      
      /*Loading data to the dot matrix*/
      
      P1OUT &= ~BIT0;                                  //RS Low, selects the Dot Matrix as the destination for serial data entry
      
      P1OUT &= ~BIT1;                              //CE set to low for the next transmission
      UCA0TXBUF |= 0x05;                          //Random data word, number 5 hopefully, unless it uses ASCII standerd or something
      P1OUT |= BIT1;                                   //CE High to latch the data to the Dot Matrix
      
      
      while(1)
      {
        __no_operation();
      }
    }
    
    
     I actually did forget to turn off the watchdog until you said something, felt stupid for that, lol.
    Doing that fixed the problems with the intermittent spikes, I was just the device resetting, but I still have the problem of nothing actually being received by the device. 
    One thing I realized while debugging is that while I was sending the byte 0x05 in TXBUF but it was when I paused the program and checked the register it said if was sending 0xEF which I then confirmed on my scope.
    
    
    -Will
  • Switched

    TXBUF |= something; 

    to 

    TXBUF = something;

    Sends the correct byte now, still doesn't work tho

    -Will

  • Alright, well I found a rather large problem with my code, the input register for the Dot Matrix on the device is a 160 bit shift register; 1 bit per led / "Dot" , 40 bits per character......

    So just to send one character I'd have to send 5 bytes, and I would need some sort of array / library with all the characters I need predefined.

    As fun as that sounds to program I think it might be a lot easier to just get a different display IC.

    Know any good ones, preferably with serial input? lol

    Well at least I know more about SPI now...

    -Will

  • Yeah, dot matrix requires a lot of data to be sent, and also font information. Unless you have an external controller that has own ram, internal font data and you can just give it ASCII chars and write them to a random location (rather than fo the full display serially).

    Sorry, I don't have any per number or such for you.

    But after all, it isn't that difficult to do. You jsu tneed to create a constant 2-dimensional array wher eone dimension is the character number and the other is the 5 byte count.

    If you use the binary constant macros I published in this forum some time ago (not my invention, Tom Torfs put them into publich domain), you can even 'see' the chars by the 0 and 1 values.

    Put the array into a separate C file and generate a header file with th edeclaration only. This speeds up compiling an keeps the main code file smaller :)

  • Thanks for the information, but I've decided to just go with a different display, standard 7 segment deal. But I do have another question involving the SPI interface. I have a DAC that I'm also using SPI to communicate with, it has serial input 2 bytes. In order to send the data right would I have to enable UCTXIFG and have the interrupt routine load the second byte into TXBUF? Is it that easy?

  • William Giasson said:
    would I have to enable UCTXIFG and have the interrupt routine load the second byte into TXBUF? Is it that easy?

    More or less. If two bytes is all you need to send in a row, you could simply stuff the first byte to TXBUF, wait for TXIFG being set, then stuff the second byte to TXBUF (due to the double-buffering, the USCI can keep almost 2 bytes internally - just with one SPI clock cycle delay before the second can be written).
    So in this case, I wouldn't go for using interupts.
    For more than two bytes, you may go for interrupts, or continue waiting for TXIFG in a while loop before sending the next byte. Usually, SPI is configured to run at high speed, so it won't pay to have the overhead for interrupt programming or going into LPM. But of course this depends on the exact application specs.

  • Two bytes is all that I will need to send at once, so that's convenient. Also, does the TXIFG automatically get set after the contents of TXBUF are moved to the shift register as long as GIE and UCTXIE are set?

    Just to try it out I ran a program through the simulator that writes a number to TXIFG and the waits for the TXIFG to set, and it never seems to set. Do I need a routine with it or should the flag set regardless?

  • William Giasson said:
    Also, does the TXIFG automatically get set after the contents of TXBUF are moved to the shift register as long as GIE and UCTXIE are set?

    Not "as long" but always.
    The IFG bits are always set when an event occurs. The IE bits only control whether this leads to calling an ISR.

    IF (xxIFG & xxIE & GIE) ISRxx;
    else next main instruction;

  • Gotcha, so all I really need to do is basically:

    Write 1st byte to TXBUF

    delay

    iF(flag set)

           write second byte

    Correct? Then all the flags should reset themselves when the buffer is rewritten.

    -Will

  • William Giasson said:
    delay
    iF(flag set)


    You can (and should) combine this into
    while(!(flag set));
    It will loop until the flag is set. But yes, basically that's it.

**Attention** This is a public forum