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),还可以分离啊!