专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
51单片机
请教大哥大姐们51单片机一个定时器,多处程序怎么用
2019-07-15 23:03
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
51单片机
8916
11
972
一个定时器,多个程序用,(如主程序中让每进20次定时中断(1秒),让灯亮一下,这样循环着,当触发外部中断时,可以是1秒也可以大于1秒,响应另一个触发事件)
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
11条回答
auqyygtj
2019-07-16 03:56
本帖最后由 auqyygtj 于 2013-8-13 22:09 编辑
大家帮我分析一下问题如下:1、现在是主程序动显在那0至7,我要的是1-8动显在那;2、触发外部中断后,加数器不动,可能是一个定时器,两个地方用,什么地方没用正确,外部中断的部分计时器没起作用;3、编译程序时出现一个警告。其它正常
#include<reg52.h>
//载入51单片机头文件
#include<intrins.h>
//载入51涵数头文件
#define uchar unsigned char
//宏定义unsigned char为 uchar
#define uint unsigned int
//宏定义unsigned int 为uint
sbit wela=P3^7;
//位定义,控制数码管有几个数量的373锁存器端口接在该I/O
sbit dula=P2^0;
//位定义,控制数码管显示什么字符的373锁存器端口接在该I/O
uchar k,j,temp,led,dd,tt,qian,bai,shi,ge;
//单字节全局变量
uint ptemp;
//双字节全局变量
uchar code dutable[]={
//定义数码管显示,code为表格的意思,该表格取名为dutable
0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90
//根据数码管硬件连接图写出0-9的16进制数
};
uchar code wetable[]={
0x01,0x02,0x04,0x08,
0x10,0x20,0x40,0x80
};
//根据数码管硬件连接图写出1-8个数码管亮的位
//…………以下延时程序…………
void delay(uint z) // 这里为什么用uint(双字节),而不是用uchar(单字节,值范围256)
{
uint x,y;
for(x=z;x>0;x--)
for(y=1000;y>0;y--);
}
//…………以上延时程序…………
//………………子程序……………………
void zuchngxiu()
{
if(dd==1) /*这里进入定时器次和触发定时器的时间一起控制显示速度,现在这样就属于动太扫描*/
{
dd=0; /*如果进入到20次定时器,那么将定时器里的变量dd清0,便于下一次计时*/
tt++;//用于外部中断时间判断
if(j==8) //检测j是否等于9
j=0; //如果是等于9就置0
//……………………………………
P1=0x00;//P1口全部送低电平,目的是将这低电平保存在点阵的高电平脚上,使用其不亮;
P3=0x07;/*P3口关闭高位开关(00000111)其中有三个脚接点阵高点位的锁存端,其中还有外部中断*/
P2=0x00; /*P2口接了三种类型,点阵低电平的锁存端5个,点阵高点位的锁存端2个,还一个是控制
8个数码管段选的锁存端,这样点阵高电平脚全部由锁器端锁存为低电平了*/
//……………关闭点阵…………………
wela=1; //打开位选
P1=wetable[j]; //P1口取wetable位码表
wela=0;//关闭位选
j++; //每取一次位码表自加1
if(k>=8) /*检测k是否大于等于11,而不是k=10(0-9)数显示,为会下面会用到*/
k=0; //如果上面K大于等于11,就将K清0 ,这样做的目的是让其显示0-9的10个数,不然后一直加上去了
dula=1; //打开段选,是显示数字
P1=dutable[k]; //P1端口取dutable数码表中值,
dula=0; //关闭段选
k++; //k自加1,如果不自加1怎么知道它现在取的是第几位数了
}
}
//……………………………………
//………………以下是累加显示子程序…………………………
void display(uchar qian,uchar bai,uchar shi,uchar ge)
{
wela=1;
P1=0x01;
wela=0;
dula=1;
P1=dutable[qian];
dula=0;
delay(5);
//………………………………
wela=1;
P1=0x02;
wela=0;
dula=1;
P1=dutable[bai];
dula=0;
delay(15);
//………………………………
wela=1;
P1=0x04;
wela=0;
dula=1;
P1=dutable[shi];
dula=0;
delay(15);
//………………………………
wela=1;
P1=0x08;
wela=0;
dula=1;
P1=dutable[ge];
dula=0;
delay(5);
}
//………………以上是累加显示子程序………………
//……………………以下初始化程序……………………
void init()
{
ptemp=0; //给累加器一个初值
EA=1; //开总中断
ET0=1;//定时器/计数器0中断
TMOD=0x01; //设为定时器,单触发,01工作方式;
TH0=(65536-5000)/256; //装高位初值
TL0=(65536-5000)%256; //装低位初值
TR0=1;//启动定时器
}
//…………………以上初始化程序………………………
//………………………以下主程序……………………………
void main()
{
init();//初始化子程序
EX0=1;//开外部中断0
IT0=0;//外部中断0以电平方式触发
PX0=0;//设外部中断0为最低优先级
PT0=1;//设该定时器为最高级优先级
P2=0x00;//程序入口就关闭点阵锁存端,要是不关闭一会数码管语句时会让点阵也显示着内容
P3=0x04;//给P3口除外部中断0高点平外,都低电平。 外部中断0是低平电有效的
wela=1;
//打开控制数码管工作的373端口,输入高电平有效,相当于输入与输出端直通
P1=0xff;
//送入让那几个数码管亮的16进制数
wela=0;
//关闭控制数码管工作373端口,这样373就保持住输入端上一次输入的值
dula=1;
//打开控制数码管显示什么数字的373端口
P1=0x00;
/*输入让数码管显示什么数,这里是全部亮就是日字,作为检测一下数码管
有无坏点*/
dula=0;
//关闭控制数码管显示什么数字的373端口
P1=0xff;//P1送入高电平
P2=0x3e; //打开低位开关
P1=0x00; //P1送入低电平
P2=0xc0;//关闭位开关
P3=0x6f; //打开高位开关
P1=0xff;//P1送入高电平
led=P0=0xfe; //这里给led赋个初值这样下面定时器里led左移才知道从什么数开始移
delay(15); //这里加延时程序,某值是时段肯定会和其它地方冲突造成不定时延时现象
//调用延时子程序
while(1)
{
zuchngxiu(); //调用子程序
}
}
// ……………………定时器0………………………………
void exter1() interrupt 1 /*exter1是中断名,后面1是单片机中断中该定时器/计数器0的中断序号 */
{
TH0=(65536-5000)/256;//求抹,将整数部分装入高8位中
TL0=(65536-5000)%256; //求余,将余数部分装入低8位中
//这里的50000就是50ms(毫秒)
dd++; // 这里的dd时50ms触发一次中断,每到50ms计一次数,便于其它调用
led=_crol_(led,1); //将上面的led值进入左移1位
P0=led; //左移一位得到的值,赋予给P0口
}
//…………………………这里定时器中断优先等级比外部中断0高…………
//……………触发外部中断0后始终循环…………
void exter0() interrupt 0 /*exter0是断名,后面0是单片机中断中该外部中断0的中断序号 */
{ //1
init();
ptemp=0; //给加累数初值0
while(1)
{ //2
if(tt>=1)//判断tt是否大于等于1,这里tt就是主程序里dd=20,tt自加1
{ //3
tt=0; //置0重新计时
ptemp++;//初值自加1
if(ptemp==10000)
{ //4
ptemp=0;
if(ptemp==0)
{ //5
wela=1; //打开位选
P1=0xff; //将P1口置数11111111全部高电平, 打开8个数码管
wela=0; //关闭位选
dula=1;//打开段选
temp=0xfe; //赋temp值为11111110 ,也就是数码管的a段
P1=temp; //将temp的值赋予给P1口
delay(10); //调用延时程序
while(1)
{ //6
if(temp==0xdf) /*检测temp是否等于(高位11011111低位),因为数码管七段加一个DP点
我们不要DP(P1.7)点和G段(P1.6)亮*/
temp=0x7f; //置位到DP(P1.7)点,也就是P1.6和P1.7跳过(高位0111 1111低位)
temp=_crol_(temp,1); //左移一位
P1=temp; //移位后的值赋予给P1口
delay(8); //调用延碧
} //6
qian=temp/1000;
bai=temp%1000/100;
shi=temp%1000%100/10;
ge=temp%10;
display(qian,bai,shi,ge);
}
}
}
}
}
加载中...
查看其它11个回答
一周热门
更多
>
相关问题
【东软载波ESF0654 PDS开发板活动】开箱
1 个回答
东软载波ESF0654 PDS开发板外部中断
1 个回答
东软载波ESF0654 PDS开发板高级控制定时器AD16C4T
1 个回答
用串口调试助手为什么只能在hex模式接收发送而在文本模式不行
9 个回答
触摸芯片SC02B/SC04B在地砖灯的设计方案
1 个回答
相关文章
51单片机与蓝牙模块连接
0个评论
51单片机的硬件结构
0个评论
基于51单片机的无线遥控器制作
0个评论
51单片机 AD转换
0个评论
51单片机数码管递增显示
0个评论
如何实现对单片机寄存器的访问
0个评论
基于51单片机的指纹密码锁
0个评论
×
关闭
采纳回答
向帮助了您的知道网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
51单片机
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
×
付费偷看金额在0.1-10元之间
确定
×
关闭
您已邀请
0
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
大家帮我分析一下问题如下:1、现在是主程序动显在那0至7,我要的是1-8动显在那;2、触发外部中断后,加数器不动,可能是一个定时器,两个地方用,什么地方没用正确,外部中断的部分计时器没起作用;3、编译程序时出现一个警告。其它正常
#include<reg52.h>
//载入51单片机头文件
#include<intrins.h>
//载入51涵数头文件
#define uchar unsigned char
//宏定义unsigned char为 uchar
#define uint unsigned int
//宏定义unsigned int 为uint
sbit wela=P3^7;
//位定义,控制数码管有几个数量的373锁存器端口接在该I/O
sbit dula=P2^0;
//位定义,控制数码管显示什么字符的373锁存器端口接在该I/O
uchar k,j,temp,led,dd,tt,qian,bai,shi,ge;
//单字节全局变量
uint ptemp;
//双字节全局变量
uchar code dutable[]={
//定义数码管显示,code为表格的意思,该表格取名为dutable
0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90
//根据数码管硬件连接图写出0-9的16进制数
};
uchar code wetable[]={
0x01,0x02,0x04,0x08,
0x10,0x20,0x40,0x80
};
//根据数码管硬件连接图写出1-8个数码管亮的位
//…………以下延时程序…………
void delay(uint z) // 这里为什么用uint(双字节),而不是用uchar(单字节,值范围256)
{
uint x,y;
for(x=z;x>0;x--)
for(y=1000;y>0;y--);
}
//…………以上延时程序…………
//………………子程序……………………
void zuchngxiu()
{
if(dd==1) /*这里进入定时器次和触发定时器的时间一起控制显示速度,现在这样就属于动太扫描*/
{
dd=0; /*如果进入到20次定时器,那么将定时器里的变量dd清0,便于下一次计时*/
tt++;//用于外部中断时间判断
if(j==8) //检测j是否等于9
j=0; //如果是等于9就置0
//……………………………………
P1=0x00;//P1口全部送低电平,目的是将这低电平保存在点阵的高电平脚上,使用其不亮;
P3=0x07;/*P3口关闭高位开关(00000111)其中有三个脚接点阵高点位的锁存端,其中还有外部中断*/
P2=0x00; /*P2口接了三种类型,点阵低电平的锁存端5个,点阵高点位的锁存端2个,还一个是控制
8个数码管段选的锁存端,这样点阵高电平脚全部由锁器端锁存为低电平了*/
//……………关闭点阵…………………
wela=1; //打开位选
P1=wetable[j]; //P1口取wetable位码表
wela=0;//关闭位选
j++; //每取一次位码表自加1
if(k>=8) /*检测k是否大于等于11,而不是k=10(0-9)数显示,为会下面会用到*/
k=0; //如果上面K大于等于11,就将K清0 ,这样做的目的是让其显示0-9的10个数,不然后一直加上去了
dula=1; //打开段选,是显示数字
P1=dutable[k]; //P1端口取dutable数码表中值,
dula=0; //关闭段选
k++; //k自加1,如果不自加1怎么知道它现在取的是第几位数了
}
}
//……………………………………
//………………以下是累加显示子程序…………………………
void display(uchar qian,uchar bai,uchar shi,uchar ge)
{
wela=1;
P1=0x01;
wela=0;
dula=1;
P1=dutable[qian];
dula=0;
delay(5);
//………………………………
wela=1;
P1=0x02;
wela=0;
dula=1;
P1=dutable[bai];
dula=0;
delay(15);
//………………………………
wela=1;
P1=0x04;
wela=0;
dula=1;
P1=dutable[shi];
dula=0;
delay(15);
//………………………………
wela=1;
P1=0x08;
wela=0;
dula=1;
P1=dutable[ge];
dula=0;
delay(5);
}
//………………以上是累加显示子程序………………
//……………………以下初始化程序……………………
void init()
{
ptemp=0; //给累加器一个初值
EA=1; //开总中断
ET0=1;//定时器/计数器0中断
TMOD=0x01; //设为定时器,单触发,01工作方式;
TH0=(65536-5000)/256; //装高位初值
TL0=(65536-5000)%256; //装低位初值
TR0=1;//启动定时器
}
//…………………以上初始化程序………………………
//………………………以下主程序……………………………
void main()
{
init();//初始化子程序
EX0=1;//开外部中断0
IT0=0;//外部中断0以电平方式触发
PX0=0;//设外部中断0为最低优先级
PT0=1;//设该定时器为最高级优先级
P2=0x00;//程序入口就关闭点阵锁存端,要是不关闭一会数码管语句时会让点阵也显示着内容
P3=0x04;//给P3口除外部中断0高点平外,都低电平。 外部中断0是低平电有效的
wela=1;
//打开控制数码管工作的373端口,输入高电平有效,相当于输入与输出端直通
P1=0xff;
//送入让那几个数码管亮的16进制数
wela=0;
//关闭控制数码管工作373端口,这样373就保持住输入端上一次输入的值
dula=1;
//打开控制数码管显示什么数字的373端口
P1=0x00;
/*输入让数码管显示什么数,这里是全部亮就是日字,作为检测一下数码管
有无坏点*/
dula=0;
//关闭控制数码管显示什么数字的373端口
P1=0xff;//P1送入高电平
P2=0x3e; //打开低位开关
P1=0x00; //P1送入低电平
P2=0xc0;//关闭位开关
P3=0x6f; //打开高位开关
P1=0xff;//P1送入高电平
led=P0=0xfe; //这里给led赋个初值这样下面定时器里led左移才知道从什么数开始移
delay(15); //这里加延时程序,某值是时段肯定会和其它地方冲突造成不定时延时现象
//调用延时子程序
while(1)
{
zuchngxiu(); //调用子程序
}
}
// ……………………定时器0………………………………
void exter1() interrupt 1 /*exter1是中断名,后面1是单片机中断中该定时器/计数器0的中断序号 */
{
TH0=(65536-5000)/256;//求抹,将整数部分装入高8位中
TL0=(65536-5000)%256; //求余,将余数部分装入低8位中
//这里的50000就是50ms(毫秒)
dd++; // 这里的dd时50ms触发一次中断,每到50ms计一次数,便于其它调用
led=_crol_(led,1); //将上面的led值进入左移1位
P0=led; //左移一位得到的值,赋予给P0口
}
//…………………………这里定时器中断优先等级比外部中断0高…………
//……………触发外部中断0后始终循环…………
void exter0() interrupt 0 /*exter0是断名,后面0是单片机中断中该外部中断0的中断序号 */
{ //1
init();
ptemp=0; //给加累数初值0
while(1)
{ //2
if(tt>=1)//判断tt是否大于等于1,这里tt就是主程序里dd=20,tt自加1
{ //3
tt=0; //置0重新计时
ptemp++;//初值自加1
if(ptemp==10000)
{ //4
ptemp=0;
if(ptemp==0)
{ //5
wela=1; //打开位选
P1=0xff; //将P1口置数11111111全部高电平, 打开8个数码管
wela=0; //关闭位选
dula=1;//打开段选
temp=0xfe; //赋temp值为11111110 ,也就是数码管的a段
P1=temp; //将temp的值赋予给P1口
delay(10); //调用延时程序
while(1)
{ //6
if(temp==0xdf) /*检测temp是否等于(高位11011111低位),因为数码管七段加一个DP点
我们不要DP(P1.7)点和G段(P1.6)亮*/
temp=0x7f; //置位到DP(P1.7)点,也就是P1.6和P1.7跳过(高位0111 1111低位)
temp=_crol_(temp,1); //左移一位
P1=temp; //移位后的值赋予给P1口
delay(8); //调用延碧
} //6
qian=temp/1000;
bai=temp%1000/100;
shi=temp%1000%100/10;
ge=temp%10;
display(qian,bai,shi,ge);
}
}
}
}
}
一周热门 更多>