Ⅰ 单片机程序的工作循环过程和循环语句while(1)的作用。
这个while(1)循环并不能阻止程序的跑飞(应该用看门狗防止程序跑飞),不过这样写也是很正确的做法,就是让程序一直在运行着(原地循环),这里的while(1)并不是防止程序“跑飞”的,而是防止main()返回。
① 在嵌入式中main是不能返回的。不同的C语言实现的单片机初始化代码会有不同的表现,有的是在call _main后jmp,而有的是jmp 0,等等这些会导致不可预料的结果。
② 在我们写的C语言后转换成汇编,再观察单片机的代码区,你会发现没有写程序的部分例如全1或者全0区域,程序运行到这里,就会有可能造成意料不到的结果。若无while(1)循环,程序全部执行后,跳转至程序起始处重新执行。
我用keil将去掉while(1)的程序编译,编译后的汇编代码如下,注意C:0x0012行(RET后会从0开始运行)和C:0x001C行(运行结束后跳转至main)这个方式是keil编译器的跳转方法,其他的可能会不同:
C:0x0000 020013 LJMP C:0013
10: void main (void){
11: P1=0x00;
C:0x0003 E4 CLR A
C:0x0004 F590 MOV P1(0x90),A
12: P20=0;
C:0x0006 C2A0 CLR P20(0xA0.0)
13: P21=0;
C:0x0008 C2A1 CLR P21(0xA0.1)
14: CS88=0;
15:
C:0x000A C2A2 CLR CS88(0xA0.2)
16: P1 = 0xFF;
17:
18:
C:0x000C 7590FF MOV P1(0x90),#0xFF
19: P1 = 0xfe;
20:
21:
22: // while (1)
C:0x000F 7590FE MOV P1(0x90),#0xFE
23: {
C:0x0012 22 RET
C:0x0013 787F MOV R0,#0x7F
C:0x0015 E4 CLR A
C:0x0016 F6 MOV @R0,A
C:0x0017 D8FD DJNZ R0,C:0016
C:0x0019 758107 MOV SP(0x81),#0x07
C:0x001C 020003 LJMP main(C:0003)
Ⅱ 读取单片机P0端口上的数据,然后让p2端口输出,结果程序没反应,为什么
跟据你的程序意思,我来写一下这个程序吧。
#include<reg51.h>
#defineucharunsignedchar
sbitp20=P2^0;
sbitp21=P2^1;
uchardat;
main()
{
while(1)
{
dat=P0;
if(dat==0x00){p20=0;p21=1;}
if(dat==0x01){p20=1;p21=0;}
}
}
Ⅲ 关于用51单片机做一个电子时钟的问题
程序中好像还没有自动加时的部分,并且按键处理还没有消抖措施
不多说了,上程序,俺刚刚为你编写的,测试的时候使用的端口和你的不一样
在我的开发板上测试成功后,按照你的板子端口做了修改
如果你直接复制到你的程序中不能使用,检查及更改一下端口即可
如果满意记得采纳哦,若有疑问可以随时向我提问
/***************************************************************************/
//#include<stdio.h>
#include<reg51.h>
sbit p20=P2^0; sbit p21=P2^1; sbit led=P2^7;
char dis_2[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//数码管显示编码
unsigned int h,m,s,t,n;
/***************************************************************************/
void delay(char hs)//延时函数
{char hk;for(;hs>0;hs--){for(hk=100;hk>0;hk--);}}
/***************************************************************************/
void XS(unsigned int xh,unsigned int xs) //显示子函数
{
char d1,d2,d3,d4;
d1=(xs/1)%10; d2=(xs/10)%10;
d3=(xh/1)%10; d4=(xh/10)%10;
P0=dis_2[d1]; P1=0x08; delay(10); P1=0x00;//秒个位
P0=dis_2[d2]; P1=0x04; delay(10); P1=0x00;//秒十位
P0=0x7f; P1=0x04; delay(10); P1=0x00;//小数点
P0=dis_2[d3]; P1=0x02; delay(10); P1=0x00;//时个位
P0=dis_2[d4]; P1=0x01; delay(10); P1=0x00;//时十位
}
/***************************************************************************/
void main(void)
{
TH0=(65536-1000)/256; TL0=(65536-1000)%256;
TMOD=0x01; EA=1; ET0=1; TR0=1;//定时器初始化
while(1)//主循环
{
if(p20==0){delay(10);if(p20==0){h++;if(h>23){h=0;}}while(!p20){XS(h,m);}}
if(p21==0){delay(10);if(p21==0){m++;if(m>59){m=0;}}while(!p21){XS(h,m);}}
XS(h,m);//调用数码管显示函数
}
}
/***************************************************************************/
void int1() interrupt 1 //定时器中断
{
TH0=(65536-1000)/256; TL0=(65536-1000)%256; n++;t++;
if(t>500){t=0;led=~led;}//LED闪烁
if(n>1000){n=0;s++;}//如果达到一秒,秒加一
if(s>59){s=0;m++;}//如果达到一分,分加一
if(m>59){m=0;h++;}//如果达到一小时,小时加一
if(h>23){h=0;}//如果达到24小时,小时清零
}
/***************************************************************************/
Ⅳ 51单片机,p20和p21发出1ms周期、相差90度的方波。定时器设置终端为250us。最后产生的波形周期是2.48ms。
这个仿真实例,稍加修改就可以了,可以下载附件仿真试试,参考一下。
Ⅳ 急救!!!做stc98c52单片机两机通信,出现怪问题,
我最近也在做两个单片机异步串行通信方面的学习,碰到的问题和你的差不多,也是两个单片机之间无法完成正常的串行通信。不同的是我采用的是查询法。尽管对于两个单片机的通信这一块我同样还是还没有搞明白,但是有一点是值得我们共同注意的,就是我们用单个的单片机和电脑进行串行通信可能是正常的,是由于PC机作为一个超级终端,省去了很多我们不必要的关于他的设置。而两个单片机之间的异步串行通信却是不同的,首先检查波特率是否一致,在一个就是程序,你要保证两个单片机之间进行正确的握手连接,就象我之前遇到的情况一样,因为是查询法,两个单片机之间应该实现正常的握手连接,否则可能上位机开始接收的数据不是从第一位开始的,有可能是下位机发送过来的数据的第二位开始的,然后从这位起开始接受八位,所以收到的数据也就不对了。要保证两个单片机之间实现正常的握手连接。
Ⅵ 如何用单片机红外发射头自己发射数据,并自己接收数据,用c怎么编写,谢谢
跟你说说方法吧
1,用单片机的某一个你要用作红外发射的端口(假设P0.0)产生一个38K的载波,即用定时器做一个13us的定时,每进一次定时器改变一次P0.0端口的状态。
2,接收端口设为外部中断,中断一开就开始接收数据
3,自己定义一个红外发射的协议,我是这么定义的
/**红外发射协议:先发头码,再发16位地址高8位,再发低8位,再发8位数据,在发8位数据反码,在发结束码
***头码 :0.5ms高0.25ms低
***地址及数据段:2ms高0.5ms低代表1, 0.5ms高2ms低代表0
***结束码:大约3.3ms低
***/
具体这个协议你只要你不是做成标准的模式就可以自己定义
4,接收的话你就可以根据每一次进入中断的时间判断当前接收的是0还是1
5,需要注意的地方时发射出去的数据和接收到的数据时相反的,即你发0xf0接收到的就是0x0f
这些希望对你有帮助
Ⅶ 51单片机两个键分别控制p2.0口延时10秒和p2.1口延时30分钟.c语言,定时器,89c52
#include<reg51.h>
#defineucharunsignedchar
#defineuintunsignedint
sbitp20=P2^0;
sbitp21=P2^1;
ucharcnt,sec,min;
voidt0isr()interrrupt1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
cnt++;
if(cnt>=0)
{
cnt=0;
sec++;
if(sec>=10)p20=1;
if(sec>=60)
{
sec=0;
min++;
if(min>=30)p21=1;
}
}
}
main()
{
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=1;
ET0=1;
EA=1;
p20=0;
p21=1;
whiile(1);
}
Ⅷ 51单片机驱动舵机
不知道你的P21脚设置的是什么模式,我认为高电平有点儿偏低,这提示高电平驱动能力不足,电流不够,可以把管脚设置成推挽模式试一试,或者加上一个适合的上拉电阻,例如1K,当然也可以使用光耦或三极管来控制。一般来讲,我认为这种单片机控制舵机应该考虑独立供电设计,中间用光耦彻底隔离,否则舵机动作的时候电流比较大,对单片机会有干扰。
当然了,如果高电平时间本来就抖动的话,舵机抖动是必然的,所以首先单片机要输出稳定的PWM波才行。
求采纳为满意回答。
Ⅸ 怎样控制单片机P21口发出15us的高电平的原理
如果用汇编语言,晶振12M时直接用15个空操作就 是15US
SETB p2.1
nop15个
CLR p2.1
当然也可以用定时器实现
Ⅹ 51单片机简单的C语言问题
#include <reg51.h>
sbit P10 = P1^0; //定义I/O口
sbit P11 = P1^1;
sbit P20 = P2^0;
sbit P21 = P2^1;
void InitT0(); //定时器0初始化函数
bit Flag_TimeOut; //定时时间到标志位
unsigned char T0INT_Count; //定时器0中断计数
void main()
{
InitT0();
Flag_TimeOut = 0;
P10 = 1; //检测输入要先输出高电平
while(P10); //检测P10口信号,若为高则一直检测,为低往下执行
TR0 = 1; //开启定时器开始计时
while(!Flag_TimeOut) //653ms没到 Flag_TimeOut为0 执行while循环
{ //这就是时间没到的检测,一直检测直到时间到
P11 = 1; //检测P11口状态
if(!P11) //为低输出状态
{
P20 = 1;
P21 = 0;
TR0 = 0; //关闭定时器
break; //这个就是检测到后跳出循环检测,也就是不再检测了
}
else //P11口为高
{
P20 = 0;
P21 = 1;
}
}
while(1); //停止
}
void InitT0()
{
T0INT_Count = 0; //定时器中断计数
TMOD = 0x01; //设置定时器0工作在定时器方式,工作方式1
TH0 = 0x00;
TL0 = 0xec; //写定时器初值 0x00ec 定时器T0中断一次时间为65.3ms (f=12MHz)
ET0 = 1; //开T0中断
EA= 1; //开总中断
}
void T0INT() interrupt 1 //定时器0中断函数
{
TH0 = 0x00;
TL0 = 0xec;
if(++T0INT_Count == 10) //当中断计数=10计时达到653ms 置Flag_TimeOut为1
{
Flag_TimeOut = 1;
}
}
我晕,不会看程序么?
我一个while循环里面一直在抓P11的信号
注意while和break