Other Parts Discussed in Thread: MSP430WARE
Hello,
For the past 4 days I have been struggling to control a 16x16 matrix display that consists of 4 daisy chained MAX7219.
I am intending to do this via SPI protocol. I have configured everything (SPI and MAX7219) and the necessary functions (to my understanding) yet I still can't get the display to even receive information correctly.
I am assuming that everything is correctly connected hardware wise, that is why I am only addressing the software issue. If everything seems to be in order I will then concentrate in debugging the hardware thoroughly.
I will attach the code below but before doing so I want to point out some relevant things:
- I have tested the MOSI Pin in the board with and oscilloscope and the output was I expected. However, since I don't have 24/7 access to one and I have progressing with the code this may not be valid anymore.
- By debugging the board while looking at the registers via CCS it seems that UCBUSY never goes up in the UCA1STATW. This means it is not busy even though the buffer is successfully changed.
- A similar issue happens with UCTXIFG in UCA1IFG, it never turns low, meaning it is ALWAYS ready to transmit.
- About the MAX7219, when I configure all the displays, do I have to configure each one individually? E.G. Send addres - data and then 3 NO OPS.
- The are many init functions since I have tried several ways of initializing the board.
That is all before attaching the code and thank you very much for reading through.
/******************************************************************************* * INCLUDE HEADER FILES ******************************************************************************/ #include <msp430.h> #include "SPIDriver.h" /******************************************************************************* * CONSTANT AND MACRO DEFINITIONS USING #DEFINE ******************************************************************************/ #define FULL 1 #define EMPTY 0 /******************************************************************************* * ENUMERATIONS AND STRUCTURES AND TYPEDEFS ******************************************************************************/ /******************************************************************************* * VARIABLES WITH GLOBAL SCOPE ******************************************************************************/ /******************************************************************************* * FUNCTION PROTOTYPES FOR PRIVATE FUNCTIONS WITH FILE LEVEL SCOPE ******************************************************************************/ /******************************************************************************* * ROM CONST VARIABLES WITH FILE LEVEL SCOPE ******************************************************************************/ /******************************************************************************* * STATIC VARIABLES AND CONST VARIABLES WITH FILE LEVEL SCOPE ******************************************************************************/ /******************************************************************************* ******************************************************************************* GLOBAL FUNCTION DEFINITIONS ******************************************************************************* ******************************************************************************/ void SPI_init(void) { CSCTL3 |= SELREF__REFOCLK; //Select REF0CLK as reference clk // Configure SPI pins3 //P2SEL1 |= BIT4 | BIT5 | BIT6; //P2SEL0 |= BIT4 | BIT5 | BIT6; // set pins 2.4, 2.5, 2.6 into SPI mode (primary) P2SEL1 |= BIT4 | BIT6; P2SEL0 |= BIT4 | BIT6; // set pins 2.4, 2.5, 2.6 into SPI mode (primary) P1DIR |= BIT0; //P1.0 as output P2DIR |= BIT4 | BIT6; //P2.4 and P2.6 as Outputs //P1OUT |= BIT0; //Configure UCA1 CONTROL register UCA1CTLW0 |= UCSWRST; // Software reset enable (To modify Settings) UCA1CTLW0 |= UCMST | UCSYNC | UCSSEL__SMCLK | UCMSB | UCCKPL; //LSB first, select master mode, //select SPI mode, select SMCLK as clk source UCA1BRW = 0x0100;//0x0010; UCA1CTLW0 &= ~UCSWRST; // Software reset disable (turn on SPI) //UCA1IE |= UCTXIE; //Transmit interrupt enable, Receive interrupt enable _BIS_SR(GIE); //Enable general interrupts } void SPI_SendData(char myData) { while ( ( UCA1IFG & UCTXIFG ) == 0 ); UCA1TXBUF = myData; } void SPI_Send8(char MSB1, char LSB1, char MSB2, char LSB2, char MSB3, char LSB3, char MSB4, char LSB4) { P1OUT &= ~BIT0; _delay_cycles(50); UCA1TXBUF = MSB1; while (UCA1STATW & UCBUSY); UCA1TXBUF = LSB1 ; while (UCA1STATW & UCBUSY); UCA1TXBUF = MSB2; while (UCA1STATW & UCBUSY); UCA1TXBUF = LSB2 ; while (UCA1STATW & UCBUSY); UCA1TXBUF = MSB3; while (UCA1STATW & UCBUSY); UCA1TXBUF = LSB3 ; while (UCA1STATW & UCBUSY); UCA1TXBUF = MSB4; while (UCA1STATW & UCBUSY); UCA1TXBUF = LSB4 ; while (UCA1STATW & UCBUSY); P1OUT |= BIT0; } void init_MAX7219(void) { SPI_Send8(0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00); // SPI_Send8(0x0A, 0x03, 0x0A, 0x03, 0x0A, 0x03, 0x0A, 0x03); // SPI_Send8(0x0B, 0x0F, 0x0B, 0x0F, 0x0B, 0x0F, 0x0B, 0x0F); // SPI_Send8(0x0C, 0x01, 0x0C, 0x01, 0x0C, 0x01, 0x0C, 0x01); // SPI_Send8(0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F); // SPI_Send8(0x0F, 0x00, 0x0F, 0x0, 0x0F, 0x00, 0x0F, 0x00); // } void init2_MAX7219(void) { SPI_Write2(0x09, 0x00); // SPI_Write2(0x0A, 0x0F); // SPI_Write2(0x0B, 0x0F); // SPI_Write2(0x0C, 0x01); // SPI_Write2(0x0F, 0x0F); // SPI_Write2(0x0F, 0x00); // } void SPI_Write2(unsigned char MSB1, unsigned char LSB1) //SPI write one byte { P1OUT &= ~BIT0; _delay_cycles(50); UCA1TXBUF = MSB1; while (UCA1STATW & UCBUSY); UCA1TXBUF = LSB1 ; while (UCA1STATW & UCBUSY); P1OUT |= BIT0; } volatile int dummy; void SPI_Send2MAX7219(char address, char data) { UCA1TXBUF = address & 0b00001111; // Send 4bit address as byte1 //UCA1IFG &= ~UCTXIFG; //while (UCA1STATW & UCBUSY); // Wait until done //while ((UCA1IFG & UCTXIFG) == 0); while (UCA1STATW & UCBUSY); UCA1TXBUF = data; // Send byte of data //UCA1IFG &= ~UCTXIFG; //while ((UCA1IFG & UCTXIFG) == 0); //while (UCA1STATW & UCBUSY); while (UCA1STATW & UCBUSY); } void SPI_MAX7219ToggleLoad(void) { P1OUT |= BIT0; P1OUT &= ~BIT0; } void init3_MAX7219(void) { int i; for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x00, 0x00); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x0B, 0x07); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x0A, 0x03); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x09, 0x00); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x01, 0x00); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x02, 0x00); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x03, 0x00); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x04, 0x00); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x05, 0x00); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x06, 0x00); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x07, 0x00); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x08, 0x00); SPI_MAX7219ToggleLoad(); for(i = 0; i < 4; i++) SPI_Send2MAX7219(0x0C, 0x01); SPI_MAX7219ToggleLoad(); } /******************************************************************************* ******************************************************************************* LOCAL FUNCTION DEFINITIONS ******************************************************************************* ******************************************************************************/ /******************************************************************************* ******************************************************************************* INTERRUPT FUNCTION DEFINITIONS ******************************************************************************* ******************************************************************************/ #pragma vector = USCI_A1_VECTOR __interrupt void mySPIisr(void) { volatile int dummy; dummy = UCA1IV; switch(dummy) { case USCI_SPI_UCRXIFG: //Receive interrupt flag break; case USCI_SPI_UCTXIFG: //Transmit interrupt flag break; default: break; } }
#include <msp430.h> #include "SPIDriver.h" void delay_ms(unsigned int ms ); int main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode // to activate 1previously configured port settings3 SPI_init(); init3_MAX7219(); SPI_Send2MAX7219(0x0F, 0x00); SPI_Send2MAX7219(0x0F, 0x00); SPI_Send2MAX7219(0x0F, 0x00); SPI_Send2MAX7219(0x0F, 0x00); SPI_MAX7219ToggleLoad(); while(1) { } return 0; } void delay_ms(unsigned int ms ) { unsigned int i; for (i = 0; i<= ms; i++) __delay_cycles(1000); //Built-in function that suspends the execution for 1000 cycles }