27,374
社区成员
发帖
与我相关
我的任务
分享
void delayus(int b) //微秒延时
{
int i;
for(;b>0;b--)
for(i=2;i>0;i--);
}
if(a==0)//输出方波
{
P1=0x00;
delayus(50);
P1=0xff;
delayus(50);
}
if(a==0)//输出方波
{
led=0;
delayus();
led=1;
delayus();
}
最后一个delayus()过后,单片机执行了多少代码,才又执行到led=0,你程序结构得好好规划。#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
//#pragma OT(4,speed)
sbit led=P2^4;
sbit key1=P3^7;
sbit key2=P3^6;
void display(char);//定义显示函数,参数为显示内容
void delayus(int);
void delayms(uint);
void init();
unsigned char tt=0;//初如化函数
sbit RS = P2^0;//定义端口
sbit RW = P2^1;
sbit EN = P2^2;
#define RS_CLR RS=0
#define RS_SET RS=1
#define RW_CLR RW=0
#define RW_SET RW=1
#define EN_CLR EN=0
#define EN_SET EN=1
/*延时函数*/
void delay_us(unsigned int n) //延时 如果需要高精度延时 请嵌入汇编
{
/*if (n == 0)
{
return ;
} */
while (--n);
}
/*延时函数*/
void delay_ms(unsigned char i)
{
unsigned char a, b;
for (a = 1; a < i; a++)
{
for (b = 1; b; b++)
{ ; }
}
}/*显示屏命令写入函数*/
void LCD_write_com(unsigned char com)
{
RS_CLR;
RW_CLR;
EN_SET;
P0 = com;
delay_us(5);
EN_CLR;
}
/*显示屏命令写入函数*/
void LCD_write_Data(unsigned char Data)
{
RS_SET;
RW_CLR;
EN_SET;
P0 = Data;
delay_us(5);
EN_CLR;
}
/*显示屏清空显示*/
void LCD_clear(void)
{
LCD_write_com(0x01);
delay_ms(5);}
/*显示屏字符串写入函数*/
void LCD_write_str(unsigned char x,unsigned char y,unsigned char *s)
{
if (y == 0)
{
LCD_write_com(0x80 + x);
}
else
{
LCD_write_com(0xC0 + x);
}
while (*s)
{
LCD_write_Data( *s);
s ++;
}
}
/*显示屏单字符写入函数*/
void LCD_write_char(unsigned char x,unsigned char y,unsigned char Data)
{
if (y == 0)
{
LCD_write_com(0x80 + x);
}
else
{
LCD_write_com(0xC0 + x);
}
LCD_write_Data( Data);
}
/*显示屏初始化函数*/
void LCD_init(void)
{
LCD_write_com(0x38); /*显示模式设置*/
delay_ms(5);
LCD_write_com(0x38);
delay_ms(5);
LCD_write_com(0x38);
delay_ms(5);
LCD_write_com(0x38);
LCD_write_com(0x08); /*显示关闭*/
LCD_write_com(0x01); /*显示清屏*/
LCD_write_com(0x06); /*显示光标移动设置*/
delay_ms(5);
LCD_write_com(0x0C); /*显示开及光标设置*/
}
void delayus(void) //微秒延时
{
/* #pragma asm
MOV R6,#13H
DL0:
MOV R5,#01H
DJNZ R5,$
DJNZ R6,DL0
RET
#pragma endasm */
unsigned char a,b;
for(b=39;b>0;b--)
for(a=1;a>0;a--);
}
void delayms(uint ms)//毫秒延时
{
int i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--);
}
void main()
{
unsigned char bb=0; //作为显示变量
char a=1,c=0,d=0,shi,ge,f=0,f_shi,f_ge,h,e;//设置标志识别位,c为选档键标志位(按1下为10s,按2下为20s,按3下为30s),d为确认键标志位,
init();//定时中断
LCD_init();
LCD_clear();
LCD_write_str(0,0,"DELAY:");
LCD_write_str(0,1,"SELECT:");
while(1){
if(key1==0)
{
delayms(10);//防抖
if(key1==0)
{
c++;
if(c==1){f=5;}
if(c==2){f=10;}
if(c==3){f=15;}
if(c==4)
{
c=0;
f=0;
}
f_shi=f/10+0x30;
f_ge=f%10+0x30;
LCD_write_char(8,1,f_shi);
LCD_write_char(9,1,f_ge);
while(!key1);//防抖
}
}
if((key2==0)&&(c!=0))//判断确认键和选档键是否同时满足条件
{
d=1;//标志位d变化
e=0;
h=e/10+0x30;
LCD_write_char(8,1,h);
LCD_write_char(9,1,h);
while(!key2);//防抖
}
if(d!=0)
{
TR0=1; //启定定时器0
if(c==1)//选档键按1下为定时10s
{
bb=f;
a=0;
d=0;
c=0;
}
if(c==2)//选档键按2下为定时20S
{
bb=f;
a=0;
d=0;
c=0;
}
if(c==3)//选档键按3下为定时30S
{
bb=f;
a=0;
d=0;
c=0;
}
if(c==4)//选档键按超过3下则清零
{
c=0;
return;
}
}
if(a==0)//输出方波
{
led=0;
delayus();
led=1;
delayus();
}
else
{
led=1;//灯灭
}
if(tt==20)
{ //20*50MS定时时间为1秒
tt=0;
bb--; //计数变量减1
if(bb==0)
{
c=0;
f=0;
a=1;
TR0=0; //启定定时器0
return;
}
}
shi=bb/10+0x30;
ge=bb%10+0x30;
LCD_write_char(8,0,shi);
LCD_write_char(9,0,ge);
} //while结束
}
void init()
{
tt=0;
TMOD=0X01; //设置定时器1为模式一,即16位计算模式
TH0=(65536-50000)/256; //给计数寄存器赋值,50毫秒时间
TL0=(65536-50000)%256;
EA=1; //开启总中断
ET0=1; //开启定时器0中断
// TR0=1; //启定定时器0
}
void timer() interrupt 1
{
TH0=(65536-50000)/256; //重新赋值
TL0=(65536-50000)%256;
tt++; //50毫秒加1,加20次为一秒
}
#include<reg52.h>
#pragma OT(4,speed)
void delayus(int);
sbit led=P2^4;
void delayus(void) //微秒延时
{
#pragma asm
MOV R6,#13H
DL0:
MOV R5,#01H
DJNZ R5,$
DJNZ R6,DL0
RET
#pragma endasm
}
void main()
{
led=0;
delayus();
led=1;
delayus();
}
嵌入汇编后,接在示波器上,显示波形的周期还是不对。加的延时是100US,那一个周期应该是200us。而示波器上一个周期显示出来是600US,请问为什么?有个叫的软件,可以很方便的生成延时函数,你可以试试。 另AT89C52是12T的51片子,12个机器周期才能执行完一条单周期指令。 单片机小精灵
单片机小精灵
按照你的代码,使用12T的51片子,周期是3ms没错的。 用模拟仿真,如图,右下角,单步运行delayus前右键reset一下计时器,然后f10单步,就能看到delayus所消耗的时间了。
这个要看晶振和生成的汇编代码的 先根据晶振算出一条指令的执行时间 然后看生成的汇编代码里一个循环有多少条指令