娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

【51單片機】矩陣鍵盤逐行掃描法仿真實驗+超詳細Proteus仿真和Keil操作步驟

發布者:RadiantEnergy最新更新時間:2024-08-26 來源: cnblogs關鍵字:51單片機  矩陣鍵盤 手機看文章 掃描二維碼
隨時隨地手機看文章

一、環境

我用的是Keil5做編譯工具,用proteus仿真。除了Keil5不知道有沒有其他好用的能生成.hex文件的軟件(要單片機運行是需要生成.hex文件的),Proteus則是一款很好用的仿真軟件,原件很多。當然,之前有試過multisim14,也是非常不錯的軟件,自帶有可以編寫代碼的文本編輯器,但沒找到我想要的原件。所以選擇了Proteus。

二、硬件部分

我們可以先打開Proteus:
Proteus的開始界面

1. Proteus新建工程

點擊開始界面的創建工程,先創建一個Proteus的工程。
在這里插入圖片描述
(注意:最好每個項目單獨一個文件夾,后期的文件很亂很雜)
工程名寫好,選擇好文件夾,后面的可以一直下一步。

2. 添加元件

在這里插入圖片描述可以直接點紅色箭頭或者先點擊“元件模式”然后點擊“P”進入元件庫。
在這里插入圖片描述

可以輸入80C51進行篩選,我用的是第一個80C51
再找到篩選keypad,我用的是keypad-smallcalc
接著找LED,選擇的是LED-BARGRAPH-GRN,作為輸出,也方便調試。
在這里插入圖片描述

選好的元件就在這了。然后點擊就能放置元件。
在這里插入圖片描述

3.連接線路

在這里插入圖片描述

4、硬件效果

當然,紅色和藍色的點不是接上線就有的,這是仿真之后的效果。其中,紅色是高電平,藍色是低電平,無色是無電平或脈沖不穩定,黃色為短路。
注意:Proteus的部分原件默認接了電源和接地,所以找不到電源和接地管腳。比如T80C51就是默認了接電源接地,所以沒有20、40管腳。


三、軟件部分

剛剛完成了硬件部分,和真實的硬件一樣,我們都需要有程序才能讓單片機工作。現在我們來用Keil5編寫程序。雖然課程是用的匯編,但由于個人不太習慣匯編的程序,所以我嘗試的是C語言。目標是做成一個簡單的計算器。


1、Keil5新建工程

菜單欄的project下的new uVision project,選擇好芯片**T80C51,**選擇好地址 (可以和Proteus的工程放一個文件夾)。
然后新建一個.c源文件,并把源文件添加到工程的 Source Group內。


2、代碼:

(1 思路分析

想要做一個計算器,其中有“+、-、*、/ ” 。最開始我想到的是數字和運算符分開存放,然后再處理。后來發現無法預測輸入的數字位數(因為每次只能輸入一位,也不能像在黑窗口那樣回車)。于是我決定把數字變成字符,跟運算符存放在一個char數列里,再分析處理數列,找出數字和運算符。


(2 添加頭文件

添加頭文件,并設置全局變量。


#include

int cro[4] = {0xFE,0xFD,0xFB,0xF7};//存放行值。分別表示是P2.0口低電平,P2.1低電平…………

char indata[50];//用于存放鍵盤輸入的字符數列

int len=0;//數列的長度

int fnum=0;//用于存放第一個操作數(處理數列得到的數字)

int lnum=0;//用于存放第二個操作數(處理數字得到的數字)

int ans=0;//存放計算結果

char op;//存放運算符

這是51單片機的頭文件,里面包含了51單片機的存儲器、端口等


(3 延時程序

在單片機中延時程序經常用到,延時的方法也很多,有硬件延時、軟件延時,匯編中可能會用nop,或者


MOV R0,100

DJNZ R0,$

在C語言中可以通過空循環來延時,就像下面這樣。當然也有其他方法。


void delay_ms(int n){

int i,j;

for(i = 0; i < n; i++)

for(j = 0; j < 1000; j++);

}//這里的值只是大概寫的,n==1時不一定真是1ms。也可以算準確值。

如果一個循環夠用或者容易控制時間的話,可以不用嵌套。


(4 鍵盤掃描程序

最先嘗試的是矩陣鍵盤的線路反轉法,但是中間出了些問題,暫時放棄了,改用 逐行掃描法。
根據書上的原理,結合以上面的電路圖 寫出程序。
在這里插入圖片描述

可見,我們的鍵盤連接了P2端口,低4位為行,高四位為列,LED則連接的P1端口。以此為例。


先使行端口(即P2端口低四位)輸出低電平,讀列值。若讀入的列值不為0FFH,則有鍵按下


int keyscan(){

int temp;

P2 = 0xf0;//給P12口送入11110000B

temp = P2 & 0xf0;//讀取列值

}

注意:在C語言里,二進制是前面加0b或0B,八進制是加0,十六進制加0x或0X。如十進制123,二進制0b123或0B123,八進制0123,十六進制0x123或0X123。


這樣就能完成 行輸出低電平,讀取列值的操作。如果列值不為0xf0,表示有鍵按下,有一位變成低電平。


當有鍵按下時,可以加10毫秒延時去抖。再進行逐行掃描。


掃描的過程是第四位逐位輸出低電平,讀不為0xff 的列值


int keyscan(){

int n;

int row;

int temp;

P2 = 0xf0;

temp = P2 & 0xf0;

if(temp != 0xf0){

    delay_ms(10)//這里需要加10毫秒延時去抖,

for(n = 0; n < 4; n++ ){//遍歷,低4位逐位輸出0,直到找到按下鍵的列值

P2 = cro[n];//P2口低位輸出0

rol = P2 & 0xf0;//讀高四維

if(rol != 0xf0){

return (row|(cro[n]&0x0f));//找到按下鍵的列值后合成鍵碼,并返回

break;

}

}

}

}

這就是逐行掃描的主要程序。


(5 配置按鍵功能

這時候我們發現,鍵碼找對了,該怎么讓它執行特定的程序呢?比如現在按'1',它并不代表'1'這個數。這個時候我們就需要給鍵配置一個功能或者含義。

我是這樣定義的:


void act(int key){

switch(key){

case 0x77:indata[len++] = '+';P1 = 0x80;break;//輸入的是運算符,輸出運算符按鍵對應的行。并存放到前面定義的數組里,長度+1

case 0xB7: show(); break;//”=“鍵的功能是展示運算結果

case 0xD7:indata[len++] = '0';P1 = 0x00;break;//輸入的是數字,輸出對應的二進制數

case 0xE7:clear(); break;//清零鍵的功能是清零

case 0x7B:indata[len++] = '-';P1 = 0x40;break;

case 0xBB:indata[len++] = '3';P1 = 0x03;break;

case 0xDB:indata[len++] = '2';P1 = 0x02;break;

case 0xEB:indata[len++] = '1';P1 = 0x01;break;

case 0x7D:indata[len++] = '*';P1 = 0x20;break;

case 0xBD:indata[len++] = '6';P1 = 0x06;break;

case 0xDD:indata[len++] = '5';P1 = 0x05;break;

case 0xED:indata[len++] = '4';P1 = 0x04;break;

case 0x7E:indata[len++] = '/';P1 = 0x10;break;

case 0xBE:indata[len++] = '9';P1 = 0x09;break;

case 0xDE:indata[len++] = '8';P1 = 0x08;break;

case 0xEE:indata[len++] = '7';P1 = 0x07;break;

default:break;

}

}

到這里我們的基本要求已經完成。接下來是完善的部分。


(6 補坑

剛才用到而沒有定義的函數,show()clear()。現在就讓我們來把這兩個函數寫出來。

首先是'='號鍵的功能函數show()


void show(){

decode();//這是一個把存放按鍵的字符數組變成可以運算的數字的函數。

operat();//把字符型的數字變成int型的數字后,就該計算了。這是運算函數。

P1 = ans;//最終要把運算結果輸出到LED。由于之前定義的是全局變量,所以不需要傳參數

}

接下來是清零按鍵的功能,清零。


void clear(){

int i;

for(i=0;i indata[i] = '

主站蜘蛛池模板: 丰宁| 依兰县| 峨山| 阿图什市| 四会市| 高密市| 华阴市| 长垣县| 富平县| 台东县| 姜堰市| 靖西县| 措美县| 遂川县| 城口县| 峨边| 赣榆县| 武汉市| 泸西县| 军事| 本溪市| 庆元县| 株洲县| 平果县| 安岳县| 梓潼县| 青海省| 宁晋县| 土默特右旗| 普安县| 陇西县| 宁都县| 获嘉县| 毕节市| 东山县| 双鸭山市| 南汇区| 广昌县| 胶南市| 饶阳县| 法库县|