51单片机频率计.docx
- 文档编号:12570648
- 上传时间:2023-04-20
- 格式:DOCX
- 页数:18
- 大小:1,001.91KB
51单片机频率计.docx
《51单片机频率计.docx》由会员分享,可在线阅读,更多相关《51单片机频率计.docx(18页珍藏版)》请在冰豆网上搜索。
51单片机频率计
实验报告
实验名称基于8255的8LED数显频率计
课程名称Protues软件设计(51单片机)
班级学号
姓名
一、实验要求
基本要求:
用P1或P3口,产生一方波信号,频率为1000Hz,用一组数码管或LCD显示频率和周期以及脉宽等参数(也可用信号源或模拟信号源)。
将输出信号输入到另一端口(INT0/INT1)作频率计的信号输入端,测量此方波信号的频率、周期和脉宽,在另一组数码管或LCD上将参数值显示出来。
(刷新时间1秒)o
发挥部分:
1、设置一功能键,能将当前数码管或LCD上的信号参数值锁定。
2、通过键盘,可修改方显示参数,刷新时间。
3、按键时,蜂鸣器发出提示音,表示按键有效
4、用图形方式显示输入波形(用模拟示波器)动态显示格式:
自定
二、实验内容
实验内容为基于8255的简易8LED数字显示频率计,利用8255的扩展功能,来扩展51单片机的功能管脚,使其可以实现利用8255的A,B端口实现输入输出功能,从而实现51单片机管脚的扩展。
三、实验原理
频率计主要功能是测量频率。
频率是指一秒内发生相同波形的次数,根据这一定义,可以初步得出测量频率的方法,就是通过计量一定时间的脉冲次数就可以通过计算累加获得频率的次数,然后通过数值译码输送的数显电路当中去。
根据实验假设,可以知道实验中需要用的两个定时装置,一个为定时装置,另一个为计数装置。
而单片机中正好就设置了这样的计时器。
8051提供两个16位的内部定时器(计数器),分别为Time0,Time1(简称T0,T1)这两个定时器可以用作为内部定时器或者外部计数器,作为内部计时的时候是计算的是内部的脉冲,以12MHz的计时脉冲系统为例,将此计数器时钟脉冲除12后送入定时器,因此定时器所计数的脉冲周期为1us。
若采用16位的
定时器,最多可以计数65536,约为0,065&因而我们选择0.05S作为单位计数时间长度。
若当成外部计数器时则计数由T0或T1管脚送入脉冲,同样地,若采用16位的定时模式,则最多可以数65536个计数量,相当可观。
在51单片机中有两个16位的定时/计数器T0,T1,分别由TH0、TL0和TH1、TL1组成,它们均是8位寄存器,在特殊功能寄存器中占地址8AH-8DH。
它们用于存放定时或计数的初始值。
此外,内部还有一个8位的方式寄存器TMOD和一个8位的控制寄存器TCON。
用于选择和控制定时/计数器的工作。
其格式见下面两表:
方式控制寄存器TMOD
GATE
C/T
M1
M0
GATE
C/T
M1
M0
门控开关
计数/定时
方式选择
门控开关
计数/定时
方式选择
TCON控制寄存器
TF1
TR1
TF0
TRO
IE1
IT1
IE0
IT0
T1请求有/无
T1工作启/停
T0请求有/无
T0工作启/停
INT1请
求有/无
INT1方
式下沿
INT1请
求有/无
INT1方
式下沿
根据定时时间要求或计数要求计算计数器初值;
将工作方式控制字写入TMOD寄存器;
将计数初值写入THX和TLX寄存器;
启动定时器/计数器,即将TRX置位。
如果工作于中断方式,需置位EA(中断总开关)及ETX(允许定时/计数器中断),并编写中断服务程序。
实验当中规定要求为使用INT0/INT1作频率计的信号输入端,所以启用的是外部中断来执行计数过程。
外部中断有INTO和INT1两个,CPU通过两个外部引脚即可接受外部中断的请求。
外部中断信号的采样方式可分为电平触发(低电平)以及边缘触发(负边沿触发)两种。
若采用电平触发,需要将TCON寄存器中的IT0(或IT1)设定为0,则只要INTO引脚为低电平,视为外部中断要求。
若采用边缘触发,需要将TCON寄存器中的IT0(或IT1)设定为1,则只要INTO引脚的信号由高电平转为低电平,则视为外部中断需求。
这些中断需求将反映在IE0(IE1)里,若IE寄存器
的EX0(或EX1)=1,且EA=1,CPU则进入我们设定好的中断程序。
IE中断启用寄存器
IE7
IE6
IE5
IE4
IE3
IE2
IE1
IE0
EA
ES
ET1
EX1
ET0
EX0
显示单路部分,因为要求使用8LED数码管显示电路,所以只用对数码管分别送入数据信号和扫描信号即可。
显示原理如图所示
所以利用8255分别写入数据和扫描信号既可以是其产生所要显示的内容8255的控制字的设置也有不少问题需要解决,
图九28255A编程模型
需要对8255A进行控制字的写入
图扎3方式控制字
根据设计的电路我设计的控制字为
D8255=0x80;
设定的各端口的地址为
#defineA8255XBYTE[OxfffO]
#defineB8255XBYTE[0xfff1]
#defineC8255XBYTE[0xfff2]
#defineD8255XBYTE[0xfff3]
四、设计思路及设计流程图
基本上可以分为三个阶段,第一阶段为读取外部指令,为测量频率,测量周期,测量脉宽。
我采用了P1端口的P1.0,P1.1P1.2三个管脚来作为外部指令的输入方式。
主程序流程图
测量函数部分我使用的是利用外部中断INTO管脚输入信号,设置为负边沿触发,利用
此来触发外部中断子程序voidEX_INT0()interrupt0。
同时计时器开始0.05s的计时程序,当
计时次数满二十次的情况是正好满1S则锁存实验所得数据然后送进显示电路进行显示。
中断程序部分为:
voidEX_INT0()interrupt0
{
countA++;
}
若要做的便是将CountA的数值在计时中断满二十次时进行锁存而后输出即可
频率测量函数流程图
因为测量数据分为测量周期还有测量脉宽等部分,对于周期测量我是对测量的频率值进行了一定的内部处理利用
周期=1/频率
这一特性进行的计算。
对于脉宽的测量也是建立在这一基础之上。
发生程序我嵌套在主程序中的扫描函数当中,当对主程序进行循环的是时候
如果检测到有按键操作则启动发生程序
voidPlay(chart)
chari;
for(i=0;i<120;i++)
{
BEEP=~BEEP;delay(t);
}
BEEP=0;}
五、实验成品
通过protues进行仿真程序,连接各电路,下图为运行后的初始画面
程序共有三个外部按键,从上往下依次为频率,周期,脉宽。
以下分别为设定外部输入信号
为1kHz的周期信号,所得到的实验画面
1000
此图为按下第三个按键后的效果图脉宽为500us
500U5
六、实验代码
#include
#include
〃******定义8255控制端口以及ABC端口的地址#defineA8255XBYTE[OxfffO]
#defineB8255XBYTE[0xfff1]
#defineC8255XBYTE[0xfff2]
#defineD8255XBYTE[0xfff3]
#define
ucharunsingedchar
#defineuintunsignedint
//*******
输入按键操作********
sbitPB0=P1A0;
sbitPB1=P1A1;
sbitPB2=P"2;
sbitBEEP=P3A0;
chardisbuffer[8]={0,1,2,3,4,5,6,7};
charTAB[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,};
〃0x83改为0x82修正了数字6的显示问题
charchocode[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
//charchocode[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
charcodevalue[8]={0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0};
〃最初没有取反,后来前后次序乱使数据原本为12345678变为87654321
#definecount_M150000
#defineH_0(65636-count_M1)/256
#defineL_0(65636-count_M1)%256
chartimes=0;
bitstatus_F=1;
//charscan=1;
unsignedlongintfreq=11;
unsignedlonginttime=0;
unsignedlongintcountA=0;
unsignedlongintmk=0;//设计处为短型,所以导致程序运行不正常
sfr16DPTR=0x82;
voiddelay(int);
voiddisplay(void);//显示函数;
voidmeasureA(void);
voidmeasureTT(void);
voidmeasureMK(void);
voiddelay(intx)
{inti;intj;
for(i=0;i } //*********发声程序*********奇怪的现象,当T0接输入时,喇叭会自动的响voidPlay(chart) { chari; for(i=0;i<120;i++) { BEEP=~BEEP; delay(t); } BEEP=0; } 〃测量频率主函数 main() {P仁Oxff;//设定P1端口的初始值防止外部干扰 D8255=0x80; while (1) { if(PB0==0) {Play (1); status_F=O; measureA(); while(status_F==O); } if(PB1==0) {Play (2); status_F=0; measureA(); while(status_F==0);measureTT(); } if(PB2==0) {Play(3); status_F=0; measureA(); while(status_F==0);measureMK(); } elsedisplay(); } } //测频率使用外部中断 voidmeasureA(void) { IE=0x8f; TMOD=Ox51; TH0=H_0; TL0=L_0;countA=O; IT仁1; IT0=1; PX0=1; TR0=1;TR1=0;} //************ 外部中断intO****计时程序*** voidEX_INT0()interrupt0{ countA++; //display。 ; } //********T0一 一秒时间中断************** voidT0_1S(void)interrupt1 {TH0=H_0;TL0=L_0; if(++times==20) {times=0; TR1=0;TR0=0; 〃DPL=TL1;DPH=TH1; freq=countA; codevalue[7]=TAB[freq/10000000];codevalue[6]=TAB[(freq/1000000)%10];codevalue[5]=TAB[(freq/100000)%10]; codevalue[4]=TAB[(freq/10000)%10]; codevalue[3]=TAB[(freq/1000)%10]; codevalue[2]=TAB[(freq/100)%10]; codevalue[1]=TAB[(freq/10)%10]; codevalue[0]=TAB[(freq%10)]; status_F=1; } } //* ********* 测量周期 ************ voidmeasureTT(void) {time=1000000/freq; codevalue[1]=0xc1;codevalue[0]=TAB[5]; codevalue[7]=TAB[(time/100000)%10];codevalue[6]=TAB[(time/10000)%10]; codevalue[5]=TAB[(time/1000)%10]; codevalue[4]=TAB[(time/100)%10]; codevalue[3]=TAB[(time/10)%10]; codevalue[2]=TAB[(time%10)]; //* ****** 测量脉宽******* voidmeasureMK(void) {mk=500000/freq; codevalue[1]=0xc1; codevalue[0]=TAB[5]; codevalue[7]=TAB[(mk/100000)%10]; codevalue[6]=TAB[(mk/10000)%10]; codevalue[5]=TAB[(mk/1000)%10]; codevalue[4]=TAB[(mk/100)%10]; codevalue[3]=TAB[(mk/10)%10]; codevalue[2]=TAB[(mk%10)]; } voiddisplay(void) { chari,p,temp; 0xc0进行比较因为类型不同所 if(codevalue[7]==TAB[0])〃不能拿codevalue直接和 以不能比较儿赋值的时候则不同! ! ! { codevalue[7]=0xff;if(codevalue[6]==TAB[0]){codevalue[6]=0xff;if(codevalue[5]==TAB[0]){codevalue[5]=0xff;if(codevalue[4]==TAB[0]){codevalue[4]=0xff;if(codevalue[3]==TAB[0]){codevalue[3]=0xff;if(codevalue[2]==TAB[0]){codevalue[2]=0xff;if(codevalue[1]==TAB[0]){codevalue[1]=0xff;if(codevalue[0]==TAB[0]){codevalue[0]=0xc0;}}}}}}}} for(i=0;i<8;i++) { p=disbuffer[i];temp=chocode[p]; B8255=~temp;temp=codevalue[p];A8255=temp; //delay (1);〃多余的延时程序 temp=chocode[i]; B8255=~temp; delay (1); } } 七、实验体会和意见 在实验过程中遇到了很多很多的问题,刚开始拿到这个实验题目的时候基于8255的 8Led的数显频率计,首先想到的8255是什么东西,想起8255是大二时的前续课程中《微 机原理》中所讲过一章的内容中有所提及,8255为并口扩展芯片,可以编程,共有多种写 入方式。 关于8255的8Led的输入输出查阅了很多的资料,后来在一些书籍当中查阅到了相关有用信息,连接中加入了一块74373锁存芯片,可以对输入的数据进行锁存,这样就解 决了控制字的问题,因而就不需要再设定控制字。 在设计数显电路时遇到的问题还有很多由于先扫描还是先输出数据的问题上颠倒了次序,导致数码管显示非常的不正常。 调换次序后该问题得到了解决,据我分析应该是数据重 叠。 实验初期因为没有看清题目要求使用的是T0,T1中断既P3.5口作为外部信号输入端口 进行测量,且同样实现了显示频率脉宽的功能。 因而对于内部中断的执行也有了深入的理解, 因为题目问题是后来最后两天才发现的,所以更改比较唐突,所以该程序仍拥有很多问题。 比如测周期使用的是利用所测频率进行数值运算所得到的值,所以运算速度需要一秒左右,比较慢,而且脉宽的测量并非准确。 通过本次试验对于单片机有了一定深度的了解,对于内部各种中断,端口地址,输入输 出,寄存器的读写都有了一定的了解。 觉得单片机是一门学科,同时设计的时候也是一门艺 术。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 51 单片机 频率计