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

智能推荐

oracle 12c 集群安装后的检查_12c查看crs状态-程序员宅基地

文章浏览阅读1.6k次。安装配置gi、安装数据库软件、dbca建库见下:http://blog.csdn.net/kadwf123/article/details/784299611、检查集群节点及状态:[root@rac2 ~]# olsnodes -srac1 Activerac2 Activerac3 Activerac4 Active[root@rac2 ~]_12c查看crs状态

解决jupyter notebook无法找到虚拟环境的问题_jupyter没有pytorch环境-程序员宅基地

文章浏览阅读1.3w次,点赞45次,收藏99次。我个人用的是anaconda3的一个python集成环境,自带jupyter notebook,但在我打开jupyter notebook界面后,却找不到对应的虚拟环境,原来是jupyter notebook只是通用于下载anaconda时自带的环境,其他环境要想使用必须手动下载一些库:1.首先进入到自己创建的虚拟环境(pytorch是虚拟环境的名字)activate pytorch2.在该环境下下载这个库conda install ipykernelconda install nb__jupyter没有pytorch环境

国内安装scoop的保姆教程_scoop-cn-程序员宅基地

文章浏览阅读5.2k次,点赞19次,收藏28次。选择scoop纯属意外,也是无奈,因为电脑用户被锁了管理员权限,所有exe安装程序都无法安装,只可以用绿色软件,最后被我发现scoop,省去了到处下载XXX绿色版的烦恼,当然scoop里需要管理员权限的软件也跟我无缘了(譬如everything)。推荐添加dorado这个bucket镜像,里面很多中文软件,但是部分国外的软件下载地址在github,可能无法下载。以上两个是官方bucket的国内镜像,所有软件建议优先从这里下载。上面可以看到很多bucket以及软件数。如果官网登陆不了可以试一下以下方式。_scoop-cn

Element ui colorpicker在Vue中的使用_vue el-color-picker-程序员宅基地

文章浏览阅读4.5k次,点赞2次,收藏3次。首先要有一个color-picker组件 <el-color-picker v-model="headcolor"></el-color-picker>在data里面data() { return {headcolor: ’ #278add ’ //这里可以选择一个默认的颜色} }然后在你想要改变颜色的地方用v-bind绑定就好了,例如:这里的:sty..._vue el-color-picker

迅为iTOP-4412精英版之烧写内核移植后的镜像_exynos 4412 刷机-程序员宅基地

文章浏览阅读640次。基于芯片日益增长的问题,所以内核开发者们引入了新的方法,就是在内核中只保留函数,而数据则不包含,由用户(应用程序员)自己把数据按照规定的格式编写,并放在约定的地方,为了不占用过多的内存,还要求数据以根精简的方式编写。boot启动时,传参给内核,告诉内核设备树文件和kernel的位置,内核启动时根据地址去找到设备树文件,再利用专用的编译器去反编译dtb文件,将dtb还原成数据结构,以供驱动的函数去调用。firmware是三星的一个固件的设备信息,因为找不到固件,所以内核启动不成功。_exynos 4412 刷机

Linux系统配置jdk_linux配置jdk-程序员宅基地

文章浏览阅读2w次,点赞24次,收藏42次。Linux系统配置jdkLinux学习教程,Linux入门教程(超详细)_linux配置jdk

随便推点

matlab(4):特殊符号的输入_matlab微米怎么输入-程序员宅基地

文章浏览阅读3.3k次,点赞5次,收藏19次。xlabel('\delta');ylabel('AUC');具体符号的对照表参照下图:_matlab微米怎么输入

C语言程序设计-文件(打开与关闭、顺序、二进制读写)-程序员宅基地

文章浏览阅读119次。顺序读写指的是按照文件中数据的顺序进行读取或写入。对于文本文件,可以使用fgets、fputs、fscanf、fprintf等函数进行顺序读写。在C语言中,对文件的操作通常涉及文件的打开、读写以及关闭。文件的打开使用fopen函数,而关闭则使用fclose函数。在C语言中,可以使用fread和fwrite函数进行二进制读写。‍ Biaoge 于2024-03-09 23:51发布 阅读量:7 ️文章类型:【 C语言程序设计 】在C语言中,用于打开文件的函数是____,用于关闭文件的函数是____。

Touchdesigner自学笔记之三_touchdesigner怎么让一个模型跟着鼠标移动-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏13次。跟随鼠标移动的粒子以grid(SOP)为partical(SOP)的资源模板,调整后连接【Geo组合+point spirit(MAT)】,在连接【feedback组合】适当调整。影响粒子动态的节点【metaball(SOP)+force(SOP)】添加mouse in(CHOP)鼠标位置到metaball的坐标,实现鼠标影响。..._touchdesigner怎么让一个模型跟着鼠标移动

【附源码】基于java的校园停车场管理系统的设计与实现61m0e9计算机毕设SSM_基于java技术的停车场管理系统实现与设计-程序员宅基地

文章浏览阅读178次。项目运行环境配置:Jdk1.8 + Tomcat7.0 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。项目技术:Springboot + mybatis + Maven +mysql5.7或8.0+html+css+js等等组成,B/S模式 + Maven管理等等。环境需要1.运行环境:最好是java jdk 1.8,我们在这个平台上运行的。其他版本理论上也可以。_基于java技术的停车场管理系统实现与设计

Android系统播放器MediaPlayer源码分析_android多媒体播放源码分析 时序图-程序员宅基地

文章浏览阅读3.5k次。前言对于MediaPlayer播放器的源码分析内容相对来说比较多,会从Java-&amp;amp;gt;Jni-&amp;amp;gt;C/C++慢慢分析,后面会慢慢更新。另外,博客只作为自己学习记录的一种方式,对于其他的不过多的评论。MediaPlayerDemopublic class MainActivity extends AppCompatActivity implements SurfaceHolder.Cal..._android多媒体播放源码分析 时序图

java 数据结构与算法 ——快速排序法-程序员宅基地

文章浏览阅读2.4k次,点赞41次,收藏13次。java 数据结构与算法 ——快速排序法_快速排序法