![](https://iknow-base.cdn.bcebos.com/lxb/notice.png)
单片机驱动lcd显示秒表的 困惑??
我想实现秒表的功能例如12.87秒,用的定时器0,晶振11.0592,那么我的定时器中断就应该是10ms一次,但是在中断服务程序中,如果我用num++;则结果无法正常显示...
我想实现秒表的功能例如12.87秒,用的定时器0,晶振11.0592,那么我的定时器中断就应该是10ms一次,
但是在中断服务程序中,如果我用num++;则结果无法正常显示
若直接num=1;结果可以正常显示
这是为什么呢?
程序如下 有注释:
#include<reg52.h>
#define uint unsigned int
#define unch unsigned char
sbit duan=P2^6; //关闭数码管段选
sbit wei=P2^7; //关闭数码管位选
sbit lcden=P3^4; //lcd使能端,高脉冲有效
sbit lcdrs=P3^5; //lcd数据-指令端,低电平-写指令,高电平-写数据
sbit lcdrw=P3^6; //lcd读-写指令端,低电平执行写,高电平执行读
unch num,msecond,sw,gw,second;
void write_com(unch com);
void calculate(unch middle);
void delay(uint z);
void initial1();
void write_data(unch date);
void initial2();
void main()
{
initial1();
initial2();
num=0;
while(1)
{
if(num==1)
{
num=0;
msecond++;
if(msecond==100)
{
msecond=0;
second++;
}
if(second==100)
second=0;
if(second>=0&&second<100)
{
calculate(second);
write_com(0x80+0x00);
write_data('0'+sw);
write_data('0'+gw);
write_data('.');
}
calculate(msecond);
write_com(0x80+0x03);
write_data('0'+sw);
write_data('0'+gw);
}
}
}
void write_data(unch date)
{
lcdrs=1; //写数据,高电平有效
P0=date; //先赋值,
delay(1); //延时后,
lcden=1; //lcden一旦拉高,数据立马写入
delay(1); //延时
lcden=0; //再次置低,准备下一次拉高
}
void write_com(unch com)
{
lcdrs=0; //写指令,低电平有效
P0=com; //赋值
delay(1); //等待拉高
lcden=1; //lcden拉高
delay(1); //延时
lcden=0; //再次置低
}
void initial2()
{
TMOD=0x01;
TH0=(65536-9174)/256;
TL0=(65536-9174)%256;
EA=1;
ET0=1;
TR0=1;
msecond=0;
}
void timing0() interrupt 1
{
TH0=(65536-9174)/256;
TL0=(65536-9174)%256;
num++;
}
//延时函数
void delay(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--)
;
}
void initial1()
{
duan=0; //关闭duan选
wei=0; //关闭wei选
lcden=0; //lcden先置低电平,等待被拉高
lcdrw=0; //执行写操作
write_com(0x38); //lcd显示
write_com(0x0c); //开显示,不显示光标
write_com(0x06); //读或写后,地址指针+1
write_com(0x01); //清屏
}
void calculate(unch middle)
{
sw=middle/10;
gw=middle%10;
} 展开
但是在中断服务程序中,如果我用num++;则结果无法正常显示
若直接num=1;结果可以正常显示
这是为什么呢?
程序如下 有注释:
#include<reg52.h>
#define uint unsigned int
#define unch unsigned char
sbit duan=P2^6; //关闭数码管段选
sbit wei=P2^7; //关闭数码管位选
sbit lcden=P3^4; //lcd使能端,高脉冲有效
sbit lcdrs=P3^5; //lcd数据-指令端,低电平-写指令,高电平-写数据
sbit lcdrw=P3^6; //lcd读-写指令端,低电平执行写,高电平执行读
unch num,msecond,sw,gw,second;
void write_com(unch com);
void calculate(unch middle);
void delay(uint z);
void initial1();
void write_data(unch date);
void initial2();
void main()
{
initial1();
initial2();
num=0;
while(1)
{
if(num==1)
{
num=0;
msecond++;
if(msecond==100)
{
msecond=0;
second++;
}
if(second==100)
second=0;
if(second>=0&&second<100)
{
calculate(second);
write_com(0x80+0x00);
write_data('0'+sw);
write_data('0'+gw);
write_data('.');
}
calculate(msecond);
write_com(0x80+0x03);
write_data('0'+sw);
write_data('0'+gw);
}
}
}
void write_data(unch date)
{
lcdrs=1; //写数据,高电平有效
P0=date; //先赋值,
delay(1); //延时后,
lcden=1; //lcden一旦拉高,数据立马写入
delay(1); //延时
lcden=0; //再次置低,准备下一次拉高
}
void write_com(unch com)
{
lcdrs=0; //写指令,低电平有效
P0=com; //赋值
delay(1); //等待拉高
lcden=1; //lcden拉高
delay(1); //延时
lcden=0; //再次置低
}
void initial2()
{
TMOD=0x01;
TH0=(65536-9174)/256;
TL0=(65536-9174)%256;
EA=1;
ET0=1;
TR0=1;
msecond=0;
}
void timing0() interrupt 1
{
TH0=(65536-9174)/256;
TL0=(65536-9174)%256;
num++;
}
//延时函数
void delay(uint z)
{
uint i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--)
;
}
void initial1()
{
duan=0; //关闭duan选
wei=0; //关闭wei选
lcden=0; //lcden先置低电平,等待被拉高
lcdrw=0; //执行写操作
write_com(0x38); //lcd显示
write_com(0x0c); //开显示,不显示光标
write_com(0x06); //读或写后,地址指针+1
write_com(0x01); //清屏
}
void calculate(unch middle)
{
sw=middle/10;
gw=middle%10;
} 展开
1个回答
展开全部
牵扯到一个关键字的应用:volatile
如果你这样定义中断函数中的变量:
unch num;
那么编译器在编译过程中可能会优化掉这个变量(这很常见),转而用寄存器代替,因为访问寄存器比访问存储器要快的多.
那么,你这么定义:
unch num=1;
编译器因为要初始化这个变量,并把它放到已初始化数据区,所以在默认情况下编译器并不会将它优化掉,但不排除改变优化级别后这个变量还能保存.
怎么让编译器一定不优化这个变量?
关键字volatile就可以,关于这个变量的用法,做单片机的不可以不知道.
一个定义为volatile 的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义;
最后,不懂得volatile 的内容将会带来灾难,这也是区分C语言和嵌入式C语言程序员的一个关键因素.更加详细的应用请网上查询.
如果你这样定义中断函数中的变量:
unch num;
那么编译器在编译过程中可能会优化掉这个变量(这很常见),转而用寄存器代替,因为访问寄存器比访问存储器要快的多.
那么,你这么定义:
unch num=1;
编译器因为要初始化这个变量,并把它放到已初始化数据区,所以在默认情况下编译器并不会将它优化掉,但不排除改变优化级别后这个变量还能保存.
怎么让编译器一定不优化这个变量?
关键字volatile就可以,关于这个变量的用法,做单片机的不可以不知道.
一个定义为volatile 的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义;
最后,不懂得volatile 的内容将会带来灾难,这也是区分C语言和嵌入式C语言程序员的一个关键因素.更加详细的应用请网上查询.
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询