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


一、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点阵的行列上,88点阵其实就是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)。

在这里插入图片描述

示例代码如下:

/*******************************************************************************
 * 函数名: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的情况下每个数据都可以独立的修改或保持。控制寄存器包括译码模式、显示亮度、扫描限制、掉电模式、显示测试五个寄存器。

在这里插入图片描述

示例代码如下:

/* 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表示正常模式。

在这里插入图片描述

示例代码如下:

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

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

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

在这里插入图片描述

示例代码如下:


#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,根据写入数据多少来设置亮度也就是电流的大小。
在这里插入图片描述
示例代码如下:

#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,根据写入数据多少来设置扫描数量。

在这里插入图片描述
示例代码如下:

#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表示显示测试模式,如果选择显示测试模式,灯会全部点亮。

在这里插入图片描述
示例代码如下:

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

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

2.3 初始化

示例代码如下:

/*******************************************************************************
 * 函数名: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灯的状态

示例代码如下:

/*******************************************************************************
 * 函数名: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灯的状态

示例代码如下:

/*******************************************************************************
 * 函数名: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)驱动灯环的简单应用。

感谢你的观看!

在这里插入图片描述

  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaobuding_QAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值