一、7219datasheet阅读
1.引脚定义:
重点介绍5个引脚
1.DIN:
串行数据总线输入引脚,每个时钟的上升沿将数据移入至芯片内部的移位寄存器中
2.DIG0-DIG7:
共阴极管的GND连接的便是DIG0-7,该引脚起作用时,便输出低电平,即共阴极数码管的GND端为低电平。不起作用时为高电平,即数码管无法被点亮。
3. LOAD:
装载信号(LOAD),在load的上升沿,16位数据被锁存器锁存,数据不发生变化
4.CLK
串行时钟输入,在每次CLK的上升沿,数据被移位至MAX7219内部的移位寄存器,配合上述的LOAD信号,便可以将数据锁存;下降沿时,数据从DOUT引脚输出(用于级联的情况)。
5.SEGA-SEGG,DP :
数码管的7段(a,b,c,d,e,f)以及一个小数点dp的驱动信号,当功能关闭时,段(seg)输出低电平,即无法点亮(由于是共阴极接法,前期已经将DIG置为低电平,只有当SEG为高电平时才能使得数码管内部的发光二极管点亮)
2. 串行数据格式:
前面提到,一次交互我们需要发送16位数据(2个字节),由上图可以看出,高字节表示着需要操作的寄存器地址,低字节表示写入的数据。对于7219来说,无论load何种状态,数据都会由于CLK的上升沿被移入数据寄存器。在发送完16位数据之后,一定要使得LOAD产生上升沿,否则在下一个CLK到来之后,移位寄存器的数据便会丢失。同时,对于数据格式来说,发送的数据总是MSB。
3.数据和控制寄存器
上表列出了14个可寻址的寄存器(8个数据寄存器和5个控制寄存器),控制寄存器由一个8*8的SRAM组成,控制寄存器由译码模式寄存器,亮度控制寄存器,扫描位数限制寄存器,关机控制寄存器,显示测试寄存器(所以LED全亮)组成。通过上述表可以看出,每个寄存器实地址由一位16进制数(4位二进制)组成,这样对应了前面数据格式中高8位中只有4位数据是有效的。
对于数据寄存器digit0-digit7便对应八位数码管,在该寄存器上写入相应的数据即可点亮对应的数码管。
4. 译码寄存器
该寄存器可以设定对输入的数据进行BCD译码。注意,由于BCD是通过四位二进制数来表示一位十进制数,因此对于输入的数据,译码寄存器只会将第四位当作BCD码,而不关心其他高位,并将这四位数进行译码得到对应的二进制数。对于第八位数据(D7),这一位是单独设置的,并不参与译码,当数据为高是,小数点自然点亮
5.扫描位数限制寄存器
该寄存器用来配置显示数码管的个数,即0x00-0x07。
6.亮度设置寄存器
数值越大,数码管越亮
二、代码编写
1.初始化工作
1.定义引脚
这里的load和cs是相同含义
#define clk GPIO_Pin_0
#define load GPIO_Pin_1
#define din GPIO_Pin_2
#define LOAD(x) GPIO_WriteBit (GPIOB,load,(BitAction)x);
#define CLK(x) GPIO_WriteBit (GPIOB,clk ,(BitAction)x);
#define DIN(x) GPIO_WriteBit (GPIOB,din ,(BitAction)x);
2.写一个字节
原理即为不断翻转CLK电平,使得移位寄存器工作将其读入
void MAX7219_WriteByte (uint8_t byte)
{
for(int i =0;i<8;i++)
{
CLK(0);
DIN(byte&0x80);
byte=byte<<1;
CLK(1);
}
}
3.写寄存器
通过此前分析可知,MAX7219为16位传输方式,且先发寄存器地址,再发数据,注意这里先拉低load引脚,等待16位数据传输完毕后,在将load拉高,使得数据锁存。
void MAX7219_WriteReg(uint8_t Reg,uint8_t data)
{
LOAD(0);
MAX7219_WriteByte (Reg);
MAX7219_WriteByte (data);
LOAD(1);
}
4.数码管显示
由手册可知,小数点是单独配置的,只需要将最高位置1即可
/**
* 函 数 显示内容 该函数为在BCD译码下的显示
* 参 数 uint8_t location:在几位显示 1~8。
* 参 数 uint8_t num:显示的数字(0~9,Line,E,H,L,P,blank)
* 参 数 uint8_t dot: 是否需要小数点
*/
void MAX7219_ShowNum(uint8_t location,uint8_t num,uint8_t dot)
{
if(dot==0) MAX7219_WriteReg (location,num);
else
{
num |=0x80;
MAX7219_WriteReg (location,num);
}
}
/**
* 函 数 MAX7219_Clear 数码管清屏
*/
void MAX7219_Clear(void)
{
for(int i=1;i<=8;i++)
{
MAX7219_ShowNum(i,blank,0);
}
}
5.引脚初始化
思路是先把5个控制寄存器配置好。
/**
* 函 数 初始化MAX7219
* 参 数 uint8_t BCD:D7~D0控制对于的数码管参与BCD译码。
* 参 数 uint8_t Intensity:控制数码管的亮度 0~15(0表示熄灭)
* 参 数 uint8_t DisplayNum: 数码管显示的个数:1~8
*/
void MAX7219_Init (uint8_t BCD,uint8_t Intensity,uint8_t DisplayNum)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init (GPIOB,&GPIO_InitStructure );
/*先配置五个控制寄存器*/
MAX7219_WriteReg (0x0c,0x01);//设置为正常模式
MAX7219_WriteReg (0x09,BCD);//设置BCD译码,8个数码管均使用BCD译码
MAX7219_WriteReg (0x0a,Intensity);//设置亮度
DisplayNum-=1;
MAX7219_WriteReg (0x0b,DisplayNum);//8个数码管参与显示
MAX7219_WriteReg (0x0f,0x01);//测试模式,所有数码管全亮
delay_ms(5000);
MAX7219_WriteReg (0x0f,0x00);//正常显示模式
MAX7219_Clear();//再清屏
}
2.实际应用——秒表
1.配置定时器,开启中断计时
uint16_t time;
uint16_t count;
void Timer_Init(uint16_t ARR,uint16_t PSC)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
TIM_TimeBaseInitTypeDef Tim4_InitStructure;
Tim4_InitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//不分频
Tim4_InitStructure.TIM_CounterMode=TIM_CounterMode_Up;//向上计数
Tim4_InitStructure.TIM_Period=ARR;
Tim4_InitStructure.TIM_Prescaler=PSC;
Tim4_InitStructure.TIM_RepetitionCounter=0x00;
TIM_TimeBaseInit(TIM4,&Tim4_InitStructure);
TIM_ClearFlag(TIM4, TIM_FLAG_Update); //清除由于初始化而置的标志位
TIM_Cmd(TIM4,ENABLE);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
NVIC_InitTypeDef TIM4_IT_InitStructure;
TIM4_IT_InitStructure.NVIC_IRQChannel=TIM4_IRQn;
TIM4_IT_InitStructure.NVIC_IRQChannelCmd=ENABLE;
TIM4_IT_InitStructure.NVIC_IRQChannelPreemptionPriority=4;
TIM4_IT_InitStructure.NVIC_IRQChannelSubPriority=4;
NVIC_Init(&TIM4_IT_InitStructure);
}
void TIM4_IRQHandler(void)
{
if(TIM_GetITStatus(TIM4,TIM_IT_Update)==SET)
{
count ++;
if(count==100)
{
count=0;
time++;
}
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
}
}
2.数码管显示
/**
* 函 数 秒表
* 参 数 定时器总时间
*/
void MAX7219_Stopwatch(uint16_t time)
{
uint16_t times=time;
uint16_t weishu;
weishu=1+log10(times);
for(int i=weishu;i>0;i--)
{
if(i==2) MAX7219_ShowNum(i,times/(int)(pow(10,i-1)),1);
else MAX7219_ShowNum(i,times/(int)(pow(10,i-1)),0);
times=times%(int)pow(10,i-1);
}
}
三、结果
源码自取
链接:https://pan.baidu.com/s/1y_ins_xLHj9oJFgG9AhzLw?pwd=hcoi
提取码:hcoi