点阵屏
跟数码管原理有一些类似


圈起来部分用来控制行或列

列直接给P0赋值来控制
但是行要用到74HC595
提出:若是单片机上只有这个LED点阵屏,其他都不要,可不可以把D1-D7的接在P1口上
回答:不行,因为单片机的IO口是弱上拉特性
弱上拉:输出低电平(直接接GND)时电流可以很大,输出高电平(相当于接了一个电阻再接VCC)时电流很小
用到三极管,接IO口就可以
IO口低电平,VCC直接通到4那,IO起控制作用,自己干不动不干活而指使别人干活
IO口给高电平的时候就会截止,相当于没有接
IO口扩展
OE(output enable输出使能)

寄存器时钟,RCLK(register clock)
上方有—-,表示它要接低电平,所以JOE那要和GND短接,才能有输出

SRCLR串行清零端
接了VCC代表它不清空

SRCLK串行时钟
上升沿是PWM波的从低电平到高电平的一瞬间

SER串行数据

主要用这三个引脚控制八个输出

串行vs并行

并行是用那八个输出端同时输出
串行输入 并行输出
每上升沿移位,从SER进的数据就向下沿移位,SERCLK高电平的时候移进,数据一位一位地往前走,等有了八位数据之后同时搬过去输出缓存那,串行那里每输入一位,SER清零,数据下移

当寄存器满位后,给RCLK高电平,把数据搬运到输出缓存那
多片级联
在寄存器的数据传到QH’,然后多片级联到下一个SER,当所有数据就位了,来一个上升沿锁存,所有数据都相应地输出,实现了IO口的扩展,但是速率会有所减慢(时间换时空)
sfr和sbit 可位寻址/不可位寻址
sfr:特殊功能寄存器声明(声明寄存器地址) 相当于把某个元件的操作地址赋给一个自定义的变量名,把相应的名称和地址给声明出来,我们才能操作那个名称
sbit:特殊位声明(声明地址的某一位)

可位寻址和不可位寻址就类比于C语言的数组,可位寻址的就是数组的首地址,不是首地址的就不能位寻址
上代码(笑脸)
main.c
#include <REGX52.H>
#include "Delay.h"
//给IO口改名
sbit RCK=P3^5; //RCLK,应该是赋值的时候用_,给地址的时候用^,这里是让rclk直接找到p3_5的地址所以用^
sbit SCK=P3^6; //SRCLK
sbit SER=P3^4; //SER
#define MATRIX_LED_PORT P0//如果以后自己焊板子玩接口不对,直接改上面sbit,不用再在下面改了
/**
* @brief 74HC595写入一个字节
* @param 要写入的字节
* @retval 无
*/
void _74JHC595_WriteByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
SER=Byte&(0x80>>i);//0x80-->1000 0000
SCK=1;//给高电平形成上升沿传入数据
SCK=0;//置零为下一次传入做准备
}
RCK=1;//高电平,形成上升沿锁存
RCK=0;//置零
}
/**
* @brief LED点阵屏显示一列数据
* @param Column 要选择的列,范围0~7,0在最左边
* @param Data 选择列显示的数据,高位在上,1为亮,0为灭
* @retval 无
*/
void MatrixLED_ShowColumn(unsigned char Cloumn,Data)
{
_74JHC595_WriteByte(Data);//放数据
MATRIX_LED_PORT=~(0x80>>Cloumn);//位选;选择列,然后把数据0xAA传到LED列中;
Delay(1);//延时
MATRIX_LED_PORT=0xFF;//位清零,下一步是段选,这样下次段选就不会串位到上一个位选了
}
void main()
{
SCK=0;//因为上电默认高电平,先置0,才能给高电平;需要一个上升沿才能传入数据
RCK=0;//初始化为低电平
while(1)
{
MatrixLED_ShowColumn(0,0x3C);
MatrixLED_ShowColumn(1,0x42);
MatrixLED_ShowColumn(2,0xA9);
MatrixLED_ShowColumn(3,0x85);
MatrixLED_ShowColumn(4,0x85);
MatrixLED_ShowColumn(5,0xA9);
MatrixLED_ShowColumn(6,0x42);
MatrixLED_ShowColumn(7,0x3C);
}
}
抠 理 解 开抠!!!
for(i=0;i<8;i++)
{
SER=Byte&(0x80>>i);//0x80-->1000 0000
SCK=1;//给高电平形成上升沿传入数据
SCK=0;//置零为下一次传入做准备
}
SER是一位而Byte是8位,涉及到位对齐问题
理解:假如Byte是0x55(0101 0101)
i=0 (0x80>>i)=1000 0000
SER=0101 0101 & 1000 0000 =0000 0000———-根据非0即1,SER为0
i=1 (0x80>>i)=0100 0000
SER=0101 0101 & 0100 0000 =0100 0000———-根据非0即1,SER为1
.
.
.
i=7 (0x80>>i)=0000 0001
SER=0101 0101 & 0000 0001 =0000 0001———-根据非0即1,SER为1

SCK=1;//给高电平形成上升沿传入数据

段选 位选 延时 位清零 段选 位选
/**
* @brief LED点阵屏显示一列数据
* @param Column 要选择的列,范围0~7,0在最左边
* @param Data 选择列显示的数据,高位在上,1为亮,0为灭
* @retval 无
*/
void MatrixLED_ShowColumn(unsigned char Cloumn,Data)
{
_74JHC595_WriteByte(Data);//放数据
MATRIX_LED_PORT=~(0x80>>Cloumn);//位选;选择列,然后把数据0xAA传到LED列中;
Delay(1);//延时
MATRIX_LED_PORT=0xFF;//位清零,下一步是段选,这样下次段选就不会串位到上一个位选了
}
MATRIX_LED_PORT=~(0x80>>Cloumn);//这里取反是为了让1表示亮,0表示灭,同时>>补位补的是0
上代码(Hello!滚屏)
main.c
#include <REGX52.H>
#include "Delay.h"
#include "MatrixLED.h"
//code 把Animation的数据放在flash里(内存大),把run的空间腾出来做其他事情,缺点是Animation的数据不能再更改了(只能读取不能写入)
unsigned char code Animation[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFF,0x08,0x08,0x08,0xFF,0x00,0x0E,0x15,
0x15,0x15,0x08,0x00,0x7E,0x01,0x02,0x00,
0x7E,0x01,0x02,0x00,0x0E,0x11,0x11,0x0E,
0x00,0x7D,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
void main()
{
unsigned char i,Offset=0,Count=0;//offset偏移量
MartrixLED_Init();
while(1)
{
for(i=0;i<8;i++)
{
MatrixLED_ShowColumn(i,Animation[i+Offset]);
}
Count++;//不能用Delay,不然会出现闪屏现象
if(Count>10)
{
Count=0;
Offset++;
if(Offset>40)//写这个为了不让Offset溢出产生乱码
{
Offset=0;
}
}
//相当于扫了10遍后移向下一帧
}
}
①先解释主函数的for
for(i=0;i<8;i++)
{
MatrixLED_ShowColumn(i,Animation[i+Offset]);
}
这个MatrixLED_ShowColumn是放数据,安排每一列的,i表示列,Animation[]是数组,i+Offset是要把一幕中的八列都打出来
②if
Count++;//不能用Delay,不然会出现闪屏现象
if(Count>10)
{
Count=0;
Offset++;
if(Offset>40)//写这个为了不让Offset溢出产生乱码
{
Offset=0;
}
用Count来计时,当Count>10后,Offset++,屏幕中的画面开始往右移,每次移动一列,Offset>40,这个40=8*6(全部)—8(第一幕的不需要移动)
③有16个0x00
unsigned char code Animation[]
{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
......
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
}
让H的左边的|从最后一列出现,让!从第一列离开
MatrixLED.c(是上一个主函数里扒拉下来的)
#include <REGX52.H>
#include "Delay.h"
//给IO口改名
sbit RCK=P3^5; //RCLK,应该是赋值的时候用_,给地址的时候用^,这里是让rclk直接找到p3_5的地址所以用^
sbit SCK=P3^6; //SRCLK
sbit SER=P3^4; //SER
#define MATRIX_LED_PORT P0//如果以后自己焊板子玩接口不对,直接改上面sbit,不用再在下面改了
/**
* @brief 74HC595写入一个字节
* @param 要写入的字节
* @retval 无
*/
void _74JHC595_WriteByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
SER=Byte&(0x80>>i);//0x80-->1000 0000
SCK=1;//给高电平形成上升沿传入数据
SCK=0;//置零为下一次传入做准备
}
RCK=1;//高电平,形成上升沿锁存
RCK=0;//置零
}
/**
* @brief 点阵屏初始化
* @param 无
* @retval 无
*/
void MartrixLED_Init()
{
SCK=0;//因为上电默认高电平,先置0,才能给高电平;需要一个上升沿才能传入数据
RCK=0;//初始化为低电平
}
/**
* @brief LED点阵屏显示一列数据
* @param Column 要选择的列,范围0~7,0在最左边
* @param Data 选择列显示的数据,高位在上,1为亮,0为灭
* @retval 无
*/
void MatrixLED_ShowColumn(unsigned char Cloumn,Data)
{
_74JHC595_WriteByte(Data);//放数据
MATRIX_LED_PORT=~(0x80>>Cloumn);//位选;选择列,然后把数据0xAA传到列中;
Delay(1);//延时
MATRIX_LED_PORT=0xFF;//位清零,下一步是段选,这样下次段选就不会串位到上一个位选了
}
MatrixLED.h
#ifndef __MATRIXLED_H__
#define __MATRIXLED_H__
void MatrixLED_ShowColumn(unsigned char Cloumn,Data);
void MartrixLED_Init();
#endif