㈠ 單片機的按鍵功能是什麼
你們知道單片機的每個按鍵的具體功能嗎?下面是我收集整理關於單片機的每個按鍵的具體功能的資料以供大家參考學習,希望大家喜歡。·
鍵盤的分類:
鍵盤分編碼鍵盤和非編碼鍵盤。
鍵盤上閉合鍵的識別由專用的硬體編碼器實現,並產生鍵編碼號或鍵值的稱為編碼鍵盤,如計算機鍵盤;
而靠軟體編程來識別的稱為非編碼鍵盤。
在單片機組成的各種系統中,用的最多的是非編碼鍵盤。也有用到編碼鍵盤的。
非編碼鍵盤有分為:獨立鍵盤和行列式(又稱為矩陣式)鍵盤。
本文主要討論矩陣鍵盤(獨立鍵盤比較簡單可以與此類比),下面是矩陣鍵盤的電路連接圖。
如果單片機檢測到的是抖動部分,則無法按鍵判斷是否有效,所以我們需要加入防抖程序。
註:也可以通過硬體防抖,如上圖(b)。
功能:矩陣鍵盤
(按相應的按鍵,數碼管從0~F的顯示)
單片機:AT89S52
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit DAT=P0^3;
sbit CLK=P0^2;
uchar temp,h;
void delay(uint); //延遲程序
void sendbyte(uchar); //數碼管顯示
void keyscan(); //按鍵掃描
uchar code tab[]={
0xed,0x09,0xbc,0x9d,0x59,0xd5,
0xf5,0x0d,0xfd,0xdd,0x7d,0xf1,
0xe4,0xb9,0xf4,0x74,0x00} ; //0-F, 全滅
void main (void)
{
sendbyte(16); //初始時數碼管無顯示
while(1)
{
keyscan(); //按鍵掃描
}
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=100;y>0;y--);
}
void sendbyte(uchar byte)
{
uchar num,c;
num=tab[byte];
for(c=0;c<8;c++)
{
CLK=0;
DAT=num&0x01;
CLK=1;
num>>=1; //右移位賦值
}
}
void keyscan()
{
/*第一行按鍵的掃描*/
P2=0xfe; //確定第一行的按鍵有效
temp=P2; //將其賦給一個變數(處理I/O口時,一般先賦值給一個變數,然後通過處理變數來處理I/O口)
temp=temp&0xf0; //用於檢測第一行的哪個按鍵按下
while(temp!=0xf0) /*這個部分只要是用來消除按下抖動的*/
{
delay(5);
temp=P2;
temp=temp&0xf0;
while(temp!=0xf0) //這個地方,已經消除了按下抖動,P2口的值已經確定
{
temp=P2; //將P2口得值賦給變數
switch(temp) //這個switch語句,用來確定哪一個按鍵按下時,數碼管的顯示值
{
case 0x7e:h=0;
break; //這個break很重要,表示如果有匹配的值,就跳出switch語句,防止程序跳不出來。
case 0xbe:h=1;
break;
case 0xde:h=2;
break;
case 0xee:h=3;
break;
default : h=16;
break;
}
while(temp!=0xf0) /*這個部分只要是用來消除釋放抖動的*/
{
temp=P2;
temp=temp&0xf0;
}
sendbyte(h); //送給數碼管顯示
}
}
/*第二行按鍵的掃描*/
P2=0xfd;
temp=P2;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P2;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case 0x7d:h=4;
break;
case 0xbd:h=5;
break;
case 0xdd:h=6;
break;
case 0xed:h=7;
break;
default : h=16;
break;
}
while(temp!=0xf0)
{
temp=P2;
temp=temp&0xf0;
}
sendbyte(h);
}
}
/*第三行按鍵的掃描*/
P2=0xfb;
temp=P2;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P2;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case 0x7b:h=8;
break;
case 0xbb:h=9;
break;
case 0xdb:h=10;
break;
case 0xeb:h=11;
break;
default : h=16;
break;
}
while(temp!=0xf0)
{
temp=P2;
temp=temp&0xf0;
}
sendbyte(h);
}
}
/*第四行按鍵的掃描*/
P2=0xf7;
temp=P2;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P2;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P2;
switch(temp)
{
case 0x77:h=12;
break;
case 0xb7:h=13;
break;
case 0xd7:h=14;
break;
case 0xe7:h=15;
break;
default : h=16;
break;
}
while(temp!=0xf0)
{
temp=P2;
temp=temp&0xf0;
}
sendbyte(h);
}
}
㈡ 單片機匯編語言里 DB
單片機匯編語言中的DB是以位元組為單位定義一個數據段,一般用於查表程序中,舉例說明:
DISPLAY:
MOV DPTR,#TAB
MOV A,R2
MOVC A,@A+DPTR
MOV P0,A
RET
TAB: ; 共陰極數碼管顯示代碼表
DB 3FH,06H,5BH,4FH,66H ;01234
DB 6DH,7DH,07H,7FH,6fh ;56789
㈢ 51單片機分支地址表中 DW 指什麼
DW 是一條匯編語言偽指令。
作用:
在機器匯編時,告訴匯編程序,從指定的地址開始,在存儲器的連續單元中定義16位數據字。
比如:
DW 「AA」 ;連續存入41H,41H
DW "A" ;連續存入00H,41H
DW "ABC" ;不合法超過兩位元組
DW 100H, 1ACH ;順序連續存入01H、00H、01H、0ACH
還有幾個同類的:
DB,是用來定義位元組數據的。
DD,定義32位雙字數據的。
DS等
希望對你有所幫助!!!!
㈣ 我想利用單片機通過串口發送幾個16進制數FF 10 11 01 DD 求高手指點,不勝感激。
單片機通過串口發送幾個16進制數FF 10 11 01 DD,程序如下:
void Send(unsigned char Tx_Data)//向串口發字元
{
SBUF=Tx_Data;
while(!TI);
TI=0;
}
main()
{
先串口初始化,然後:
Send(0xFF);
Send(0x10);
Send(0x11);
Send(0x01);
Send(0xDD);
即可。
}
㈤ 如何用單片機控制直流電機
通過與單片機相連的按鍵控制直流電機停啟的電路如下圖所示,通過P3.6口按鍵觸發啟動直流電機,P3.7口的按鍵觸發停止直流電機的運行。由圖可知,當P1.0輸出高電平「1」時,NPN型三極體導通,直流電機得電轉動;當P1.0輸出低電平「0」時,NPN型三極體截止,直流電機停止轉動。
通過單片機產生PWM波控制直流電機程序
#include"reg52.h"
#defineucharunsignedchar
#defineuintunsignedint
ucharcodetable[10]={0x3f,0x06,0x5b,
0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共陰數碼管顯示碼(0-9)
sbitxiaoshudian=P0^7;
sbitwei1=P2^4;//數碼管位選定義
sbitwei2=P2^5;
sbitwei3=P2^6;
sbitwei4=P2^7;
sbitbeep=P2^3;//蜂鳴器控制端
sbitmotor=P1^0;//電機控制
sbits1_jiasu=P1^4;//加速按鍵
sbits2_jiansu=P1^5;//減速按鍵
sbits3_jiting=P1^6;//停止/開始按鍵
uintpulse_count;//INT0接收到的脈沖數
uintnum=0;//num相當於占空比調節的精度
ucharspeed[3];//四位速度值存儲
floatbianhuasu;//當前速度(理論計算值)
floatreallyspeed;//實際測得的速度
floatvv_min=0.0;vv_max=250.0;
floatvi_Ref=60.0;//給定值
floatvi_PreError,vi_PreDerror;
uintpwm=100;//相當於占空比標志變數
intsample_time=0;//采樣標志
floatv_kp=1.2,v_ki=0.6,v_kd=0.2;//比例,積分,微分常數
voiddelay(uintz)
{
uintx,y;
for(x=z;x>0;x--)
for(y=20;y>0;y--);
}
voidtime_init()
{
ET1=1;//允許定時器T1中斷
ET0=1;//允許定時器T0中斷
TMOD=0x15;//定時器0計數,模式1;定時器1定時,模式1
TH1=(65536-100)/256;//定時器1值,負責PID中斷,0.1ms定時
TL1=(65536-100)%6;
TR0=1;//開定時器
TR1=1;
IP=0X08;//定時器1為高優級
EA=1;//開總中斷
}
voidkeyscan()
{
floatj;
if(s1_jiasu==0)//加速
{
delay(20);
if(s1_jiasu==0)
vi_Ref+=10;
j=vi_Ref;
}
while(s1_jiasu==0);
if(s2_jiansu==0)//減速
{
delay(20);
if(s2_jiansu==0)
vi_Ref-=10;
j=vi_Ref;
}
while(s2_jiansu==0);
if(s3_jiting==0)
{
delay(20);
motor=0;
P1=0X00;
P3=0X00;
P0=0x00;
}
while(s3_jiting==0);
}
floatv_PIDCalc(floatvi_Ref,floatvi_SpeedBack)
{
registerfloaterror1,d_error,dd_error;
error1=vi_Ref-vi_SpeedBack;//偏差的計算
d_error=error1-vi_PreError;//誤差的偏差
dd_error=d_error-vi_PreDerror;//誤差變化率
vi_PreError=error1;//存儲當前偏差
vi_PreDerror=d_error;
bianhuasu=(v_kp*d_error+v_ki*vi_PreError+v_kd*dd_error);
return(bianhuasu);
}
voidv_Display()
{
uintsu;
su=(int)(reallyspeed*10);//乘以10之後強制轉化成整型
speed[3]=su/1000;//百位
speed[2]=(su00)/100;//十位
speed[1]=(su0)/10;//個位
speed[0]=su;//小數點後一位
wei1=0;//第一位打開
P0=table[speed[3]];
delay(5);
wei1=1;//第一位關閉
wei2=0;
P0=table[speed[2]];
delay(5);
wei2=1;
wei3=0;
P0=table[speed[1]];
xiaoshudian=1;
delay(5);
wei3=1;
wei4=0;
P0=table[speed[0]];
delay(5);
wei4=1;
}
voidBEEP()
{
if((reallyspeed)>=vi_Ref+5||(reallyspeed
{
beep=~beep;
delay(4);
}
}
voidmain()
{
time_init();
motor=0;
while(1)
{
v_Display();
BEEP();
}
if(s3_jiting==0)//對按鍵3進行掃描,增強急停效果
{
delay(20);
motor=0;
P1=0X00;
P3=0X00;
P0=0x00;
}
while(s3_jiting==0);
}
voidtimer0()interrupt1
{
}
voidtimer1()interrupt3
{
TH1=(65536-100)/256;//1ms定時
TL1=(65536-100)%6;
sample_time++;
if(sample_time==5000)//采樣時間0.1ms*5000=0.5s
{
TR0=0;//關閉定時器0
sample_time=0;
pulse_count=TH0*255+TL0;//保存當前脈沖數
keyscan();//掃描按鍵
reallyspeed=pulse_count/(4*0.6);//計算速度
pwm=pwm+v_PIDCalc(vi_Ref,reallyspeed);
if(pwm
if(pwm>100)pwm=100;
TH0=TL0=0;
TR0=1;//開啟定時器0
}
num++;
if(num==pwm)//此處的num值,就是占空比
{
motor=0;
}
if(num==100)//100相當於占空比調節的精度
{
num=0;
motor=1;
}
}