点阵屏


点阵屏

跟数码管原理有一些类似

显示原理

行与列的控制关系

圈起来部分用来控制

开发板引脚对应关系

列直接给P0赋值来控制

但是行要用到74HC595

提出:若是单片机上只有这个LED点阵屏,其他都不要,可不可以把D1-D7的接在P1口上

回答:不行,因为单片机的IO口是弱上拉特性

弱上拉:输出低电平(直接接GND)时电流可以很大,输出高电平(相当于接了一个电阻再接VCC)时电流很小

IO口用到三极管,接IO口就可以

IO口低电平,VCC直接通到4那,IO起控制作用,自己干不动不干活而指使别人干活

IO口给高电平的时候就会截止,相当于没有接

IO口扩展

OE(output enable输出使能)

OE

寄存器时钟,RCLK(register clock)

上方有—-,表示它要接低电平,所以JOE那要和GND短接,才能有输出

RCLK

SRCLR串行清零端

接了VCC代表它不清空

SRCLR

SRCLK串行时钟

上升沿是PWM波的从低电平到高电平的一瞬间

SRCLK

SER串行数据

SER

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

三个引脚控制八个输出

串行vs并行

串行是这样子一个一个出去的

并行是用那八个输出端同时输出

串行输入 并行输出

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

74HC595

当寄存器满位后,给RCLK高电平,把数据搬运到输出缓存那

多片级联多片级联

在寄存器的数据传到QH’,然后多片级联到下一个SER,当所有数据就位了,来一个上升沿锁存,所有数据都相应地输出,实现了IO口的扩展,但是速率会有所减慢(时间换时空)

sfr和sbit 可位寻址/不可位寻址

sfr:特殊功能寄存器声明(声明寄存器地址) 相当于把某个元件的操作地址赋给一个自定义的变量名,把相应的名称和地址给声明出来,我们才能操作那个名称

sbit:特殊位声明(声明地址的某一位)

C51的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

文章作者: WB
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WB !
  目录