74hc595 e Max7219 juntos no mesmo barramento.Posted by Dicas Arduino on Domingo, 4 de outubro de 2015
Agora rodando em um attiny85.74hc595 e Max7219 juntos no mesmo barramento.Posted by Dicas Arduino on Domingo, 4 de outubro de 2015
Apesar de a ideia não ser entrar em detalhes do que são e como funcionam Registradores de Deslocamento, vou deixar aqui um trecho do que a wikipedia diz sobre eles:
Em eletrônica digital um registrador de deslocamento é um conjunto de registradores configurados em um arranjo linear de tal forma que a informação é deslocada pelo circuito conforme o mesmo é ativado.
Os registradores de deslocamento podem possuir uma combinação de entradas e saídas seriais e paralelas, incluindo as configurações entrada serial, saída paralela (SIPO) e entrada paralela, saída serial (PISO). Existem outra configurações possuindo ambas as entradas serial e paralela e outra com saídas serial paralela. Existem também registradores de deslocamento bi-direcionais, os quais permitem que se varie a direção do deslocamento da informação. As entradas e saídas seriais de um registrador podem ser conectadas juntas, de modo a formar um registrador de deslocamento circular. Poderiam também ser desenvolvidos registradores de deslocamento multi-dimensionais, os quais podem realizar processamentos mais complexos. Mais informações, aqui.
Os registradores de deslocamento podem possuir uma combinação de entradas e saídas seriais e paralelas, incluindo as configurações entrada serial, saída paralela (SIPO) e entrada paralela, saída serial (PISO). Existem outra configurações possuindo ambas as entradas serial e paralela e outra com saídas serial paralela. Existem também registradores de deslocamento bi-direcionais, os quais permitem que se varie a direção do deslocamento da informação. As entradas e saídas seriais de um registrador podem ser conectadas juntas, de modo a formar um registrador de deslocamento circular. Poderiam também ser desenvolvidos registradores de deslocamento multi-dimensionais, os quais podem realizar processamentos mais complexos. Mais informações, aqui.
Dois exemplos de Registradores de Deslocamento são o Max7219 e o 74HC595, cada um com uma finalidade diferente. Enquanto o 595 é usado apenas para expandir saídas, o Max7219 tem o objetivo de servir como driver para display de 7 segmentos e matriz de Leds 8x8. Apesar de terem suas diferenças, a comunicação entre os dois é basicamente a mesma, com a pequena diferença de que o 595 possui 8 bits de Saída, enquanto que o Max7219 possui 16.
Também não vou entrar em maiores detalhes de como cada um funciona, mas pra quem quiser mais informações, seguem os links para os datasheets:
https://www.sparkfun.com/datasheets/Components/General/COM-09622-MAX7219-MAX7221.pdf
http://www.nxp.com/documents/data_sheet/74HC_HCT595.pdf
Aqui no blog mesmo, há várias postagens sobre o 74HC595: http://fabianoallex.blogspot.com.br/search?q=74HC595
A grande vantagem dos Registradores de Deslocamento é que eles podem ser ligados em cascata e sem um limite de quantidade. Ambos possuem 3 pinos de comunicação, clock e data, além do Load no max7219 e o seu equivalente Latch para o 74HC595.
Fisicamente não há grandes dificuldades na comunicação entre eles, uma estudada sobre como são as ligações de ambos dará pra entender (instintivamente) como liga-los juntos. Mas no caso específico que mostro aqui, há algumas regras. Foi necessário ligar primeiramente os Max7219, e por último os 595, nunca intercalando um com o outro.
Programação
A parte que deu mais trabalho foi a parte de programação, já que a ideia foi reutilizar as classes já existentes para controle de ambos, no caso do Max 7219 a biblioteca LedControl, e do 74HC595, utilizar uma classe que já disponibilizei aqui no blog ( veja ). Eu poderia criar uma classe do zero e recriar todas as funcionalidades nessa única classe, mas achei que seria retrabalho, então a ideia foi fazer algo que unisse a funcionalidade das duas.
As explicações dadas daqui pra baixo irão exigir um conhecimento básico de conceitos de Orientação a Objetos. Já fiz um vídeo falando algumas coisas sobre o assunto: http://fabianoallex.blogspot.com.br/2014/09/arduino-dicas-de-programacao-04.html
Ambas as classes agora precisam funcionar de maneira unificada. Quando os dados de qualquer uma das duas for atualizado, será necessário envia-los para todos os CIs que estão ligados em cascata e não apenas a que foi alterada. Pra isso foi necessário criar uma terceira classe que controlasse o envio dos dados para os registradores, a qual chamei de ShiftRegisterController.
A finalidade dessa classe é gerenciar o envio dos dados para os CIs. Porém ainda há um outro detalhe, foi necessário criar uma outra classe que fosse a classe-base para LedControl e para a classe Expansor74HC595, de modo que as duas herdem as mesmas funcionalidades básicas.
class ShiftRegisterController; //prototipo
class ShiftRegister{
protected:
ShiftRegisterController * _controller;
public:
virtual void shiftOutRegister() ;
};
class ShiftRegisterController {
private:
int _pin_latch; // ou load no max7219
ShiftRegister * _exp_595;
ShiftRegister * _exp_lc;
public:
ShiftRegisterController(int pin_latch) {
_pin_latch = pin_latch;
pinMode(_pin_latch,OUTPUT);
digitalWrite(_pin_latch, HIGH);
}
void setLedControl(ShiftRegister * lc) { _exp_lc = lc; }
void setExp74HC595(ShiftRegister * exp_595) { _exp_595 = exp_595; }
void shiftOutRegisters() {
if (_exp_595 && _exp_lc){
digitalWrite(_pin_latch, LOW);
_exp_595->shiftOutRegister();
_exp_lc ->shiftOutRegister();
digitalWrite(_pin_latch, HIGH);
}
}
};
Além da inclusão dessas novas classes, foram feitas alterações nas definições das classes já existentes, indicando que as mesmas, agora serão herdadas de ShiftRegister:
class Expansor74HC595 : public ShiftRegister {...};
class LedControl : public ShiftRegister {...};
Podemos ver que há um atributo chamado _pin_latch na classe ShiftRegisterController, que anteriormente ficava nas classes LedControl e Expansor74HC595, pois é através desse pino que todos os CIs são "notificados" que as alterações estão prontas e devem ser aplicadas as suas respectivas saídas, logo, as duas classes citadas não controlam mais quando os dados são finalizados, ficando essa função para a classe ShiftRegisterController.
Observação: Pra não ter que fazer essas alterações diretamente na biblioteca LedControl, eu copiei todo o conteúdo da classe dentro da própria sketch e fiz as alterações necessárias, como pode ser visto no código completo mais abaixo. Em outro artigo eu já mostrei como fazer isso, incluindo algumas melhorias na classe LedControl, a quais explico nesse artigo: http://fabianoallex.blogspot.com.br/2015/09/arduino-alteracoes-na-biblioteca.html
O código abaixo mostra como devem ser declarados os objetos, que são 3.
int const PIN_DATA = 10; int const PIN_CLK = 9; int const PIN_LATCH = 8; int const QUANTIDADE_MAX7219 = 2; int const QUANTIDADE_74HC595 = 1; ShiftRegisterController exp_src = ShiftRegisterController(PIN_LATCH); LedControl exp_lc = LedControl (PIN_DATA,PIN_CLK,QUANTIDADE_MAX7219, &exp_src); Expansor74HC595 exp_595 = Expansor74HC595(PIN_DATA,PIN_CLK,QUANTIDADE_74HC595 , &exp_src);
Primeiramente foi necessário criar o objeto controlador e posteriormente criar os outros dois Objetos, um LedControl e outro Expansor74HC595. Veja que o primeiro objeto recebeu como parâmetro o PIN_LATCH, enquanto que as demais classes não recebem mais esse parâmetro, recebendo apenas o pino de clock e o pino de data, porém recebem como parâmetro o endereço do objeto controlador.
Código-Fonte - Arduino Uno:
/*
Criado em 04/10/2015
Por:
Fabiano A. Arndt
http://www.youtube.com/fabianoallex
http://fabianoallex.blogspot.com.br
fabianoallex@gmail.com
*/
/*
* LedControl.h / LedControl.cpp - A library for controling Leds with a MAX7219/MAX7221
* Copyright (c) 2007 Eberhard Fahle
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* This permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*************************************************************************************************************
*******************************CLASSES ShiftRegister E ShiftRegisterController********************************
**************************************************************************************************************/
class ShiftRegisterController; //prototipo
class ShiftRegister{
protected:
ShiftRegisterController * _controller;
public:
virtual void shiftOutRegister() ;
};
class ShiftRegisterController {
private:
int _pin_latch;
ShiftRegister * _exp_595;
ShiftRegister * _exp_lc;
public:
ShiftRegisterController(int pin_latch) {
_pin_latch = pin_latch;
pinMode(_pin_latch,OUTPUT);
digitalWrite(_pin_latch, HIGH);
}
void setLedControl(ShiftRegister * lc) { _exp_lc = lc; }
void setExp74HC595(ShiftRegister * exp_595) { _exp_595 = exp_595; }
void shiftOutRegisters() {
if (_exp_595 && _exp_lc){
digitalWrite(_pin_latch, LOW);
_exp_595->shiftOutRegister();
_exp_lc ->shiftOutRegister();
digitalWrite(_pin_latch, HIGH);
}
}
};
/*************************************************************************************************************
***************************FIM CLASSES ShiftRegister E ShiftRegisterController********************************
**************************************************************************************************************/
/*************************************************************************************************************
*******************************EXPANSOR 74HC595***************************************************************
**************************************************************************************************************/
class Expansor74HC595 : public ShiftRegister {
private:
int _pin_clock;
int _pin_data;
int _num_cis;
byte* _pins;
int _auto_send;
public:
Expansor74HC595(int pin_data, int pin_clock, int num_cis, ShiftRegisterController * controller){
_pin_clock = pin_clock;
_pin_data = pin_data;
_num_cis = num_cis;
_auto_send = true;
_pins = new byte[_num_cis];
_controller = controller;
_controller->setExp74HC595(this);
pinMode(_pin_clock,OUTPUT);
pinMode(_pin_data, OUTPUT);
//clear();
};
void startWrite() { _auto_send = false; };
void clear() {
for (int i=0; i<_num_cis; i++){ _pins[i] = 0b00000000; }
send();
};
int read(int pin) {
if (pin >= _num_cis * 8) {return LOW;}
int pos = pin / 8;
pin = pin % 8;
return (_pins[pos] & (1 << pin)) != 0;
};
byte readByte(int num_ci) {
return _pins[num_ci];
};
void shiftOutRegister(){ for(int i=_num_cis-1; i>=0; i--) { shiftOut(_pin_data, _pin_clock, MSBFIRST, readByte(i) ); } };
void send(){
_controller->shiftOutRegisters();
_auto_send = true;
};
void writeByte(int num_ci, byte b, int first = MSBFIRST) {
if (first == MSBFIRST){
byte reversed;
for(int i=0;i<8;i++){ reversed |= ((b>>i) & 0b1)<<(7-i); }
b = reversed;
}
_pins[num_ci] = b;
if (_auto_send) { send(); }
};
void write(int pin, int value) {
if (pin >= _num_cis * 8) { return; }
int pos = pin / 8;
pin = pin % 8;
if (value){
_pins[pos] |= (1 << pin); //set a bit HIGH
} else {
_pins[pos] &= ~(1 << pin); //set a bit LOW
}
if (_auto_send) { send(); }
};
};
/*************************************************************************************************************
*******************************FIM 74HC595********************************************************************
**************************************************************************************************************/
/*************************************************************************************************************
*******************************LEDCONTROL ALTERADA************************************************************
**************************************************************************************************************/
//the opcodes for the MAX7221 and MAX7219
#define OP_DECODEMODE 9
#define OP_INTENSITY 10
#define OP_SCANLIMIT 11
#define OP_SHUTDOWN 12
#define OP_DISPLAYTEST 15
class LedControl : public ShiftRegister {
private :
byte spidata[16];
byte * status;
int SPI_MOSI;
int SPI_CLK;
int maxDevices;
int _auto_send;
void spiTransfer(int addr, volatile byte opcode, volatile byte data) {
int offset = addr*2;
int maxbytes = maxDevices*2;
for(int i=0;i<maxbytes;i++) { spidata[i]=(byte)0; }
spidata[offset+1] = opcode;
spidata[offset] = data;
_controller->shiftOutRegisters();
}
public:
void shiftOutRegister(){ for(int i=maxDevices*2;i>0;i--) { shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]); } };
LedControl(int dataPin, int clkPin, int numDevices, ShiftRegisterController * controller) {
_auto_send = true;
SPI_MOSI = dataPin;
SPI_CLK = clkPin;
maxDevices = numDevices;
_controller = controller;
_controller->setLedControl(this);
pinMode(SPI_MOSI, OUTPUT);
pinMode(SPI_CLK, OUTPUT);
status = new byte[maxDevices * 8]; //instancia o array de acordo com a quantia de displays usados
for(int i=0;i<maxDevices * 8 ;i++) { status[i]=0x00; }
}
void begin(){
for(int i=0;i<maxDevices;i++) {
spiTransfer(i, OP_DISPLAYTEST,0);
setScanLimit(i, 7); //scanlimit is set to max on startup
spiTransfer(i, OP_DECODEMODE,0); //decode is done in source
clearDisplay(i);
shutdown(i,true); //we go into shutdown-mode on startup
}
}
void startWrite() { _auto_send = false; };
void send() {
for (int j=0; j<maxDevices; j++) {
int offset = j*8;
for(int i=0;i<8;i++) { spiTransfer(j, i+1, status[offset+i]); }
}
_auto_send = true;
}
int getDeviceCount(){ return maxDevices; }
void shutdown(int addr, bool b){
if(addr<0 || addr>=maxDevices) return;
spiTransfer(addr, OP_SHUTDOWN, b ? 0 : 1);
}
void setScanLimit(int addr, int limit){
if(addr<0 || addr>=maxDevices) return;
if(limit>=0 && limit<8) spiTransfer(addr, OP_SCANLIMIT,limit);
}
void setIntensity(int addr, int intensity) {
if(addr<0 || addr>=maxDevices) { return; }
if(intensity>=0 && intensity<16) { spiTransfer(addr, OP_INTENSITY, intensity); }
}
void clearDisplay(int addr){
if(addr<0 || addr>=maxDevices) return;
int offset = addr*8;
for(int i=0;i<8;i++) {
status[offset+i] = 0;
if (_auto_send) { spiTransfer(addr, i+1, status[offset+i]); }
}
}
void setLed(int addr, int row, int column, boolean state) {
if(addr<0 || addr>=maxDevices) { return; }
if(row<0 || row>7 || column<0 || column>7) { return; }
int offset = addr*8;
byte val = B10000000 >> column;
if(state) { status[offset+row] = status[offset+row] | val; }
else {
val=~val;
status[offset+row] = status[offset+row]&val;
}
if (_auto_send) { spiTransfer(addr, row+1, status[offset+row]); }
}
void setRow(int addr, int row, byte value) {
if(addr<0 || addr>=maxDevices) return;
if(row<0 || row>7) return;
int offset = addr*8;
status[offset+row] = value;
if (_auto_send) {
spiTransfer(addr, row+1, status[offset+row]);
}
}
void setColumn(int addr, int col, byte value) {
if(addr<0 || addr>=maxDevices) return;
if(col<0 || col>7) return;
byte val;
for(int row=0; row<8; row++) {
val=value >> (7-row);
val=val & 0x01;
setLed(addr,row,col,val);
}
}
};
/*************************************************************************************************************
*******************************FIM LEDCONTROL ALTERADA********************************************************
**************************************************************************************************************/
/*
pin 10 is connected to the DataIn
pin 9 is connected to the CLK
pin 8 is connected to LOAD
*/
int const PIN_DATA = 10;
int const PIN_CLK = 9;
int const PIN_LATCH = 8;
int const QUANTIDADE_MAX7219 = 2;
int const QUANTIDADE_74HC595 = 1;
ShiftRegisterController exp_src = ShiftRegisterController(PIN_LATCH);
LedControl exp_lc = LedControl (PIN_DATA,PIN_CLK,QUANTIDADE_MAX7219, &exp_src);
Expansor74HC595 exp_595 = Expansor74HC595(PIN_DATA,PIN_CLK,QUANTIDADE_74HC595 , &exp_src);
const int LINHAS = 8;
const int COLUNAS = 16;
int cont=0;
void update_displays() {
exp_lc.startWrite();
for (int lin=0; lin<8; lin++) {
for (int col=0; col<16; col++) {
for (int i=0; i<2; i++) {
int l = lin;
int c = col - (i*8);
if (l>=0 && l<=7 && c>=0 && c<=7) {
exp_lc.setLed(i, l, c, (l+c+cont)%2 );
}
}
}
}
cont++;
exp_lc.send();
}
void setup() {
//Serial.begin(9600);
exp_lc.begin();
exp_lc.shutdown(0,false);
exp_lc.setIntensity(0,8);
exp_lc.clearDisplay(0);
exp_lc.shutdown(1,false);
exp_lc.setIntensity(1,8);
exp_lc.clearDisplay(1);
}
void loop() {
for (byte b=0; b<=255; b++) { //i=0-> B00000000 i=255-> B11111111
exp_595.startWrite();
exp_595.writeByte(0, b, LSBFIRST);
exp_595.send();
update_displays();
delay(500);
}
}
Código-fonte Attiny85:
/*
Criado em 04/10/2015
Por:
Fabiano A. Arndt
http://www.youtube.com/fabianoallex
http://fabianoallex.blogspot.com.br
fabianoallex@gmail.com
*/
/*
* LedControl.h / LedControl.cpp - A library for controling Leds with a MAX7219/MAX7221
* Copyright (c) 2007 Eberhard Fahle
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* This permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*************************************************************************************************************
*******************************CLASSES ShiftRegister E ShiftRegisterController********************************
**************************************************************************************************************/
class ShiftRegisterController; //prototipo
class ShiftRegister{
protected:
ShiftRegisterController * _controller;
public:
virtual void shiftOutRegister() ;
};
class ShiftRegisterController {
private:
int _pin_latch;
ShiftRegister * _exp_595;
ShiftRegister * _exp_lc;
public:
ShiftRegisterController(int pin_latch) {
_pin_latch = pin_latch;
pinMode(_pin_latch,OUTPUT);
digitalWrite(_pin_latch, HIGH);
}
void setLedControl(ShiftRegister * lc) { _exp_lc = lc; }
void setExp74HC595(ShiftRegister * exp_595) { _exp_595 = exp_595; }
void shiftOutRegisters() {
if (_exp_595 && _exp_lc){
digitalWrite(_pin_latch, LOW);
_exp_595->shiftOutRegister();
_exp_lc ->shiftOutRegister();
digitalWrite(_pin_latch, HIGH);
}
}
};
/*************************************************************************************************************
***************************FIM CLASSES ShiftRegister E ShiftRegisterController********************************
**************************************************************************************************************/
/*************************************************************************************************************
*******************************EXPANSOR 74HC595***************************************************************
**************************************************************************************************************/
class Expansor74HC595 : public ShiftRegister {
private:
int _pin_clock;
int _pin_data;
int _num_cis;
byte* _pins;
int _auto_send;
public:
Expansor74HC595(int pin_data, int pin_clock, int num_cis, ShiftRegisterController * controller){
_pin_clock = pin_clock;
_pin_data = pin_data;
_num_cis = num_cis;
_auto_send = true;
_pins = new byte[_num_cis];
_controller = controller;
_controller->setExp74HC595(this);
pinMode(_pin_clock,OUTPUT);
pinMode(_pin_data, OUTPUT);
//clear();
};
void startWrite() { _auto_send = false; };
void clear() {
for (int i=0; i<_num_cis; i++){ _pins[i] = 0b00000000; }
send();
};
int read(int pin) {
if (pin >= _num_cis * 8) {return LOW;}
int pos = pin / 8;
pin = pin % 8;
return (_pins[pos] & (1 << pin)) != 0;
};
byte readByte(int num_ci) { return _pins[num_ci]; };
void shiftOutRegister(){ for(int i=_num_cis-1; i>=0; i--) { shiftOut(_pin_data, _pin_clock, MSBFIRST, readByte(i) ); } };
void send(){
_controller->shiftOutRegisters();
_auto_send = true;
};
void writeByte(int num_ci, byte b, int first = MSBFIRST) {
if (first == MSBFIRST){
byte reversed;
for(int i=0;i<8;i++){ reversed |= ((b>>i) & 0b1)<<(7-i); }
b = reversed;
}
_pins[num_ci] = b;
if (_auto_send) { send(); }
};
void write(int pin, int value) {
if (pin >= _num_cis * 8) { return; }
int pos = pin / 8;
pin = pin % 8;
if (value){
_pins[pos] |= (1 << pin); //set a bit HIGH
} else {
_pins[pos] &= ~(1 << pin); //set a bit LOW
}
if (_auto_send) { send(); }
};
};
/*************************************************************************************************************
*******************************FIM 74HC595********************************************************************
**************************************************************************************************************/
/*************************************************************************************************************
*******************************LEDCONTROL ALTERADA************************************************************
**************************************************************************************************************/
//the opcodes for the MAX7221 and MAX7219
#define OP_DECODEMODE 9
#define OP_INTENSITY 10
#define OP_SCANLIMIT 11
#define OP_SHUTDOWN 12
#define OP_DISPLAYTEST 15
class LedControl : public ShiftRegister {
private :
byte spidata[16];
byte * status;
int SPI_MOSI;
int SPI_CLK;
int maxDevices;
int _auto_send;
void spiTransfer(int addr, volatile byte opcode, volatile byte data) {
int offset = addr*2;
int maxbytes = maxDevices*2;
for(int i=0;i<maxbytes;i++) { spidata[i]=(byte)0; }
spidata[offset+1] = opcode;
spidata[offset] = data;
_controller->shiftOutRegisters();
}
public:
void shiftOutRegister(){ for(int i=maxDevices*2;i>0;i--) { shiftOut(SPI_MOSI,SPI_CLK,MSBFIRST,spidata[i-1]); } };
LedControl(int dataPin, int clkPin, int numDevices, ShiftRegisterController * controller) {
_auto_send = true;
SPI_MOSI = dataPin;
SPI_CLK = clkPin;
maxDevices = numDevices;
_controller = controller;
_controller->setLedControl(this);
pinMode(SPI_MOSI, OUTPUT);
pinMode(SPI_CLK, OUTPUT);
status = new byte[maxDevices * 8]; //instancia o array de acordo com a quantia de displays usados
for(int i=0;i<maxDevices * 8 ;i++) { status[i]=0x00; }
}
void begin(){
for(int i=0;i<maxDevices;i++) {
spiTransfer(i, OP_DISPLAYTEST,0);
setScanLimit(i, 7); //scanlimit is set to max on startup
spiTransfer(i, OP_DECODEMODE,0); //decode is done in source
clearDisplay(i);
shutdown(i,true); //we go into shutdown-mode on startup
}
}
void startWrite() { _auto_send = false; };
void send() {
for (int j=0; j<maxDevices; j++) {
int offset = j*8;
for(int i=0;i<8;i++) { spiTransfer(j, i+1, status[offset+i]); }
}
_auto_send = true;
}
int getDeviceCount(){ return maxDevices; }
void shutdown(int addr, bool b){
if(addr<0 || addr>=maxDevices) return;
spiTransfer(addr, OP_SHUTDOWN, b ? 0 : 1);
}
void setScanLimit(int addr, int limit){
if(addr<0 || addr>=maxDevices) return;
if(limit>=0 && limit<8) spiTransfer(addr, OP_SCANLIMIT,limit);
}
void setIntensity(int addr, int intensity) {
if(addr<0 || addr>=maxDevices) { return; }
if(intensity>=0 && intensity<16) { spiTransfer(addr, OP_INTENSITY, intensity); }
}
void clearDisplay(int addr){
if(addr<0 || addr>=maxDevices) return;
int offset = addr*8;
for(int i=0;i<8;i++) {
status[offset+i] = 0;
if (_auto_send) { spiTransfer(addr, i+1, status[offset+i]); }
}
}
void setLed(int addr, int row, int column, boolean state) {
if(addr<0 || addr>=maxDevices) { return; }
if(row<0 || row>7 || column<0 || column>7) { return; }
int offset = addr*8;
byte val = B10000000 >> column;
if(state) { status[offset+row] = status[offset+row] | val; }
else {
val=~val;
status[offset+row] = status[offset+row]&val;
}
if (_auto_send) { spiTransfer(addr, row+1, status[offset+row]); }
}
void setRow(int addr, int row, byte value) {
if(addr<0 || addr>=maxDevices) return;
if(row<0 || row>7) return;
int offset = addr*8;
status[offset+row] = value;
if (_auto_send) {
spiTransfer(addr, row+1, status[offset+row]);
}
}
void setColumn(int addr, int col, byte value) {
if(addr<0 || addr>=maxDevices) return;
if(col<0 || col>7) return;
byte val;
for(int row=0; row<8; row++) {
val=value >> (7-row);
val=val & 0x01;
setLed(addr,row,col,val);
}
}
};
/*************************************************************************************************************
*******************************FIM LEDCONTROL ALTERADA********************************************************
**************************************************************************************************************/
/*
pin 2 is connected to the DataIn
pin 1 is connected to the CLK
pin 0 is connected to LOAD
*/
int const PIN_DATA = 2;
int const PIN_CLK = 1;
int const PIN_LATCH = 0;
int const QUANTIDADE_MAX7219 = 2;
int const QUANTIDADE_74HC595 = 1;
ShiftRegisterController exp_src = ShiftRegisterController(PIN_LATCH);
LedControl exp_lc = LedControl (PIN_DATA,PIN_CLK,QUANTIDADE_MAX7219, &exp_src);
Expansor74HC595 exp_595 = Expansor74HC595(PIN_DATA,PIN_CLK,QUANTIDADE_74HC595, &exp_src);
const int LINHAS = 8;
const int COLUNAS = 16;
int cont=0;
void update_displays() {
exp_lc.startWrite();
for (int lin=0; lin<8; lin++) {
for (int col=0; col<16; col++) {
for (int i=0; i<2; i++) {
int l = lin;
int c = col - (i*8);
if (l>=0 && l<=7 && c>=0 && c<=7) {
exp_lc.setLed(i, l, c, (l+c+cont)%2 );
}
}
}
}
cont++;
exp_lc.send();
}
void setup() {
//Serial.begin(9600);
exp_lc.begin();
exp_lc.shutdown(0,false);
exp_lc.setIntensity(0,8);
exp_lc.clearDisplay(0);
exp_lc.shutdown(1,false);
exp_lc.setIntensity(1,8);
exp_lc.clearDisplay(1);
}
void loop() {
for (byte b=0; b<=255; b++) { //i=0-> B00000000 i=255-> B11111111
exp_595.startWrite();
exp_595.writeByte(0, b, LSBFIRST);
exp_595.send();
update_displays();
delay(500);
}
}
Nenhum comentário:
Postar um comentário