产品选型

单片机等待 单片机的独立按键学习,实现60秒循环数字的启动暂停与清零

小编 2024-11-23 产品选型 23 0

单片机的独立按键学习,实现60秒循环数字的启动暂停与清零

想要学习单片机必须要准备单片机开发板一块,和单片机C语言版本的书籍,我会把每天录制视频的源代码到头条,并且录制相同文章名字视频到西瓜视频,如果你再学习独立按键这一块有不明白的地方可以点开我的头像,进入我的主页,点击视频观看学习。

目前视频录制了9个左右,没学过的结合书本,结合我的视频,都可以学会。

话不多说先上今天的仿真效果图:

然后下面是本仿真图的源代码:如果有错误,请大神指教。

#include<reg52.h> //头文件,把芯片的数据地址编译成C语言可以调用的句子。

#define uchar unsigned char //宏定义 把后面的长句 给他们一个新定义,实现同样的功能。

#define uint unsigned int //宏定义 把后面的长句 给他们一个新定义,实现同样的功能。

sbit dula=P2^0; //把p2.0给他一个新名字叫dula 用于数码管锁存器段选位置

sbit wela=P2^1;//把p2.1给他一个新名字叫wela 用于数码管锁存器位选的位置

sbit key1=P3^0; //同样的,给按键1和按键2分别找两个串行口来对接。

sbit key2=P3^1;

uchar code table[]={0x3f,0x06,0x5b,0x4f, //定义的一个数码管的编码表。

0x66,0x6d,0x7d,0x07, //阴极数码管

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71};

void delayms(uint); //延时子程序

void display(uchar,uchar); //显示子程序

void keyscan(); //独立按键子程序

uchar num,shi,ge,num1; //定义四个无符号字符

void main() //主程序

{

TMOD=0x01; //中断确定工作方式,和选择定时器0

TH0=(65536-45872)/256; //装初值,

TL0=(65536-45872)%256; //对这一块不太明白的,可以看我上一个视频

EA=1; //开启总的中断

ET0=1; ////开启定时器/计数器寄存器中断 开启中断具体定时器中断

while(1) //循环式判断,

{

keyscan(); // 调用按键子程序,对按键子程序进项不断地扫描

display(shi,ge);//调用显示子程序,对显示子程序,进行不断地刷新显示

}

}

void display(uchar shi,uchar ge) //显示子函数,并且调用形式参数

{

P0=0x00; //为了在仿真电路让P0口没有其他的数据来影响段选显示的/阴极数码管,高电平有效。让数码管变得干净。

dula=1; //锁存器开

P0=table[shi]; 把十位的数字送到P0

dula=0; //锁存器关闭// 段选位置

P0=0XFF; //低电平有效,让位选的位置变得干净。

wela=1; //位选锁存器开启。//低电平有效。

P0=0xfe;//送入位选的 选位。

wela=0; 位选锁存器关闭。

delayms(5); /延时5毫秒。

P0=0x00;

dula=1;

P0=table[ge];

dula=0;

P0=0xff;

wela=1;

P0=0xfd; //选择数码管的第一个位置 来显示数字

wela=0;

delayms(5);

}

void delayms(uint xms) //延时子程序

{

uint i,j; //定义两个无符号字符

for(i=xms;i>0;i--)

for(j=110;j>0;j--);

}

void keyscan() //今天的重点:按键扫描子程序

{

if(key1==0) //判断按键1 有没有按下

{

delayms(10); //延时10毫秒,延时去抖动

if(key1==0) //在判断一次按键1有没有按下

{

while(!key1); //等待按键释放,如果没有释放那么按键始终等于0,也就是低电平。按键按下去了,

TR0=~TR0; //定时器的开启与关闭,开启 开始计数,关闭就会暂停

}

}

if(key2==0) //判断按键2是否按下

{

delayms(10); //延时去抖动

if(key2==0) //再次判断

{

num1=0;// num1是送给数码管的数值,0-60根据定时器变化的值。

while(!key2);//判断按键2时候松开,没有松开始终等于低电平。

}

}

}

void T0_time() interrupt 1 //定时器的子程序

{

TH0=(65536-45872)/256; //重装初值,这一块如果听不懂,可以去看上个视频。

TL0=(65536-45872)%256;

num++;

if(num==20) //定时器每次50毫秒,这里加个20次的循环,用来凑足1秒钟。

{

num=0;

num1++;

if(num1==60) //给num1进行每一秒钟数值变化送数值。

num1=0;

shi = num1/10; //求模的数,送到shi

ge = num1%10;

}

}

单片机实例分享,射频卡流量监控系统

回想以前,学校浴室的收费标准是1.5元/次,每次可以持续洗一个小时,但是很多人洗澡的时间并不是很长,根本用不了一个小时,于是浪费水的情况便时有出现。我经常看到有些同学在浴室里洗衣服,所以这样的收费方式有滋生学生浪费习惯的弊端。为此我想到了通过改进浴室管理方案,修改计费方式,从而遏制大学生的浪费行为,这个系统可先在饮水机上进行测试。

我所在学校使用的“一卡通”是一张 IC 卡,用它可以到图书馆借书、到食堂就餐,学校还能通过IC卡获得使用者的详细信息等。我设想也可以利用IC卡对淋浴流量管理,每秒或者每几秒读取一次流量器的数据,再经过计算然后扣费,如果某个同学一直开启喷头,那么他一卡通内的钱也会随着流量的增加被更多地扣除。

我们设计的射频卡进行流量计费管理的系统具有以下优点。

(1)存储容量大。磁卡的存储容量大约在200个字符;IC卡的存储容量根据型号不同,小的有几百个字符,大的有上百万个字符。

(2)安全保密性好,不容易被复制,IC卡上的信息能够随意读取、修改、擦除,但都需要密码。

(3)IC卡具有数据处理能力。在与读卡器进行数据交换时,可对数据进行加密、解密,以确保交换数据的准确可靠;而磁卡则无此功能。

(4)使用寿命长,可以重复充值。

(5)IC卡具有防磁、防静电、防机械损坏和防化学破坏等能力,信息保存年限长,读写次数在数万次以上。

(6)IC卡能广泛应用于金融、电信、交通、商贸、社保、税收、医疗、保险等方面,几乎涵盖所有的公共事业领域。

设计思路

通过单片机对流量计、射频卡、电磁阀等实施控制。单片机会按照流量,对射频卡内的信息进行修改(修改余额信息,对其他信息无影响),单片机访问流量计的频率大约为3s访问一次,也就是,单片机每3s扫描一次流量计的数据,同时进行运算费用,然后修改射频卡内的信息(修改余额)。余额不足会通过12864液晶显示器显示。整个系统的设计框图如图19.1所示。

图19.1 整个系统同的设计框图

本系统的主控采用STC12C5A60S2单片机,该单片机是增强型51单片机,ROM高达61KB,运算速度是普通51单片机的8倍。STC12C5A60S2兼容51单片机的指令、引脚,而且该单片机具有A/D转换功能、高速低功耗、抗干扰等特点。电磁阀采用12V六分管通水电磁阀,直流持续式工作模式,工作压力在0.02~0.8MPa,介质温度在1~85℃。并且导体与非导体之间应能承受AC2500V电压,1min不击穿以及产生飞弧等现象。流量计采用六分管高精度水流量传感器,频率F=26×Q(Q表示流量,单位为L/min),内径3.0mm,流量范围0.5~5L/min。射频卡采用RFID读卡模块和EHUOYAN IC卡。

本系统的设计分为3个具体实施阶段。

第一个阶段,如图19.2所示,识别IC卡,读取IC卡信息,检查余额,满足条件后打开电磁阀,准备读取流量计数据。如果余额不足,则产生提示。

图19.2 第一阶段

射频卡相关知识

IC卡工作的基本原理是:射频读写器向IC卡发一组固定频率的电磁波,卡片内有一个LC串联谐振电路,其频率与读写器发射的频率相同,这样在电磁波激励下,LC谐振电路产生共振,从而使电容内有了电荷;在这个电容的另一端,接有一个单向导通的电子泵,将电容内的电荷送到另一个电容内存储,当所积累的电荷达到2V时,此电容可作为电源为其他电路提供工作电压,将卡内数据发射出去或接受读写器的数据。

IC卡的外形与磁卡相似,它与磁卡的区别在于数据存储的媒体不同。磁卡是通过卡上条的磁场变化来存储信息的,而IC卡是通过嵌入卡中的电擦式可编程只读存储器集成电路芯(EEPROM)来存储数据信息的。

作为电子货币的IC卡,其上记录有大量重要信息,安全性是很重要的,作为IC卡应用系统开发者必须为IC卡系统提供合理有效的安全措施,以保证IC卡及其应用系统的数据安全。影响IC卡及应用系统安全的主要方式有:使用用户丢失或被窃的IC卡,冒充合法用户进入应用系统,获得非法利益;用伪造的或空白卡非法复制数据,进入应用系统;使用系统外的IC卡读写设备,对合法卡上的数据进行修改,改变操作级别等;在IC卡交易过程中,用正常卡完成身份认证后,中途变换IC卡,从而使卡上存储的数据与系统中不一致;在IC卡读写操作中,对接口设备与IC卡通信时所作交换的信息流进行截听、修改,甚至插入非法信息,以获取非法利益,或破坏系统。常用的安全技术有:身份鉴别和IC卡合法性确认、指纹鉴别技术、数据加密通信技术等。这些技术采用可以保证IC卡的数据在存储和交易过程中的完整性、有效性和真实性,从而有效地防止对IC卡进行非法读写和修改。总体上,IC卡的安全包括物理安全和逻辑安全两方面。

物理安全包括:IC卡本身的物理特性上的安全性,通常指对一定程度的应力、化学、电气、静电作用的防范能力;对外来的物理攻击的抵抗能力,要求IC卡应能防止复制、窜改、伪造或截听等。常采用的措施有:采用高技术和昂贵的制造工艺,使之无法被伪造;在制造和发行过程中,一切参数严格保密;制作时在存储器外面加若干保护层,防止分析其中内容,即很难破译;在卡内安装监控程序,以防止处理器或存储器数据总线和地址总线的截听。

常用的逻辑安全措施有:存储器分区保护,一般将IC卡中存储器的数据分成3个基本区:公开区、工作区和保密区;用户鉴别,用户鉴别又叫个人身份鉴别,一般有验证用户个人识别PIN、生物鉴别。

卡片有着16个扇区,每个扇区包含4个数据块,每个数据块具有16byte的存储容量。扇区被定义为扇区0~扇区15,数据块被分为数据块0~数据块3,整个卡共有64个数据块。

每个扇区的密码和存取控制都是独立的,可以根据实际需要设定各自的密码及存取控制。存取控制为4个字节,共32位,扇区中的每个块(包括数据块和控制块)的存取条件是由密码和存取控制共同决定的。

第二个阶段,如图19.3所示,首先采集流量计数据,然后流量计产生的脉冲通过单片机计数。目前市场上常见的流量计是1L水共输出450个脉冲。1L水的质量是1kg,一个脉冲大概是2.2g水,利用单片机对脉冲数进行计数,每过一个脉冲扣除一定费用(单价×2.2即可)。实时监测IC卡内余额,如果余额不足,则触发单片机中断,等待关闭电磁阀,延迟1min后关闭电磁阀。

图19.3 第二阶段

第三阶段,如图19.4所示,监测IC卡状态,如果未识别到IC卡,则关闭电磁阀(防止使用者不关喷头直接拔卡)。

图19.4 第三阶段

制作过程

表19.1 制作所需材料

制作所需材料见表19.1,整个系统的电路图和PCB如图19.5所示。

图19.5 电路图和PCB图

PCB图是外加工的,需要注意的是,图中长方形白色框体是射频卡模块,尺寸可根据购买的射频卡模块尺寸进行修改。焊接电路板时,遵循“先贴片后插件,先低后高,先小后大”的原则,这样做会让你事半功倍,按照电路图焊接完成并通电之后的的系统可以进行简要的操作(见图19.6~图19.9)。

图19.6 驱动12864,没有用户,等待模式

图19.7 读到卡了,显示姓名、学号、钱包

图19.8 随着流量计脉冲个数增长,单片机进行计费,同时进行扣款操作,操作完毕显示当前余额

图19.9 用户移走卡,蜂鸣器长鸣一声,提示卡已移走

简单的测试之后,下位机就制作完成了,接下来就是进行上位机的编写,上位机(改变姓名、充值、初始化等操作依赖于模块)是用于改变射频卡信息的PC软件,我使用C#语言编写,第一次编写上位机软件,虽然界面很普通,但是功能还是比较完备的(见图19.10~图19.12)。

图19.10 没选择串口前所有的都是灰色表示不可操作

图19.11 选择串口后,按钮可操作更改框可以进行改写

此制作需要用到的射频卡通信设备(此设备需要和上位机搭配使用)如图19.13所示,设备上面黄色的纸是打印的,然后用双面胶贴上去,内部使用一个USB转TTL模块以及一个射频卡读写卡模块。

图19.12 单击读卡按钮后的显示

图19.13 此制作需要用到的的射频卡通信设备

程序部分

按照设计的流程图编写程序,由于程序过多,我不一一附上,只截取部分进行说明。下列程序是本制作要用到的命令数组、处理数组、显示数组等程序,也是上位机和下位机都需要的部分,需要注意的地方是,数组的个数和串口发送与接收命令的长度一定要搭配,否则会出错。比如某个命令的返回值的数组大小为10,如果我们在写串口中断处理函数的时候,没注意接收的个数,写成了9,那么处理函数会一直等待最后一个数,才满足跳出函数的条件,当然,你可以写个报错的函数,调试完成后关闭它。

//search card and get card serial number

uchar xdata ComSearchCard[5] = {0xAA,0xBB,0x02,0x20};// 寻卡,返回AA BB 06 20 92 BF 72 59 20

//read block No.x

uchar xdata ComReadBlock[13] = {0xAA, 0xBB, 0x0a, 0x21, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};// 读哪一块,第6位就是0x0几

//read block No.8

//uchar ComReadBlock6[13] = {0xAA, 0xBB, 0x0a, 0x21, 0x00, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

// write block No.8 with 0x01 to 0x0f

uchar xdata ComWriteBlock[29] = {0xAA, 0xBB, 0x1a, 0x22, 0x00, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,//0xff 是密码

0x02, 0x00, 0x01, 0x01, 0x00, 0x07, 0x00, 0x01,//

0x04, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00};// 要写的数据

//initialize block No.8 as a purse

uchar xdata ComIntiPurse[17] = {0xAA, 0xBB, 0x0e, 0x23, 0x00, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 0x00, 0x00};//初始化钱包。分区5为钱包

//read purse value of block No.5

uchar xdata ComReadPurse[13] = {0xAA,0xBB,0x0a, 0x24, 0x00, 0x05,0xff, 0xff, 0xff, 0xff, 0xff, 0xff};// 读取分区5的钱包 返回4字节的数据

// purse in block No.5 increase with value“2”

uchar xdata ComIncrPurse[17] = {0xAA,0xBB,0x0e, 0x25, 0x00, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //增加钱包的余额

0x01, 0x00, 0x00, 0x00};//要增加的值

// purse in block No.5 decrease with value“1”

uchar xdata ComDecrPurse[17] = {0xAA,0xBB,0x0e, 0x26, 0x00, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,//扣费

0x01, 0x00, 0x00, 0x00};//要减少的值

提取数据的数组:

uchar xdata user_block8[12]={0}; //学号(8位)

uchar xdata user_card[4]={0}; //卡号

uchar xdata user_cash[4]={0}; //现金

uchar xdata user_name[6]={0}; //姓名

程序中有一个举足轻重的“指令选择”函数,由于程序太长,就不附上,有兴趣的朋友可以到我的QQ群下载。这个函数是一个带返回值的函数,整个系统的命令都由这个函数发出。下面的解释一目了然,以后如果需要升级本系统,在这个函数内部添加命令即可。

指令选择入口函数:

输入:j 1~8

输出:1或0

功能概述:

a. 确认返回数组的正确性(数组最后一个数据的异或校验以及数组的长度)。

b. 序号说明:

(1)寻卡,返回射频卡序列号;

(2)读取某个模块的值,返回16位数值;

(3)写某个模块,返回成功命令;

(4)初始化钱包,即定义制定射频卡分区为钱包返回成功命令;

(5)读取钱包的值;

(6)增加钱包的值;

(7)减少钱包的值;

(8)返回增加、减少后钱包的值。

由于这个制作的初步设想是在学校里使用的,因此价格基本稳定,就没有给管理员权限使用输入设备更改资费。更改资费需要改动源代码,当然,做成产品肯定需要设计输入设备,由于本次制作的用户就是我,所以就简化了。

更改资费的程序段如下:

EX0 = 0;

countflag = 0;//脉冲标志清零

feetemp = 0x01;//这里是扣的金额

feecount = feecount + feetemp;//计算使用总额,需要显示也可以显示的

ComDecrPurse[12] = feetemp;//写入扣钱金额

j = Command_choic(7);//100个脉冲减少一分钱

关于脉冲个数与消费金额关系的问题,在外部中断里去修改一下就好了,建议大家使用宏定义,直接在顶部修改。

count++;

if (count == 1) //这里更改脉冲个数

{

countflag = 1;

count = 0;

}

注:之所以使用双串口单片机是有原因的,因为一边要和模块通信,一边要打印出来数据观察是否正确,所以要使用两个串口,当然,此制作我用串口2与模块通信,这也是为什么用12C5A60S2的原因。

流量管理系统制作好了,现在就试着将它搭建到饮水机上进行测试。总的来说,就是先断开饮水机的水管,把电磁阀和流量计串连进去,再连接上即可。但连接的时候需要用一些胶布,以防止漏水,并避免饮水机发生漏电危险。

总结

此制作的射频卡读取模块,使用的是串口协议,它的所有命令都是以“AA BB”开头,最后一位数据是前面除开头以外的异或结果,串口收数据的时候本来就不知道收多长,这个版本的模块没有解决这个问题。例如,寻卡的命令是“AA BB 02 20 22”,“AA BB”为开头,22是前面02和20的异或结果。因此推荐大家使用其他协议,其他协议可以自己规定头和尾,检测的时候非常方便,当然也纯属个人意见。

相关问答

单片机 用while(1); 等待 中断?

过程是这样的:程序一直在while(1)里面,直到定时器计满产生中断;产生中断后,执行中断服务程序(中断中大部分是有重新对定时器赋值的命令的)中断程序完成后回...

单片机 AD中断太频繁怎么办?

可以用以下办法:如果单片机没有其他工作的时候,可以用循环等待的方式等AD转换结束(转换结束后DONE位会被置位)。但如果你的单片机还有其他工作,那就没必要...

32 单片机 怎么设置20毫秒的延时?

要实现20毫秒的延时,可以使用定时器来实现。首先需要配置定时器的时钟源和分频系数,使得定时器的时钟频率为1MHz。然后设置定时器的计数值为20000(即20毫秒的...

为何 单片机 进入休眠时容易死机?

2.这是因为单片机在进入休眠状态时,会停止运行主程序,只保留一些必要的电路和功能。在这个过程中,如果出现了一些异常情况,比如电压波动、外部干扰等,单片...

51 单片机 怎么休眠 - 04535败笔 的回答 - 懂得

呵呵,最近刚好研究了一下这个问题51单片机空闲和掉电模式应用我们知道单片机内部有一个电源管理寄存器PCON,这个寄存器的最低两位,IDL和PD这两位...

AT89S51 单片机 的P1.0~P1.3接四个发光二极管, P1.4~P1.7接四个开关.编程反应对应关系?

ORG0000HMOVP1,#0FFH//低四位LED全灭,高四位送“1”等待开关按下ABC:MOVA,P1//把P1送入ASWAPA//A高四位和低四位互换,反...ORG000...

单片机 烧不进程序一般是什么問題-ZOL问答

单片机坏了,或者引脚与插座接触不良都可能烧录不进程序。有用(0)回复q88362...STC的芯片在上电后首先进入BOOT段程序,如果不需要下载,在等待了很小一段时间后...

单片机 rst是什么?

就是引导内部复位程序或电路。可以看到SFR的复位值,同时等待时钟电路稳定工作,提高抗干扰能力,提供一种有效的重启方式,目的就是单片机重生。就是引导内部复...

单片机 问题:用一个按键控制一个灯,按一下,灯亮,再按一下,灯灭。只能用P3口,汇编语言如何写这个程序?

ORG00HSAT:JBP3.1;等待按钮按下ACALLDELAY;延时,避开按钮毛刺JNBP3.1;等待按钮松开ACALLDELAY;延时,避开按钮毛刺CPLP3.0;灯状态取反JMPSAT;延时程...

flymcu如何烧录51 单片机 ?

要使用flymcu烧录器烧录51单片机,可以按照以下步骤进行操作:1.连接flymcu烧录器和电脑,确保设备驱动程序已正确安装。2.打开flymcu烧录器软件,选择“芯片...

猜你喜欢