Используя AVR Atmega32 SPI без штырьков SPI
Я довольно новичок в программировании микроконтроллеров. У меня есть некоторый опыт работы с Arduino, но после того, как я почти закончил свой проект, я решил перевести свой текущий проект на что-то более дешевое и меньшее. Поэтому я сейчас использую AVR ATmega32 со студией Atmel.
Я пытаюсь использовать ATmega32 для связи с чипом MAX7219 для мультиплексирования со светодиодной матрицей. однако у меня есть несколько разных устройств, с которыми я хочу общаться.
Как я могу общаться с устройством без фактического использования выводов SPI на микроконтроллере? Я сделал тестовый проект, но, похоже, что-то не так, и я не могу понять, в чем проблема. Я думаю, что мне удалось получить его в тестовом режиме, потому что все светодиоды горят, но я не могу заставить его что-либо делать после этого. Я даже не могу очистить дисплей / выключить его. Я проверил проводку снова. Возможно, мое кодирование неверно относительно конфигурации контактов и назначения контактов? Есть какие-нибудь предложения для этого или лучший способ написать мой код?
Вот ссылка на техническое описание MA7219
//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
}
1 ответ
Да, у вашего кода побитового удара есть проблема в том, что вы каждый раз присваиваете полное значение регистра без сохранения существующего значения. Следовательно, вы стираете свой сигнал данных в тот момент, когда вы управляете часами, нарушая время удержания приемника и приводя к непредсказуемой работе.
Вместо того, чтобы назначать контакты с =
, вы должны установить их с |=
или очистить их &= ~(value)
Например:
PORTB = 1 << PINB0; //drive data
// tick
PORTB |= 1 << PINB1; //clock high PRESERVING data
// tock
PORTB &= ~(1 << PINB1); //clock low
Вам также может понадобиться вставить небольшую задержку между операциями с булавками.
Технически, учитывая, что вы уже используете if
для состояния данных вы также можете переопределить сигнал данных с помощью ИЛИ в назначении, например
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;
}