单片机C语言编写共阳0~999,最好解释详细点!

如题所述

第1个回答  2012-03-28
/***数显秒表,范围0~999***/
/***源程序默认硬件环境:52单片机,12MHz晶振,3位共阳数码管,P0 口段选,P10~P12 高电平位选(NPN三极管驱动),P12为最高位数码管***/
#include"reg52.h" //包含52头文件
#define TRUE 1 //定义布尔量'1':真
#define FALSE 0 //定义布尔量'0':假
#define uchar unsigned char //定义 无符号字符型数据 简称
#define uint unsigned int //定义 无符号整型数据 简称
#define th0 0xfc
#define tl0 0x18 //1ms at 12MHz(定时器工作模式1 状态)
#define SEG_Num 3 //数码管位数
#define SEG_Data P0 //数码管段驱动接口
#define SEG_En P1 //数码管位驱动接口
#define SEG_AllOff (SEG_En&=0xf8) //关闭所有数码管(位驱动)
#define DisTimeAt1msCount 5 //单'位'数码管显示时间,数码管刷新频率f=1/(N×t),其中 N为数码管位数, t为单'位'数码管显示时间
#define T1sAt1msCount 1000 //1秒 计数值(在定时器为1ms 情况下计数)
#define TimesEnd 1000 //显示内容范围 0~999
uchar code SEG_B_List[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //共阳数码管代码表"0-9"
uint Sec;
uchar bdata Flag=1;
sbit DisplayFlag=Flag^0; //显示标志位
sbit TimesUpFlag=Flag^1; //时间更新标志位
void Timer0() interrupt 1 //定时器0中断函数
{
static uchar t1ms; //定义静态变量 t1ms 定时计数寄存空间
static uint t1ms_sec;
TL0=tl0;
TH0=th0; //重赋 1ms 定时初值
t1ms=++t1ms%DisTimeAt1msCount; //先计数值加1,后对计数范围进行限制0~(DisTimeAt1msCount-1)
if(!t1ms) DisplayFlag=TRUE; //若定时计数值归0,则表示计数值曾到达 单'位'显示时间(DisTimeAt1msCount),显示标志 置位
t1ms_sec=++t1ms_sec%T1sAt1msCount; //在 T1sAt1msCount(1000) 范围内加1
if(!t1ms_sec) TimesUpFlag=TRUE; //若 归0,则1s 时间到,时间更新标志位 置位
}
void SystemInit() //系统初始化函数
{
TMOD=0x01; //关闭定时器1,开启定时器0,且工作在模式1(16位定时器)
TH0=th0;
TL0=tl0; //装定时初值(1ms at 12MHz)
TR0=1; //启动计时
ET0=1; //允许定时器0中断
EA=1; //开启系统中断功能
}

float Pow_Self(float x,uint y)//自编简易 x 的 y 次方函数,y只能是 非负整数
{
float sum;
if(x==0 && y==0) return; //0 的 0 次方无意义
else if(x==0) sum=0; //可有可无,y!=0的情况已经包含x=0,不加不影响结果,但影响运算速度
else if(y==0) sum=1; //除上述情况外,任何数的 0 次方均为 1
else if(y==1) sum=x; //任何数的 1 次方 均为 本身
else if(y>1) sum=Pow_Self(x,--y)*x; //递归调用,降幂
return sum; //返回计算结果
}
void TimesUpdata() //时间更新 函数
{
if(TimesUpFlag) //若 时间更新标志 为真
{
Sec=++Sec%TimesEnd; //Sec (秒)在 TimesEnd (0~999) 范围内加1
TimesUpFlag=FALSE; //清 时间更新标志位
}
}
void Display(uint dis_num) //显示函数,显示内容为 无符号整型数据 dis_num
{
static uchar dis_loca; //定义静态变量 显示位置
if(DisplayFlag) //若显示标志位为真(单'位'显示时间结束),则执行以下任务
{
DisplayFlag=FALSE; //清显示标志位
dis_loca=++dis_loca%SEG_Num; //先对 显示位置 加1,后对变量范围进行限制 0~(SEG_Num-1)
SEG_AllOff; //关闭所有数码管显示(位驱动)
SEG_Data=SEG_B_List[(dis_num/(uint)(Pow_Self(10,dis_loca)))%10]; //将显示内容(dis_num) 本次需显示的位(dis_loca)上的数值转成代码,并送到数据端口
SEG_En|=1<<dis_loca; //开启本次需要显示的位驱动
}
}
void main() //主函数
{
SystemInit(); //调用 系统初始化函数
while(1) //循环系统
{
TimesUpdata(); //调用 时间更新函数
Display(Sec); //调用 显示函数 显示内容为 Sec
}
}
第2个回答  2012-03-27
#include <reg52.h>
#define u8 unsigned char
#define u16 unsigned int

#define LED_DATA P0

u8 code LED[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90} ; //0~9对应码段

sbit COM0 = P1^0;
sbit COM1 = P1^1;
sbit COM2 = P1^2;
void Display(u16 Num) //eg. Num = 123
{
//将每位的数值取出
u16 bai,shi,ge;
bai = Num/100; // 1
shi = Num/10%10; // 2
ge = Num%10; // 3

//第一个数码管显示qian其他数码管灭
P1 = 0x04;
P0 = LED[qian];
delay(); //时间自己调,当1,2,3快速切换,眼睛看不出他们是分别亮就行

/第二个数码管显示bai 其他数码管灭
P1 = 0x02;
P0 = LED[bai];
delay();

//第三个数码管显示ge其他数码管灭
P1 = 0x01;
P0 = LED[ge];
delay();

}

可能有小错误,但是主体思路正确,大概就是这个意思,主函数调用就行了Display()就行了
祝你成功,谢谢
第3个回答  2012-03-29
/********************************************************
* 显示在p0口,位控制在p1口低位对应 *
* 开机000,逐个加,到999后又 *
* 从000开始 *
*******************************************************/
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code LED[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90} ; //0~9对应码段
void delay(uint a) //延时
{
while(a)
{
uchar i,j;
for(i=0;i<300;i++)
for(j=0;j<300;j++)

}
}
void dis()//显示子程序

uint m;
P0=0XFF;//清屏
P0=LED[m%100%10]; //显示低位
P1=0XFE;
delay(10);
m++; //改变数值
if(m>999) //判断m是否大于999
m=0;
P0=0XFF; //清屏,消除“鬼影”
P0=LED[m/10%10]; //显示十位
P1=0XFD;
delay(10);
m++; //改变数值
if(m>999)
m=0;
P0=LED[m/100]; //显示百位
P1=0XFB;
delay(10);
m++; //改变数值
if(m>999)
m=0;

main()
{
dis();
}

主程序中就只有一个dis()显示程序,程序都是成块成块的,让我们初学者更加容易的理解和阅读,没有计算时间,如果显示过快,调整i,j数值;
相似回答