在舍友提议下,做了个。8*8RGB点阵。功能有单色、彩色、各种图形显示,循环显示数字0至9、左右移动;整体刷屏。目前屏大小只有8*8,还不支持显示汉字,不过驱动板留出了级联接口,慢慢完善。
参考:http://blog.spitzenpfeil.org/wordpress/wp-content/uploads/2008/10/matrix_code.pde
附上原理图:
附上代码:
只需要连接三根线,74595的SCK、RCK、SER(需要级联,前一个595的QH连接到下一个的SER)
- #define __spi_clock 13 // SCK
- #define __spi_latch 10 //RCK
- #define __spi_data 11 //SER+
- #define __display_enable 9
- #define __rows 8
- #define __max_row __rows-1
- #define __leds_per_row 8
- #define __max_led __leds_per_row-1
- #define __brightness_levels 32 // 0...15 above 28 is bad for ISR ( move to timer1, lower irq freq ! )
- #define __max_brightness __brightness_levels-1
- #define __fade_delay 4
- #define __TIMER1_MAX 0xFFFF // 16 bit CTR
- #define __TIMER1_CNT 0x0130 // 32 levels --> 0x0130; 38 --> 0x0157 (flicker)
- #include <avr/interrupt.h>
- #include <avr/io.h>
- #include <stdint.h>
- byte brightness_red[__leds_per_row][__rows];
- byte brightness_green[__leds_per_row][__rows];
- byte brightness_blue[__leds_per_row][__rows];
- ISR(TIMER1_OVF_vect) {
- //TCNT2 = __TIMER2_MAX - __TIMER2_CNT; // precharge TIMER2 to maximize ISR time --> max led brightness
- TCNT1 = __TIMER1_MAX - __TIMER1_CNT;
- byte cycle;
-
- digitalWrite(__display_enable,LOW); // enable display inside ISR
-
- for(cycle = 0; cycle < __max_brightness; cycle++) {
- byte led;
- byte row = B00000000; // row: current source. on when (1)
- byte red; // current sinker when on (0)
- byte green; // current sinker when on (0)
- byte blue; // current sinker when on (0)
- for(row = 0; row <= __max_row; row++) {
-
- red = B11111111; // off
- green = B11111111; // off
- blue = B11111111; // off
-
- for(led = 0; led <= __max_led; led++) {
- if(cycle < brightness_red[row][led]) {
- red &= ~(1<<led);
- }
- if(cycle < brightness_green[row][led]) {
- green &= ~(1<<led);
- }
- if(cycle < brightness_blue[row][led]) {
- blue &= ~(1<<led);
- }
- }
- digitalWrite(__spi_latch,LOW);
- spi_transfer(blue);
- spi_transfer(green);
- spi_transfer(red);
- spi_transfer(B00000001<<row);
- digitalWrite(__spi_latch,HIGH);
- digitalWrite(__spi_latch,LOW);
- }
- }
- digitalWrite(__display_enable,HIGH); // disable display outside ISR
- }
- int data[]={0x00,0x36,0x7f,0x7f,0x3e,0x1c,0x08,0x00,//xin
- 0x00,0x06,0x69,0x90,0x00,0x42,0x24,0x18,/*"xiaonian",0*/
- 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x38,/*"1",0*/
- 0x00,0x18,0x24,0x04,0x08,0x10,0x20,0x3C,/*"2",1*/
- 0x00,0x18,0x24,0x04,0x18,0x04,0x24,0x18,/*"3",2*/
- 0x00,0x08,0x18,0x18,0x28,0x28,0x3C,0x08,/*"4",3*/
- 0x00,0x3C,0x20,0x20,0x38,0x04,0x04,0x38,/*"5",4*/
- 0x00,0x18,0x24,0x20,0x38,0x24,0x24,0x18,/*"6",5*/
- 0x00,0x3C,0x24,0x04,0x08,0x10,0x10,0x10,/*"7",6*/
- 0x00,0x18,0x24,0x24,0x18,0x24,0x24,0x18,/*"8",7*/
- 0x00,0x18,0x24,0x24,0x1C,0x04,0x24,0x18,/*"9",8*/
- 0x00,0x18,0x24,0x24,0x24,0x24,0x24,0x18,/*"0",9*/
- };
- void setup(void) {
- //Serial.begin(9600);
- randomSeed(555);
- byte ctr1;
- byte ctr2;
-
- pinMode(__spi_clock,OUTPUT);
- pinMode(__spi_latch,OUTPUT);
- pinMode(__spi_data,OUTPUT);
- pinMode(__display_enable,OUTPUT);
- digitalWrite(__spi_latch,LOW);
- digitalWrite(__spi_data,LOW);
- digitalWrite(__spi_clock,LOW);
-
- setup_hardware_spi();
- delay(10);
- set_matrix_rgb(0,0,0);
- setup_timer1_ovf();
- }
- void loop(void) {
- int ctr;
-
- for(ctr=0; ctr < 2; ctr++) {
- fader_hue();//整体刷屏,颜色随设定值改变
- }
- for(ctr=0; ctr < 1; ctr++) {
- matrix_test();//从上往下刷屏,颜色随设定值改变
- }
- for(ctr=0; ctr < 4; ctr++) {
- matrix_heart_2(); //彩色
- // matrix_heart(100); //单色
- }
- }
- byte spi_transfer(byte data)
- {
- SPDR = data; // Start the transmission
- while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
- {
- };
- return SPDR; // return the received byte, we don't need that
- }
- void set_led_red(byte row, byte led, byte red) {
- brightness_red[row][led] = red;
- }
- void set_led_green(byte row, byte led, byte green) {
- brightness_green[row][led] = green;
- }
- void set_led_blue(byte row, byte led, byte blue) {
- brightness_blue[row][led] = blue;
- }
- void set_led_rgb(byte row, byte led, byte red, byte green, byte blue) {
- set_led_red(row,led,red);
- set_led_green(row,led,green);
- set_led_blue(row,led,blue);
- }
- void set_matrix_rgb(byte red, byte green, byte blue) {
- byte ctr1;
- byte ctr2;
- for(ctr2 = 0; ctr2 <= __max_row; ctr2++) {
- for(ctr1 = 0; ctr1 <= __max_led; ctr1++) {
- set_led_rgb(ctr2,ctr1,red,green,blue);
- }
- }
- }
- void set_led_hue(byte row, byte led, int hue) {
- // see wikipeda: HSV
- float S=100.0,V=100.0,s=S/100.0,v=V/100.0,h_i,f,p,q,t,R,G,B;
-
- hue = hue%360;
- h_i = hue/60;
- f = (float)(hue)/60.0 - h_i;
- p = v*(1-s);
- q = v*(1-s*f);
- t = v*(1-s*(1-f));
-
- if ( h_i == 0 ) {
- R = v;
- G = t;
- B = p;
- }
- else if ( h_i == 1 ) {
- R = q;
- G = v;
- B = p;
- }
- else if ( h_i == 2 ) {
- R = p;
- G = v;
- B = t;
- }
- else if ( h_i == 3 ) {
- R = p;
- G = q;
- B = v;
- }
- else if ( h_i == 4 ) {
- R = t;
- G = p;
- B = v;
- }
- else {
- R = v;
- G = p;
- B = q;
- }
- set_led_rgb(row,led,byte(R*(float)(__max_brightness)),byte(G*(float)(__max_brightness)),byte(B*(float)(__max_brightness)));
-
- /*
- Serial.println(byte(R*(float)(__max_brightness)),DEC);
- Serial.println(byte(G*(float)(__max_brightness)),DEC);
- Serial.println(byte(B*(float)(__max_brightness)),DEC);
- Serial.println("---");
- */
- }
- void set_row_byte_hue(byte row, byte data_byte, int hue) {
- byte led;
- for(led = 0; led <= __max_led; led++) {
- if( (data_byte>>led)&(B00000001) ) {
- set_led_hue(row,led,hue);
- }
- else {
- set_led_rgb(row,led,0,0,0);
- }
- }
- }
- void set_matrix_hue(int hue) {
- byte ctr1;
- byte ctr2;
- for(ctr2 = 0; ctr2 <= __max_row; ctr2++) {
- for(ctr1 = 0; ctr1 <= __max_led; ctr1++) {
- set_led_hue(ctr2,ctr1,hue);
- }
- }
- }
- void set_column_hue(byte column, int hue) {
- byte ctr1;
- for(ctr1 = 0; ctr1 <= __max_row; ctr1++) {
- set_led_hue(ctr1,column,hue);
- }
- }
- void setup_hardware_spi(void) {
- byte clr;
- SPCR |= ( (1<<SPE) | (1<<MSTR) ); // enable SPI as master
- //SPCR |= ( (1<<SPR1) ); // set prescaler bits
- SPCR &= ~ ( (1<<SPR1) | (1<<SPR0) ); // clear prescaler bits
- clr=SPSR; // clear SPI status reg
- clr=SPDR; // clear SPI data reg
- SPSR |= (1<<SPI2X); // set prescaler bits
- //SPSR &= ~(1<<SPI2X); // clear prescaler bits
- }
- void setup_timer1_ovf(void) {
-
- TCCR1B &= ~ ( (1<<CS11) );
- TCCR1B |= ( (1<<CS12) | (1<<CS10) );
- //normal mode
- TCCR1B &= ~ ( (1<<WGM13) | (1<<WGM12) );
- TCCR1A &= ~ ( (1<<WGM11) | (1<<WGM10) );
- //Timer1 Overflow Interrupt Enable
- TIMSK1 |= (1<<TOIE1);
- TCNT1 = __TIMER1_MAX - __TIMER1_CNT;
- // enable all interrupts
- sei();
- }
- /*---------------------------单色图形--------------------------------------------*/
- //通过改变 hue的值,来改变颜色
- void matrix_heart(int hue) {
- int k,i;
- for(k = 0; k < 600; k=k+48) {
- for(int j=0;j<8;j++)
- {
- set_row_byte_hue(j,data[j+i],hue);
- delay(20*__fade_delay);
- if(j>=7)
- i+=8;
- else if(i>=96)
- i=0;
- }
- }
- }
- /*---------------------------彩色图形--------------------------------------------*/
- //通过改变 hue=hue++*里面*的值,来改变颜色变换速率
- void matrix_heart_2(void) {
- int hue,i=0;
- for(hue = 0; hue < 600; hue=hue+48) {
- for(int j=0;j<8;j++)
- {
- set_row_byte_hue(j,data[j+i],hue);
- delay(20*__fade_delay);
- if(j>=7)
- i+=8;
- else if(i>=96)
- i=0;
- }
- }
- }
- /*---------------------------满屏切换不同颜色--------------------------------------------*/
- //通过改变 ctr1=ctr1+*里面*的值,来改变颜色变换速率
- void fader_hue(void) {
- int ctr1;
- byte row;
- byte led;
- for(ctr1 = 0; ctr1 < 360; ctr1=ctr1+3) {
- set_matrix_hue((float)(ctr1));
- delay(__fade_delay);
- }
- }
- /*---------------------------从上往下单行切换不同颜色--------------------------------------------*/
- //通过改变 hue=hue++*里面*的值,来改变颜色变换速率
- void matrix_test(void) {
- byte ctr1;
- byte ctr2;
- int hue;
-
- for(hue = 0; hue < 360; hue=hue+32) {
- for(ctr2 = 0; ctr2 <= __max_row; ctr2++) {
- for(ctr1 = 0; ctr1 <= __max_led; ctr1++) {
- set_led_hue(ctr2,ctr1,hue);
- delay(5);
- }
- }
- }
- }
复制代码
视频:
|