邏輯有問題,51單片機的IO埠是「線與」的關系,你用按鍵將兩個管腳連在一起,若一個輸出0,另外一個若是1,也會被強制變成0,而不是二個都變成1
像程序中 { P2=0xf0; if(P2==0xf8) 是不可能成立的,因P2的低4 位輸出 0,當按下S10/ S11 /S12三個按鍵時,P2.6/P2.5 /P2.4 會被拉低,而不P2.3被拉高
2. 51單片機如何在一個工程中同時加入延時和多組次數循環
假設循環10次和20次
c=10;
while(c--)
{
你要循環的程序1
}
c=20;
while(c--)
{
你要循環的程序2
}
當然也可用for循環
3. 如何利用單片機讓4位數碼管顯示
程序如下(用的是STC89C52晶元):
#include<reg52.h>//52系列單片機頭文件
#defineucharunsignedchar
#defineuintunsignedint
uintx,y;
ucharcodetable[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};//共陰極數碼管編碼
voiddisplay(uchar,uchar,uchar,uchar);//聲明子函數
voiddelay(int);//聲明子函數
voidmain()
{
while(1)
{
display(1,2,3,4);//主程序始終調用數碼管顯示子程序
}
}
voiddisplay(uchara,ucharb,ucharc,uchard)
{
P2=0xef;
P0=table[a];//給第一個數碼管送"a"
delay(1);//延時1ms
P2=0xdf;
P0=table[b];//給第二個數碼管送"b"
delay(1);//延時1ms
P2=0xbf;
P0=table[c];//給第三個數碼管送"c"
delay(1);//延時1ms
P2=0x7f;
P0=table[d];//給第三個數碼管送"d"
delay(1);//延時1ms
}
voiddelay(uintz)//延時子函數
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
(3)單片機中p06p06擴展閱讀
led數碼管是由多個發光二極體封裝在一起組成「8」字型的器件,引線已在內部連接完成,只需引出它們的各個筆劃,公共電極。led數碼管常用段數一般為7段有的另加一個小數點,還有一種是類似於3位「+1」型。
位數有半位,1,2,3,4,5,6,8,10位等等,led數碼管根據LED的接法不同分為共陰和共陽兩類,了解LED的這些特性,對編程是很重要的,因為不同類型的數碼管,除了它們的硬體電路有差異外,編程方法也是不同的。
4. 51單片機如何產生8路PWM波
我來說一下我的方案,這個我驗證過,方法如下:
其實用一個定時器就夠了,外部中斷接按鍵,一個用來頻率加,一個用來頻率減,即做調節頻率用,8路頻率從P0口輸出,定時器產生中斷,比如1us,那麼我到1us時對P0.0取反,同時中斷里在定義一個變數t1,那麼t1計中斷次數,假如計到5時我讓P1.0取反,兒至於計到幾有外部中斷來定義,比如定義一個全局變數f,INT0按一次則f++,INT1S按一次f- -,如此頻率得以控制,定時器處理如下:
void TIME0_ISR(void) interrupt 2
{
t1++;
if(t1==f) p00=~p00;
if(t1==f) p01=~p01;
if(t1==f) p02=~p02;
if(t1==f) p03=~p03;
if(t1==f) p04=~p04;
if(t1==f) p05=~p05;
if(t1==f) p06=~p06;
if(t1==f) {p07=~p07; f=0;}
}
當然這只是簡單的用51本身資源產生而已,還可以用專門的外圍電路來實現,我給你一個四路頻率產生程序,思想如上,已驗證過
/*************************四路頻率產生器***************************************/
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
/*************************常量定義***************************************/
sbit pwm1=P1^0; //第一路頻率 1s內產生5000個脈沖
sbit pwm2=P1^1; //第二路頻率 1s內產生1000個脈沖
sbit pwm3=P1^2; //第三路頻率 1s內產生2500個脈沖
sbit pwm4=P1^3; //第四路頻率 1s內產生500個脈沖
uchar cout1,cout2; //分別用來定義時間寬度
uchar t0_max=10,t1_max=100;
/*******************定時器0初始化函數***************************************/
void time0_ini() //定時0初始化
{
TMOD=0X02; //採用定時器0,選擇模式2
TH0=0xA3; //0.1ms定時
TL0=0Xa3;
ET0=1; //允許定時器溢出中斷
TR0=1; //啟動定時器
}
/***************************外部中斷0初始化***********************************/
void INT0_ini()
{
EX0=1; //外部中斷0允許
IT0=1; //選擇邊沿觸發方式
}
/***************************定時器1初始化*****************************************/
void time1_ini()
{
TMOD=0X20; //採用定時器1,選擇模式2
TH1=0XA3 ; //定時0.1ms
TL1=0XA3;
ET1=1; //允許定時器中斷
TR1=1; //啟動定時器1
}
/*************************主函數************************************************/
void main()
{
time0_ini(); //調用定時器0初始化函數
time1_ini(); //調用定時器1初始化函數
INT0_ini();
cout1=0;
cout2=0;
pwm1=0; //沒一路頻率都從低電平開始
pwm2=0;
pwm3=0;
pwm4=0;
EA=1; //打開總中斷
while(1); //一直停留在主函數中
}
/***************************定時器中斷服務程序************************************/
void tim0_ISR() interrupt 1 //定時0中斷服務程序
{
cout1++; //計數變數加1
if(cout1==t0_max)
{
pwm1=~pwm1; //每當到了1ms時取反一次電平,即周期為2ms,1s內產生500個脈沖
}
if(cout1==(t0_max+10))
{
cout1=0; //每當到了2ms時取反一次電平,即周期為4ms,1s內產生250個脈沖
pwm2=~pwm2;
}
}
/**************************定時器1中斷服務程序************************************/
void time1_ISR() interrupt 3 //定時器3中斷服務程序
{
cout2++;
if(cout2==t1_max)
{
pwm3=~pwm3; //每當到了10ms時取反一次電平,即周期為20ms,1s內產生50個脈沖
}
if(cout2==(t1_max+150))
{
cout2=0; //每當到了25ms時取反一次電平,即周期為50ms,1s內產生20個脈沖
pwm4=~pwm4;
}
}
/********************外部中斷0服務程序**************************/
void INT0_ISR() interrupt 0
{
if(t0_max>200) t0_max=10; //清楚上限
if(t1_max>2000) t1_max=100;
t0_max=t0_max+10;
t1_max=t1_max+100;
}
5. 如何讓其定義51單片機p0介面宏定義p07-p06-p05和p00-p01-p02一樣順序
那是宏定義不是定義成變數
6. 51單片機檢測引腳電平變化的C語言程序
#include <reg52.h>
sbit LED0 = P0^0; sbit LED1 = P0^1; sbit LED2 = P0^2; sbit LED3 = P0^3;
sbit LED4 = P0^4; sbit LED5 = P0^5; sbit LED6 = P0^6; sbit LED7 = P0^7;
sbit LED10 = P1^0;
void main() {
LED0 = 0; LED1 = 0; LED2 = 0; LED3 = 0; LED4 = 0; LED5 = 0; LED6 = 0;
LED7 = 0;
LED7 = 1;//假設有變化
if(LED7) {
LED10 = 1;
LED0 = 1; LED1 = 1; LED2 = 1; LED3 = 1; LED4 = 1; LED5 = 1; LED6 = 1; }
}
7. 關於51單片機點陣心形顯示問題
首先你要搞清楚點陣顯示原理。
8*8點陣要顯示一個畫面,通常採用掃描的形式。點陣內部發光陣列每一行的陰極連在一起,引出一條共陰線;每一縱向陽極連在一起,引出一條共陽線。這樣8*8點陣就共有8條共陰線和8條共陽線。具體請參考點陣內部結構示意圖!
掃描的過程:例如將共陽線作為掃描線,即每次給其中一條陽線供電,其它陽線斷電。這樣,在該條陽線上的LED點亮與否就取決於8條陰線的電平高低了。快速地掃描陽線,並且每掃描一條就給陰線變化相應的電平,就實現了一組圖像的顯示。
在你給的程序中,很明顯的 tabP2是用來形成掃描輸出的。你自己分析一下這些值每次是不是只發生了0這個值的移位。這是採用查表法來得到掃描功能的,每次讓IO口(一組)輸出這表中的一個值,最終就形成了掃描動作。至於tabP0就是對應於每一個掃描線輸出的心形數據表了。每次掃描IO輸出 tabP2的一個值,對應數據IO輸出tabP0的一個值。
至於你說的「還有8X8點陣圖中介面P23,P25,LP04,LP06,其中的LP04,LP06是不是指單片機的P04和P06介面啊?」我個人認為你應該自己有能力對這等電路進行分析了,不要一味只是單純復制製作。只有自己嘗試了解,以後才能做出更具特色的東西而不會僅僅停留在心形顯示。
8. 單片機sbit問題
在C語言中,「^」這個符號叫「按位異或運算符」,不能用來取寄存器的位。也就是說,在C語言中,如果寫 P0^6=1,這是個錯誤表達式。所以,C51語言中,需要將寄存器的位先進行位定義:sbit P06=P0^6; 才能進行後續的 位操作:P06=1;
當然,如果你要直接 P0=0x40,也可以讓 P0.6=1,但是,它又同時會修改P0的其他位。
又當然,用與、或運算能避免:P0 |=0x40,這個 P06=1了,而其他又不改變。但是,這不符合C語言的可讀性、移植性要求,因為,你壓根就不知道P06=1是要幹嘛。而且也移植不了。
正確使用的時候是這樣的:sbit LED=P0^6;這就表示LED了
9. 單片機控制繼電器
這個事專為你寫的程序。在keil里編譯通過。
ORG 00H
LJMP START
ORG 0BH
LJMP TIM
ORG 30H
START:
MOV IE,#10000010B
MOV TMOD,#00000010B
MOV TH0,#05H
SETB TR0
CLR 20H.0
MOV R0,#00H
MOV R1,#00H
MOV R2,#00H
MOV R3,#00H
MOV R4,#00H
MOV SP,#2FH
LOOP:
JBC 20H.0,NEXT1
SJMP LOOP
NEXT1:
CJNE R3,#00H,NEXT2
INC R3
MOV R1,#00H
MOV R2,#00H
MOV R4,#00H
CLR 20H.2
JNB 20H.2,$
CLR 20H.2
MOV P0,#11111101B
AJMP LOOP
NEXT2:
CJNE R3,#01H,NEXT3
INC R3
MOV R1,#00H
MOV R2,#00H
MOV R4,#00H
CLR 20H.1
JNB 20H.1,$
MOV P0,#11111011B
AJMP LOOP
NEXT3:
CJNE R3,#02H,NEXT4
INC R3
MOV P0,#11110111B
AJMP LOOP
NEXT4:
CJNE R3,#03H,NEXT5
INC R3
AJMP LOOP
NEXT5:
CJNE R3,#04H,NEXT6
INC R3
AJMP LOOP
NEXT6:
CJNE R3,#05H,NEXT7
INC R3
AJMP LOOP
NEXT7:
CJNE R3,#06H,NEXT8
INC R3
AJMP LOOP
NEXT8:
CJNE R3,#07H,NEXT9
INC R3
MOV P0,#11101111B
AJMP LOOP
NEXT9:
CJNE R3,#08H,NEXT10
INC R3
AJMP LOOP
NEXT10:
CJNE R3,#09H,NEXT11
INC R3
MOV P0,#11011111B
AJMP LOOP
NEXT11:
CJNE R3,#0AH,NEXT12
INC R3
MOV P0,#11011111B
AJMP LOOP
NEXT12:
CJNE R3,#0BH,NEXT13
INC R3
MOV P0,#11011111B
AJMP LOOP
NEXT13:
CJNE R3,#0CH,NEXT14
INC R3
MOV P0,#11011111B
AJMP LOOP
NEXT14:
CJNE R3,#0DH,NEXT15
INC R3
MOV P0,#11011111B
AJMP LOOP
NEXT15:
CJNE R3,#0EH,NEXT16
INC R3
MOV P0,#10111111B
AJMP LOOP
NEXT16:
CJNE R3,#0EH,NEXT
INC R3
MOV P0,#10111111B
AJMP LOOP
NEXT:
MOV R3,#00H
AJMP NEXT1
TIM:
INC R0
CJNE R0,#40,OVER
MOV R0,#00H
INC R1
CJNE R1,#10,OVER
MOV R1,#00H
SETB 20H.0
INC R2
CJNE R2,#100,OVER
MOV R2,#00H
SETB 20H.1
INC R4
CJNE R4,#18,OVER
MOV R4,#00H
SETB 20H.2
OVER:
RETI
END
10. 51單片機紅外遙控接收程序,請幫忙修改一下錯誤
這跟你使用的單片機、晶振,也就是速度有關系,單純的一個程序,根本沒辦法更改。
給你個我的,很好用,關鍵是精簡,不使用外部中斷,使用定時器一枚。
STc89c52+11.0592
SBITIRrecPort=PORTD^3;
BITIRprotLaststatus=0;//埠狀態位
unsignedcharcodeCount=0;//數據碼位計數
unsignedcharirTime;//碼時間,用於以125us時間計時
[4];//接收數據緩存
/*******************************
*Function:
*Description:函數功能、性能描述
*Calls:被本函數調用的函數清單
*CalledBy:調用本函數的函數清單
*Tableaccessed:被訪問的表(資料庫操作用)
*TabledUpdated:被修改的表(資料庫操作用)
*Input:輸入參數、取值說明與關系
*Output:輸出參數、類型說明
*Return:函數返回值說明
*Others:(Screensequence)
******************************/
(void)
{
T2MOD=0X00;
T2CON=0X00;
RCAP2L=(unsignedint)(0XFFFF-(250/((12/FOSC)+0.00005))+1);
RCAP2H=(unsignedint)(0XFFFF-(250/((12/FOSC)+0.00005))+1)>>8;
TL2=RCAP2L;
TH2=RCAP2H;
//TR2=1;
ET2=1;
EA=1;
}
/*******************************
*Function:
*Description:函數功能、性能描述
*Calls:被本函數調用的函數清單
*CalledBy:調用本函數的函數清單
*Tableaccessed:被訪問的表(資料庫操作用)
*TabledUpdated:被修改的表(資料庫操作用)
*Input:輸入參數、取值說明與關系
*Output:輸出參數、類型說明
*Return:函數返回值說明
*Others:(Screensequence)
******************************/
voidIRreceive_Hander(void)interrupt5
{
TR0=0;
if(TF2)
{
TF2=0;
irTime++;
if(irTime==120)//存活時間240*125=30MS
{
irTime--;
codeCount=0x3f;
}
if(IRrecPort)IRprotLaststatus=1;
elseif(IRprotLaststatus)
{
IRprotLaststatus=0;
if(irTime<12)
{
codeCount++;
codeCount&=0x1f;//限制其codeCount不大於某某數
InfarereceiveArray[codeCount>>3]<<=1;
if(irTime>7)
{
InfarereceiveArray[codeCount>>3]++;
}
}
irTime=0;
}
}
TR0=1;
}