嵌入式开发学习(STC51-9-led点阵)

内容

点亮一个点;
显示数字;
显示图像;

LED点阵简介

LED 点阵是由发光二极管排列组成的显示器件
通常应用较多的是8 * 8点阵,然后使用多个8 * 8点阵可组成不同分辨率的LED点阵显示屏,比如16 * 16点阵可以使用4个8 * 8点阵构成;因此理解了8 * 8LED点阵的工作原理,其他分辨率的LED点阵显示屏都是一样的;

8 * 8点阵共由64个发光二极管组成,且每个发光二极管是放置在行线和列线的交叉点上,当对应的某一行置1电平,某一列置0电平,则相应的二极管就亮;

原理图

嵌入式开发学习(STC51-9-led点阵)_第1张图片
由图可知,点亮一个点,只需让对应行输出高电平,对应列输出低电平即可;

点亮一个点

思路

第一列置低电平,第一行置高电平;

编码

main.c

/*
 * @Description: 点亮一个点
 */
#include "reg52.h"

typedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;

// 定义74HC595控制管脚
sbit SCK = P3 ^ 6; // 移位寄存器时钟输入
sbit RCK = P3 ^ 5; // 存储寄存器时钟输入
sbit SER = P3 ^ 4; // 串行数据输入

#define LEDDZ_COL_PORT P0 // 点阵列控制端口

/**
 * @description: 延时函数(循环一次大约10us)
 * @param {u16} ten_us
 * @return {*}
 */
void delay_10us(u16 ten_us)
{
	while (ten_us--)
		;
}

/**
 * @description: 延时函数(循环一次大约1ms)
 * @param {u16} ms
 * @return {*}
 */
void delay_ms(u16 ms)
{
	u16 i, j;
	for (i = ms; i > 0; i--)
		for (j = 110; j > 0; j--)
			;
}

/**
 * @description: 向74HC595写入一个字节的数据
 * @param {u8} dat 要写入的数据
 * @return {*}
 */
void hc595_write_data(u8 dat)
{
	u8 i = 0;

	for (i = 0; i < 8; i++) // 循环8次即可将一个字节写入寄存器中
	{
		SER = dat >> 7; // 优先传输一个字节中的高位
		dat <<= 1;		// 将低位移动到高位
		SCK = 0;
		delay_10us(1);
		SCK = 1; // 移位寄存器SCK时钟上升沿将端口数据送入存储寄存器RCK中
		delay_10us(1);
	}
	RCK = 1; // 存储寄存器RCK时钟上升沿将前面写入到寄存器的数据输出
	delay_10us(1);
	RCK = 0;
}

void main()
{
	u8 i = 0;

	LEDDZ_COL_PORT = 0x7f; // 将LED点阵左边第一列设置为0,即LED阴极为低电平,其余列为1,即高电平
	while (1)
	{
		hc595_write_data(0x80); // 将LED点阵上边第一行设置为1,即LED阳极为高电平,其余行为0,即低电平
	}
}

编译和结果

按F7编译,无错误,生成.hex文件,使用pz-isp将hex文件下载到单片机

(注意把LED点阵旁的J24黄色跳线帽短接到GND一端)

结果:led点阵第一个点被点亮
嵌入式开发学习(STC51-9-led点阵)_第2张图片

显示数字

思路

利用动态扫描的思想,只要使两个点被点亮间隔不超过24ms,那么点看起来就像连续点亮一样;

把我们想要显示的数字在8 * 8点阵里用每个点表示出来(推荐使用文字取模软件)

循环扫描8行(每次让一行为1,其余行为0),显示每行需要点亮的点(行扫描法)

编码

main.c

/*
 * @Description: 显示数字
 */
#include "reg52.h"

typedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;

// 定义74HC595控制管脚
sbit SCK = P3 ^ 6; // 移位寄存器时钟输入
sbit RCK = P3 ^ 5; // 存储寄存器时钟输入
sbit SER = P3 ^ 4; // 串行数据输入

#define LEDDZ_COL_PORT P0 // 点阵列控制端口

u8 gled_row[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; // LED点阵显示数字6的行数据
u8 gled_col[8] = {0xff, 0x83, 0xbf, 0xbf, 0x83, 0xbb, 0xbb, 0x83}; // LED点阵显示数字6的列数据

/**
 * @description: 延时函数(循环一次大约10us)
 * @param {u16} ten_us
 * @return {*}
 */
void delay_10us(u16 ten_us)
{
	while (ten_us--)
		;
}

/**
 * @description: 延时函数(循环一次大约1ms)
 * @param {u16} ms
 * @return {*}
 */
void delay_ms(u16 ms)
{
	u16 i, j;
	for (i = ms; i > 0; i--)
		for (j = 110; j > 0; j--)
			;
}

/**
 * @description: 向74HC595写入一个字节的数据
 * @param {u8} dat 要写入的数据
 * @return {*}
 */
void hc595_write_data(u8 dat)
{
	u8 i = 0;

	for (i = 0; i < 8; i++) // 循环8次即可将一个字节写入寄存器中
	{
		SER = dat >> 7; // 优先传输一个字节中的高位
		dat <<= 1;		// 将低位移动到高位
		SCK = 0;
		delay_10us(1);
		SCK = 1; // 移位寄存器SCK时钟上升沿将端口数据送入存储寄存器RCK中
		delay_10us(1);
	}
	RCK = 1; // 存储寄存器RCK时钟上升沿将前面写入到寄存器的数据输出
	delay_10us(1);
	RCK = 0;
}

void main()
{
	u8 i = 0;

	while (1)
	{
		for (i = 0; i < 8; i++) // 循环8次扫描8行、列
		{
			hc595_write_data(gled_row[i]); // 传送行选数据
			LEDDZ_COL_PORT = gled_col[i];  // 传送列选数据
			delay_10us(100);			   // 延时一段时间,等待显示稳定
			hc595_write_data(0x00);		   // 消影
		}
	}
}

编译和结果

按F7编译,无错误,生成.hex文件,使用pz-isp将hex文件下载到单片机

结果:显示数字6

显示图像

思路

与显示数字相同,但是我们这里用列扫描法;

编码

main.c

/*
 * @Description: 显示图像
 */
#include "reg52.h"

typedef unsigned int u16; // 对系统默认数据类型进行重定义
typedef unsigned char u8;

// 定义74HC595控制管脚
sbit SCK = P3 ^ 6; // 移位寄存器时钟输入
sbit RCK = P3 ^ 5; // 存储寄存器时钟输入
sbit SER = P3 ^ 4; // 串行数据输入

#define LEDDZ_COL_PORT P0 // 点阵列控制端口

u8 gled_row[8] = {0x38, 0x7C, 0x7E, 0x3F, 0x3F, 0x7E, 0x7C, 0x38}; // LED点阵显示数字6的行数据
u8 gled_col[8] = {0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe}; // LED点阵显示数字6的列数据

/**
 * @description: 延时函数(循环一次大约10us)
 * @param {u16} ten_us
 * @return {*}
 */
void delay_10us(u16 ten_us)
{
	while (ten_us--)
		;
}

/**
 * @description: 延时函数(循环一次大约1ms)
 * @param {u16} ms
 * @return {*}
 */
void delay_ms(u16 ms)
{
	u16 i, j;
	for (i = ms; i > 0; i--)
		for (j = 110; j > 0; j--)
			;
}

/**
 * @description: 向74HC595写入一个字节的数据
 * @param {u8} dat 要写入的数据
 * @return {*}
 */
void hc595_write_data(u8 dat)
{
	u8 i = 0;

	for (i = 0; i < 8; i++) // 循环8次即可将一个字节写入寄存器中
	{
		SER = dat >> 7; // 优先传输一个字节中的高位
		dat <<= 1;		// 将低位移动到高位
		SCK = 0;
		delay_10us(1);
		SCK = 1; // 移位寄存器SCK时钟上升沿将端口数据送入存储寄存器RCK中
		delay_10us(1);
	}
	RCK = 1; // 存储寄存器RCK时钟上升沿将前面写入到寄存器的数据输出
	delay_10us(1);
	RCK = 0;
}

void main()
{
	u8 i = 0;

	while (1)
	{
		for (i = 0; i < 8; i++) // 循环8次扫描8行、列
		{
			LEDDZ_COL_PORT = gled_col[i];  // 传送列选数据
			hc595_write_data(gled_row[i]); // 传送行选数据
			delay_10us(100);			   // 延时一段时间,等待显示稳定
			hc595_write_data(0x00);		   // 消影
		}
	}
}

编译和结果

按F7编译,无错误,生成.hex文件,使用pz-isp将hex文件下载到单片机

结果:显示一个爱心

你可能感兴趣的:(嵌入式开发学习,学习,51单片机)