usando AVR Atmega32 SPI sem pinos SPI
-
21-12-2019 - |
Pergunta
Sou bastante novo na programação de microcontroladores.Tenho alguma experiência com Arduino, mas depois de quase terminar meu projeto, decidi mudar meu projeto atual para algo mais barato e menor.Então agora estou usando o AVR ATmega32 com o estúdio Atmel.
Estou tentando usar o ATmega32 para me comunicar com um chip MAX7219 para multiplexação com matriz de led.no entanto, tenho vários dispositivos diferentes com os quais desejo me comunicar.
Como posso me comunicar com o dispositivo sem realmente usar os pinos SPI fornecidos no microcontrolador?Fiz um projeto de teste, mas parece haver algo errado e não consigo descobrir qual é o problema.Acho que consegui colocá-lo em modo de teste, porque todos os LEDs estão acesos, mas não consigo fazer nada depois disso.Não consigo nem limpar/desligar a tela.Verifiquei a fiação novamente.Minha codificação está incorreta no que diz respeito à configuração dos pinos e à atribuição dos pinos?Há alguma sugestão para isso ou uma maneira melhor de escrever meu código?
Aqui está o link para o Folha de dados 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
}
Solução
Sim, seu código bit bang tem um problema porque você atribui todo o valor do registro a cada vez, sem preservar o valor existente.Conseqüentemente, você apaga o sinal de dados no instante em que aciona o relógio, violando o tempo de espera do receptor e resultando em uma operação imprevisível.
Em vez de atribuir pinos com =
, você deve configurá-los com |=
ou limpe-os com &= ~(value)
Por exemplo:
PORTB = 1 << PINB0; //drive data
// tick
PORTB |= 1 << PINB1; //clock high PRESERVING data
// tock
PORTB &= ~(1 << PINB1); //clock low
Você também pode precisar inserir um pequeno atraso entre as operações dos pinos.
Tecnicamente, dado que você já está usando um if
para o estado dos dados, você também pode reorientar o sinal de dados com um OR na atribuição, por exemplo
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;
}