目录
前言
51单片机之数码管控制,数码管是生活中随处可见的一种外设,数码管的驱动是对单个LED灯的驱动,特别是家电领域应用极为广泛,空调、热水器、冰箱等等。绝大多数热水器用的都是数码管
一、共阴数码管
共阴极数码管是把所有led的阴极连接到共同接点COM,而每个led的阳极分别为a、b、c、d、e、f、g及dp(小数点)。其中8个led分别与概述图中的a~dp各段相对应,通过控制各个led的亮灭来显示数字。共阴极数码管是把所有led的阴极连接到共同接点COM,而每个led的阳极分别为a、b、c、d、e、f、g及dp(小数点)。其中8个led分别与概述图中的a~dp各段相对应,通过控制各个led的亮灭来显示数字。
二、138译码器
138译码器是一种二进制译码器,提供8个互斥(Y0-Y7,8个脚互不影响)的低电平输出,
三个使能管脚E1,E2,E3,我们这里使用的是使能为低低高,当使能不为低低高时38译码器总是输出高电平。
三、示例程序
1.实现单个数码管的点亮
代码如下:
这里我写的比较随意,没有建立数组来调用,实现在数字0
#include <REG51.h> //51专属头文件
#include <public.h> //延时函数头文件
#define led P0 //定义P0寄存器端口为led
#define ymq P2 //定义P2寄存器端口为led
int main() //创建函数
{
ymq=0xe3; //定义38译码器电平为0
while(1) //循环体
led=0x3f; //控制数码管输出数字0
return 0;
}
2.实现数字顺序显示0-7
代码如下:
#include <REG51.h> //51专属头文件
#include <public.h> //延时函数头文件
#define led P0 //定义P0寄存器端口为led
sbit A =P2^2;
sbit D =P2^3; //对译码器位操作
sbit C =P2^4;
int led_display[9]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,0x7f}; //定义数字0-8
int main()
{
int i=0;
for(i=0;i<8;i++)
{
switch(i)
{
case 0:A=1,D=1,C=1;break; //真值表选择数码管
case 1:A=0,D=1,C=1;break;
case 2:A=1,D=0,C=1;break;
case 3:A=0,D=0,C=1;break;
case 4:A=1,D=1,C=0;break;
case 5:A=0,D=1,C=0;break;
case 6:A=1,D=0,C=0;break;
case 7:A=0,D=0,C=0;break;
}
led=led_display[i]; // 取数组中的数字
delay_ms(1); //延时
led=0x00; //消影
if(i==7)
i=-1; //循环,此处习惯给i赋值为-1,循环进去为 0
}
return 0;
}
此处给i赋值为-1是for函数之后循环不会执行i=0直接i++,会跳过0的显示,加长延时得到流水数码管,此处数码管的调用可以单独封装为一个函数,然后在主函数里进行调用。代码如下:
#include <REG51.h> //51专属头文件
#include <public.h> //延时函数头文件
#define led P0 //定义P0寄存器端口为led
sbit A =P2^2;
sbit D =P2^3; //对译码器位操作
sbit C =P2^4;
int led_display[9]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,0x7f}; //定义数字0-8
void led_function()
{ int i=0;
for(i=0;i<8;i++)
{
switch(i)
{
case 0:A=1,D=1,C=1;break; //真值表选择数码管
case 1:A=0,D=1,C=1;break;
case 2:A=1,D=0,C=1;break;
case 3:A=0,D=0,C=1;break;
case 4:A=1,D=1,C=0;break;
case 5:A=0,D=1,C=0;break;
case 6:A=1,D=0,C=0;break;
case 7:A=0,D=0,C=0;break;
}
led=led_display[i]; // 取数组中的数字
delay_ms(1);
led=0x00;
}
}
int main()
{
while(1)
{
led_function();
}
return 0;
}
3.秒表
想用延时实现一个999s的秒表,由于数码管为三八译码器去快速扫描实现动态数码管,所以加了延时的话不能实现,数码管的快速扫描,导致只有一个数码管点亮,实现了一个10秒钟的秒表,有没有人知道在不用定时器可以实现吗,基于38译码器的动态数码管切换。
以下为半成品代码,误差大,不可以同时显示三位
第二种方案是在主函数中一直循环扫描三个数码管,然后进行中断
#include <REG51.h> //51专属头文件
#include <public.h> //延时函数头文件
#define led P0 //定义P0寄存器端口为led
sbit A =P2^2;
sbit D =P2^3; //对译码器位操作
sbit C =P2^4;
int led_display[9]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,0x7f,}; //定义数字0-9
void led_function(int x)
{
switch(x)
{
case 7:A=1,D=1,C=1;break; //真值表选择数码管
case 6:A=0,D=1,C=1;break;
case 5:A=1,D=0,C=1;break;
case 4:A=0,D=0,C=1;break;
case 3:A=1,D=1,C=0;break;
case 2:A=0,D=1,C=0;break;
case 1:A=1,D=0,C=0;break;
case 0:A=0,D=0,C=0;break;
}
}
int main()
{
int i;
int j;
int k;
int x;
for(i=0;i<=9;i++)
{
led_function(2);
led=led_display[i];
delay_ms(900);
for(j=0;j<=9;j++)
{
led_function(1);
led=led_display[j];
delay_ms(900);
for(k=0;k<=9;k++)
{
led_function(0);
led=led_display[k];
delay_ms(900);
}
}
}
return 0;
}
总结
以上就是今天的内容,简单介绍了51数码管外设的共阴,以及138译码器,数码管的点亮和动态数码管扫描。