將unsigned char var=0;看作溝通二進制和十進制的橋梁
var是8位,初始為0000 0000;
同時可以進行十進制的運算
邏輯運算
位運算
& 按位與(有0則0)
| 按位或(有1則1)
~ 按位非
^ 按位異或(相同則1,不同為0)
<<按位左移 >>按位右移位運算符解釋: 0011 1100 <<1 則變為 0111 1000 本質就是去掉最高K個位,最低K個位補充為0 右移同理,最低位k個全舍棄,最高位補充k個0 0011 1100 >>2 0000 11110011 1100 & 0010 0110 0010 0100
但是有符號數中負數的右移相當于填個1
單片機管腳指IO口
前面的LED燈有高低電平才會亮
單片機上電,所有IO口默認高電平
所以獨立按鍵如果按下則低電平,沒有按下默認高電平
寄存器寫值會送到IO口
寄存器檢測IO口電平,又會讀回寄存器中
松開按鍵讀寄存器則是高電平1,按下則讀的是0
所以檢測管腳電平高低,可以知道是否按下了按鍵.
#include <REGX52.H>
void main(){P2=0xfe; //MIN bit=0;other bit =1;while(1){;}
}
不難看出,這個點亮單個燈是通過控制寄存器實現的
但是需要給其它位賦值(8位為一組),即通過P2賦值
但我們只想操作最低位,不干涉別的位數強行賦值.
如何制定一位來控制?
打開頭文件不難看到有指定位的方法
原來P2寄存器有指定的變量!
P2-0to7有八個引腳的賦值變量
所以有:
不使用0x十六進制全位賦值,指定控制某個位
#include <REGX52.H>
void main(){//P2=0xfe; //MIN bit=0;other bit =1;P2_0=0;//1-7 bit is unknown,but maybe default 1while(1){;}
}
0是低電平,默認有高電平,此時存在一高一低,所以第一個燈會點亮,而其他的因為沒有賦值默認為1不會點亮因為這些燈全是高電平.
此時你寫了寄存器,那么就會被送到IO口
IO口產生的電平也會被送到寄存器從而得知0與1
獨立按鍵
翻看手冊,看到K1按鍵的口是RXD
所以K1-RXD-P3_1(P3_1,0,2,3)這個設計有點老了,本應該是0123對應K1234
#include <REGX52.H>
void main(){
//p2是燈,p3是按鍵,pk_num的num指的是第幾個,一般從0開始,但是p3是1023順序,p2是正常的0123while(1){if(P3_1==0){//如果按鍵是低電平,那么說明按下了P2_7=0;//點亮}else{P2_7=1;//高電平,說明是默認值高電平沒有按下,那么不點亮}}
}
按鍵抖動
對于獨立按鍵,由于單片機檢測頻率不同于家用電器,單片機是可以監測到抖動的,因為按鍵的小鐵片有彈性,不會馬上變成穩定狀態從而低電平,按下或松開都會發生5-10ms的抖動,這個抖動會導致頻繁的被單片機監測到,從而造成按一下相當于按多次的情況,需要避免.
消抖方法:
1.硬件(不會)
2.軟件,首次監測到執行,然后接下來5-10ms的抖動用延時單片機檢測(delay啥也不干)來處理(首次按下瞬間,松開瞬間后都要消抖)
#include <REGX52.H>
void Delay(unsigned int x) //@12.000MHz
{while(x--){unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i);}
}void main(){while(1){if(P3_1==0){//檢測到按鍵的第一瞬間,馬上執行按鍵消抖Delay(15);while(P3_1==0);//如果沒放手則一直等待//松手對應從while出來的一瞬間,馬上執行松手消抖Delay(15);//消抖完畢,此時執行點亮操作//P2_7=0;P2_7=~P2_7;//按位取反也可點亮,特別適合開關邏輯,p2_7原來是1則變為0,若再按則0變為1熄滅}}
}
按一下,燈光移動一下
8個位置避免溢出,取余解決
燈光移動,以0000 0001邏輯左移解決
這是第k次按,則0000 0001<<k賦給燈光P2
#include <REGX52.H>
void Delay(unsigned int x);void main(){unsigned char ledvar=0;//because un char is 8bits data , and compatible with register data(8 bits)while(1){//default all bits is 1: just as 1111 1111if(P3_1==0){Delay(5);while(P3_1==0);Delay(5);++ledvar;ledvar%=8;P2=~(0x01<<ledvar);}}
}void Delay(unsigned int x) //@12.000MHz
{while(x--){unsigned char i, j;i = 2;j = 239;do{while (--j);} while (--i);}
}
稍作更改得到
按鍵1得到右移,按鍵2得到左移
主要還是在代碼的邏輯
因為最終的顯示取決于P2每位的值,以便賦予各管腳高低電平
而P2由0x01即0000 0001的每輪左右得到,這是0x01是不變的
關鍵在于移的位數
如果本輪左移動了7位,那么下一輪左移就左移6位即可(通過右移的位數偏差,實現當輪左移的邏輯)
void main(){unsigned char ledvar=0;//because un char is 8bits data , and compatible with register data(8 bits)while(1){//default all bits is 1: just as 1111 1111if(P3_1==0){Delay(5);while(P3_1==0);Delay(5);++ledvar;ledvar%=8;P2=~(0x01<<ledvar);}else if(P3_0==0){Delay(5);while(P3_0==0);Delay(5);--ledvar;ledvar%=8;P2=~(0x01<<ledvar); }}
}
按鍵實現二進制燈光模擬:
按k次,二進制是多少,則亮對應的燈
邏輯上,初始全0,恰好無符號字符var就是8位,剛好適合,那么初始置為0,既有0000 0000的數據
此時++,有:
0000 0001第一次
0000 0010第二次
0000 0011第三次按下
…
1111 1111
0000 0000
…
核心代碼
void main(){unsigned char ledvar=0//because un char is 8bits data , and compatible with register data(8 bits)while(1){//default all bits is 1: just as 1111 1111if(P3_1==0){Delay(5);while(P3_1==0);Delay(5);++ledvar;p2=~ledvar;}}
}
今天晚上單片機剛到,先結束一個章節.
收工,刷抖音去了