[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         //显示数字01
100         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         //显示数字00
108         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         //显示字母GO
116         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中,所以需要先移入data3
129     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],多出来的几位因为数组没初始化过,所以不知道相对应的地址会是什么值。所以可能会造成有点地方亮,影响最终效果。

总而言之,最后的判断值越接近实际数组大小越好。

个人意见,解析也不是很专业,不过希望能看懂。。哈哈。。

结语:对于纵向移动的话采用的是行扫描法,然后显示信息放在列中。横向移动的话就采用列扫描法,显示信息放在行中。

这里具体的就不呈现了,因为都差不多啦。

原文地址:https://www.cnblogs.com/one-meter/p/4188277.html