博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c语言中p20Flag, 用单片机开发板能否把流水灯数码管动态显示结合起来,两个程序中都有while(1),不知道怎么结...
阅读量:5869 次
发布时间:2019-06-19

本文共 5582 字,大约阅读时间需要 18 分钟。

满意答案

改改你的想法,这种 汇编思想 编C语言程序要不得。

/***数显电子时钟——火柴天堂作品-20120603***/

/***源程序默认硬件环境:52单片机,12MHz晶振,四位共阳数码管,P0段选,P20-P23低电平位选,P20最高位,P23最低位,P24~P25独立按键,P1口8位低电平驱动LED***/

/***功能描述:4位数显时钟:HH.MM,小数点闪烁表示秒,P24设置键,P25调时键,不调秒,P1口流水灯(间隔1s)***/

#include"reg52.h"//包含52头文件

#define TRUE1//定义布尔量'1':真

#define FALSE0//定义布尔量'0':假

#define uchar unsigned char//定义 无符号字符型数据 简称

#define uint unsigned int//定义 无符号整型数据 简称

#define th00x3c

#define tl00xb0//50ms at 12MHz(定时器工作模式1 状态)

#define th10xfc

#define tl10x18//1ms at 12MHz(定时器工作模式1 状态)

#define T500msAt50msCount10//定义 500ms 在 50ms 计时基准状态下的计数值为10

#define T1sAt50msCount20//定义 1s 在 50ms 计时基准状态下的计数值为20

#define SEG_Num4//数码管位数

#define SEG_DataP0//数码管段驱动接口

#define SEG_EnP2//数码管位驱动接口

#define SEG_AllOff(SEG_En|=0x0f)//关闭所有数码管(位驱动)

#define DisTimeAt1msCount4//单'位'数码管显示时间,数码管刷新频率f=1/(N*t),其中 N为数码管位数,t 为单'位'数码管显示时间

#define SetStatus3//设置状态数量,三个,0 显示态,1调时态,2调分态

uchar SEG_B_List[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//共阳数码管代码表"0-9"

#define SEG_B_Point0x7f//共阳数码管小数点

sbit KeySet=P2^4;//定义 设置键接口

sbit KeyAdj=P2^5;//定义 调整键接口

#define KeySetValue1//定义 设置键键值为1

#define KeyAdjValue2//定义 调整键键值为2

#define LED_PortP1//定义 流水灯端口

#define LED_Num8//定义 流水灯数量

uchar Sec=0,Min=0,Hour=0,SetLoca=0;

uchar bdata Flag=0x12;//可位寻址标志位寄存器

sbit T1sTimesUpFlag=Flag^0;//1s时间标志位

sbit DisplayFlag=Flag^1;//显示标志位

sbit FlickFlag=Flag^2;//闪烁显示标志位:1显示,0不显示

sbit SettingFlag=Flag^3;//设置标志位

sbit MarqFlag=Flag^4;//流水标志位

void Timer0() interrupt 1//定时器0中断函数

{

static uchar t50ms;

TL0=tl0;

TH0=th0;

t50ms=++t50ms%T1sAt50msCount;//先对50ms计时变量加1,后对变量范围进行限制(0~19)(即对20取模)

if(!t50ms)//若计时变量归0,表示计时变量曾经到达20(1s),则

{

MarqFlag=TRUE;//流水标志位 置位

if(!SettingFlag) T1sTimesUpFlag=TRUE;//若在显示态,则对1s计时标志位 置位

}

if(!(t50ms%T500msAt50msCount))FlickFlag=~FlickFlag;//每500ms 秒(小数点)切换状态一次(即1s闪一次)

}

void Timer1() interrupt 3

{

static uchar t1ms;

TL1=tl1;

TH1=th1;

t1ms=++t1ms%DisTimeAt1msCount;//先计数值加1,后对计数范围进行限制0~(DisTimeAt1msCount-1)

if(!t1ms) DisplayFlag=TRUE;//若定时计数值归0,则表示计数值曾到达 单'位'显示时间(DisTimeAt1msCount),显示标志 置位

}

void TimerInit()

{

TMOD=0x11;//开启定时器0、定时器1,并都工作在模式1

TH0=th0;

TL0=tl0;

TR0=1;//启动T0定时器 计时

ET0=1;//允许定时器0中断

TH1=th1;

TL1=tl1;

TR1=1;//启动T1定时器 计时

ET1=1;//允许定时器1中断

EA=1;//开启系统中断功能

}

void TimesUpdata()//时间更新函数

{

if(T1sTimesUpFlag)//若 1s计时标志位 为 真,即 1s定时时间到

{

Sec=++Sec%60;//秒Sec在0-59范围内加1

if(!Sec)//若秒Sec 为0,则

{

Min=++Min%60;//分Min 在0-59范围内加1

if(!Min) Hour=++Hour%24;//若 分Min 为0,则 时Hour 在0-23范围内加1

}

T1sTimesUpFlag=FALSE;//清 1s计时标志位

}

}

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 Display(uint dis_num)//显示函数,显示内容为 无符号整型数据 dis_num

{

static uchar dis_loca;//定义静态变量 显示位置

dis_loca=++dis_loca%SEG_Num;//先对 显示位置 加1,后对变量范围进行限制 0~(SEG_Num-1)

SEG_AllOff;//关闭所有数码管显示(位驱动)

if(!SettingFlag || FlickFlag ||(SetLoca==1 && dis_loca<2)||(SetLoca==2 && dis_loca>1))//显示态、闪烁显示态、调Hour时的分位 或 调Min时的时位,均正常显示

SEG_Data=SEG_B_List[(dis_num/(uint)(Pow_Self(10,dis_loca)))%10];//将显示内容(dis_num) 本次需显示的位(dis_loca)上的数值转成代码,并送到数据端口

if(dis_loca==2 &&(SettingFlag||FlickFlag)) SEG_Data &=SEG_B_Point;//闪烁显示 小数点,代替 秒Sec(共阳数码管)

SEG_En&=~(1<

}

void ClockDisplay()//时钟显示函数

{

if(DisplayFlag)//若 显示标志位 为 真

{

Display(Hour*100+Min);//调用 显示函数,显示内容为:高2位显示 分Min,低2位显示 秒Sec

DisplayFlag=FALSE;//清 显示标志

}

}

uchar KeyScan()//按键扫描函数

{

if(KeySet && KeyAdj) return 0;//无按键 返回0

if(!KeySet) return KeySetValue;//设置键 返回设置键键值

if(!KeyAdj) return KeyAdjValue;//调整键 返回调整键键值

return 0;//非以上按键,返回0

}

void KeyResp()//按键响应函数

{

static uchar KeyValue;//定义静态变量 存储按键值

static bit KeyDownFlag,KeyReadyFlag;//定义静态变量 按键按下标志位,按键准备(响应)标志位

uchar key_value=KeyScan();//调用 按键扫描函数,并将扫描结果放在 key_value中

if(key_value)//若扫描结果 有按键

{

KeyValue=key_value;//存储按键值

KeyDownFlag=TRUE;//按键按下标志位 置位

KeyReadyFlag=TRUE;//按键准备(响应)标志位 置位

}

else KeyDownFlag=FALSE;//若扫描结果 无按键,则 清 按键按下标志位

if(KeyReadyFlag && !KeyDownFlag)//若按键准备就绪,且无按键按下,则表示已松手情况

{

switch(KeyValue)//选择按键对应处理

{

case KeySetValue://设置键处理

SetLoca=++SetLoca%SetStatus;//切换状态,0显示态,1调时态,2调分态

if(SetLoca) SettingFlag=TRUE;//若非显示态,则设置标志位 置位

else SettingFlag=FALSE;//否则,清 设置标志位

break;//设置键处理完毕

case KeyAdjValue://调整键处理

switch(SetLoca)//选择状态对应处理对象

{

case 1:Hour=++Hour%24;break;//调时态,时Hour在0-23之间加1

case 2:Min=++Min%60;break;//调分态,分Min在0-59之间加1

default://其他情况

SetLoca=0;//切换回显示态,或忽略操作

SettingFlag=FALSE;//清 设置标志位

break;

}

break;//调整键处理完毕

default:break;//按键处理完毕

}

KeyValue=0;//清 按键值

KeyReadyFlag=FALSE;//清 按键准备(响应)标志位

}

}

void Marquee()//跑马灯函数

{

static uchar marq_loca=LED_Num-1;//静态变量,初始化为最后一盏LED,进入if后,直接到第一盏LED

if(MarqFlag)//若流水标志位为真,则

{

marq_loca=++marq_loca%LED_Num;//切换下一个LED

LED_Port=~(1<

MarqFlag=FALSE;//清 流水标志位

}

}

void SystemInit()

{

TimerInit();//调用 定时器初始化函数

KeySet=1;

KeyAdj=1;//初始化按键端口

}

void main()

{

SystemInit();//调用 系统初始化函数

while(1)//循环系统

{

KeyResp();//调用 按键响应函数

TimesUpdata();//调用 时间更新函数

ClockDisplay();//调用 时钟显示函数

Marquee();//调用 跑马灯函数

}

}追问: 能不能说下思路

追答:思路一大把,还有这个是 俺 12年的程序,让你学习思路的,你的一句“复制”,心塞啊!

先了解下,子函数需要 while 来干嘛呢??

流水灯:它需要 while 来 不停的“流”,它的作用是 在 流水灯跑到末尾的时候,能回到开头。

数码管:它需要 while 来 不停的“换位”,它的作用跟流水大同小异,也是在 数码管 显示最后一位的时候,能回到开头。

想要 删除 while ,必须找得能替代 它作用 的东西,从上面的作用看,while 只是让 函数 末尾跑回开头。如果你能 记录 它的位置,能知道它在末尾,就能让它又回到开头,也就不在需要while 了。于是,需要一个变量 来记录“位置”。(例程里面:dis_loca 是显示位置,marq_loca 是跑马位置,这就是它们取代while 的地方)

另外,要想它们 能正常替代 while的功能,必须排除 另一个东西 的干扰,这个干扰就是 延时函数(delay(uint xx))。

延时函数,顾名思义,就是用来 拖时间的。它对函数的作用是,保证某个时间要求(如跑马1s,显示4ms),但对于CPU来说却是天大的浪费,所以找到替代它的东西也是不可避免的。

延时的作用是保证时间要求,而定时器,却是专为定时而生。它就是替代延时函数的“最佳机选”,于是……

追问: 别复制啊

追问: 谢谢

00分享举报

转载地址:http://qbtnx.baihongyu.com/

你可能感兴趣的文章
ios 开发 NSArray 排序
查看>>
数据库连接池参数参考
查看>>
简述JVM、GC
查看>>
实现页面静态化的两种方法
查看>>
测试测试
查看>>
解决U盘制作系统盘后隐藏未分配的空间
查看>>
VS 2010 /Oi
查看>>
mongodb GridFS存储pdf文件 测试
查看>>
Server Tomcat v7.0 Server at localhost was unable
查看>>
Linux就该这么学:rhce考试经验分享
查看>>
shell学习七函数
查看>>
losetup命令和loop设备的使用
查看>>
Fdfs错误tracker_query_storage fail, error no: 2, ...
查看>>
PHP汉字转换拼音的类
查看>>
微服务实战(一):微服务架构的优势与不足
查看>>
TFT LCD 7寸1024*600 FPGA点亮
查看>>
教你如何抢注一个快过期的域名
查看>>
request.getInputStream()乱码处理方法
查看>>
golang更改自动重新编译gowatch
查看>>
lua 数据以table表的形式存储
查看>>