8x8点阵
显示原理
LED点阵屏由几个独立的点阵屏组成LED组成,LED以矩阵的形式排列
LED点阵屏的结构类似于数字管,但数字管以8字形排列每列像素
LED点阵屏和数字管一样,有两种连接方式:共阴和共阳。不同的连接方式对应不同的电路结构
LED点阵屏幕需要逐行或逐行扫描,使所有点阵屏幕都能逐行扫描LED同时显示
共阳接法:发光二极管的阳极引脚连接在一起
共阴二极管的阴极引脚连接在一起
开发板上的点阵可以理解为自上而下的行标号h,g,f,e,d,c,b,a,从左到右的列号分别是P0_7~P0_0,a,b,c不管怎样,数据的高度是8x8点阵在高位,即靠LCD那部分
74HC595
因为8x8点阵需要的引脚较多,为了节约单片机的IO口,用74HC595芯片串行输入并输出驱动点阵
74HC595是移位寄存器可以用3根线输入串行数据,8根线输出并行数据,多片级联后可以输出16位、24位、32位等。IO口扩展。
//74HC595移位寄存器配置 void _595sendByte(u_char dat) {
unsigned char i; for(i = 0;i < 8;i ) {
SER = dat&(0x80>>i);//从dat高位开始取值,分别是0x80,0x40,0x20...则可以取出对应位的值,放到SER中 SRCLK = 1; ///每次上升沿移动一个位置 SRCLK = 0; //重新置0,为下一个上升沿作准备 } RCLK1 = 1; //待所有移位完成后,RCLK上升边缘,将所有数据移动到右端口并行输出 RCLK1 = 0; }
概括来说:SER放入等待并行输出的数据,只能一个一个放,放入后SRCLK将已放入的位置向下移动,直到所有数据并移,RCLK上升沿将数据移动到端口并行输出
消隐操作
因为同样是cpu不断扫描点阵屏,所以8x8点阵类似于数字管,需要在连续显示的情况下进行消影操作,以确保亮灯时不会串联
可以将P点亮一个数据后,全置10口
显示图形
首先用取字模软件取出要显示的图形数据
#include <REGX52.H> #include "Delay.h" typedef unsigned char u_char; sbit RCLK1 = P3^5; sbit SRCLK = P3^6; sbit SER = P3^4; ///待显示的图形数据,圆脸 unsigned char icon[] = {
0x3C,0x42,
0x95
,
0x85
,
0x85
,
0x95
,
0x42
,
0x3C
}
;
//74HC595移位寄存器配置
void
_595sendByte
(u_char dat
)
{
unsigned
char i
;
for
(i
=
0
;i
<
8
;i
++
)
{
SER
= dat
&
(
0x80
>>i
)
;
//从dat的高位开始取值,分别与上0x80,0x40,0x20...则可以取出对应位的值,放到SER中 SRCLK
=
1
;
//每来一次上升沿,则移一个位 SRCLK
=
0
;
//重新置0,为下一个上升沿作准备
} RCLK1
=
1
;
//待全部移位完成,RCLK来上升沿,将数据全部移到右边的端口上并行输出 RCLK1
=
0
;
}
/** * @brief图形显示 * @param column控制列,dat控制行 * @retval无 */
void
show_graphics
(u_char column
,u_char dat
)
{
_595sendByte
(dat
)
;
//控制行,595芯片并行输出数据 P0
=
~
(
0X80
>>column
)
;
//控制列,根据参数选择P0的哪一位为0,当column为0,则P0 =~0x80,P0_7口为低电平
Delay
(
1
)
; P0
=
0xFF
;
//延时后将P0口全置1,作消影操作
}
void
main
(
)
{
u_char i
; SRCLK
=
0
;
//初始化SRCLK和RCLK为0 RCLK1
=
0
;
while
(
1
)
{
/*开发板上可以理解为从上到下是h,g,f,e,d,c,b,a,从左到右为P0_7~P0_0 a,b,c编号可以不用管,反正数据的高位在8x8点阵中是在高位部分的,即靠LCD那部分*/
//_595sendByte();
for
(i
=
0
;i
<
8
;i
++
)
{
/*进行快速扫描,i控制的是列,因为行的数据已经通过字模软件生成了,只要在i列的时候显示这一列的哪一行要亮,根据人眼 余晖暂留,就可看到一个图形*/
show_graphics
(i
,icon
[i
]
)
;
}
}
}
动态显示字符或图形
实验现象是Hello!从右往左滚动显示
#include <REGX52.H>
#include "Delay.h"
typedef unsigned char u_char;
sbit RCLK1 = P3^5;
sbit SRCLK = P3^6;
sbit SER = P3^4;
//待显示的图形的数据
//Hello!
unsigned char code icon[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFE,0x10,0x10,0x10,0xFE,0x00,0x3C,0x42,
0x4A,0x4A,0x32,0x00,0xFE,0x02,0x02,0x00,
0xFE,0x02,0x02,0x3C,0x42,0x42,0x42,0x3C,
0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
//74HC595移位寄存器配置
void _595sendByte(u_char dat)
{
unsigned char i;
for(i = 0;i < 8;i++)
{
SER = dat&(0x80>>i);//从dat的高位开始取值,分别与上0x80,0x40,0x20...则可以取出对应位的值,放到SER中
SRCLK = 1; //每来一次上升沿,则移一个位
SRCLK = 0; //重新置0,为下一个上升沿作准备
}
RCLK1 = 1; //待全部移位完成,RCLK来上升沿,将数据全部移到右边的端口上并行输出
RCLK1 = 0;
}
/** * @brief图形显示 * @param column控制列,dat控制行 * @retval无 */
void show_graphics(u_char column,u_char dat)
{
_595sendByte(dat); //595芯片并行输出数据控制行
P0 =~ (0X80>>column); //根据参数选择P0的哪一位为0,当column为0,则P0 =~0x80,P0_7口为低电平
Delay(1);
P0 = 0xFF; //延时后将P0口全置1,作消影操作
}
void main()
{
u_char i;
u_char offset = 3; //定义偏移量
u_char count = 0; //用于计数
SRCLK = 0; //初始化SRCLK和RCLK为0
RCLK1 = 0;
while(1)
{
for(i = 0;i < 8;i++)
{
show_graphics(i,icon[i+offset]); //数据加上偏移量
}
count++;
if(count > 10) //控制滚动的速度,越小则越快
{
count = 0;
offset++;
if(offset > 35) //防止访问数组溢出
{
offset = 0;
}
}
}
}
code
在定义显示字符或图形的数据时,往往数据会比较大,如果不加其他关键字,直接定义,则保存在RAM区,而RAM的大小比较小,可能会放不下,所以可以加关键字code,把数据定义在ROM区,即flash区,但放在ROM区的数据只能读不能改,如想修改数组里的某一个值是不允许的
unsigned char code icon[] = {
0xFE,0x10,0x10,0x10,0xFE,0x00,0x3C,0x42}; //将数组放在ROM区,只能读不能写
注意点
如果用单片机的引脚直接驱动这些端口(不一定是8x8点阵),而不使用芯片时,是否可行?
答案是的
因为单片机的引脚是弱上拉,其接了一个上拉的电阻,如果输出低电平还正常,如果输出高电平驱动能力就不够了,驱动LED灯时会很暗
解决办法:可以在单片机引脚和接收信号的引脚之间加个三极管,三极管接一个VCC,此时单片机的高电平就相当于信号,不直接驱动,而是导通三极管,用VCC的电平驱动其他引脚
代码地址:https://gitee.com/ONE_Day168/dynamicdisplay.git