单片机proteus 8如何编写程序(基于proteus的51单片机开发实例31-MAX7219驱动8位数码管)

1. 基于proteus的51单片机开发实例31-MAX7219驱动8位数码管1.1. 实验目的

单片机proteus 8如何编写程序(基于proteus的51单片机开发实例31-MAX7219驱动8位数码管)(1)

图1 MAX7219驱动8位数码管

从本实例开始,我们将要学习一系列51单片机项目开发中常用的外设芯片。本实例我们来了解数码管驱动芯片MAX7219的电路设计和程序实现。使用MAX7219芯片驱动8位数码管显示数字。

1.2. 设计思路

首先设计使用MAX7219驱动数码管的电路,了解掌握MAX7219与单片机和数码管的接口电路是如何连接的,然后编程实现单片机通过MAX7219驱动8位数码管显示数字。

1.3. 基础知识

MAX7219是一种常用的数码管驱动芯片,它不但可以节省单片机的I/O口,还可以提供足够的驱动电流点亮数码管显示。

MAX7219是一种串行输入/输出的共阴极显示驱动器,可以驱动8位共阴极数码管,也可以连接64个独立的LED等。MAX7219内部包含了bcd编码器、多路扫描回路、段字驱动器以及一个8*8的静态RAM(用来存储临时数据),还有一个外部寄存器可以用来设置每个段输出的电流的大小。

1.3.1. MAX7219的引脚说明

下图所示是MAX7219的引脚图。我们来详细了解一下MAX7219各引脚的功能。

单片机proteus 8如何编写程序(基于proteus的51单片机开发实例31-MAX7219驱动8位数码管)(2)

图2 MAX7219引脚图

DIN:串行数据输入引脚

CLK:时钟输入引脚

DOUT:串行数据输出引脚,用于多片MAX7219级联扩展。

DIG0~DIG7:数码管位选择引脚

LOAD:数据锁存控制引脚,在LOAD上升沿时,片内数据被锁定。

SEGA~SEGG、DP:数码管段驱动引脚,没有输入时为低电平。

ISET:段电流控制引脚,可以通过一个电阻连接到电源来增大段驱动电流,使数码管亮度更高。

VCC、GND:电源、地引脚。

MAX7219使用串行移位方式与51单片机进行通信,其串行数据大小为2字节(这2字节包含4位无效数据、4位地址数据、8位有效数据位)。这些数据从DIN引脚输入,在每一个CLK时钟信号的上升沿被移入内部移位寄存器,然后在LOAD信号的上升沿时,数据被送到数据寄存器或控制寄存器。数据发送过程中按照高位在前、低位在后的原则发送。

1.3.2. MAX7219驱动控制

MAX7219内部有14个可位寻址的数据/控制寄存器,单片机通过这些寄存器控制MAX7219进行各种操作。

这14个寄存器包含:8个数据寄存器(组成一个8*8的内存空间),5个控制寄存器(控制编码模式、显示亮度、扫描限制、关闭模式、显示检测)。

MAX7219的内部寄存器如下图所示。

单片机proteus 8如何编写程序(基于proteus的51单片机开发实例31-MAX7219驱动8位数码管)(3)

图3 MAX7219寄存器

MAX7219的模式编码寄存器用于设置对显示内存中的待显示数据进行BCD译码或不译码。当选择编码模式时,其内置的译码器只对数据的第四位D3~D0进行译码,D4~D6无效,D7位用来设置小数点,不受译码器的控制且始终为高电平。

MAX7219可以通过加在VCC和ISET引脚之间的电阻来控制数码管的显示亮度。该电阻最小值是9.53kΩ。显示亮度可以用亮度寄存器的低4位用脉宽调制的方法控制。脉宽调制将段电流平均分为16级。

扫描控制寄存器用来控制需要显示的数码管的位数,最多8位,最低1位。如果数码管少于3位,ISET外加的电阻的大小必须根据显示数据的个数来确定,从而限制个别数据驱动对功耗的浪费。

1.3.3. 51单片机驱动MAX7219的初始化流程

1、设置模式编码寄存器;

2、设置显示亮度寄存器;

3、设置扫描控制寄存器;

4、设置自关闭模式寄存器。

1.4. 电路设计

本实例的电路图如图1所示。单片机的P2.3,P2.4,P2.5端口分别连接MAX7219的DIN,LOAD,CLK引脚。8为共阴极数码管的8个段分别连接MAX7219的SEGA~SEGG、DP。8个位分别连接MAX7219的DIG0~DIG7。MAX7219的ISET引脚通过一个10K电阻连到VCC。

1.5. 程序设计

程序代码如下。根据上一实例中的模块化程序设计方法,将程序分为主程序模块、延时程序模块、MAX7219控制程序模块。

主程序代码

//实例72:DS18B20温度检测及其液晶显示 #include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 #include"MAX7219.h" // #include"Delay.h" // //MAX7219的输出缓冲 unsigned char Disp_Buffer1[8] = {0,0,0,0,0,0,0,0}; unsigned char Disp_Buffer2[8] = {0,0,0,0,0,0,0,1}; unsigned char Disp_Buffer3[8] = {0,0,0,0,0,0,1,2}; unsigned char Disp_Buffer4[8] = {0,0,0,0,0,1,2,3}; unsigned char Disp_Buffer5[8] = {0,0,0,0,1,2,3,4}; unsigned char Disp_Buffer6[8] = {0,0,0,1,2,3,4,5}; unsigned char Disp_Buffer7[8] = {0,0,1,2,3,4,5,6}; unsigned char Disp_Buffer8[8] = {0,1,2,3,4,5,6,7}; unsigned char Disp_Buffer9[8] = {1,2,3,4,5,6,7,8}; /***************************************************** 函数功能:主函数 ***************************************************/ void main(void) { unsigned char i; InitMAX7219(); //首先初始化MAX7129 DelayMs(1); //延时1毫秒 while(1) { for(i=0;i<8;i ) { WriteMAX7219(i 1,Disp_Buffer1[i]); //将显示缓冲区内的数据循环送出 } DelayMs(800); for(i=0;i<8;i ) { WriteMAX7219(i 1,Disp_Buffer2[i]); // } DelayMs(800); for(i=0;i<8;i ) { WriteMAX7219(i 1,Disp_Buffer3[i]); // } DelayMs(800); for(i=0;i<8;i ) { WriteMAX7219(i 1,Disp_Buffer4[i]); // } DelayMs(800); for(i=0;i<8;i ) { WriteMAX7219(i 1,Disp_Buffer5[i]); // } DelayMs(800); for(i=0;i<8;i ) { WriteMAX7219(i 1,Disp_Buffer6[i]); // } DelayMs(800); for(i=0;i<8;i ) { WriteMAX7219(i 1,Disp_Buffer7[i]); // } DelayMs(800); for(i=0;i<8;i ) { WriteMAX7219(i 1,Disp_Buffer8[i]); // } DelayMs(800); for(i=0;i<8;i ) { WriteMAX7219(i 1,Disp_Buffer9[i]); // } DelayMs(800); } }

MAX7219.h代码

//MAX7219.h sbit MAX7219DIN= P2^3; //MAX7219的数据引脚 sbit MAX7219LOAD = P2^4; //MAX7219的控制引脚 sbit MAX7219CLK = P2^5; //MAX7219的时钟引脚 //写MAX7219函数,Addr为MAX7219的内部寄存器地址,Dat为待写入的数据 void WriteMAX7219(unsigned char MA//MAX7219.c #include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 #include"MAX7219.h" // #include"Delay.h" // extern unsigned char Disp_Buffer[8]; //写MAX7219函数,Addr为MAX7219的内部寄存器地址,Dat为待写入的数据 void WriteMAX7219(unsigned char MAX7219Addr,unsigned char MAX7219Data) { unsigned char i; MAX7219LOAD = 0; for(i=0;i<8;i ) //先送出8位地址 { MAX7219CLK = 0; //时钟拉低 MAX7219Addr <<= 1; //移位送出地址 MAX7219DIN = CY; //送出数据 MAX7219CLK = 1; //时钟上升沿 _nop_(); _nop_(); MAX7219CLK = 0; } for(i=0;i<8;i ) //再送出8位数据 { MAX7219CLK = 0; MAX7219Data <<= 1; //移位送出数据 MAX7219DIN = CY; MAX7219CLK = 1; _nop_(); _nop_(); MAX7219CLK = 0; } MAX7219LOAD = 1; } //MAX7129的初始化函数 void InitMAX7219() { WriteMAX7219(0x09,0xff); //编码模式寄存器 WriteMAX7219(0x0a,0x07); //显示亮度控制 WriteMAX7219(0x0b,0x07); //扫描控制 WriteMAX7219(0x0c,0x01); //关闭模式控制寄存器设置 } X7219Addr,unsigned char MAX7219Data); //MAX7129的初始化函数 void InitMAX7219();//MAX7219.c #include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 #include"MAX7219.h" // #include"Delay.h" // extern unsigned char Disp_Buffer[8]; //写MAX7219函数,Addr为MAX7219的内部寄存器地址,Dat为待写入的数据 void WriteMAX7219(unsigned char MAX7219Addr,unsigned char MAX7219Data) { unsigned char i; MAX7219LOAD = 0; for(i=0;i<8;i ) //先送出8位地址 { MAX7219CLK = 0; //时钟拉低 MAX7219Addr <<= 1; //移位送出地址 MAX7219DIN = CY; //送出数据 MAX7219CLK = 1; //时钟上升沿 _nop_(); _nop_(); MAX7219CLK = 0; } for(i=0;i<8;i ) //再送出8位数据 { MAX7219CLK = 0; MAX7219Data <<= 1; //移位送出数据 MAX7219DIN = CY; MAX7219CLK = 1; _nop_(); _nop_(); MAX7219CLK = 0; } MAX7219LOAD = 1; } //MAX7129的初始化函数 void InitMAX7219() { WriteMAX7219(0x09,0xff); //编码模式寄存器 WriteMAX7219(0x0a,0x07); //显示亮度控制 WriteMAX7219(0x0b,0x07); //扫描控制 WriteMAX7219(0x0c,0x01); //关闭模式控制寄存器设置 }

MAX7219.c代码

//MAX7219.c #include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 #include"MAX7219.h" // #include"Delay.h" // //写MAX7219函数,Addr为MAX7219的内部寄存器地址,Dat为待写入的数据 void WriteMAX7219(unsigned char MAX7219Addr,unsigned char MAX7219Data) { unsigned char i; MAX7219LOAD = 0; for(i=0;i<8;i ) //先送出8位地址 { MAX7219CLK = 0; //时钟拉低 MAX7219Addr <<= 1; //移位送出地址 MAX7219DIN = CY; //送出数据 MAX7219CLK = 1; //时钟上升沿 _nop_(); _nop_(); MAX7219CLK = 0; } for(i=0;i<8;i ) //再送出8位数据 { MAX7219CLK = 0; MAX7219Data <<= 1; //移位送出数据 MAX7219DIN = CY; MAX7219CLK = 1; _nop_(); _nop_(); MAX7219CLK = 0; } MAX7219LOAD = 1; } //MAX7129的初始化函数 void InitMAX7219() { WriteMAX7219(0x09,0xff); //编码模式寄存器 WriteMAX7219(0x0a,0x07); //显示亮度控制 WriteMAX7219(0x0b,0x07); //扫描控制 WriteMAX7219(0x0c,0x01); //关闭模式控制寄存器设置 }

Delay.h代码

//Delay.h /***************************************************** 函数功能:延时1ms (3j 2)*i=(3×33 2)×10=1010(微秒),可以认为是1毫秒 ***************************************************/ void Delay1ms(); /***************************************************** 函数功能:延时若干毫秒 入口参数:n ***************************************************/ void DelayMs(unsigned int DelayCounter);

Delay.c代码

//Delay.c #include<reg51.h> //包含单片机寄存器的头文件 #include<intrins.h> //包含_nop_()函数定义的头文件 #include"Delay.h" // /***************************************************** 函数功能:延时1ms (3j 2)*i=(3×33 2)×10=1010(微秒),可以认为是1毫秒 ***************************************************/ void Delay1ms() { unsigned char i,j; for(i=0;i<10;i ) for(j=0;j<33;j ) ; } /***************************************************** 函数功能:延时若干毫秒 入口参数:n ***************************************************/ void DelayMs(unsigned int DelayCounter) { unsigned int i; for(i=0;i<DelayCounter;i ) Delay1ms(); }

1.6. 实例仿真

在Proteus环境下建立图1所示的电路,将编译完成的hex文件装载到单片机中,开始仿真,观察8位数码管的显示变化情况。

1.7. 总结

通过本实例,我们学习了数码管驱动芯片MAX7219驱动8位共阴极数码管的电路设计、编程方法。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页