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); } }