51单片机使用8×8点阵显示心形以及各种其他图案教程_单片机控制led点阵显示器显示爱心图案-程序员宅基地

技术标签: 51单片机  嵌入式硬件  单片机  

一.硬件连接

我使用的是普中A3的开发板,板子已经默认连接好了,点阵的列线接到了595芯片,行线直接连接到了单片机的P0口。
在这里插入图片描述
在这里插入图片描述

二.595的使用

我只讲用到的引脚:
OE:输出使能控制脚,它是低电才使能输出,所以接GND,所有你要在开发板上找到J24这个排针,用跳线帽把DE跟GND连接到一起。
RCLK:存储寄存器时钟输入引脚。上升沿时,数据从移位寄存器转存带存储寄存器。此引脚连接到了单片机的P35引脚
SRCLK:移位寄存器时钟引脚,上升沿时,移位寄存器中的bit 数据整体后移,并接受新的bit。此引脚连接到了单片机的P36引脚
SER:串行数据输入引脚。此引脚连接到了单片机的P34引脚

595输出一个字节

#define SER P34 //串行数据输入引脚
#define RCLK P35 //存储寄存器时钟输入引脚。上升沿时,数据从移位寄存器转存带存储寄存器。
#define SRCLK P36 //移位寄存器时钟引脚,上升沿时,移位寄存器中的bit数据整体后移,并接受新的bit

void _74HC595_Write_Byte(u8 Data)
{
    
	u8 i;
	RCLK=0;
	for(i=0;i<8;i++)	//低位在前
	{
    
		SRCLK=0;
		if(Data & 0x01) SER=1;
		else SER=0;
		SRCLK=1;
		Data=Data>>1;
	}
	RCLK=1;
	RCLK=0;
}

三.动态刷新

我们采用行列式的点阵刷新方式,列线从左到右依次选中,行线(595)输出对应数据。

void refresh_buff(u8 *buff)	//对应取模软件:行列式、逆向
{
    
	u8 i,Data=0x80;
	for(i=0;i<8;i++)	//从左到右
	{
    
		_74HC595_Write_Byte(buff[i]);
		P0=~Data;
		Data=Data>>1;
		Delay_us();	//消影
		P0=0xFF;
	}
}

static unsigned char Love_Heart[8]={
    0x1C,0x22,0x42,0x84,0x84,0x42,0x22,0x1C};	//爱心图案

void main()
{
    
	while(1)
	{
    
		refresh_buff(Love_Heart);	//显示心形图案
	}
}

我们现在只需要写入8*8像素的图案数组就能显示出对应图形。怎么样?代码是不是很优雅简洁。

四.取模软件的使用

我们使用文字取模软件PCtoLCD2002完美版
1.首先我们选择图形模式:

2.然后点击设置图标,配置选项跟我一样,然后点确定
在这里插入图片描述

3.然后选择新建一个BMP图片
在这里插入图片描述
4.然后你就能在上面绘画啦,鼠标左键点亮,右键取消像素点。绘制好你想要的图形后点击生成字模,然后复制生成的数组到程序里面就行啦。
在这里插入图片描述

五.显示心形完整代码

refresh.c

#include "refresh.h"

void Delay_us()	//@11.0592MHz
{
    
	u8 i;
	i = 50;
	while (--i);
}

void _74HC595_Write_Byte(u8 Data)
{
    
	u8 i;
	RCLK=0;
	for(i=0;i<8;i++)	//低位在前
	{
    
		SRCLK=0;
		if(Data & 0x01) SER=1;
		else SER=0;
		SRCLK=1;
		Data=Data>>1;
	}
	RCLK=1;
	RCLK=0;
}

void refresh_buff(u8 *buff)	//对应取模软件:行列式、逆向
{
    
	u8 i,Data=0x80;
	for(i=0;i<8;i++)	//从左到右
	{
    
		_74HC595_Write_Byte(buff[i]);
		P0=~Data;
		Data=Data>>1;
		Delay_us();	//消影
		P0=0xFF;
	}
}

refresh.h

#ifndef __REFRESH_H__
#define __REFRESH_H__

#include <STC89C5xRC.H>

#define SER P34 //串行数据输入引脚
#define RCLK P35 //存储寄存器时钟输入引脚。上升沿时,数据从移位寄存器转存带存储寄存器。
#define SRCLK P36 //移位寄存器时钟引脚,上升沿时,移位寄存器中的bit数据整体后移,并接受新的bit

void refresh_buff(u8 buff[]);	//显存动态刷新函数

#endif

main.c

#include <STC89C5xRC.H>
#include "refresh.h"
#include "img.h"

u8 show_buff[8];//显存 8byte;

void main()
{
    
	while(1)
	{
    
		refresh_buff(Love_Heart0);
	}
}

img.h 此文件用来存放各种取模后的图形数组

/********图案/文字取模********/

//取模方式:行列式、逆向、阴码、像素8*8

static unsigned char Love_Heart0[8]={
    0x1C,0x22,0x42,0x84,0x84,0x42,0x22,0x1C};/*"空心图形",0*/
static unsigned char Love_Heart1[8]={
    0x1C,0x3E,0x7E,0xFC,0xFC,0x7E,0x3E,0x1C};/*"实心图形",1*/

显示效果:我对你是实心的哦!哈哈哈
在这里插入图片描述

这样你就能显示你想要显示的任何图案啦!img.h里面有我做好的一个空心和实心图案,如果我想实现一个空心实心转换的动画,需要怎么做呢?

六.利用定时器实时刷新显存

由于我们使用的是STC89C52RC单片机,RAM大小512byte,ROM大小8K,创建一个8byte的数组用来当显存完全够了哈!然后这个系列单片机有定时器2,我们就用定时器2中断实时刷新显存

先初始化配置定时器2,打开定时器2中断,每5ms中断一次,在中断服务函数里面执行refresh_buff(show_buff);函数,这样显存(点阵)刷新率就有200HZ。现在我们只需要在主循环里面把要显示的图案复制到显存就行。

u8 show_buff[8];//创建一个显存 8byte;

//5ms 定时器2中断,动态刷新显存,刷新率200HZ
void Timer2_Isr(void) interrupt 5	
{
    
	TF2 = 0;
	refresh_buff(show_buff);	//动态刷新显存
}

void Timer2_Init(void)
{
    
	T2MOD = 0;				//初始化模式寄存器
	T2CON = 0;				//初始化控制寄存器
	TL2 = 0x00;				//设置定时初始值
	TH2 = 0xEE;				//设置定时初始值
	RCAP2L = 0x00;			//设置定时重载值
	RCAP2H = 0xEE;			//设置定时重载值
	TR2 = 1;				//定时器2开始计时
	ET2 = 1;				//使能定时器2中断
	EA=1;
}

main.c文件需要引入string.h头文件,主要用到他里面的memcpy()函数,实现内存复制。

#include <STC89C5xRC.H>
#include "string.h"	//memcpy()
#include "refresh.h"
#include "img.h"

u8 show_buff[8];//显存 8byte;

void Delay500ms()		//@11.0592MHz
{
    
	unsigned char data i, j, k;
	i = 4;
	j = 129;
	k = 119;
	do
	{
    
		do
		{
    
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
    
	Timer2_Init();
	while(1)
	{
    
		memcpy(show_buff,Love_Heart0,sizeof(Love_Heart0));	//复制空心图案到显存
		Delay500ms();
		memcpy(show_buff,Love_Heart1,sizeof(Love_Heart1));	//复制实心图案到显存
		Delay500ms();
	}
}

最终实现的效果,这不赶紧把.hex文件发给你正在学51单片机的女朋友?发完女朋友想分手别来找我哈,哈哈哈哈。

51单片机点阵显示动态心形


51单片机点阵显示动画心动

7.显示数字与字母

其实实现了显存动态刷新后,咱们可以自定义封装很多函数了,本质都是在8*8像素的白纸上画画嘛,比如封装一个显示字母的函数,封装一个滚动显示字符串的函数等等。

这个过程对你以后学习OLED,LCD屏幕很有帮助哦,因为原理都差不多的。

本来想对所有ASCII字符进行取模,由于RAM空间太小了放不下,只能把数字放到内部RAM,大写字母放到外部RAM中。

/********图案/文字取模********/

//取模方式:行列式、逆向、阴码、像素8*8

static unsigned char Love_Heart0[8]={
    0x1C,0x22,0x42,0x84,0x84,0x42,0x22,0x1C};/*"爱心图形",0*/
static unsigned char Love_Heart1[8]={
    0x1C,0x3E,0x7E,0xFC,0xFC,0x7E,0x3E,0x1C};/*"爱心图形",1*/
static unsigned char Love_Heart2[8]={
    0x00,0x1C,0x3C,0x78,0x78,0x3C,0x1C,0x00};/*"小心心",2*/

unsigned char number[][8]={
    
{
    0x00,0x7E,0x81,0x81,0x81,0x7E,0x00,0x00},/*"0",0*/
{
    0x00,0x00,0x82,0xFF,0x80,0x00,0x00,0x00},/*"1",1*/
{
    0x00,0xC6,0xA1,0x91,0x89,0x86,0x00,0x00},/*"2",2*/
{
    0x00,0x42,0x81,0x89,0x89,0x76,0x00,0x00},/*"3",3*/
{
    0x00,0x30,0x28,0xA6,0xFF,0xA0,0x00,0x00},/*"4",4*/
{
    0x00,0x5F,0x89,0x89,0x89,0x71,0x00,0x00},/*"5",5*/
{
    0x00,0x7C,0x92,0x89,0x89,0x72,0x00,0x00},/*"6",6*/
{
    0x00,0x00,0x01,0xF1,0x0D,0x03,0x00,0x00},/*"7",7*/
{
    0x00,0x76,0x89,0x89,0x89,0x76,0x00,0x00},/*"8",8*/
{
    0x00,0x4E,0x91,0x91,0x49,0x3E,0x00,0x00},/*"9",9*/
};

//8*8 24大小字母
unsigned char xdata letter[][8]={
    
{
    0x00,0x80,0xF8,0x27,0x3C,0xE0,0x80,0x00},/*"A",0*/
{
    0x00,0x81,0xFF,0x89,0x89,0x76,0x00,0x00},/*"B",1*/
{
    0x00,0x7E,0x81,0x81,0x81,0x43,0x00,0x00},/*"C",2*/
{
    0x00,0x81,0xFF,0x81,0x81,0x7E,0x00,0x00},/*"D",3*/
{
    0x00,0x81,0xFF,0x89,0x9D,0xC3,0x00,0x00},/*"E",4*/
{
    0x00,0x81,0xFF,0x89,0x1D,0x03,0x00,0x00},/*"F",5*/
{
    0x00,0x3C,0x42,0x81,0x91,0x73,0x10,0x00},/*"G",6*/
{
    0x00,0x81,0xFF,0x08,0x08,0xFF,0x81,0x00},/*"H",7*/
{
    0x00,0x81,0x81,0xFF,0x81,0x81,0x00,0x00},/*"I",8*/
{
    0x00,0x00,0x01,0x01,0xFF,0x01,0x01,0x00},/*"J",9*/
{
    0x00,0x81,0xFF,0x89,0x14,0xE3,0x81,0x00},/*"K",10*/
{
    0x00,0x81,0xFF,0x81,0x80,0x80,0xC0,0x00},/*"L",11*/
{
    0x81,0xFF,0x0F,0xF0,0x0F,0xFF,0x81,0x00},/*"M",12*/
{
    0x00,0x81,0xFF,0x8C,0x31,0xFF,0x01,0x00},/*"N",13*/
{
    0x00,0x7E,0x81,0x81,0x81,0x7E,0x00,0x00},/*"O",14*/
{
    0x00,0x81,0xFF,0x89,0x09,0x06,0x00,0x00},/*"P",15*/
{
    0x00,0x7E,0xA1,0xA1,0xC1,0x7E,0x00,0x00},/*"Q",16*/
{
    0x00,0x81,0xFF,0x89,0x19,0xE6,0x80,0x00},/*"R",17*/
{
    0x00,0xC6,0x89,0x89,0x91,0x63,0x00,0x00},/*"S",18*/
{
    0x00,0x03,0x81,0xFF,0x81,0x03,0x00,0x00},/*"T",19*/
{
    0x00,0x01,0x7F,0x80,0x80,0x7F,0x01,0x00},/*"U",20*/
{
    0x00,0x01,0x1F,0xE0,0x38,0x07,0x01,0x00},/*"V",21*/
{
    0x00,0x0F,0xF0,0x1F,0xF0,0x0F,0x00,0x00},/*"W",22*/
{
    0x00,0x81,0xE7,0x18,0xE7,0x81,0x00,0x00},/*"X",23*/
{
    0x00,0x01,0x8F,0xF0,0x8F,0x01,0x00,0x00},/*"Y",24*/
{
    0x00,0x83,0xE1,0x99,0x87,0xC1,0x00,0x00},/*"Z",25*/
};

现在封装一个显示滚动字母与数字的函数

u8 show_buff[8];//显存 8byte;

//显示图片
void Show_Img(u8 *img)	
{
    
	memcpy(show_buff,img,8);
}

//显示一个字母
void Show_Char(u8 let)
{
    
	u8 i=let-'A';	//获取偏移值,字母顺序按照ASCII码表
	memcpy(show_buff,letter+i,8);
}

//显示一个数字
void Show_Num(u8 num)
{
    
	memcpy(show_buff,number+num,8);
}

//显示滚动 大小字母混合数字串
void Show_StrNum(u8 *str)	
{
    
	u8 chr[8]={
    0};	//暂存拼接后的图形
	while(*str!='\0')//判断是不是非法字符!
	{
    
		u8 i;
		for(i=0;i<8;i++)
		{
    
			u8 j;
			for(j=0;j<7;j++){
    
				chr[j]=chr[j+1];
			}
			if(*str>64)	//大写字母
				chr[7]=letter[*str-'A'][i];
			else	//数字
				chr[7]=number[*str-'0'][i];
			memcpy(show_buff,chr,8);
			Delay_ms(100);	//修改延时时间将调整滚动速度
		}
		str++;
  }
}

//清除缓存区
void Clear_Buff(void)
{
    
	memset(show_buff,0,8);
}

来看看效果吧!

51单片机点阵显示滚动字符

8.整合后的代码

其实变化不大,就是一些细节的地方小改了一下而已。
这里直接贴出整个工程链接吧

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_64346054/article/details/134356528

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签