首页 > 代码库 > [51单片机学习笔记FOUR]----16*16LED点阵
[51单片机学习笔记FOUR]----16*16LED点阵
一、LED点阵发光原理
8*8单色单片机结构图如下:
从电路图中很简单的就可以看出来,想要点亮点阵中的某一个LED灯。只要使得那个灯所在的行输出高电平,所在列输出低电平就好。
二、点阵扫描实验
1 /*********************************************** 2 实验名称: 点阵扫描 3 实验说明: 扫描每个LED灯,检查点阵是否完好 4 实验时间: 2014/12/24 5 ***********************************************/ 6 #include <reg51.h> 7 #include <intrins.h> 8 9 #define uchar unsigned char 10 #define uint unsigned int 11 12 sbit MOSIO = P3^4;//输入口 13 sbit R_CLK = P3^5;//锁存器时钟 14 sbit S_CLK = P3^6;//移位寄存器时钟 15 16 //data3:右边半块列数据;data2:左边半块列数据 17 //data1:下边半块行数据;data0:上边半块行数据 18 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0); 19 20 void main() 21 { 22 uint i,j; 23 uchar d; 24 25 while(1) 26 { 27 //全亮 28 HC595Pro(0x00,0x00,0xFF,0xFF); 29 for(i=0;i<40000;i++); //延时40ms 30 31 /*行扫描*/ 32 //上半块行扫描 33 d = 0x01; 34 for(i=0;i<8;i++) 35 { 36 HC595Pro(0x00,0x00,0x00,d); 37 d <<= 1; 38 for(j=0;j<20000;j++); //延时20ms 39 } 40 //下半块行扫描 41 d = 0x01; 42 for(i=0;i<8;i++) 43 { 44 HC595Pro(0x00,0x00,d,0x00); 45 d <<= 1; 46 for(j=0;j<20000;j++); //延时20ms 47 } 48 49 /*列扫描*/ 50 //左半快列扫描 51 d = 0xFE; 52 for(i=0;i<8;i++) 53 { 54 HC595Pro(0xFF,d,0xFF,0xFF); 55 //如果还想用跟行扫描一样的形式,看main()最下面注释行 56 d = _crol_(d,1); //循环左移 57 for(j=0;j<20000;j++); //延时20ms 58 } 59 //右半块列扫描 60 d = 0xFE; 61 for(i=0;i<8;i++) 62 { 63 HC595Pro(d,0xFF,0xFF,0xFF); 64 d = _crol_(d,1); 65 for(j=0;j<20000;j++); //延时20ms 66 } 67 /****************************************************** 68 b1 = 0x01; 69 for(i = 0; i<8; i++) 70 { 71 HC595Pro(0xFF, ~b1, 0xFF, 0xFF); 72 b1 <<= 1; 73 for(j=0; j<20000; j++); 74 } 75 76 b1 = 0x01; 77 for(i = 0; i<8; i++) 78 { 79 HC595Pro(~b1, 0xFF, 0xFF, 0xFF); 80 b1 <<= 1; 81 for(j=0; j<20000; j++); 82 } 83 ******************************************************/ 84 } 85 } 86 87 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0) 88 { 89 uchar i; 90 //先移入的会被后面移入的数据推移到后面的595中,所以需要先移入data3 91 for(i=0;i<8;i++) 92 { 93 //先移入高位再移入低位,移位寄存器移入的第一位就是输出的最高位 94 MOSIO = data3 >> 7; 95 data3 <<= 1; 96 S_CLK = 0;//给一个上升沿,移位 97 S_CLK = 1; 98 } 99 for(i=0;i<8;i++)100 {101 MOSIO = data2 >> 7;102 data2 <<= 1;103 S_CLK = 0;104 S_CLK = 1;105 }106 for(i=0;i<8;i++)107 {108 MOSIO = data1 >> 7;109 data1 <<= 1;110 S_CLK = 0;111 S_CLK = 1;112 }113 for(i=0;i<8;i++)114 {115 MOSIO = data0 >> 7;116 data0 <<= 1;117 S_CLK = 0;118 S_CLK = 1;119 }120 121 //上升沿时将移位寄存器数据移到锁存器中用于显示,平时保持低电平,数据不变122 R_CLK = 0;123 R_CLK = 1;124 R_CLK = 0;125 126 }
这里我用到的是16*16的点阵。其实也就是4个8*8的小点阵组成起来的。其结构图如下:
1 | 2 |
3 | 4 |
这里只是简单示意一下。。。其中4个小块都是与一个相对应的74HC595相连。每个74HC595又是级联的,入口只有一个,我们需要输入相对应的行,列电平情况来控制LED灯的亮灭。
根据74HC595的结构可以知道,输入的数据是8位8位的输入的。最开始输入的8位数据会被后面的输入数据推移到第四个74HC595中。
所以实际输入时,是先输入2和4的列数据,再输入1和3的列数据,然后再是3和4的行数据,最后才是1和2的行数据。
三、16*16点阵倒计时
1 /*********************************************************************** 2 实验名称: 16*16点阵数字倒计时 3 实验时间: 2014/12/26 4 ***********************************************************************/ 5 #include <reg51.h> 6 #include <array.h> 7 8 #define uchar unsigned char 9 #define uint unsigned int 10 11 sbit MOSIO = P3^4; 12 sbit R_CLK = P3^5; 13 sbit S_CLK = P3^6; 14 15 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0); 16 17 void main() 18 { 19 uint i,c; 20 uchar j; 21 i = 100; 22 23 while(1) 24 { 25 //显示数字10 26 for(c=i;c>0;c--)//延时 27 for(j=0;j<16;j++) 28 { 29 //字模取出来的数据是跟实际实际所需数据相反的,所以要取反。 30 //函数对应的参数分别表示列2,列1,行2,行1 31 HC595Pro(~tab1[2*j+1],~tab1[2*j],tab0[2*j],tab0[2*j+1]); 32 } 33 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 34 35 //显示数字09 36 for(c=i;c>0;c--) 37 for(j=0;j<16;j++) 38 { 39 HC595Pro(~tab2[2*j+1],~tab2[2*j],tab0[2*j],tab0[2*j+1]); 40 } 41 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 42 43 //显示数字08 44 for(c=i;c>0;c--) 45 for(j=0;j<16;j++) 46 { 47 HC595Pro(~tab3[2*j+1],~tab3[2*j],tab0[2*j],tab0[2*j+1]); 48 } 49 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 50 51 //显示数字07 52 for(c=i;c>0;c--) 53 for(j=0;j<16;j++) 54 { 55 HC595Pro(~tab4[2*j+1],~tab4[2*j],tab0[2*j],tab0[2*j+1]); 56 } 57 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 58 59 //显示数字06 60 for(c=i;c>0;c--) 61 for(j=0;j<16;j++) 62 { 63 HC595Pro(~tab5[2*j+1],~tab5[2*j],tab0[2*j],tab0[2*j+1]); 64 } 65 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 66 67 //显示数字05 68 for(c=i;c>0;c--) 69 for(j=0;j<16;j++) 70 { 71 HC595Pro(~tab6[2*j+1],~tab6[2*j],tab0[2*j],tab0[2*j+1]); 72 } 73 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 74 75 //显示数字04 76 for(c=i;c>0;c--) 77 for(j=0;j<16;j++) 78 { 79 HC595Pro(~tab7[2*j+1],~tab7[2*j],tab0[2*j],tab0[2*j+1]); 80 } 81 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 82 83 //显示数字03 84 for(c=i;c>0;c--) 85 for(j=0;j<16;j++) 86 { 87 HC595Pro(~tab8[2*j+1],~tab8[2*j],tab0[2*j],tab0[2*j+1]); 88 } 89 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 90 91 //显示数字02 92 for(c=i;c>0;c--) 93 for(j=0;j<16;j++) 94 { 95 HC595Pro(~tab9[2*j+1],~tab9[2*j],tab0[2*j],tab0[2*j+1]); 96 } 97 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 98 99 //显示数字01100 for(c=i;c>0;c--)101 for(j=0;j<16;j++)102 {103 HC595Pro(~tab10[2*j+1],~tab10[2*j],tab0[2*j],tab0[2*j+1]);104 }105 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏106 107 //显示数字00108 for(c=i;c>0;c--)109 for(j=0;j<16;j++)110 {111 HC595Pro(~tab11[2*j+1],~tab11[2*j],tab0[2*j],tab0[2*j+1]);112 }113 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏114 115 //显示字母GO116 for(c=i;c>0;c--)117 for(j=0;j<16;j++)118 {119 HC595Pro(~tab12[2*j+1],~tab12[2*j],tab0[2*j],tab0[2*j+1]);120 }121 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏122 } 123 }124 125 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0)126 {127 uchar i;128 //先移入的会被后面移入的数据推移到后面的595中,所以需要先移入data3129 for(i=0;i<8;i++)130 {131 //先移入高位再移入低位,移位寄存器移入的第一位就是输出的最高位132 MOSIO = data3 >> 7;133 data3 <<= 1;134 S_CLK = 0;//给一个上升沿,移位135 S_CLK = 1;136 } 137 for(i=0;i<8;i++)138 {139 MOSIO = data2 >> 7;140 data2 <<= 1;141 S_CLK = 0;142 S_CLK = 1;143 }144 for(i=0;i<8;i++)145 {146 MOSIO = data1 >> 7;147 data1 <<= 1;148 S_CLK = 0;149 S_CLK = 1;150 }151 for(i=0;i<8;i++)152 {153 MOSIO = data0 >> 7;154 data0 <<= 1;155 S_CLK = 0;156 S_CLK = 1;157 }158 159 //上升沿时将移位寄存器数据移到锁存器中用于显示,平时保持低电平,数据不变160 R_CLK = 0;161 R_CLK = 1;162 R_CLK = 0;163 }
array.h头文件如下:
1 //点阵显示数组 2 //用于行扫描 3 unsigned char code tab0[] = {0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 4 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00}; 5 //1数字10的字模 6 unsigned char code tab1[] = {0, 0, 0, 0, 0, 0, 8, 24, 14, 36, 8, 66, 8, 66, 8, 66, 7 8, 66, 8, 66, 8, 66, 8, 36, 62, 24, 0, 0, 0, 0, 0, 0}; 8 //数字09的字模 9 unsigned char code tab2[] = {0, 0, 0, 0, 0, 0, 24, 24, 36, 36, 66, 66, 66, 66, 66,10 66, 66, 100, 66, 88, 66, 64, 66, 64, 36, 36, 24, 28, 0, 0, 0, 0} ;11 //数字08的字模12 unsigned char code tab3[] = {0, 0, 0, 0, 0, 0, 24, 60, 36, 66, 66, 66, 66, 66, 66, 36,13 66, 24, 66, 36, 66, 66, 66, 66, 36, 66, 24, 60, 0, 0, 0, 0};14 //数字07的字模15 unsigned char code tab4[] = {0, 0, 0, 0, 0, 0, 24, 126, 36, 34, 66, 34, 66, 16, 66, 16,16 66, 8, 66, 8, 66, 8, 66, 8, 36, 8, 24, 8, 0, 0, 0, 0};17 //数字06的字模18 unsigned char code tab5[] = {0, 0, 0, 0, 0, 0, 24, 56, 36, 36, 66, 2, 66, 2, 66, 26, 66,19 38, 66, 66, 66, 66, 66, 66, 36, 36, 24, 24, 0, 0, 0, 0};20 //数字05的字模21 unsigned char code tab6[] = {0, 0, 0, 0, 0, 0, 24, 126, 36, 2, 66, 2, 66, 2, 66, 26, 66,22 38, 66, 64, 66, 64, 66, 66, 36, 34, 24, 28, 0, 0, 0, 0};23 //数字04的字模24 unsigned char code tab7[] = {0, 0, 0, 0, 0, 0, 24, 32, 36, 48, 66, 40, 66, 36, 66, 36, 66,25 34, 66, 34, 66, 126, 66, 32, 36, 32, 24, 120, 0, 0, 0, 0};26 //数字03的字模27 unsigned char code tab8[] = {0, 0, 0, 0, 0, 0, 24, 60, 36, 66, 66, 66, 66, 32, 66, 24, 66,28 32, 66, 64, 66, 64, 66, 66, 36, 34, 24, 28, 0, 0, 0, 0};29 //数字02的字模30 unsigned char code tab9[] = {0, 0, 0, 0, 0, 0, 24, 60, 36, 66, 66, 66, 66, 66, 66, 32, 66,31 32, 66, 16, 66, 8, 66, 4, 36, 66, 24, 126, 0, 0, 0, 0};32 //数字01的字模33 unsigned char code tab10[] = {0, 0, 0, 0, 0, 0, 24, 8, 36, 14, 66, 8, 66, 8, 66, 8, 66, 8, 66,34 8, 66, 8, 66, 8, 36, 8, 24, 62, 0, 0, 0, 0};35 //数字00的字模36 unsigned char code tab11[] = {0, 0, 0, 0, 0, 0, 24, 24, 36, 36, 66, 66, 66, 66, 66, 66, 66, 66,37 66, 66, 66, 66, 66, 66, 36, 36, 24, 24, 0, 0, 0, 0};38 //数字GO的字模39 unsigned char code tab12[] = {0, 0, 0, 0, 0, 0, 60, 28, 34, 34, 34, 65, 1, 65, 1, 65, 1, 65, 113,40 65, 33, 65, 34, 65, 34, 34, 28, 28, 0, 0, 0, 0};
头文件的数据是通过字模软件得出的。字模软件的工作原理就是对于一个点阵,你想要什么样的图像,然后就在相应位置数据为1。然后再通过从左到右,从上到下的顺序,组成一个个8位数据。
这些8位数据就是头文件的内容。
由此我们就可以知道,通过字模取出来的数据,而我们实际运用过程中对于列来说是相反的。
因为我们想要点亮对应的LED灯是将它所在行输出高电平,所在列输出低电平。所以取出来的字模数据作为列的值的话是相反的。所以这里用了取反。
四、显示汉字
1 #include <reg51.h> 2 #include <array.h> 3 4 #define uchar unsigned char 5 #define uint unsigned int 6 7 sbit MOSIO = P3^4; 8 sbit R_CLK = P3^5; 9 sbit S_CLK = P3^6; 10 11 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0); 12 13 void main() 14 { 15 uint i,c; 16 uchar j; 17 i = 100; 18 19 while(1) 20 { 21 //显示“我” 22 for(c=i;c>0;c--)//延时 23 for(j=0;j<16;j++) 24 { 25 //字模取出来的数据是跟实际实际所需数据相反的,所以要取反。 26 //函数对应的参数分别表示列2,列1,行2,行1 27 HC595Pro(~tab1[2*j+1],~tab1[2*j],tab0[2*j],tab0[2*j+1]); 28 } 29 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 30 31 //显示“叫” 32 for(c=i;c>0;c--) 33 for(j=0;j<16;j++) 34 { 35 HC595Pro(~tab2[2*j+1],~tab2[2*j],tab0[2*j],tab0[2*j+1]); 36 } 37 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 38 39 //显示“做” 40 for(c=i;c>0;c--) 41 for(j=0;j<16;j++) 42 { 43 HC595Pro(~tab3[2*j+1],~tab3[2*j],tab0[2*j],tab0[2*j+1]); 44 } 45 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 46 47 //显示“大” 48 for(c=i;c>0;c--) 49 for(j=0;j<16;j++) 50 { 51 HC595Pro(~tab4[2*j+1],~tab4[2*j],tab0[2*j],tab0[2*j+1]); 52 } 53 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 54 55 //显示“熙” 56 for(c=i;c>0;c--) 57 for(j=0;j<16;j++) 58 { 59 HC595Pro(~tab5[2*j+1],~tab5[2*j],tab0[2*j],tab0[2*j+1]); 60 } 61 for(c=i;c>0;c--) 62 { 63 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 64 } 65 66 //显示“熙” 67 for(c=i;c>0;c--) 68 for(j=0;j<16;j++) 69 { 70 HC595Pro(~tab6[2*j+1],~tab6[2*j],tab0[2*j],tab0[2*j+1]); 71 } 72 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 73 } 74 } 75 76 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0) 77 { 78 uchar i; 79 //先移入的会被后面移入的数据推移到后面的595中,所以需要先移入data3 80 for(i=0;i<8;i++) 81 { 82 //先移入高位再移入低位,移位寄存器移入的第一位就是输出的最高位 83 MOSIO = data3 >> 7; 84 data3 <<= 1; 85 S_CLK = 0;//给一个上升沿,移位 86 S_CLK = 1; 87 } 88 for(i=0;i<8;i++) 89 { 90 MOSIO = data2 >> 7; 91 data2 <<= 1; 92 S_CLK = 0; 93 S_CLK = 1; 94 } 95 for(i=0;i<8;i++) 96 { 97 MOSIO = data1 >> 7; 98 data1 <<= 1; 99 S_CLK = 0;100 S_CLK = 1;101 }102 for(i=0;i<8;i++)103 {104 MOSIO = data0 >> 7;105 data0 <<= 1;106 S_CLK = 0;107 S_CLK = 1;108 }109 110 //上升沿时将移位寄存器数据移到锁存器中用于显示,平时保持低电平,数据不变111 R_CLK = 0;112 R_CLK = 1;113 R_CLK = 0;114 }
array.h头文件如下:
1 //点阵显示数组 2 //用于行扫描 3 unsigned char code tab0[] = {0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 4 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00}; 5 // 我 6 unsigned char code tab1[] ={96,2,28,10,16,18,16,2,254,63,16,2,16,18,112,18,24,10,22,10,16,36,16,42,16,49,156,32,0,0,0,0}; 7 // 叫 8 unsigned char code tab2[] ={0,16,0,16,158,16,146,16,146,16,146,16,146,24,146,22,146,17,158,16,18,16,0,16,0,16,0,16,0,0,0,0}; 9 // 做10 unsigned char code tab3[] ={80,2,80,2,72,2,232,62,76,17,74,18,232,18,168,18,168,10,168,10,168,4,232,10,40,17,136,32,0,0,0,0};11 // 大12 unsigned char code tab4[] ={128,0,128,0,128,0,128,0,254,63,128,0,64,1,64,1,64,1,32,2,32,2,16,4,8,8,6,48,0,0,0,0};13 // 熙14 unsigned char code tab5[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};15 // 熙16 unsigned char code tab6[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};
汉字输出显示其实跟数字没什么差别,这里不做累赘讲述了。
五、用指针方式显示汉字
1 #include <reg51.h> 2 #include <array.h> 3 4 #define uchar unsigned char 5 #define uint unsigned int 6 7 sbit MOSIO = P3^4; 8 sbit R_CLK = P3^5; 9 sbit S_CLK = P3^6;10 11 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0);12 13 void main()14 {15 uchar *p[] = {tab1, tab2, tab3, tab4, tab5, tab6};16 17 uint i,j,c,k;18 i = 100;19 20 while(1)21 {22 //分别显示“我叫做大熙熙”23 for(k=0;k<6;k++)//一共六个字24 {25 for(c=i;c>0;c--)//延时26 {27 for(j=0;j<16;j++)28 {29 //p[k]+2*j+1就是p[k][2*j+1], p[k]+2*j就是p[k][2*j]30 HC595Pro(~(*(p[k]+2*j+1)),~(*(p[k]+2*j)),tab0[2*j],tab0[2*j+1]); 31 }32 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 33 }34 } 35 } 36 }37 38 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0)39 {40 uchar i;41 for(i=0;i<8;i++)42 {43 MOSIO = data3 >> 7;44 data3 <<= 1;45 S_CLK = 0;46 S_CLK = 1;47 } 48 for(i=0;i<8;i++)49 {50 MOSIO = data2 >> 7;51 data2 <<= 1;52 S_CLK = 0;53 S_CLK = 1;54 }55 for(i=0;i<8;i++)56 {57 MOSIO = data1 >> 7;58 data1 <<= 1;59 S_CLK = 0;60 S_CLK = 1;61 }62 for(i=0;i<8;i++)63 {64 MOSIO = data0 >> 7;65 data0 <<= 1;66 S_CLK = 0;67 S_CLK = 1;68 }69 70 R_CLK = 0;71 R_CLK = 1;72 R_CLK = 0;73 }
array.h头文件如下:
1 //点阵显示数组 2 //用于行扫描 3 unsigned char code tab0[] = {0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 4 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00}; 5 // 我 6 unsigned char code tab1[] ={96,2,28,10,16,18,16,2,254,63,16,2,16,18,112,18,24,10,22,10,16,36,16,42,16,49,156,32,0,0,0,0}; 7 // 叫 8 unsigned char code tab2[] ={0,16,0,16,158,16,146,16,146,16,146,16,146,24,146,22,146,17,158,16,18,16,0,16,0,16,0,16,0,0,0,0}; 9 // 做10 unsigned char code tab3[] ={80,2,80,2,72,2,232,62,76,17,74,18,232,18,168,18,168,10,168,10,168,4,232,10,40,17,136,32,0,0,0,0};11 // 大12 unsigned char code tab4[] ={128,0,128,0,128,0,128,0,254,63,128,0,64,1,64,1,64,1,32,2,32,2,16,4,8,8,6,48,0,0,0,0};13 // 熙14 unsigned char code tab5[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};15 // 熙16 unsigned char code tab6[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};
这里需要注意的一点就是数组指针的用法。明白那个之后整个程序就很容易了。
六、汉字纵向移屏
1 #include <REG51.H> 2 #include "array.h" 3 4 #define uchar unsigned char 5 #define uint unsigned int 6 7 //--定义SPI要使用的 IO--// 8 sbit MOSIO = P3^4; 9 sbit R_CLK = P3^5;10 sbit S_CLK = P3^6;11 12 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0);13 14 void main(void)15 { 16 int k, j, ms;17 18 //--定义一个指针数组指向每个汉字--//19 uchar *p[] = {tab8, tab1, tab2, tab3, tab4, tab5, tab6, tab7}; 20 while(1)21 {22 23 for(ms = 20; ms > 0; ms--) //移动定格时间设置24 {25 for(k = 0; k < 16; k++) 26 {27 //因为字模软件取的数组是高电平有效,所以列要取反 28 HC595Pro(~(*(p[0] + 2*(k+j) + 1)),~(*(p[0] + 2*(k+j) )),tab0[2*k],tab0[2*k + 1]); 29 }30 31 HC595Pro(0xFF,0xFF,0x00,0x00);//清屏 32 } 33 j++;34 if(j == (7*16) )35 {36 j = 0; 37 }38 39 } 40 }41 42 43 void HC595Pro(uchar data3,uchar data2,uchar data1,uchar data0)44 {45 uchar i;46 for(i=0;i<8;i++)47 {48 MOSIO = data3 >> 7;49 data3 <<= 1;50 S_CLK = 0;51 S_CLK = 1;52 } 53 for(i=0;i<8;i++)54 {55 MOSIO = data2 >> 7;56 data2 <<= 1;57 S_CLK = 0;58 S_CLK = 1;59 }60 for(i=0;i<8;i++)61 {62 MOSIO = data1 >> 7;63 data1 <<= 1;64 S_CLK = 0;65 S_CLK = 1;66 }67 for(i=0;i<8;i++)68 {69 MOSIO = data0 >> 7;70 data0 <<= 1;71 S_CLK = 0;72 S_CLK = 1;73 }74 75 R_CLK = 0;76 R_CLK = 1;77 R_CLK = 0;78 }
array.h头文件如下:
//点阵显示数组//用于行扫描unsigned char code tab0[] = {0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00};//全灭unsigned char code tab8[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // 我unsigned char code tab1[] ={96,2,28,10,16,18,16,2,254,63,16,2,16,18,112,18,24,10,22,10,16,36,16,42,16,49,156,32,0,0,0,0};// 叫unsigned char code tab2[] ={0,16,0,16,158,16,146,16,146,16,146,16,146,24,146,22,146,17,158,16,18,16,0,16,0,16,0,16,0,0,0,0};// 做unsigned char code tab3[] ={80,2,80,2,72,2,232,62,76,17,74,18,232,18,168,18,168,10,168,10,168,4,232,10,40,17,136,32,0,0,0,0};// 大unsigned char code tab4[] ={128,0,128,0,128,0,128,0,254,63,128,0,64,1,64,1,64,1,32,2,32,2,16,4,8,8,6,48,0,0,0,0};// 熙unsigned char code tab5[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};// 熙unsigned char code tab6[] ={252,62,36,34,36,34,244,34,148,62,148,2,244,2,36,34,36,34,252,60,0,0,36,17,68,34,66,34,0,0,0,0};//全灭unsigned char code tab7[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
主函数中的*(p[0] + 2*(k+j) + 1)就是P[0][2(k+j)+1],*(p[0] + 2*(k+j))就是P[0][2(k+j)],就是P数组的第0行。
我们先来看看怎么纵向显示汉字。纵向移动就可以理解为一开始是有一个无限大的点阵是让你放你想要的内容的。加入你一开始放好了。但是一开始只显示一个汉字,然后隔一段时间,整个向上移一行,再显示一张图像。以此循环,直到整个全部显示完。
就是通过这个原理,实现纵向移动的。
至于j的值怎么判断,我是这么理解的:
“我叫做大熙熙”一共六个字,然后加上最前面和最后的全灭,一共是8*32位。
所以整个数组最大为P[0][255](根据所指向的位置分析,P[0][32]就是P[1][0])。
所以这里j取7*16时,数组最大为P[0][255],最后一位没读,但是数组本身存的值为0,取反之后就是1,列为高电平的话就算不读也是灭的。
相反,但是如果取8*16的话,数组最大为P[0][287],多出来的几位因为数组没初始化过,所以不知道相对应的地址会是什么值。所以可能会造成有点地方亮,影响最终效果。
总而言之,最后的判断值越接近实际数组大小越好。
个人意见,解析也不是很专业,不过希望能看懂。。哈哈。。
结语:对于纵向移动的话采用的是行扫描法,然后显示信息放在列中。横向移动的话就采用列扫描法,显示信息放在行中。
这里具体的就不呈现了,因为都差不多啦。
[51单片机学习笔记FOUR]----16*16LED点阵