View previous topic :: View next topic |
Author |
Message |
StingzLD
Joined: 18 Jul 2010 Posts: 42 Location: Richmond, VA
|
Simple Bit Bang Code |
Posted: Sun Jul 25, 2010 4:08 pm |
|
|
Hey Y'all,
I was wondering if somebody could help me out by giving me a very simplistic piece of bit banging code. I don't need this to be specific to any PIC, but the one I will be using the code on is the PIC16F684. I know it would be easier to get a new chip with a UART, but I am broke and teaching myself all of this and it's all I have at the time. So what I need help with is to be able to send a 16-bit packet (MSB first) out of any I/O pin you desire.
[I have tried searching for this on the forum, but everything I find is far beyond my knowledge of C right now and too specific to their programs that I don't have a clue as to what is happening in them. I just started teaching myself C a week and a half ago! So the simpler you can make it, the better ]
Thanks! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 25, 2010 4:15 pm |
|
|
There is no need to start a new thread. You have an existing thread here
on the same topic:
http://www.ccsinfo.com/forum/viewtopic.php?t=43122
In fact, in that thread I gave you a link to a bit-banged driver for the
MAX7219 and you were happy. What happened ? |
|
|
StingzLD
Joined: 18 Jul 2010 Posts: 42 Location: Richmond, VA
|
|
Posted: Sun Jul 25, 2010 4:36 pm |
|
|
I was happy that there was a readily available source code that interfaced with the MAX7219. Unfortunately, from what I can gather from the code, it is not doing what I want it to do. But I do not know C well enough to say what I can delete from it and what I need to add to make it fit my situation. I am not using the driver for 7-segment displays; I am using the driver to illuminate numerous LEDs. I do thank you for that post, and I still have the code sitting in front of me trying to figure it out. But it's not hitting me.
And I know I had another thread, but I figured since I kind of finalized my needs in that one before I actually took a long hard look at the code that people would just stop looking at that thread. I apologize if that was the wrong thing to do. I am pretty new to asking for help on forums as well. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 25, 2010 4:50 pm |
|
|
The MAX7219 is designed for 7-segment displays. It has Segment pins
and Digit pins. What is your project ? Maybe there is a more suitable
driver chip for it. |
|
|
StingzLD
Joined: 18 Jul 2010 Posts: 42 Location: Richmond, VA
|
|
Posted: Sun Jul 25, 2010 4:51 pm |
|
|
I guess I should have clarified what I meant by "it is not doing what I want it to do." The MAX7219.c file that you provided me a link to in my old thread used an array to store letters to display on the displays. The way he used that file to in his main code is used strictly to illuminate those letters on the display specified. His code also reversed the way the bits of the packet were arranged, and that kind of messed my head as well. What I am saying is that I just need a simple piece of code that will allow me to bit bang 0000111100001111 or 1111000011110000 etc. |
|
|
StingzLD
Joined: 18 Jul 2010 Posts: 42 Location: Richmond, VA
|
|
Posted: Sun Jul 25, 2010 4:55 pm |
|
|
You are correct, it is made for 7-segment displays. What I am using it for is the alternative method of driving LEDs that allows me to only use 3 pins instead of a million (so-to-speak of course). This method is introduced in the actual datasheet itself. The beauty of the chip is you can use it to illuminate whichever LED you wish just like a single segment of a display. I just don't know how to send the information to the driver haha. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 25, 2010 5:32 pm |
|
|
Here is a simple routine that will send a 16-bit word to the MAX7219.
Code: |
#include <16F684.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT
#use delay(clock=4000000)
#define MAX7219_SCLK PIN_C0
#define MAX7219_DIN PIN_C1
void send_word(int16 data)
{
int8 i;
output_low(MAX7219_SCLK);
for(i=0; i<16; i++)
{
output_bit(MAX7219_DIN, shift_left(&data, 2, 0)); // Send data bit
output_high(MAX7219_SCLK); // Create a positive clock pulse
output_low(MAX7219_SCLK);
}
}
//==========================================
void main()
{
send_word(0x1234);
while(1);
} |
|
|
|
StingzLD
Joined: 18 Jul 2010 Posts: 42 Location: Richmond, VA
|
|
Posted: Sun Jul 25, 2010 5:35 pm |
|
|
Wow... That is so much simpler than I was trying to make it! Haha. Thank you so much! Sorry about the confusion earlier. |
|
|
StingzLD
Joined: 18 Jul 2010 Posts: 42 Location: Richmond, VA
|
|
Posted: Sun Jul 25, 2010 6:19 pm |
|
|
Unfortunately I am having trouble getting this code to work. I, of course, changed the word to be sent to 0x01FF which according to the datasheet should turn on all of the LEDs connected to Digit 1. I have also checked all of my connections, and they appear to be correct. I even tried disconnecting my USB power and powering through a wall wart to see if the driver was just not receiving enough power. Still nothing. I tried tinkering around with the code, but nothing I did seem to change anything. Since you wrote it, I feel you will probably have the upper hand in this. |
|
|
StingzLD
Joined: 18 Jul 2010 Posts: 42 Location: Richmond, VA
|
|
Posted: Sun Jul 25, 2010 6:30 pm |
|
|
NEVERMIND! I figured it out! There was only one thing you left out. You needed to make the MAX7219_DIN pin low before sending the data through it.
So:
Code: |
for(i=0; i<16; i++)
{
output_low(MAX7219_DIN);
output_bit(MAX7219_DIN, shift_left(&data, 2, 0)); // Send data bit
output_high(MAX7219_SCLK); // Create a positive clock pulse
output_low(MAX7219_SCLK);
}
|
Thanks again for your help! |
|
|
StingzLD
Joined: 18 Jul 2010 Posts: 42 Location: Richmond, VA
|
|
Posted: Sun Jul 25, 2010 6:38 pm |
|
|
.... I take back my previous excitement. As it turns out, that change in code made all of the LEDs turn on that were connected to the driver while programming the chip. Unfortunately, it didn't turn only the LEDs I told it to on. And if I removed power and gave it back, the LEDs didn't light back up.
UPDATE:
Okay, I figured out the problem. I just need your help again with the coding. Apparently what is happening is the driver has gone into test mode. This happens when the first eight bits are 00001111. Which considering I am trying to send the packet 0x1FF (0000000111111111), shows that the code is sending the packet LSB first not MSB first! Now do I just change the shift_left to shift_right? Or with the way it is setup, will that send bit 0 and then go to bit 15, 14, etc.?
Last edited by StingzLD on Sun Jul 25, 2010 8:08 pm; edited 1 time in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 25, 2010 8:21 pm |
|
|
I made a test program to prove what it's doing, and it appears to be
working correctly. The program shown below has the following output:
Separating it into nybbles, gives this:
Code: |
0 1 F F
0000 0001 1111 1111
|
Here's the test program. I changed the PIC to one that has a hardware
UART so I can display the output in MPLAB. I ran the program in MPLAB
simulator. I changed the send_word() routine so that instead of sending
the bits with the output_bit() function, it displays them with putc().
This shows that the correct bit order is being maintained. The high bit
is sent out first.
Code: |
#include <16F877.H>
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
void send_word(int16 data)
{
int8 i;
int8 value;
for(i=0; i<16; i++)
{
value = shift_left(&data, 2, 0);
if(value)
putc('1');
else
putc('0');
}
}
//==========================================
void main()
{
send_word(0x01FF);
while(1);
} |
|
|
|
StingzLD
Joined: 18 Jul 2010 Posts: 42 Location: Richmond, VA
|
|
Posted: Sun Jul 25, 2010 8:44 pm |
|
|
Huh, this is crazy. I don't understand why it's not working properly on my breadboard then. I have even tried sending the register that ensures that it is in No-decode Mode. After fiddling for a while I did eventually get the LEDs to light up just on Digit 1 like I have been trying to do... but I put them in a blinking loop and they were not blinking while being extremely dim. I don't know what else I can try modifying in the code to make it work. I mean, obviously, the test you did in MPLAB shows that it's suppose to work. Maybe my hardware just hates me, even though it's wired correctly? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Jul 26, 2010 1:22 am |
|
|
Quote: | ... but I put them in a blinking loop and they were not blinking while being extremely dim. | One possibility is that you are blinking the leds but at a very high frequency. The standard method for dimming leds is to switch them on/off rapidly and I wouldn't be surprised if that's what you are doing.
Post your code for the blinking leds. |
|
|
StingzLD
Joined: 18 Jul 2010 Posts: 42 Location: Richmond, VA
|
|
Posted: Mon Jul 26, 2010 8:27 am |
|
|
I can't imagine why they would be blinking fast enough to basically be dimming via PWM, but here's the code for that section:
Code: |
while (1)
{
send_word(0x01FF);
delay_ms(1000);
send_word(0x0100);
delay_ms(1000);
}
|
But even if the blinking part gets fixed, there is still the problem that nothing lights up after I have broken the power connection and reapplied it. I am starting to wonder if there is some kind of special timing with this driver in order to make the code work. I mean MPLAB showed that the packet was being sent MSB first, but that doesn't mean that the chip is actually receiving the sent code. |
|
|
|