目录
(2)1.2版本(解决P0口有多个输出同时存在的问题,但仍存在数码管阴影问题)
一、对数码管函数进行改造
(1)1.1版本(存在P0口有多个输出同时存在的问题)
最初的数码管显示函数虽便于理解但过于反锁,在最初版本对函数做出以下修改:
- 创建变量DigCom,用于控制数码管位选,决定打开第几个数码管
- 创建数组DigBuf[](unsigned char DigBuf[8]={10,10,10,10,10,10,10,10};//数码管显示数值)来确定数码管显示的数值,默认初始上电,全部显示-。
- 函数每执行一遍DigCom+1,直到为8时清零。
//数码管显示函数
void SEG_Display(void)
{
P0=0XFF;
P2=0XC0;
P0=(0x01 << DigCom); //打开控制数码管位选的锁存器,然后选中第一个数码管
P2=0XFF; //P2=0XE0;
P0=tab[DigBuf[DigCom]]; //打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
Delay(1);
P0=0XFF;//消影
if(++DigCom == 8) DigCom = 0;
}
(2)1.2版本(解决P0口有多个输出同时存在的问题,但仍存在数码管阴影问题)
- 通过P2 |= 0XC0 == P2 = P2|0XC0;即P2或上 1100 0000 只对P2的高两位进行操作,XXXX XXXX| 1100 0000 = 11XX XXX;保证只操作高两位,而其他位不变
- 通过P2 &= 0xDF;是将
P2
的第 5 位(从右边开始数,从 0 开始)清零,而保持其他位不变,实现对寄存器中的特定位进行精确地操作而不影响其他位。
void SEG_Display(void)
{
P2 |= 0xC0; // 设置数码管位选
P2 &= 0xDF; // 清除数码管位选
P0 = (0x01 << DigCom); // 设置数码管位选
P2 |= 0xE0; // 打开数码管段选锁存器
P0 = tab[DigBuf[DigCom]]; // 设置数码管段选值
Delay(1);
P0 = 0xFF; // 关闭数码管段选
if(++DigCom == 8) DigCom = 0;
}
(3)1.3版本(解决数码管阴影问题)
- 出现阴影的原因:已经对P0进行赋值的时候,再次打开573的时候,P0的值是前面的值,导致P0再次显示,会出现数码管阴影问题。
- 为了解决数码管阴影问题可以采取,先赋值,再打开锁存器的思路。
void SEG_Display(void)
{
//1.3版本 先赋值 再打开数码管
P0 =0X00; //先设置选择数码管位选的P0输出值(全不选)
P2|=0XC0; //将P27P26设置为1其他位保持不变
P2&=0XDF; //将P26设置为0其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
P0=tab[DigBuf[DigCom]];
P2|= 0XE0; //P2=P2|0XE0l XXXX XXXX | 1110 0000 = 111X XXXX
P2&=0XFF; // P2=P2&0XDF; 11XX XXXX & 1101 1111 = 110X XXXX
P2&=0X1F; //关闭所有的74HC573锁存器
P0 =(0X01 << DigCom);//然后选中第一个数码管
P2 |=0XC0; //P2-P210XC0;XXXx XXXX1100 0000-11XXXXXX
P2 &=0XDF; // P2=P2&0XDF;11Xx XXxX & 1101 1111- 110X XXXX
P2 &=0X1F; //关闭所有的74日C573锁存器
Delay(1);
if(++DigCom == 8) DigCom = 0;
}
二、初始化函数改造
void All_Init(void)
{
P0 =0X00; //先设置蜂鸣器继电器的P0输出值(全关)
P2|=0XA0; //将P27 P25设置为1 其他位保持不变
P2&=0XBF; //将P26设置为0 其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
P0 =0XFF; //先设置关闭所有的LED的P0输出值(全关)
P2|=0X80; //将P27设置为1其他位保持不变
P2&=0X9F; //将P26P25设置为0其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
P0 =0X00; //先设置选择数码管位选的P0输出值(全不选)
P2|=0XC0; //将P27P26设置为1其他位保持不变
P2&=0XDF; //将P26设置为0其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
}
三、1.1版本基础模板
//头文件声明区域
#include <STC15F2K60S2.H>
#include<intrins.h>
//变量定义区域
#define uchar unsigned char
#define uint unsigned int
uchar tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
uchar DigCom = 0;//数码管位选
uchar DigBuf[8]={10,10,10,10,10,10,10,10};//数码管显示数值
uchar Key_Value = 0;
//函数定义区域
//毫秒级延迟函数
void Delay(unsigned int ms);
//初始化程序
void All_Init(void);
//数码管显示函数
void SEG_Display(void);
//按键扫描函数
void Key_Scan(void);
//主程序
void main()
{
All_Init();
while(1)
{
Key_Scan();
if(Key_Value !=0)
{
DigBuf[0] = Key_Value/10;
DigBuf[1] = Key_Value%10;
Key_Value = 0;
}
if(Key_Value==7) {Key_Value=0;DigBuf[0] = 1;}
if(Key_Value==6) {Key_Value=0;DigBuf[1] = 2;}
if(Key_Value==5) {Key_Value=0;DigBuf[2] = 3;}
if(Key_Value==4) {Key_Value=0;DigBuf[3] = 4;}
SEG_Display();
}
}
//毫秒级延迟函数
void Delay(unsigned int ms) //@11.0592MHz
{
unsigned char i, j;
while(ms--)
{
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
}
//初始化
void All_Init(void)
{
P0 =0X00; //先设置蜂鸣器继电器的P0输出值(全关)
P2|=0XA0; //将P27 P25设置为1 其他位保持不变
P2&=0XBF; //将P26设置为0 其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
P0 =0XFF; //先设置关闭所有的LED的P0输出值(全关)
P2|=0X80; //将P27设置为1其他位保持不变
P2&=0X9F; //将P26P25设置为0其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
P0 =0X00; //先设置选择数码管位选的P0输出值(全不选)
P2|=0XC0; //将P27P26设置为1其他位保持不变
P2&=0XDF; //将P26设置为0其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
}
//数码管显示函数
void SEG_Display(void)
{
//1.3版本 先赋值 再打开数码管
P0 =0X00; //先设置选择数码管位选的P0输出值(全不选)
P2|=0XC0; //将P27P26设置为1其他位保持不变
P2&=0XDF; //将P26设置为0其他位保持不变
P2&=0X1F; //关闭所有的74HC573锁存器
P0=tab[DigBuf[DigCom]];
P2|= 0XE0; //P2=P2|0XE0l XXXX XXXX | 1110 0000 = 111X XXXX
P2&=0XFF; // P2=P2&0XDF; 11XX XXXX & 1101 1111 = 110X XXXX
P2&=0X1F; //关闭所有的74HC573锁存器
P0 =(0X01 << DigCom);//然后选中第一个数码管
P2 |=0XC0; //P2-P210XC0;XXXx XXXX1100 0000-11XXXXXX
P2 &=0XDF; // P2=P2&0XDF;11Xx XXxX & 1101 1111- 110X XXXX
P2 &=0X1F; //关闭所有的74日C573锁存器
Delay(1);
if(++DigCom == 8) DigCom = 0;
//(1.2版本)解决P0口有多个输出同时存在的问题,但仍存在数码管阴影问题
// P2 |= 0xC0; // 设置数码管位选
// P2 &= 0xDF; // 清除数码管位选
// P0 = (0x01 << DigCom); // 设置数码管位选
// P2 |= 0xE0; // 打开数码管段选锁存器
// P0 = tab[DigBuf[DigCom]]; // 设置数码管段选值
// Delay(1);
// P0 = 0xFF; // 关闭数码管段选
// if(++DigCom == 8) DigCom = 0;
//
//以下根据最基础的数码管程序进行修改,1.1版本便于理解
// P0=0XFF;
// P2=0XC0;
// P0=(0x01 << DigCom); //打开控制数码管位选的锁存器,然后选中第一个数码管
// P2=0XFF; //P2=0XE0;
// P0=tab[DigBuf[DigCom]]; //打开控制数码管段选的锁存器,然后给上述打开的数码管输出码值
// Delay(1);
// P0=0XFF;//消影
//
// if(++DigCom == 8) DigCom = 0;
}
//按键扫描函数
void Key_Scan(void)
{
if(P30 == 0)
{
Delay(30);
if(P30 == 0) Key_Value=7;
while(!30);
}
else if(P31==0)
{
Delay(30);
if(P31 == 0) Key_Value=6;
while(!30);
}
else if(P32==0)
{
Delay(30);
if(P32 == 0) Key_Value=5;
while(!30);
}
else if(P33==0)
{
Delay(30);
if(P33 == 0) Key_Value=4;
while(!30);
}
}