PIC16F877A > MAX7219 > 8x8 Multiplex Communications

Thread Starter

Ben_C

Joined Oct 19, 2010
65
Hi, this is my last resort after attempting setting up communications and getting the correct result from my code.

Basically I need a simple working example program in C to display say:

Code:
//Digit 1

B01000000
B11000000
B01000000
B01000000
B01000000
B01000000
B11100000
I have it connected as so:
(MAX7219 > PIC16F877A)

DIN.........> RC5
LOAD/CS.> RC0
CLK.........> RC3
ISET........> +VE (through 10K)

I'm using PIC16F877A, MAX7219CNG and 1088BS Multiplex display. I have tried numerous times looking on data sheet to set the SFR's but I'm getting no where. There is plenty of examples on Google for Arduino but would prefer to use the PIC as it's what I'm used to.

I've never used a display driver before I've always used PORTS on the Microchip and could do this using them, but I have a big project in mind and would love to use Serial data instead.

Any help would be massively appreciated!

Ben.
 

JohnInTX

Joined Jun 26, 2012
4,787
Do you have any code so far?
I haven't used the 7219 but it doesn't look too difficult. I'd start by not worrying about the internal specifics too much - the thing is controlled by shifting 16 bits, MSbit first, to it. Start there.
I think I'd make a function that accepts 2 chars, the digit data byte and command byte. The function combines these into an unsigned int and shifts that int out bit by bit then strobes the LOAD input on the 7219. After that, its just data.
With no programming/setup, the 7219 scans one digit at low intensity with no decoding. Test the shift code by calling the output routine with 01xxh where 01 addresses digit 0 and xx is a segment pattern.
Post what you have and we can take a look at it.

Good luck.
 

Thread Starter

Ben_C

Joined Oct 19, 2010
65
I have this at the moment, as I said I don't fully understand SPI and never used it before so this is probably a million miles away from what I need. I just need a simple working program on which I can build on.

Code:
unsigned char i = 0xAA;

void SPI_Init()
{
     SSPEN = 0; //disable SPI for setup

     TRISC5 = 0; //data out
     TRISC4 = 1; //data in
     TRISC3 = 0; //clock
     TRISC1 = 0; //CEpin
     TRISC0 = 0; //ChipSelect

     SSPCON = 0b00000001;
     CKP = 0;
     CKE = 1;

     SSPEN = 1; //enable SPI
}

int main ()
{
    while (1)
    {
    SPI_Init();

    SSPBUF = i;    // send character
    while (SSPSTATbits.BF);    // wait until sent

    }
}
Cheers
 

Papabravo

Joined Feb 24, 2006
21,157
Why is the call to SPIInit() inside your while loop and why do you keep spewing the constant character 0xAA every time the process completes. Can't you come up with a saner test program? What SPI data comes back from the device. How about the chip select, have you made a provision for that? Don't you need to unload that data from the buffer after the transmission is complete? What test equipment are you using? I suggest more reading on your part.
 

John P

Joined Oct 14, 2008
2,025
I've used the MAX7219 with SPI communication from a PIC, but it was a PIC16F690. However, they're all the same as far as operation of the registers is concerned, so that shouldn't make any difference.

Here's my code, as written for the CCS compiler; I don't use this any more, but it should be clear how the code functions. [But edited to say--it is a feature of CCS that an "int" is actually a single byte--so any time you see it, remember it's actually "unsigned char".] In my design, I had a 74HC595 shift register in line with two 7219's, so that data passed serially through each component in turn; the clock and strobe lines were in common. The 74HC595 was closest to the processor, so its data went out last. You can just ignore that. Note that the 7219 takes 16 bits on the SPI line, which means the processor must send 2 bytes for every write operation, the first one being an internal address for the 7219, and the other being data. With 2 7219's and the 74HC595, I have to send 5 bytes every time I write anything. The use of the "portc_shadow" register is to get around the PIC processor's annoying feature of read-modify-write on the output pins, where writing one pin can make others change. Just to be safe, I wrote to a dummy register and then loaded it all at once to the port.

I have to tell you, I do all my programming with an oscilloscope on a shelf above my bench, and I can check all the outputs from the processor. If I couldn't do that, I'd spend endless time trying to figure out if something wasn't working because of software problems or a wiring error. I can't imagine how anyone gets anything done without the ability to see what's happening!

Code:
void write_to_7219(int addr_l, int data_l, int addr_h, int data_h, int to_local)
{

   bit_clear(sspcon, 7);                      // Clear write collision detect

   sspbuf = addr_h;                           // Send a byte
   while (!bit_test(sspstat, 0)) ;         // Wait for it to complete
   sspbuf = data_h;
   while (!bit_test(sspstat, 0)) ;         // Every write involves 5 SPI bytes
   sspbuf = addr_l;
   while (!bit_test(sspstat, 0)) ;
   sspbuf = data_l;
   while (!bit_test(sspstat, 0));
   sspbuf = to_local;                         // To 74HC595
   while (!bit_test(sspstat, 0)) ;

   bit_set(portc_shadow, 6);
   portc = portc_shadow;                 // Strobe high

   bit_clear(portc_shadow, 6);
   portc = portc_shadow;                 // 7219 strobe low
}

void init_7219 (void)
{
  int i;

   write_to_7219(0xC, 1, 0xC, 1, 0);               // Turn displays on
   write_to_7219(0x9, 0x0, 0x9, 0x0, 0   );     // Decode mode, no decode for all digits
   write_to_7219(0xA, 0x8, 0xA, 0x8, 0);        // Intensity, set for full brightness
   write_to_7219(0xB, 7, 0xB, 7, 0);               // Scan limit, use all digits

   for (i = 0; i < 8; i++)
     write_to_7219(i+1, 0, i+1, 0, 0);              // Blank display, all segments (write 0 to each digit)
}


This part is in main():
   sspstat = 0b01000000;
   sspcon = 0b00100000;                              // Master mode, Fosc/4 (1MHz)
   init_7219();
   //write_to_7219(0xF, 1, 0xF, 1, 0x7F);      // Display test mode on
   write_to_7219(0xF, 0, 0xF, 0, 0);              // Display test mode off
 
Last edited:

Thread Starter

Ben_C

Joined Oct 19, 2010
65
I have it working! :D Thanks for the help to both Johns, I had a working code it turns out I had the 1088BS opposed to the 1088AS matrix, basically rewired it and got it working. Papabravo it was almost 3AM in the morning, I had been staring at my screen all day my mind was way out! :D

But yes, I will sure be studying more on this subject. Thanks again.
 

Attachments

Top