【普中】基于51單片機的7人多數(shù)投票表決器設(shè)計
( proteus仿真+程序+設(shè)計報告+講解視頻)
仿真圖proteus8.16(有低版本)
程序編譯器:keil 4/keil 5
編程語言:C語言
設(shè)計編號:P13
1.主要功能:
基于51單片機AT89C51/52(與AT89S51/52、AT89C51/52、STC89C51/52等51內(nèi)核單片機通用)
具體功能:
(1)設(shè)定矩陣鍵盤的14個鍵作為7位投票人的按鍵,其中每人2個鍵,分別作為“贊成”鍵和“反對”鍵;設(shè)定1個獨立按鍵作為投票開始鍵;設(shè)定兩個數(shù)碼管用于顯示計時信息,兩個數(shù)碼管用于顯示“贊成”及贊成數(shù),兩個數(shù)碼管用于顯示“反對”及反對數(shù)。
(2)只有當(dāng)主持人按下開始鍵時才可進(jìn)行投票,否則不接收投票按鍵的信息。
(3)當(dāng)投票開始鍵按下時開始10秒倒計時,此時數(shù)碼管顯示倒計時信息,同時“贊成”鍵或“反對”鍵每按一下,相應(yīng)的數(shù)碼管顯示A(贊成)及贊成累加數(shù)或O(反對)及反對累加數(shù),倒計時結(jié)束即投票結(jié)束。
(4)投票開始鍵按下(即開始投票)和倒計時結(jié)束(即投票結(jié)束)時蜂鳴器響一聲,數(shù)碼管顯示的結(jié)果即為最終投票的結(jié)果。7票中,“贊成”票≥4票表示通過,此時,計時數(shù)碼管顯示“P”;否則為不通過,計時數(shù)碼管顯示“F”。
(目前僅完全適配普中開發(fā)板A234,其他普中開發(fā)板型號可能需要做代碼修改或接線)
需注意仿真中51單片機芯片是兼容的,AT89C51,AT89C52是51單片機的具體型號,內(nèi)核是一樣的。相同的原理圖里,無論stc還是at都一樣,引腳功能都是一樣的,程序是兼容的,芯片可以替換為STC89C52/STC89C51/AT89C52/AT89C51等51單片機芯片。
講解視頻:
仿真講解+實物演示+代碼講解
2.仿真
開始仿真
打開仿真工程,雙擊proteus中的單片機,選擇hex文件路徑,然后開始仿真。
系統(tǒng)開始運行,主持人按下開始按鍵,蜂鳴器發(fā)給“滴滴”聲,數(shù)碼管的第3,4位開始進(jìn)行10s的倒計時。如圖5-1所示,數(shù)碼管倒計時顯示倒計時到了9s時的圖形。
圖5-1 系統(tǒng)開始運行
系統(tǒng)運行中,主持人可以緊急情況下重新表決,表決人可以按下自己對應(yīng)的按鍵進(jìn)行表決,當(dāng)表決人按下自己的按鍵后,他自己對應(yīng)的投票權(quán)失效不能再投票。如圖5-2所示,數(shù)碼管倒計時到1s的時候,有五位表決人按下了自己的表決按鍵,分別是兩票贊同,三票反對。
圖5-2 系統(tǒng)運行中的圖
系統(tǒng)運行結(jié)束后,數(shù)碼管不再顯示倒計時的數(shù)據(jù),數(shù)碼管的第四位會顯示表決是否通過,通過即顯示P,不通過即顯示F。表決結(jié)束要開始新的表決主持人可以按下復(fù)位按鍵進(jìn)行下一次的表決。如圖5-3所示,10s倒計時結(jié)束,數(shù)碼管的第四位顯示為F,則說明有低于4人同意表決。
圖5-3 系統(tǒng)運行結(jié)束圖
3. 程序代碼
使用keil4或者keil5編譯,代碼有注釋,可以結(jié)合報告理解代碼含義。
#include <reg52.h>
#include <intrins.h>
#include <string.h> // 對于C語言
#include <stdio.h>
#define u8 unsigned char // 以后unsigned char就可以用u8代替
#define u16 unsigned int // 以后unsigned int 就可以用u16 代替
#define TIME_CNT 10 //倒計時 時間單位秒
sbit k1 = P1^0; //按鍵定義
sbit k2= P1^1;
sbit k3= P1^2;
sbit k4 = P1^3;
sbit key1=P1^4;
sbit key2=P1^5;
sbit key3=P1^6;
sbit key4=P1^7;
sbit kk1=P3^1; //獨立按鍵定義
完整代碼見文章下載鏈接
//sbit LSA=P2^2; //數(shù)碼管位選
//sbit LSB=P2^3;
//sbit LSC=P2^4;
sbit beep=P2^5;
u8 key,x,y,duia=10,duib=11,z1,z2,flag; //變量
unsigned char cnt = 0,cnt1,cnt2; //中斷次數(shù)
u8 jieshu=0; //復(fù)位
u8 AA=0,BB,jishi=TIME_CNT,jj;
u8 state[7]={0,0,0,0,0,0,0};
u8 code led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x5c,
0x73,0x71}; //端選 P/F
unsigned char code table[]={0x00,0x04,0x08,0x0c,0x10,0x14,0x18,0x1c}; //位選
void delay(u16 z) //延時函數(shù)
{
u16 i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
void display() // 定義一個名為display的函數(shù),用于控制數(shù)碼管顯示
{
P0=0x00; // 將P0口設(shè)置為0x00,即關(guān)閉所有段(清零,可能為了消隱效果)
P0=led[duia]|0x80; // 將led數(shù)組中對應(yīng)duia索引的值與0x80進(jìn)行或操作后輸出到P0口,0x80通常用于開啟小數(shù)點
P2=table[7]; // 設(shè)置P2口為table數(shù)組的第7個元素的值,可能用于選擇數(shù)碼管的位選
delay(2); // 延時2毫秒,確保數(shù)碼管穩(wěn)定顯示
P0=0x00; // 再次關(guān)閉所有段,準(zhǔn)備顯示下一位
// 以下代碼重復(fù)上述過程,分別顯示AA的十位、個位,jishi(計時)的十位、個位,
// 以及BB的十位、個位,利用led數(shù)組和table數(shù)組配合P0和P2口實現(xiàn)數(shù)碼管的動態(tài)顯示。
// 每次顯示前都會關(guān)閉所有段以清除上一次的顯示,然后設(shè)置相應(yīng)的位選和段選,最后延時確保顯示穩(wěn)定。
P0=led[AA/10]; // 顯示AA的十位
P2=table[6];
delay(2);
P0=0x00;
P0=led[AA%10]; // 顯示AA的個位
P2=table[5];
delay(2);
P0=0x00;
P0=led[jishi/10]; // 顯示jishi(計時)的十位
P2=table[4];
delay(2);
P0=0x00;
P0=led[jishi%10]; // 顯示jishi的個位
P2=table[3];
delay(2);
P0=0x00;
P0=led[duib]|0x80; // 顯示duib,并開啟該位的小數(shù)點
P2=table[2];
delay(2);
P0=0x00;
P0=led[BB/10]; // 顯示BB的十位
P2=table[1];
delay(2);
P0=0x00;
P0=led[BB%10]; // 顯示BB的個位
P2=table[0];
delay(2);
P0=0x00;
}
void display1() //數(shù)碼管顯示,投票結(jié)束顯示
{
P0=0x00;
P0=led[jj];
P2=table[4];
delay(2);
}
void t0(void) interrupt 1 //定時器0中斷服務(wù)程序
{
TH0 = (65536-20000)/256; //20ms計時初值
TL0 =(65536-20000)%256;
cnt++; //溢出次數(shù)加1
if(cnt == 50) //時長達(dá)到1秒
{
cnt = 0;
jishi--; //時間減1
if(jishi==0)
{
TR0=0; //關(guān)閉定時器0
jieshu=1; //結(jié)束標(biāo)志位
TR1=1; //打開定時器1
flag=0; //開始標(biāo)志位清零
}
}
}
void t1(void) interrupt 3 //定時器1中斷服務(wù)程序
{
TH1 = (65536-1000)/256; //1ms計時初值
TL1 =(65536-1000)%256;
cnt1++; //溢出次數(shù)加1
cnt2++; //溢出次數(shù)加1
if(cnt1 == 1)
{
cnt1 = 0;
beep=~beep; //蜂鳴器報警
}
if(cnt2 == 100) //蜂鳴器關(guān)閉
{
cnt2 = 0;
TR1=0;
beep=1;
}
}
void delay_uint(u16 i)//延時
{
while(i--);
}
// 定義一個函數(shù)用于掃描矩陣鍵盤并返回按鍵值
u8 Matrix_buttons_scan(){
u8 i, j; // 定義變量i和j分別存儲行列索引
i = 0;
j = 0;
// 設(shè)置P1端口的低四位輸出為0,高四位保持不變,準(zhǔn)備讀取鍵盤列信號
P1 = 0x0f;
// 判斷是否有鍵被按下(即P1端口的值不全為0x0f)
if(P1 != 0x0f) {
// 延時去抖,等待10ms再次檢測,確保按鍵穩(wěn)定
delay_uint(10000);
// 再次檢查,確認(rèn)按鍵確實被按下
if(P1 != 0x0f) {
// 根據(jù)P1的值判斷是哪一行被按下
switch(P1) {
case 0x0e: i = 3; break; // 第4行
case 0x0d: i = 2; break; // 第3行
case 0x0b: i = 1; break; // 第2行
case 0x07: i = 0; // 第1行
}
// 設(shè)置P1端口的高四位輸出為0,低四位保持不變,準(zhǔn)備讀取鍵盤行信號
P1 = 0xf0;
// 根據(jù)P1的新值判斷是哪一列被按下
switch(P1) {
case 0xe0: j = 13; break; // 第4列
case 0xd0: j = 9; break; // 第3列
case 0xb0: j = 5; break; // 第2列
case 0x70: j = 1; // 第1列
}
}
}
// 檢查新獲取的按鍵值(行列索引組合)是否與上一次的不同
if(key != i + j) {
// 更新按鍵值并返回
key = i + j;
return key;
} else {
// 如果按鍵值沒有變化,返回0表示沒有新按鍵事件
return 0;
}
}
//按鍵掃描子函數(shù)
void keyscan()
{
u8 i=0;
if(kk1==0) // 開始按鍵
{
delay_uint(100);
if(kk1==0){
if(flag==0){//開始投票
TR0=1;//開啟定時器0
flag=1;//標(biāo)志位寫1,開始投票
TR1=1;
jishi=TIME_CNT;//重寫定時時間
AA=BB=0;//清0贊成和反對票
while (kk1==0){}//等待松手
}else{//復(fù)位
TR0=0;
flag=0;
TR1=0;
jieshu=0;
jishi=TIME_CNT;
AA=BB=0;
memset(state,0,sizeof(state));//數(shù)組清零
while (kk1==0){}//等待松手
}
}
}
if(flag==0){//未開始不掃碼矩陣按鍵
return;
}
i=Matrix_buttons_scan();//按鍵檢測
if(i==1)
{
if(state[0]==0)BB++; //1號反對票
state[0]=1; //清除1號投票權(quán)
}
else if(i==2)
{
if(state[0]==0)AA++; //1號贊同票
state[0]=1; //清除1號投票權(quán)
}else if(i==3)
{
if(state[1]==0)BB++; //2號反對票
state[1]=1; //清除2號投票權(quán)
}else if(i==4)
{
if(state[1]==0)AA++; //2號贊同票
state[1]=1; //清除2號投票權(quán)
}else if(i==5)
{
if(state[2]==0)BB++; //3號反對票
state[2]=1; //清除3號投票權(quán)
}else if(i==6)
{
if(state[2]==0)AA++; //3號贊同票
state[2]=1; //清除3號投票權(quán)
}
else if(i==7)
{
if(state[3]==0)BB++; //4號反對票
state[3]=1;
}else if(i==8)
{
if(state[3]==0)AA++; //4號贊同票
state[3]=1;
}
else if(i==9)
{
if(state[4]==0)BB++; //5號反對票
state[4]=1;
}else if(i==10)
{
if(state[4]==0)AA++; //5號贊同票
state[4]=1;
}
else if(i==11)
{
if(state[5]==0)BB++; //6號反對票
state[5]=1;
}else if(i==12)
{
if(state[5]==0)AA++; //6號贊同票
state[5]=1;
}
else if(i==13)
{
if(state[6]==0)BB++; //7號反對票
state[6]=1;
}else if(i==14)
{
if(state[6]==0)AA++; //7號贊同票
state[6]=1;
}
}
4. 設(shè)計報告
5676字設(shè)計報告,內(nèi)容包括目錄,硬件設(shè)計、軟件設(shè)計、軟硬件框圖、調(diào)試、結(jié)論等
表決器的實現(xiàn)主要涉及開始表決的控制、表決的方案、狀態(tài)的指示、倒計時時間和表決同意人數(shù)及表決是否通過的顯示。首先,倒計時時間與表決同意人數(shù)及表決是否通過的顯示,可使用液晶屏或者數(shù)碼管來實現(xiàn),倒計時時間為 10s,表決人數(shù)為7人,則一共需要顯示8位數(shù),使用數(shù)碼管比較簡便。一般選用七段數(shù)碼管顯示器,其應(yīng)用簡單、可靠性高、成本低,可用于顯示輸出。由于有8位數(shù)字需要顯示,使用兩個4位數(shù)碼管。
數(shù)碼管可使用靜態(tài)或者動態(tài)顯示,很明顯,動態(tài)顯示能夠滿足本設(shè)計的需求。段選與位選信號可由單片機的I/O口直接提供,或者可使用鎖存器間接獲得。只要單片機的驅(qū)動電流足夠,便可以直接控制數(shù)碼管,但這樣會占用很多單片機的端口,也可以使用鎖存器既能節(jié)約單片機端口,又能增加驅(qū)動電流,選擇使用鎖存器驅(qū)動數(shù)碼管,這樣也可簡化軟件編程。狀態(tài)指示包括顯示當(dāng)前處于表決的哪個環(huán)節(jié),以及哪位表決人成功等提示,可選用蜂鳴器、發(fā)光二極管等來指示,發(fā)光二極管更能持續(xù)、鮮明地指示當(dāng)前狀態(tài),因此選擇使用發(fā)光二極管來指示當(dāng)前狀態(tài)。搶答開始或結(jié)束的開關(guān),以及表決人表決設(shè)備均可使用按鍵,這樣比較簡單方便。整個方案中使用了很多的I/O口,并且系統(tǒng)的邏輯比較復(fù)雜,整個系統(tǒng)的軟件設(shè)計可采用查詢的方式,由各函數(shù)完成各自的功能。
5. 設(shè)計資料內(nèi)容清單&&下載鏈接
資料設(shè)計資料包括仿真,程序代碼、講解視頻、功能要求、設(shè)計報告、軟硬件設(shè)計框圖等。
0、常見使用問題及解決方法–必讀!?。?!
1、仿真圖
2、程序源碼注釋
3、功能要求
4、開題報告
5、設(shè)計報告
6、軟硬件流程框圖
7、燒錄工具
8、講解視頻
9、實物圖
Altium Designer 安裝破解
KEIL+proteus 單片機仿真設(shè)計教程
KEIL安裝破解
Proteus安裝
Proteus簡易使用教程
單片機學(xué)習(xí)資料
普中-2&普中-3&普中-4開發(fā)板原理圖.pdf
相關(guān)數(shù)據(jù)手冊
答辯技巧
設(shè)計報告常用描述
鼠標(biāo)雙擊打開查找嘉盛單片機51 STM32單片機課程畢業(yè)設(shè)計.url
資料下載鏈接:
https://docs.qq.com/doc/DS2pPenNRaHB6SlR1