51单片机关于中断的问题。。。求大神帮忙。。。

laexl 2017-07-30 02:33:05
问题:代码L41-43,对定时器1赋值,并且打开定时器1的运行控制位。但是除了这三行,没有看到其他地方调用定时器1,不知道这三行有什么作用。我尝试把这三行备注掉,程序仍能正常运行,但是板子上的数码管不能正常工作,将一直显示000。同时串口助手也将无法接收到任何数据。求大神解释一下其中缘由。



单片机上电后等待从上位机串口发送来的命令,同时在数码管前三位以十进制方式显示A/D菜鸡的数值,在未收到上位机发送来的启动A/D转换命令之前数码管始终显示000。
当收到上位机以十六进制发送来的01后,想上位机发送字符串“Turn on ad!”,同时间隔一秒读取一次A/D的值,然后把A/D采集回来的8位二进制数转换成十进制数表示的实际电压浮点数,并且从串口发送给上位机,形式如“The voltage is 3.398438V”,发送周期也是一秒一次,同时在数码管上也要每秒刷新显示的数值。
当收到上位机以十六进制发送来的02后,向上位机发送字符串“Turn off ad!”,然后停止发送电压值,数码管上显示上次结束时保持的值。
当收到上位机发来的其他任何数时,向上位机发送字符串“Error”。

#include<reg52.h>
#include<intrins.h>
#include<stdio.h>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;//液晶显示屏上的显示
sbit wela=P2^7;//液晶显示屏上的显示
sbit adwr=P3^6;//控制ad转换器的写
sbit adrd=P3^7;//控制ad转换器的读
uchar flag;
uchar a;
uchar flag_uart;//中断4的标志位
uchar flag_time;//中断1 的标志位
uchar flag_on ;//在中断4中赋值,通过此变量与switch可以控制选择工作模式
uchar i;
uchar t0_num;
uchar ad_val;//储存ad转换后得到的结果
float ad_vo;//储存电压值

uchar code table []= //数码管的固定编制
{
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71
};

void delayms(uint xms) //固定的延时函数
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}

void init() //初始化函数,是串行口这一部分的设置
{
TMOD=0x21;//0010 0001 定时器工作方式寄存器
//SCON=0x50; 设置串行口控制寄存器。常用的SM0、SM1、REN、TI都可以在这里设置,此处吧SCON设置为0101 0000,SM0 SM1 SM2 REN TB8 RB8 TI RI.即通过SM1SM0设置工作方式为10位异步收发(8位数据)波特率可变。通过REN设置允许串行口接受数据。
TH0=(65536-50000)/256;//装填初值
TL0=(65536-50000)%256;//装填初值
TH1=0xfd;//1111 1101 十进制254,装填初值 ???
TL1=0xfd;//1111 1101 十进制254,装填初值 ???
TR1=1;//定时器1运行控制位:启动定时器1
ET0=1;//定时器0中断允许位:置1时允许定时器1发生中断。
SM0=0;//设定串行口控制寄存器的工作方式选择位
SM1=1;//设定串行口控制寄存器的工作方式选择位
REN=1;//允许串行接收位
EA=1;//全局中断允许位
ES=1;//串行口中断允许位
}

void display(uchar value)//显示函数,分解成三个数,分别显示
{
uchar bai,shi,ge;
bai=value/100;
shi=value%100/10;
ge=value%10;

dula=1;
P0=table[bai];
dula=0;
P0=0xff;
wela=1;
P0=0x7e;
wela=0;

delayms(5);

dula=1;
P0=table[shi];
dula=0;
P0=0xff;
wela=1;
P0=0x7d;
wela=0;

delayms(5);

dula=1;
P0=table[ge];
dula=0;
P0=0xff;
wela=1;
P0=0x7b;
wela=0;

delayms(5);
}

uchar get_ad()//获取ad转换后的值
{
uchar num;//定义一个临时变量num对读取倒的数进行储存
adwr=1;//关闭ad转换
_nop_();//延时函数,延时一个机器周期
adwr=0;//打开ad写入
_nop_();
adwr=1;//关闭ad写入
P1=0xff;//消影
adrd=1;//关闭ad读取
_nop_();
adrd=0;//打开ad读取
_nop_();
num=P1;//把读取到的数据从P1口取出,赋值给变量num
adrd=1;//关闭ad读取
return num;//把读取到的返回值返回。
}

void main()
{
init();//先把文件初始化,即运行一次init中的东西。
wela=1;//打开控制电脑屏幕的wela设置
P0=0x7f;//ADCS,片选信号输入端
wela=0;//关闭位选
while(1)//始终执行while循环内的语句。
{
if(flag_uart==1)//如果发生串行口中断(达到一秒)
{
flag_uart=0;//中断重置
ES=0;//关闭串行口中断允许位,暂时不允许发生串行口中断
TI=1;//发送中断标志位
switch(flag_on)
{
case 0:puts("Turn on ad!\n");
TR0=1;//定时器0运行控制位
break;
case 1:printf("Turn off ad!\n");
TR0=0;//定时器0运行控制位
break;
case 2:puts("Error!\n");
break;
}
while(!TI);//TI=0时,才能跳出循环,这是中断标志位,
TI=0;
ES=1;//打开串行口中断允许位
}
if(flag_time==1)//如果发生中断1(定时器0),满一定时间发生中断。
{
flag_time=0;
ad_val=get_ad();//利用get_ad()函数获得ad转换之后的结果,赋值给ad_val
ad_vo=(float)ad_val*5.0/256.0;//把获得的模拟量转化成电压值
ES=0;//关闭串行口中断允许位
TI=1;
printf("The voltage is %fV\n",ad_vo);
while(!TI);
TI=0;//利用软件将TI发送中断标志位置0
ES=1;//打开串行口中断允许位
}
display(ad_val);//显示模拟量的大小。。。
}
}

void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
t0_num++;
if(t0_num==20)
{
t0_num=0;
flag_time=1;
}
}

void ser() interrupt 4
{
RI=0;
a=SBUF;
flag_uart=1;
if(a==1)
{
flag_on=0;
}
else if(a==2)
{
flag_on=1;
}
else
{
flag_on=2;
}
}
...全文
260 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
of123 2017-08-04
  • 打赏
  • 举报
回复
楼主是问 Timer0 为什么那样设置后影响数码管显示。
Colorful_lights 2017-08-03
  • 打赏
  • 举报
回复
TIME1是用来产生波特率的,因为你用到了printf函数,可以参考下面的博客,关于51中使用printf进行串口通信的文章,方法二其实就是printf实现的原理。http://blog.csdn.net/googlemi/article/details/8996605
of123 2017-08-03
  • 打赏
  • 举报
回复
当配置了 Timer 中断并使能后,每当 Timer 计数溢出时,会触发中断,执行中断服务 void timer0() interrupt 1。累计到 20 次时,会执行 flag_time=1;。 主循环中,会查询 flag_time 的值: if(flag_time==1) //如果发生中断1(定时器0),满一定时间发生中断。 { flag_time=0; ad_val=get_ad(); //利用get_ad()函数获得ad转换之后的结果,赋值给ad_val ad_vo=(float)ad_val*5.0/256.0; //把获得的模拟量转化成电压值 ES=0; //关闭串行口中断允许位 TI=1; printf("The voltage is %fV\n",ad_vo); while(!TI); TI=0;//利用软件将TI发送中断标志位置0 ES=1;//打开串行口中断允许位 }
worldy 2017-08-03
  • 打赏
  • 举报
回复
波特率发生器用
surge1 2017-07-31
  • 打赏
  • 举报
回复
不知道哦,等待

27,373

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧