MAX7219(模拟SPI)驱动灯环的简单应用

文章目录

  • 一、MAX7219是什么?
  • 二、使用步骤
    • 1.硬件
      • [1.1 引脚说明](#1.1 引脚说明)
      • [1.2 应用电路](#1.2 应用电路)
        • [1.2.1 驱动数码管](#1.2.1 驱动数码管)
        • [1.2.2 驱动点阵](#1.2.2 驱动点阵)
    • 2.软件
      • [2.1 时序](#2.1 时序)
      • [2.2 寄存器](#2.2 寄存器)
        • [2.2.1 掉电寄存器](#2.2.1 掉电寄存器)
        • [2.2.2 译码模式寄存器](#2.2.2 译码模式寄存器)
        • [2.2.3 亮度寄存器](#2.2.3 亮度寄存器)
        • [2.2.4 扫描寄存器](#2.2.4 扫描寄存器)
        • [2.2.5 显示测试寄存器](#2.2.5 显示测试寄存器)
      • [2.3 初始化](#2.3 初始化)
      • [2.4 控制左侧灯环特定位置中的LED灯的状态](#2.4 控制左侧灯环特定位置中的LED灯的状态)
      • [2.5 控制右侧灯环特定位置中的LED灯的状态](#2.5 控制右侧灯环特定位置中的LED灯的状态)
  • 三、总结

一、MAX7219是什么?

MAX7219是一个集成化的串行输入/输出共阴极显示驱动芯片,它一般驱动8位数字的7段数码管或者连接8*8点阵又或者是64个独立的LED。它可以通过亮度寄存器来设置LED的电流,又或者是通过硬件上修改V+和ISET直接的电阻阻值大小来设置。同时,它还拥有译码模式寄存器,可以选择采用BCD译码或不采用。

有些人可能不清楚什么是BCD译码,下面简单解释下,

BCD译码 是一种将二进制数转换成BCD(Binary-Coded Decimal)格式的过程。BCD码是一种特殊的二进制编码方式,用于表示十进制数,其中每一位十进制数由4位二进制数表示,范围从0到9。例如,十进制数13在BCD码中表示为0001 0011。BCD码的优点是可以直接对每个十进制位进行处理,而无需进行二进制到十进制的转换,这在数字显示、计算机存储和控制系统等领域中具有重要意义。

二、使用步骤

1.硬件

1.1 引脚说明

1.2 应用电路

1.2.1 驱动数码管

MAX7219通过加在V+和ISET之间的一个外部电阻来控制显示亮度,段驱动电流一般是流入ISET端电流的100倍,这里用的电阻是9.53K,它设定的段电流为40mA。显示亮度也可以通过亮度寄存器来设置。

MAX7219的SPI只需要用到串行信号时钟CLK,片选信号CS以及主机输出从机输入数据DIN(MOSI),和常规相比少了个主机输入从机输出DO(MISO)。

1.2.2 驱动点阵

和上面的驱动数码管相比,无非就是把接在数码管的段和位接到了88点阵的行列上,8 8点阵其实就是64个LED组成,之前我的一篇文章有提及到,感兴趣可以自行去看下基于51单片机的点阵显示的proteus仿真(附源码)

这里级联没有涉及,先不讲。

2.软件

2.1 时序

对MAX7219来说,串行数据在DIN输入16为数据包,无论LOAD端处于何种状态,在时钟的上升沿数据均移入到内部16位移位寄存器。无论数据输入或输出CS必须为低电平,然后数据在LOAD/CS上升沿被载入数据寄存器或控制寄存器。LOAD/CS端在第16个时钟的上升沿同时或之后,下个时钟上升沿之前变为高电平,否则数据将会丢失。在DIN端的数据传输到移位寄存器在16.5个时钟周期之后出现在DOUT端。在时钟的下降沿数据将被输出。

数据位标记位D0-D15(如下表1所示)。其中D8-D11为寄存器地址位,D0-D7为数据位,D12-D15为无效位。在传输过程中,首先接收到的是D15位。是非常重要的一位(MSB)。

示例代码如下:

c 复制代码
/*******************************************************************************
 * 函数名:Write_Max7219_Date
 * 描述  :向Max7219写入数据
 * 输入  :addr地址,dat数据
 * 输出  :void
 * 调用  :内部调用
 * 备注  :
*******************************************************************************/
void Write_Max7219_Date(uint8_t addr,uint8_t dat)
{
	uint8_t i;	
	
	SPI2_CLK_LOW();		
	SPI2_CS_LOW();//拉低CS,选中器件	
	
	//发送地址
	for(i=0;i<8;i++)
	{
		  if(addr & 0x80)
			{
		    SPI2_SI_HIGH();			
			}
			else
			{
		    SPI2_SI_LOW();					
			}
			addr <<= 1;
			SPI2_CLK_HIGH();	
	        SPI2_CLK_LOW();					
	}
	
	//发送数据
	for(i=0;i<8;i++)
	{
		  if(dat & 0x80)
			{
		    SPI2_SI_HIGH();			
			}
			else
			{
		    SPI2_SI_LOW();					
			}
			dat <<= 1;
			SPI2_CLK_HIGH();	
	       SPI2_CLK_LOW();					
	}	
	
	SPI2_CS_HIGH();//发送结束,上升沿锁存数据	
	SPI2_CLK_LOW();			
    SPI2_SI_LOW();	
}

2.2 寄存器

MAX7219如下表所示有14个可寻址的数据寄存器和控制寄存器。数据寄存器由一个在片上的8X8的双向SRAM来实现。它们可以直接寻址所有只要在V+大于2V的情况下每个数据都可以独立的修改或保持。控制寄存器包括译码模式、显示亮度、扫描限制、掉电模式、显示测试五个寄存器。

示例代码如下:

c 复制代码
/* Defines ------------------------------------------------------------------*/
#define DIG0_Registe  0x01//选位0寄存器
#define DIG1_Registe  0x02//选位1寄存器
#define DIG2_Registe  0x03//选位2寄存器
#define DIG3_Registe  0x04//选位3寄存器
#define DIG4_Registe  0x05//选位4寄存器
#define DIG5_Registe  0x06//选位5寄存器
#define DIG6_Registe  0x07//选位6寄存器
#define DIG7_Registe  0x08//选位7寄存器

#define DECODE_MODE   0x09//译码模式寄存器
//0x00:7-0不采用译码
//0x01:0采用BCD译码,7-1不采用
//0x0F:3-0采用BCD译码,7-4不采用
//0xFF:7-0采用BCD译码
//当选择BCD译码模式时,译码器只对数据的低四位进行译码(D3-D0),D4-D6为无效位。D7位用来设置小数点,不受译码器的控制且为高电平。
//当选择不译码时,数据的八位与MAX7219的各段线上的信号一致。

#define INTENSITY    0x0A//亮度寄存器
//亮度等级设置 0x00-0x0F 设置电流为最大电流的 1/32 - 31/32(间隔2/32)
//也可以通过硬件来改变,修改V+和ISET之间的电阻阻值大小,最小阻值为9.53kΩ,它设定段电流为40mA。

#define SCAN_LIMIT   0x0B//扫描寄存器
//0x00:只显示数字0
//0x01:显示数字0&1
//0x02:显示数字0,1,2
//0x03:显示数字0,1,2,3
//0x04:显示数字0,1,2,3,4
//0x05:显示数字0,1,2,3,4,5
//0x06:显示数字0,1,2,3,4,5,6
//0x07:显示数字0,1,2,3,4,5,6,7

#define SHUTDOWN 0x0C//掉电寄存器
//0x00:掉电模式
//0x01:正常模式

#define DISPLAY_TEST  0x0F//显示测试寄存器
//0x00:正常模式
//0x01:显示测试模式
2.2.1 掉电寄存器

可以从下表看出掉电寄存器的地址位0x0C,写入数据0x00表示掉电模式,写入数据0x01表示正常模式。

示例代码如下:

c 复制代码
#define SHUTDOWN 0x0C//掉电寄存器
//0x00:掉电模式
//0x01:正常模式

Write_Max7219_Date(SHUTDOWN,0x01);//掉电模式:0;普通模式:1	
2.2.2 译码模式寄存器

可以从下表看出译码模式寄存器的地址位0x09,写入数据0x00表示不采用BCD译码,这里我实际电路接的是16个独立的LED组成的灯环,所有选择非译码模式。

示例代码如下:

c 复制代码
#define DECODE_MODE   0x09//译码模式寄存器
//0x00:7-0不采用译码
//0x01:0采用BCD译码,7-1不采用
//0x0F:3-0采用BCD译码,7-4不采用
//0xFF:7-0采用BCD译码
//当选择BCD译码模式时,译码器只对数据的低四位进行译码(D3-D0),D4-D6为无效位。D7位用来设置小数点,不受译码器的控制且为高电平。
//当选择不译码时,数据的八位与MAX7219的各段线上的信号一致。

Write_Max7219_Date(DECODE_MODE,0x00);//译码方式:非BCD译码
2.2.3 亮度寄存器

可以从下表看出亮度寄存器的地址位0x0A,根据写入数据多少来设置亮度也就是电流的大小。

示例代码如下:

c 复制代码
#define INTENSITY    0x0A//亮度寄存器
//亮度等级设置 0x00-0x0F 设置电流为最大电流的 1/32 - 31/32(间隔2/32)
//也可以通过硬件来改变,修改V+和ISET之间的电阻阻值大小,最小阻值为9.53kΩ,它设定段电流为40mA。

Write_Max7219_Date(INTENSITY,0x0C);//亮度
2.2.4 扫描寄存器

可以从下表看出扫描寄存器的地址位0x0B,根据写入数据多少来设置扫描数量。

示例代码如下:

c 复制代码
#define SCAN_LIMIT   0x0B//扫描寄存器
//0x00:只显示数字0
//0x01:显示数字0&1
//0x02:显示数字0,1,2
//0x03:显示数字0,1,2,3
//0x04:显示数字0,1,2,3,4
//0x05:显示数字0,1,2,3,4,5
//0x06:显示数字0,1,2,3,4,5,6
//0x07:显示数字0,1,2,3,4,5,6,7

Write_Max7219_Date(SCAN_LIMIT,0x07);//扫描界限:8个数码管显示	
2.2.5 显示测试寄存器

可以从下表看出显示测试存器的地址位0x0F,写入数据0x00表示正常模式,写入数据0x01表示显示测试模式,如果选择显示测试模式,灯会全部点亮。

示例代码如下:

c 复制代码
#define DISPLAY_TEST  0x0F//显示测试寄存器
//0x00:正常模式
//0x01:显示测试模式

Write_Max7219_Date(DISPLAY_TEST,0x00);//显示测试:1;测试结束,正常显示:0	

2.3 初始化

示例代码如下:

c 复制代码
/*******************************************************************************
 * 函数名:User_Max7219_Init
 * 描述  :MAX7219配置初始化
 * 输入  :void
 * 输出  :void
 * 调用  :初始化
 * 备注  :
*******************************************************************************/
void User_Max7219_Init(void)
{
	User_SPI2_Init();//SPI引脚配置初始化	
	Write_Max7219_Date(SHUTDOWN,0x01);//掉电模式:0;普通模式:1	
	Write_Max7219_Date(DISPLAY_TEST,0x00);//显示测试:1;测试结束,正常显示:0			
    Write_Max7219_Date(DECODE_MODE,0x00);//译码方式:非BCD译码
	Write_Max7219_Date(SCAN_LIMIT,0x07);//扫描界限:8个数码管显示	
	Write_Max7219_Date(INTENSITY,0x0C);//亮度
}

2.4 控制左侧灯环特定位置中的LED灯的状态

示例代码如下:

c 复制代码
/*******************************************************************************
 * 函数名:ConLeft
 * 描述  :控制左侧灯环特定位置中的LED灯的状态
 * 输入  :num代表要控制的LED灯的位置,status代表LED灯的状态,0表示关闭,1表示打开
 * 输出  :void
 * 调用  :内部调用
 * 备注  :
*******************************************************************************/
void ConLeft(uint8_t num, uint8_t Status)	// num 从 0 开始 (中间位置)
{
    if ( ( Status != 0 ) &&	( Status != 1 ) )
    {
        Sendstr_U1 ( "*_ERR: Status$" );
        return;
    }
    if ( num > 15 )
    {
        Sendstr_U1 ( "*_ERR: num > 15$" );
        num = 15;
    }

    if ( Status == 0 )
    {
        LeftStatus &= ( ~ ( 0x0001 << num ) );
        Left_RegVal[ ( num >> 2 )] &= ( ~Left_Val[num] );
    }
    else
    {
        LeftStatus |= ( 0x0001 << num );
        Left_RegVal[ ( num >> 2 )] |= ( Left_Val[num] );
    }
    Write_Max7219_Date ( Left_Reg[num], Left_RegVal[ ( num >> 2 )] );
}

2.5 控制右侧灯环特定位置中的LED灯的状态

示例代码如下:

c 复制代码
/*******************************************************************************
 * 函数名:ConRight
 * 描述  :控制右侧灯环特定位置中的LED灯的状态
 * 输入  :num代表要控制的LED灯的位置,status代表LED灯的状态,0表示关闭,1表示打开
 * 输出  :void
 * 调用  :内部调用
 * 备注  :
*******************************************************************************/
void ConRight(uint8_t num, uint8_t Status )	// num 从 0 开始 (中间位置)
{
    if ( ( Status != 0 ) &&	( Status != 1 ) )
    {
        Sendstr_U1 ( "*_ERR: Status$" );
        return;
    }
    if ( num > 15 )
    {
        Sendstr_U1 ( "*_ERR: num > 15$" );
        num = 15;
    }

    if ( Status == 0 )
    {
        RightStatus &= ( ~ ( 0x0001 << num ) );
        Right_RegVal[ ( num >> 2 )] &= ( ~Right_Val[num] );
    }
    else
    {
        RightStatus |= ( 0x0001 << num );
        Right_RegVal[ ( num >> 2 )] |= ( Right_Val[num] );
    }
    Write_Max7219_Date ( Right_Reg[num], Right_RegVal[ ( num >> 2 )] );
}

三、总结

今天主要讲了MAX7219(模拟SPI)驱动灯环的简单应用。

感谢你的观看!

相关推荐
小菜鸟学代码··16 分钟前
STM32文件详解
stm32·单片机·嵌入式硬件
马浩同学1 小时前
【GD32】从零开始学GD32单片机 | DAC数模转换器 + 三角波输出例程
c语言·单片机·嵌入式硬件·mcu
最后一个bug4 小时前
STM32MP1linux根文件系统目录作用
linux·c语言·arm开发·单片机·嵌入式硬件
wenchm5 小时前
细说STM32F407单片机IIC总线基础知识
stm32·单片机·嵌入式硬件
嵌入式lover5 小时前
STM32项目之环境空气质量检测系统软件设计
stm32·单片机·嵌入式硬件
kenwblack6 小时前
STM32 SPI读取SD卡
stm32·单片机
兰_博7 小时前
51单片机驱动1602液晶显示
单片机·嵌入式硬件·51单片机
深圳市青牛科技实业有限公司 小芋圆7 小时前
开关电源特点、分类、工作方式
前端·科技·单片机·物联网·分类·数据挖掘·新能源
我qq不是451516527 小时前
单片机优先级
单片机·嵌入式硬件
相醉为友8 小时前
在开发嵌入式系统时,尤其是处理大数时,会遇到取值范围的问题。51单片机通常没有内建大整数支持,因此我们需要采用不同的方法来解决这一问题
单片机·嵌入式硬件·51单片机