I am fairly new to programming microcontrollers. I have some experience with the Arduino, but after I had nearly finished my project, I deceided to moved my current project to something cheaper and smaller. So I am now using the AVR ATmega32 with Atmel studio.
I'm trying to use the ATmega32 to communicate to a MAX7219 chip for multiplexing with an led matrix. however, I do have multiple different devices that I want to communicate with.
How can I communicate with the device without actually using the SPI pins provided on the microcontroller? I have made a test project, but there seems to be something wrong and I can't figure it out what the issue is. I think I managed to get it in test mode, because all LEDs are lit, but I can't get it to do anything after that. I can't even clear the display/shut it down. I have checked the wiring over again. Is my coding perhaps incorrect as far as pin configuration and assigning the pins? Are there any suggestions for this or a better way to write my code?
Here is the link to the MA7219 datasheet
//test
#include <avr/io.h>
int main(void)
{
DDRB = 0b00000111; // pin 1(data), 2(clock) and 3(latch) are outputs
PORTB = 0 << PINB0; // data pin 1 is low
PORTB = 0 << PINB1; // clock pin 2 is low
PORTB = 0 << PINB2; // latch pin 3 is low
uint16_t data;
data = 0b0000110000000000; // data to shift out to the max7219
//read bit
uint16_t mask;
for (mask = 0b0000000000000001; mask>0; mask <<= 1)
{
//iterate through bit mask
if (data & mask)
{ // if bitwise AND resolves to true
// send one
PORTB = 1 << PINB0;
// tick
PORTB = 1 << PINB1;
// tock
PORTB = 0 << PINB1;
}
else{ //if bitwise and resolves to false
// send 0
// send one
PORTB = 0 << PINB0;
// tick
PORTB = 1 << PINB1;
// tock
PORTB = 0 << PINB1;
}
}
PORTB = 1 << PINB2; // latch all the data
PORTB = 1 << PINB0; // data pin 1 is high
PORTB = 0 << PINB1; // clock pin 2 is low
PORTB = 0 << PINB2; // latch pin 3 is low
}
Yes, your bit-bang code has a problem in that you assign the entire value of the register each time without preserving the existing value. Hence you erase your data signal at the instant you drive your clock, violating the hold time of the receiver and resulting in unpredictable operation.
Instead of assigning pins with =
, you should set them with |=
or clear them with &= ~(value)
For example:
PORTB = 1 << PINB0; //drive data
// tick
PORTB |= 1 << PINB1; //clock high PRESERVING data
// tock
PORTB &= ~(1 << PINB1); //clock low
You may also need to insert a slight delay between pin operations.
Technically, given that you are already using an if
for the data state, you could also re-drive the data signal with an OR in the assignment, for example
if (data & mask)
{ // if bitwise AND resolves to true
// send one
PORTB = 1 << PINB0;
// tick
PORTB = (1 << PINB1) | (1 << PINB0);
// tock
PORTB = 0 << PINB1 | (1 << PINB0);
}
else{ //if bitwise and resolves to false
// send 0
// send one
PORTB = 0 << PINB0;
// tick
PORTB = 1 << PINB1;
// tock
PORTB = 0 << PINB1;
}