Max7219点阵屏
一 最重要的地址操作
MAX7219 :多位LED显示驱动器。是一种集成化的 串行
输入/输出 共阴极
显示驱动器。
通过 SPI 接口
与微控制器通信,3条引线:DIN
(即MOSI主设输出从设备接受)、CLK
(时钟)、CS
(片选)
1 基本模式
- 模式介绍:MAX7219 内部有多个寄存器:包括 8 个数字显示寄存器、
译码模式
寄存器、亮度
控制寄存器、扫描
界限寄存器、关闭模式
寄存器和测试
模式寄存器等。可以通过写入地址,可以对这些模式及进行开关或调整。 - 数据传输:在 CLK 的上升沿,DIN 引脚上的数据被锁存到内部移位寄存器中。当 16 位数据发送完毕后,在 LOAD 引脚的上升沿,将移位寄存器中的数据锁存到对应的寄存器中。
- 要点:每次传输16位数据,CS拉低–>传输16位数据–>每传输一位:产生时钟脉冲 1-0–> 拉高CS引脚,结束通信
每个数字显示寄存器对应一个 8 段
LED 数码管
或一个8×8 点阵
的一个字节,用于存储要显示的数据。而当代表点阵屏
的时候,可以不考虑译码
模式,因为需要手动设置驱动代码控制显示图案,或使用取模软件
把信息保存到二维数组中。
(1)寄存器-模式地址:
以下面发送16位数据的函数为例;
void Max7219_SendByte(uint8_t address, uint8_t data)
模式名称 | 作用 | 地址 | 案例/解释 |
---|---|---|---|
REG1-8 | 简易理解:选中第1-8行某行, 若设为0为代表关闭 | (行地址1-8,用1字节表示该行的灯亮灭 | (1,0xff)第一行全亮 |
译码方式 | 数码管可用,点阵屏不用考虑 | (0X09,0) | 开启后,能更方便显示数字,不用再挨个编辑设计 |
亮度设置 | 0-15可选16级亮度 | (0X0A,0-15) | (0X0A,8)8级亮度 |
扫描界限 | 设置0-7,代表扫描1-8列,未扫描的地方不亮灯 | (0X0B,0-7) | (0X0B,7)设为7全开即可 |
停机模式 | 1:正常工作 0:掉电模式(别称) | (0X0C,0-1) | (0X0C,1)设1就可以,0会直接熄屏 |
显示模式 | 可设0或1,开启后,以最大亮度全亮 | (0X0F,0-1) | (0X0F,0)没特殊需求不用开 |
初始化代码设定:
Max7219_SendByte(0X0A,5); //设置初始亮度,可选 0-15
Max7219_SendByte(0X0C,1);//工作模式选择 1:正常工作 0:掉电模式(熄屏但不丢数据)
Max7219_SendByte(0X0F,0);//测试模式开关 1:开测试模式 0:正常工作
Max7219_SendByte(0X0B,7); //扫描方式选择 0-7 设置扫描1-8个LED
Max7219_SendByte(0X09,0); //译码方式 0:为不解码
Max7219_Clear();
(2)十进制地址解释
由于地址的巧妙,很多地址在数值
上可以直接用十进制代替,所以有了上表格中的0-7,0-15等。如下图,由于D7-D4为0
,D3-D0 的四位二进制16级亮度,刚好对应数字:0-15:
亮度寄存器:
扫描模式寄存器:
原理同上
2 显示数据
(1)提前取模法
- 选中某行:即寄存器地址(0x01-0x08分别对应8行)
- 加上用1字节值表示一行1*8灯的亮灭
- 即每一行对应一个8个数的数组,显示
一个图
案至少需要8*8的二位数组
,使用取模软件提提前生成:效果如下:
(2)封装函数法
- 通过二进制计算,设计一个公式:
效果如:
ShowGraph(l,x,y);
- 效果为:点亮:第L行,【x,y】
区间式的点亮
Led灯,并支持覆盖
操作与单行清除操作,即可通过设定区间,与循环搭配直接一行一行去构建需要的图形,如:
<1> 拼凑数字1:
for(int i=1;i<=8;i++)
Max7219_ShowGraph(i,4,5); //第i行,点亮[4-5]的灯
//覆盖
Max7219_ShowGraph(1,3,3);
Max7219_ShowGraph(2,2,3);
Max7219_ShowGraph(8,2,7);
Max7219_Clear();
<2 > 支持具备一定规律
,或要求动态变化
的图案
如:蛇形矩阵
//循环便可实现
for(int i=1;i<=8;i++)
for(int st=i,ed=1; ;st--,ed++){
if(st==0&&ed==i+1) break;
Max7219_ShowGraph(st,ed,ed); //凡有规律的图形,或动态变化,皆可实现
Delay_ms(270);
}
Max7219_Clear();
二 封装功能与测试样例
1 封装函数一览
(1)头文件:完整功能函数
//#include "Max7219.h"
#ifndef __MAX7219_H
#define __MAX7219_H
//接线:Din-A6 Cs-A4 Clk-A5
//模拟SPI,如有需求自己改动即可
#define MAX7219_CS_PIN GPIO_Pin_4
#define MAX7219_CS_PORT GPIOA
#define MAX7219_CLK_PIN GPIO_Pin_5
#define MAX7219_CLK_PORT GPIOA
#define MAX7219_DIN_PIN GPIO_Pin_6
#define MAX7219_DIN_PORT GPIOA
void Max7219_InitDisplay(void); //初始化点阵屏:亮度、模式、测试、扫描、译码方式
void Max7219_Bright(uint8_t dt);//16级亮度:dt=0-15
void Max7219_Clear(void); //全部清空
void Max7219_Clearline(uint8_t l);//仅清空第L行,L:1-8
void Max7219_SendByte(uint8_t address, uint8_t data);//二进制值点亮灯阵;SPI通信,发送2字节
void Max7219_ShowGraph(uint8_t line,uint8_t x,uint8_t y);//点亮第line行,x-y的点,三者皆:1-8
#endif
(2)预处理数组:图案库:0-9,A-Z
/*
图案模数组
*/
//#include "Preprocessdesign.h"
//心
uint8_t Heart[8] = {0x38,0x7C,0x7E,0x3F,0x3F,0x7E,0x7C,0x38};
uint8_t data[36][8]={
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//0
{0x10,0x18,0x14,0x10,0x10,0x10,0x10,0x10},//1
{0x7E,0x2,0x2,0x7E,0x40,0x40,0x40,0x7E},//2
{0x3E,0x2,0x2,0x3E,0x2,0x2,0x3E,0x0},//3
{0x8,0x18,0x28,0x48,0xFE,0x8,0x8,0x8},//4
{0x3C,0x20,0x20,0x3C,0x4,0x4,0x3C,0x0},//5
{0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x0},//6
{0x3E,0x22,0x4,0x8,0x8,0x8,0x8,0x8},//7
{0x0,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E},//8
{0x3E,0x22,0x22,0x3E,0x2,0x2,0x2,0x3E},//9
{0x8,0x14,0x22,0x3E,0x22,0x22,0x22,0x22},//A
{0x3C,0x22,0x22,0x3E,0x22,0x22,0x3C,0x0},//B
{0x3C,0x40,0x40,0x40,0x40,0x40,0x3C,0x0},//C
{0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x0},//D
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C},//E
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x40},//F
{0x3C,0x40,0x40,0x40,0x40,0x44,0x44,0x3C},//G
{0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44},//H
{0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x7C},//I
{0x3C,0x8,0x8,0x8,0x8,0x8,0x48,0x30},//J
{0x0,0x24,0x28,0x30,0x20,0x30,0x28,0x24},//K
{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C},//L
{0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81},//M
{0x0,0x42,0x62,0x52,0x4A,0x46,0x42,0x0},//N
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//O
{0x3C,0x22,0x22,0x22,0x3C,0x20,0x20,0x20},//P
{0x1C,0x22,0x22,0x22,0x22,0x26,0x22,0x1D},//Q
{0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21},//R
{0x0,0x1E,0x20,0x20,0x3E,0x2,0x2,0x3C},//S
{0x0,0x3E,0x8,0x8,0x8,0x8,0x8,0x8},//T
{0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1C},//U
{0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18},//V
{0x0,0x49,0x49,0x49,0x49,0x2A,0x1C,0x0},//W
{0x0,0x41,0x22,0x14,0x8,0x14,0x22,0x41},//X
{0x41,0x22,0x14,0x8,0x8,0x8,0x8,0x8},//Y
{0x0,0x7F,0x2,0x4,0x8,0x10,0x20,0x7F},//Z
};
2 功能实现
(1)CPP文件:功能实现代码,完整注释
//" Max7219.c "
#include "stm32f10x.h" // USE_STDPERIPH_DRIVER
#include "delay.h"
#include "Max7219.h"
#include "math.h"
uint8_t graph[10]={0};//函数调用内部:每一行的二进制值,记忆化,防止每次修改闪屏
/*
功能:初始化引脚参数
参数:-
介绍:注意 引脚模式
*/
void Max7219_SpiInit(void) {
GPIO_InitTypeDef GPIO_InitStructure;
// 使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// 配置CS引脚为推挽输出模式
GPIO_InitStructure.GPIO_Pin = MAX7219_CS_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(MAX7219_CS_PORT, &GPIO_InitStructure);
// 配置CLK引脚为推挽输出模式
GPIO_InitStructure.GPIO_Pin = MAX7219_CLK_PIN;
GPIO_Init(MAX7219_CLK_PORT, &GPIO_InitStructure);
// 配置DIN引脚为推挽输出模式-Mosi
GPIO_InitStructure.GPIO_Pin = MAX7219_DIN_PIN;
GPIO_Init(MAX7219_DIN_PORT, &GPIO_InitStructure);
}
/*
功能:初始化Max7219
参数:-
介绍:有需求可自己调参,一般不需改动
*/
void Max7219_InitDisplay(void) {
Max7219_SpiInit();
Max7219_Bright(3); //设置初始亮度,可选 0-15
Max7219_SendByte(0X0C,1);//工作模式选择 1:正常工作 0:掉电模式(熄屏但不丢数据)
Max7219_SendByte(0X0F,0);//测试模式开关 1:开测试模式 0:正常工作
Max7219_SendByte(0X0B,7); //扫描方式选择 0-7 设置扫描1-8个LED
Max7219_SendByte(0X09,0); //译码方式 0:为不解码,点阵屏没这个功能。
Max7219_Clear(); //MA7219数码管中,开启译码可以用Send(DIGX,num)一键显示
}
//清空全部内容,熄灭
void Max7219_Clear(void){
for(int i=1;i<=8;i++){
Max7219_SendByte(i,0);
graph[i]=0;
}
}
/*
功能:仅清空一行
参数:某一行:1-8
介绍:防止多数覆盖少数,如:先点亮第一行【1,6】的灯,再点【2,4】
若不事先清空,则效果被覆盖。仅用于有覆盖性的变化需求时,仅一个图案则用不到。
*/
void Max7219_Clearline(uint8_t l){
graph[l]=0;
Max7219_SendByte(l,graph[l]);
//Max7219_SendByte(l,0)也可以,但无法让数组保存记忆,只能做到即时显示
}
/*
功能1:模拟SPI通信
参数1:地址
参数2:数据值
介绍:SPI为16位通信,将片CS信号拉低开始发送,数据位发送后,将时钟信号置高再置低产生
时钟脉冲发送完成后,将片选信号拉高结束通信。
功能2:二进制值,设定某行的灯阵
参数1:选中某一行,1-8(地址恰为0x01-0x08,可直接用十进制)
参数2:数据值的二进制形式,对应每一行8个LEd的亮灭
介绍:可用取模软件得图案值,然后快速输出
*/
void Max7219_SendByte(uint8_t address, uint8_t data) {
uint8_t i;
// 拉低CS引脚,选中Max7219
GPIO_ResetBits(MAX7219_CS_PORT, MAX7219_CS_PIN);
// 发送地址字节
for (i = 0; i < 8; i++) {
// 设置DIN引脚数据位-写入数据
if (address & 0x80) {
GPIO_SetBits(MAX7219_DIN_PORT, MAX7219_DIN_PIN);
} else {
GPIO_ResetBits(MAX7219_DIN_PORT, MAX7219_DIN_PIN);
}
// 产生时钟脉冲 1-0
GPIO_SetBits(MAX7219_CLK_PORT, MAX7219_CLK_PIN);
Delay_us(1); // 延迟1微秒
GPIO_ResetBits(MAX7219_CLK_PORT, MAX7219_CLK_PIN);
Delay_us(1); // 延迟1微秒
address <<= 1;
}
// 发送数据字节
for (i = 0; i < 8; i++) {
// 设置DIN引脚数据位
if (data & 0x80) {
GPIO_SetBits(MAX7219_DIN_PORT, MAX7219_DIN_PIN);
} else {
GPIO_ResetBits(MAX7219_DIN_PORT, MAX7219_DIN_PIN);
}
// 产生时钟脉冲 1-0
GPIO_SetBits(MAX7219_CLK_PORT, MAX7219_CLK_PIN);
Delay_us(1); // 延迟1微秒
GPIO_ResetBits(MAX7219_CLK_PORT, MAX7219_CLK_PIN);
Delay_us(1); // 延迟1微秒
data <<= 1;
}
// 拉高CS引脚,结束通信
GPIO_SetBits(MAX7219_CS_PORT, MAX7219_CS_PIN);
}
//设置点阵屏亮度:0-15
void Max7219_Bright(uint8_t dt){
Max7219_SendByte(0X0A,dt);
}
/*
功能:点亮某一行的【x,y】间的LED灯,支持重复操作同一行,效果覆盖。
参数1:第几行:1-8
参数2:起始LEd位置:1-8
参数3:结束LEd位置:1-8
介 绍:原理是计算出仅[x,y]点亮对应的二进制值,写入对应行。
*/
void Max7219_ShowGraph(uint8_t line,uint8_t x,uint8_t y){
uint8_t tem=pow(2,9-x) - pow(2,8-y);
graph[line]|=tem;
Max7219_SendByte(line,graph[line]);
}
3 主函数:demo全面测试
(1)拖出来册注释代码,即可观察效果
#include "stm32f10x.h" // USE_STDPERIPH_DRIVER
#include "delay.h"
#include "OLED.h"//无需
#include "Max7219.h"
#include "Preprocessdesign.h" //预处理二维图案数组
int main(void)
{
OLED_Init();//oled非必要
OLED_Clear();
OLED_ShowString(1,1,"Max7219 string");
OLED_ShowString(2,1,"SPI_case");
Max7219_InitDisplay();//初始化
//Max7219_Bright(15);//0-15亮度
while (1)
{
/*<1> 图案0-9,A-Z:预处理二进制取模
uint8_t t=0;
do{
for(int j=0;j<8;j++)
Max7219_SendByte(j+1,data[t][j]); //data[0-35][~]: 0-9,A-Z,
Delay_ms(300);
t++;
}while(t<36);
Max7219_Clear();
*/
/*<2> 图案 心:预处理二进制取模
for(int j=0;j<8;j++)
Max7219_SendByte(j+1,Heart[j]);
Delay_ms(500);
Max7219_Clear();
*/
/*<3> 使用封装函数:数字1
for(int i=1;i<=8;i++)
Max7219_ShowGraph(i,4,5); //第i行,点亮[4-5]的灯
Max7219_ShowGraph(1,3,3);
Max7219_ShowGraph(2,2,3);
Max7219_ShowGraph(8,2,7);
Delay_ms(800);
Max7219_Clear();
*/
/*<4> 使用封装函数:蛇形矩阵
for(int i=1;i<=8;i++)
for(int st=i,ed=1; ;st--,ed++){
if(st==0&&ed==i+1) break;
Max7219_ShowGraph(st,ed,ed); //凡有规律的图形,或动态变化,皆可实现
Delay_ms(270);
}
Max7219_Clear();
*/
}
}
三 取模软件
粘贴生成的:C语言数组,共阳或共阴
选TABH或TABL
其中一个的数据即可,取模软件有很多款,网上也可直接搜索下载。
完全开源,愿与君共勉