多种方式实现数码管的动态显示

 1、动态显示,基本形式

/*
filename:segment.h
*/
#ifndef SEGMENT_H
#define SEGMENT_H
#include "type.h"
void  segemt_Init();
void  segment_Display(u8 pat);
void  segment_DynamicDisplay();//新加的
#endif
/*
filename:segment.c
描述:共阴数码管段接在P2端口上,位选线接在P3端口
*/
#include "reg51.h"
#include"segment.h"
#define SEGMENT P2
#define POS    P3
extern void delay(u16);
//共阳数码管段码表0~F,消影
static u8 code _table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xFF};
//显示位置
static u8 code _pos[]={~(1<<0),~(1<<1),~(1<<2),~(1<<3),~(1<<4),~(1<<5),~(1<<6),~(1<<7)};
//显示初始化
void  segemt_Init(){};
static u8 disp_pos=0;//显示的位置
u8 display_table[]={1,2,3,4,5,6,7,8};//显示的数值,也可以修改,且其他源文件中可以声明这个值以便修改
void  segment_DyamicDisplay(){
      SEGMENT=_table[display_table[disp_pos]];//显示
      POS=_pos[disp_pos];
      delay(50);//延时
      SEGMENT=_table[16];//消影
      disp_pos++;
      if(disp_pos==8)
             disp_pos=0;
 }

2、采用74HC138实现动态显示,减少口线的使用

74HC138是3-8译码器

/*
实例:采用74HC138控制,输出数码管
*/
#include"reg51.h"
void delay(unsigned int t){
   while(t--);
}
unsigned char code table[]={0xFF,0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
unsigned char disp_table[]={0,1,2,3,4,5,6,7};//显示的数值
void main(){
   //初始化
   int i=0;//循环变量
   //显示特定数字的字段码,本质上还是流水灯的花型数据
  
   //工作循环
   while(1){
     for(i=0;i<8;i++){
       P2=table[disp_table[i]+1];//输出字段码
       P3=i;//输出位码--改了这里
       delay(50);//亮一段时间
       P2=table[0];//LED熄灭,实际上这就是消影
       delay(50);//熄灭一段时间     
     }
   }
}

3、采用74HC595进一步减少口线的使用

74HC595可以实现串转并功能,其中ST_CP是时钟信号,上升沿有效;DS位数据输入口;RCK属于锁存端,上升沿有效。

//595发送一个字节
SCK = P2^0;//时钟信号
DS  = P2^1;//数据位
RCK = P2^2;//锁存信号,低电平有效

#define setSCK()  SCK=1
#define clrCLK()  SCK=0
#define setDS(x)  DS=x
#define setRCK()  RCK=1
#define clrRCK()  RCK=0

#define __NOP()__   __nop()__

void HC595_SendOneByte(u8 byteData){
  u8 i=0;
 
  RCK=0;//与RCK=1对应,这是锁存数据

  for(i=0;i<8;i++){//首先输出高位接着输出低位
     SCK=0; //产生一个上升沿,将8位全部输出

     DS=byteData>>7;//获得高位,将该位输出
     byteData<<=1;//最高位已经获得,将此高位移到最高位

     SCK=1;

     __nop()__;//延时一段时间
     __nop()__;
 
  }
 
  RCK=1;//产生一个上升沿然后再锁存
  __nop()__;//延时一段时间
  __nop()__;
 
}
/*
实例:采用74HC138控制,输出数码guan
*/
#include"reg51.h"
void delay(unsigned int t){
   while(t--);
}
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xFF};
unsigned char disp_table[]={0,1,2,3,4,5,6,7};//显示的数值
void main(){
   //初始化
   int i=0;//循环变量
   //显示特定数字的字段码,本质上还是流水灯的花型数据
  
   //工作循环
   while(1){
     for(i=0;i<8;i++){
       HC595_sendOneByte(table[disp_table[i]]);//输出字段码---改了这里
       P3=i;//输出位码
       delay(50);//亮一段时间
       HC595_sendOneByte(table[16]);//LED熄灭,实际上这就是消影
       delay(50);//熄灭一段时间     
     }
   }
}

4、采用CD4511进一步简化设计

--有没有觉得数码管的段码让你很郁闷?用CD4511帮忙吧

CD4511是BCD译码器,可以将输入的BCD码转换为7段数码管共阴字段码

/*
实例:采用74HC138控制,输出数码管
*/
#include"reg51.h"
void delay(unsigned int t){
   while(t--);
}
//字段码不需要了
//unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xFF};
unsigned char disp_table[]={0,1,2,3,4,5,6,7};//显示的数值
void main(){
   //初始化
   int i=0;//循环变量
   //显示特定数字的字段码,本质上还是流水灯的花型数据
  
   //工作循环
   while(1){
     for(i=0;i<8;i++){
       //P2=table[disp_table[i]];//输出字段码---这里改了,不需要了
       P2=disp_table[i];//--改成了这句
       P3=i;//输出位码--改了这里
       delay(50);//亮一段时间
       P2=table[16];//LED熄灭,实际上这就是消影
       delay(50);//熄灭一段时间     
     }
   }
}

速度快了,代码省了,成本增了。 

同一种功能,搞了那么多的花样,可以统一吗?

/---------------------------------------------驱动与应用分开----------------------------------------------/

#ifndef TYPE_H
#define TYPE_H
typedef unsigned char u8;
typedef unsigned short u16;
#endif
#ifndef MISC_H
#define MISC_H
  void delay(unsigned int t);
#endif
#include"misc.h"
void delay(unsigned int t){
   while(t--);
}
#ifndef SEGMENT_H
#define SEGMET_H
void segment_DispAt(u8 pos,u8 d);
void segment_UndispAt(u8 pos);
#endif
#include"segment.h"
#include"misc.h"
#include"type.h"
unsigned char buffer[]={0,1,2,3,4,5,6,7];
void Init(){
 
}

void  segment_Disp(){
      static u8 pos=0;//显示的位置
      segment_DispAt(pos,buffer[pos]);
      delay(50);//延时
      segment_UndispAt(pos);//消影
      delay(50);//延时

      pos++;
      pos/=8;
 }
void main(){
   //初始化
   Init();  
   //工作循环
   while(1){
      segment_Disp();
   }
}

   驱动,4种都在了

#include"segment.h"
#include"misc.h"
#include"type.h"
//字段码
u8 code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xFF};
//显示的数值
void _out_seg(u8 pos);//输出段码
void _out_pos(u8 pos);//输出位码
void segment_DispAt(u8 pos,u8 d){
      _out_seg(table[d%16]);//段码
      _out_pos(pos);//位码
}
void segment_UndispAt(u8 pos){
      _out_seg(table[15]);//段码
      _out_pos(pos);//位码
}
/*******************************************/
#include<reg51.h>
#include<intrins.h>
#define BASIC 1
#define HC138 2
#define HC595 3
#define CD4511 4
#define DISP_MODE  BASIC

#if DISP_MODE==BASIC
static void _out_seg(u8 pos){
   P2=table[disp_table[pos]];
}
static void _out_pos(u8 pos){
   P3=~(1<<pos);
}
#endif

#if DISP_MODE==HC138
static void _out_seg(u8 pos){
   P2=table[disp_table[pos]];
}
static void _out_pos(u8 pos){
   P3=pos;
}
#endif

#if DISP_MODE==HC595
//595发送一个字节
static void HC595_SendOneByte(u8 byteData){
  sbit SCK = P2^0;//时钟信号
  sbit DS  = P2^1;//数据位
  sbit RCK = P2^2;//锁存信号,低电平有效
  u8 i=0;
 
  RCK=0;//与RCK=1对应,这是锁存数据
 
  for(i=0;i<8;i++){//首先输出高位接着输出低位
     SCK=0; //产生一个上升沿,将8位全部输出
 
     DS=byteData>>7;//获得高位,将该位输出
     byteData<<=1;//最高位已经获得,将此高位移到最高位
 
     SCK=1;
 
     __nop()__;//延时一段时间
     __nop()__;
 
  }
 
  RCK=1;//产生一个上升沿然后再锁存
  __nop()__;//延时一段时间
  __nop()__;
 
}
static void _out_seg(u8 pos){
  HC595_SendOneByte(pos);
}
static void _out_pos(u8 pos){
   P3=pos;
}
#endif

#if DISP_MODE==CD4511
static void _out_seg(u8 pos){
   P2=pos;
}
static void _out_pos(u8 pos){
   P3=d;
}
#endif

 上述的驱动已经太长了,还可以进一步拆分的;同时也可以看出上述驱动主要有三个函数与硬件直接相关(segment_Init, _out_pos, _out_seg),还可以分离啊!

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值