【普中】基于51单片机的7人多数投票表决器设计
( proteus仿真+程序+设计报告+讲解视频)
仿真图proteus8.16(有低版本)
程序编译器:keil 4/keil 5
编程语言:C语言
设计编号:P13
1.主要功能:
基于51单片机AT89C51/52(与AT89S51/52、AT89C51/52、STC89C51/52等51内核单片机通用)
具体功能:
(1)设定矩阵键盘的14个键作为7位投票人的按键,其中每人2个键,分别作为“赞成”键和“反对”键;设定1个独立按键作为投票开始键;设定两个数码管用于显示计时信息,两个数码管用于显示“赞成”及赞成数,两个数码管用于显示“反对”及反对数。
(2)只有当主持人按下开始键时才可进行投票,否则不接收投票按键的信息。
(3)当投票开始键按下时开始10秒倒计时,此时数码管显示倒计时信息,同时“赞成”键或“反对”键每按一下,相应的数码管显示A(赞成)及赞成累加数或O(反对)及反对累加数,倒计时结束即投票结束。
(4)投票开始键按下(即开始投票)和倒计时结束(即投票结束)时蜂鸣器响一声,数码管显示的结果即为最终投票的结果。7票中,“赞成”票≥4票表示通过,此时,计时数码管显示“P”;否则为不通过,计时数码管显示“F”。
(目前仅完全适配普中开发板A234,其他普中开发板型号可能需要做代码修改或接线)
需注意仿真中51单片机芯片是兼容的,AT89C51,AT89C52是51单片机的具体型号,内核是一样的。相同的原理图里,无论stc还是at都一样,引脚功能都是一样的,程序是兼容的,芯片可以替换为STC89C52/STC89C51/AT89C52/AT89C51等51单片机芯片。
讲解视频:
仿真讲解+实物演示+代码讲解
2.仿真
开始仿真
打开仿真工程,双击proteus中的单片机,选择hex文件路径,然后开始仿真。
系统开始运行,主持人按下开始按键,蜂鸣器发给“滴滴”声,数码管的第3,4位开始进行10s的倒计时。如图5-1所示,数码管倒计时显示倒计时到了9s时的图形。
图5-1 系统开始运行
系统运行中,主持人可以紧急情况下重新表决,表决人可以按下自己对应的按键进行表决,当表决人按下自己的按键后,他自己对应的投票权失效不能再投票。如图5-2所示,数码管倒计时到1s的时候,有五位表决人按下了自己的表决按键,分别是两票赞同,三票反对。
图5-2 系统运行中的图
系统运行结束后,数码管不再显示倒计时的数据,数码管的第四位会显示表决是否通过,通过即显示P,不通过即显示F。表决结束要开始新的表决主持人可以按下复位按键进行下一次的表决。如图5-3所示,10s倒计时结束,数码管的第四位显示为F,则说明有低于4人同意表决。
图5-3 系统运行结束图
3. 程序代码
使用keil4或者keil5编译,代码有注释,可以结合报告理解代码含义。
#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; //数码管位选
//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; //中断次数
u8 jieshu=0; //复位
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) //延时函数
{
u16 i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
void display() // 定义一个名为display的函数,用于控制数码管显示
{
P0=0x00; // 将P0口设置为0x00,即关闭所有段(清零,可能为了消隐效果)
P0=led[duia]|0x80; // 将led数组中对应duia索引的值与0x80进行或操作后输出到P0口,0x80通常用于开启小数点
P2=table[7]; // 设置P2口为table数组的第7个元素的值,可能用于选择数码管的位选
delay(2); // 延时2毫秒,确保数码管稳定显示
P0=0x00; // 再次关闭所有段,准备显示下一位
// 以下代码重复上述过程,分别显示AA的十位、个位,jishi(计时)的十位、个位,
// 以及BB的十位、个位,利用led数组和table数组配合P0和P2口实现数码管的动态显示。
// 每次显示前都会关闭所有段以清除上一次的显示,然后设置相应的位选和段选,最后延时确保显示稳定。
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,并开启该位的小数点
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() //数码管显示,投票结束显示
{
P0=0x00;
P0=led[jj];
P2=table[4];
delay(2);
}
void t0(void) interrupt 1 //定时器0中断服务程序
{
TH0 = (65536-20000)/256; //20ms计时初值
TL0 =(65536-20000)%256;
cnt++; //溢出次数加1
if(cnt == 50) //时长达到1秒
{
cnt = 0;
jishi--; //时间减1
if(jishi==0)
{
TR0=0; //关闭定时器0
jieshu=1; //结束标志位
TR1=1; //打开定时器1
flag=0; //开始标志位清零
}
}
}
void t1(void) interrupt 3 //定时器1中断服务程序
{
TH1 = (65536-1000)/256; //1ms计时初值
TL1 =(65536-1000)%256;
cnt1++; //溢出次数加1
cnt2++; //溢出次数加1
if(cnt1 == 1)
{
cnt1 = 0;
beep=~beep; //蜂鸣器报警
}
if(cnt2 == 100) //蜂鸣器关闭
{
cnt2 = 0;
TR1=0;
beep=1;
}
}
void delay_uint(u16 i)//延时
{
while(i--);
}
// 定义一个函数用于扫描矩阵键盘并返回按键值
u8 Matrix_buttons_scan(){
u8 i, j; // 定义变量i和j分别存储行列索引
i = 0;
j = 0;
// 设置P1端口的低四位输出为0,高四位保持不变,准备读取键盘列信号
P1 = 0x0f;
// 判断是否有键被按下(即P1端口的值不全为0x0f)
if(P1 != 0x0f) {
// 延时去抖,等待10ms再次检测,确保按键稳定
delay_uint(10000);
// 再次检查,确认按键确实被按下
if(P1 != 0x0f) {
// 根据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行
}
// 设置P1端口的高四位输出为0,低四位保持不变,准备读取键盘行信号
P1 = 0xf0;
// 根据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;
}
}
//按键扫描子函数
void keyscan()
{
u8 i=0;
if(kk1==0) // 开始按键
{
delay_uint(100);
if(kk1==0){
if(flag==0){//开始投票
TR0=1;//开启定时器0
flag=1;//标志位写1,开始投票
TR1=1;
jishi=TIME_CNT;//重写定时时间
AA=BB=0;//清0赞成和反对票
while (kk1==0){}//等待松手
}else{//复位
TR0=0;
flag=0;
TR1=0;
jieshu=0;
jishi=TIME_CNT;
AA=BB=0;
memset(state,0,sizeof(state));//数组清零
while (kk1==0){}//等待松手
}
}
}
if(flag==0){//未开始不扫码矩阵按键
return;
}
i=Matrix_buttons_scan();//按键检测
if(i==1)
{
if(state[0]==0)BB++; //1号反对票
state[0]=1; //清除1号投票权
}
else if(i==2)
{
if(state[0]==0)AA++; //1号赞同票
state[0]=1; //清除1号投票权
}else if(i==3)
{
if(state[1]==0)BB++; //2号反对票
state[1]=1; //清除2号投票权
}else if(i==4)
{
if(state[1]==0)AA++; //2号赞同票
state[1]=1; //清除2号投票权
}else if(i==5)
{
if(state[2]==0)BB++; //3号反对票
state[2]=1; //清除3号投票权
}else if(i==6)
{
if(state[2]==0)AA++; //3号赞同票
state[2]=1; //清除3号投票权
}
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. 设计报告
5676字设计报告,内容包括目录,硬件设计、软件设计、软硬件框图、调试、结论等
表决器的实现主要涉及开始表决的控制、表决的方案、状态的指示、倒计时时间和表决同意人数及表决是否通过的显示。首先,倒计时时间与表决同意人数及表决是否通过的显示,可使用液晶屏或者数码管来实现,倒计时时间为 10s,表决人数为7人,则一共需要显示8位数,使用数码管比较简便。一般选用七段数码管显示器,其应用简单、可靠性高、成本低,可用于显示输出。由于有8位数字需要显示,使用两个4位数码管。
数码管可使用静态或者动态显示,很明显,动态显示能够满足本设计的需求。段选与位选信号可由单片机的I/O口直接提供,或者可使用锁存器间接获得。只要单片机的驱动电流足够,便可以直接控制数码管,但这样会占用很多单片机的端口,也可以使用锁存器既能节约单片机端口,又能增加驱动电流,选择使用锁存器驱动数码管,这样也可简化软件编程。状态指示包括显示当前处于表决的哪个环节,以及哪位表决人成功等提示,可选用蜂鸣器、发光二极管等来指示,发光二极管更能持续、鲜明地指示当前状态,因此选择使用发光二极管来指示当前状态。抢答开始或结束的开关,以及表决人表决设备均可使用按键,这样比较简单方便。整个方案中使用了很多的I/O口,并且系统的逻辑比较复杂,整个系统的软件设计可采用查询的方式,由各函数完成各自的功能。
5. 设计资料内容清单&&下载链接
资料设计资料包括仿真,程序代码、讲解视频、功能要求、设计报告、软硬件设计框图等。
0、常见使用问题及解决方法–必读!!!!
1、仿真图
2、程序源码注释
3、功能要求
4、开题报告
5、设计报告
6、软硬件流程框图
7、烧录工具
8、讲解视频
9、实物图
Altium Designer 安装破解
KEIL+proteus 单片机仿真设计教程
KEIL安装破解
Proteus安装
Proteus简易使用教程
单片机学习资料
普中-2&普中-3&普中-4开发板原理图.pdf
相关数据手册
答辩技巧
设计报告常用描述
鼠标双击打开查找嘉盛单片机51 STM32单片机课程毕业设计.url
资料下载链接:
https://docs.qq.com/doc/DS2pPenNRaHB6SlR1