Ⅰ 單片機程序的工作循環過程和循環語句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