89c51仿真时出现问题,请教各位大侠!
来源:百度文库 编辑:神马文学网 时间:2024/04/19 01:32:12
相关搜索: 大侠, 仿真, 请教
本帖最后由 ANSI_gao 于 2010-8-1 10:51 编辑
我用了两片89c51,一片用来产生两个负边缘信号(前后时间相差0.3秒,输出到另一块89c51的INT0,INT1用来触发外部中断。)同时不断发出38.5kHZ的频率信号。另一块89c51接到第一个外部中断后Timer0开始计时,Timer1计数clock发出的脉冲信号,在接到0.3秒后的第二个外部中断INT1停止计时计数。把测得的时间和脉冲显示在lcd上。但是用protued 仿真时没成功。我弄不懂,好郁闷啊。特来请教各位大侠。
/*********************************************
程序功能:按键按下P1.0产生一个负边缘输出信号
定时0.3秒之后P1.1产生另外一个负边缘输出信号
**********************************************/
#include
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define TH_M1 (65536-50000)/256 //timer0定时0.05sX6次=0.3s
#define TL_M1 (65536-50000)%256
extern void cs_t(void); //超声波发生函数
sbit flag_P=P0^0;
sbit P1_0=P1^0; //P1^0 P1^1用来产生两个下降沿信号
sbit P1_1=P1^1;
uint cou_t=0; //每0.05s cou_t加1
void main()
{
IE=0x82; /*允许T0中断*/
TMOD=0x01; //timer0选择mode1
P1_0=1; P1_1=1; //初始设置两个输出口为高电平
if(flag_P=1)
while(flag_P)
cs_t(); //P0^0的按键没有按下前发射超声波
if(flag_P==0){
P1_0=0;
TR0=1;
TH0=TH_M1;
TL0=TL_M1; //P0^0的按键按下后启动Timer0定时
for(;cou_t<7;)
cs_t(); //定时6次=0.3s
P1_1=0;
for(;;)
cs_t(); //发射超声波
}
return ;
}
void timer0(void) interrupt 1 //timer0定时中断
{
TH0=TH_M1;
TL0=TL_M1;
cou_t++;
}
/*****************************************************
在INT0~INT1两个外部中断的时间间隔内计时timer1传来的外部脉冲
同时timer0对这段时间间隔进行计时,把时间,脉冲数在液晶上显示
*****************************************************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define TH_M2 (256-100) // 定时100us
#define TL_M2 (256-100)
uchar msg1[]="Pulse:"; //液晶第一行显示的信息
uchar msg2[]="Time:0."; //液晶第二行显示的信息
uchar num1[5]={0,0,0,0,0}; //存放测得脉冲个数
uchar num2[4]={0,0,0,0}; //0.————秒
ulong cou_t=0; //记录时间,每100us cou_t加1
ulong pulses=0; //记录测得的脉冲个数
sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚
sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚
sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚
sbit BF=P0^7; //忙碌标志位,,将BF位定义为P0.7引脚
bit end_flag=0;
/*****************************************************
函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒
***************************************************/
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++)
;
}
/*****************************************************
函数功能:延时若干毫秒
入口参数:n
***************************************************/
void delay(unsigned char n)
{
unsigned char i;
for(i=0;i delay1ms(); } /***************************************************** 函数功能:判断液晶模块的忙碌状态 返回值:result。result=1,忙碌;result=0,不忙 ***************************************************/ unsigned char BusyTest(void) { bit result; RS=0; //根据规定,RS为低电平,RW为高电平时,可以读状态 RW=1; E=1; //E=1,才允许读写 _nop_(); //空操作 _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 result=BF; //将忙碌标志电平赋给result E=0; //将E恢复低电平 return result; } /***************************************************** 函数功能:将模式设置指令或显示地址写入液晶模块 入口参数:dictate ***************************************************/ void WriteInstruction (unsigned char dictate) { while(BusyTest()==1); //如果忙就等待 RS=0; //根据规定,RS和R/W同时为低电平时,可以写入指令 RW=0; E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲, // 就是让E从0到1发生正跳变,所以应先置"0" _nop_(); _nop_(); //空操作两个机器周期,给硬件反应时间 P0=dictate; //将数据送入P0口,即写入指令或地址 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=1; //E置高电平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令 } /***************************************************** 函数功能:指定字符显示的实际地址 入口参数:x ***************************************************/ void WriteAddress(unsigned char x) { WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x" } /***************************************************** 函数功能:将数据(字符的标准ASCII码)写入液晶模块 入口参数:y(为字符常量) ***************************************************/ void WriteData(unsigned char y) { while(BusyTest()==1); RS=1; //RS为高电平,RW为低电平时,可以写入数据 RW=0; E=0; //E置低电平(根据表8-6,写指令时,E为高脉冲, // 就是让E从0到1发生正跳变,所以应先置"0" P0=y; //将数据送入P0口,即将数据写入液晶模块 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=1; //E置高电平 _nop_(); _nop_(); _nop_(); _nop_(); //空操作四个机器周期,给硬件反应时间 E=0; //当E由高电平跳变成低电平时,液晶模块开始执行命令 } /***************************************************** 函数功能:对LCD的显示模式进行初始化设置 ***************************************************/ void LcdInitiate(void) { delay(15); //延时15ms,首次写指令时应给LCD一段较长的反应时间 WriteInstruction(0x38); //显示模式设置:16×2显示,5×7点阵,8位数据接口 delay(5); //延时5ms ,给硬件一点反应时间 WriteInstruction(0x38); delay(5); WriteInstruction(0x38); //连续三次,确保初始化成功 delay(5); WriteInstruction(0x delay(5); WriteInstruction(0x06); //显示模式设置:光标右移,字符不移 delay(5); WriteInstruction(0x01); //清屏幕指令,将以前的显示内容清除 delay(5); } void int0(void) interrupt 0 //int0外部中断 { TH0=TH_M2;TL0=TL_M2;TR0=1; //启动timer0定时中断 mode2 TH1=0;TL1=0;TR1=1; //启动timer1计数 } void int1(void) interrupt 1 //t0定时中断 { cou_t++;} void int2(void) interrupt 2 //int1外部中断 { pulses=TH1*256+TL1; //脉冲数 TR0=0;TR1=0; //停止timer0 timer1 end_flag=1; //结束标志 } void translate() //转换函数 { if(pulses>10000&&pulses<40000&&cou_t>1000&&cou_t<9000) { num1[0]=(uchar)pulses/10000;pulses=pulses%10000; num1[1]=(uchar)pulses/1000; pulses=pulses%1000; num1[2]=(uchar)pulses/100; pulses=pulses%100; num1[3]=(uchar)pulses/10; pulses=pulses%10; num1[4]=(uchar)pulses; num2[0]=(uchar)cou_t/1000;cou_t=cou_t%1000; num2[1]=(uchar)cou_t/100; cou_t=cou_t%100; num2[2]=(uchar)cou_t/10; cou_t=cou_t%10; num2[3]=(uchar)cou_t; } } void main() { uint i,j; IE=0x IP=0x05; //INT0 INT1 优先级为1 TMOD=0x25; //T0为Timer选择MODE2,T1为counter选择Mode1 IT0=1;IT1=1; //INT0,INT1选择下降沿触发 LcdInitiate(); //lcd初始化 WriteAddress(0x00); for(i=0;i<6;i++) WriteData(msg1); WriteAddress(0x40); for(j=0;j<7;j++) WriteData(msg2[j]); while(end_flag==0); //等待结束 if(end_flag==1) { _nop_(); _nop_(); translate(); //转换函数 } WriteAddress(0x00+6); for(i=0;i<4;i++) WriteData(num1); WriteAddress(0x40+7); for(j=0;j<5;j++) WriteData(num1); } protues仿真图.png (15.27 KB) 下载次数:0 2010-8-1 10:51 c文件和电路图.rar (16.29 KB) 下载次数:4 2010-8-1 10:43 本文来自:proteus仿真论坛(http://proteus.5d6d.com),详细出处参考:http://proteus.5d6d.com/thread-1