《单片机C语言应用技术》课件-第7章_第1页
《单片机C语言应用技术》课件-第7章_第2页
《单片机C语言应用技术》课件-第7章_第3页
《单片机C语言应用技术》课件-第7章_第4页
《单片机C语言应用技术》课件-第7章_第5页
已阅读5页,还剩25页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

模块7综合应用任务14简易数字频率计的设计习题7实践中,单片机应用系统的设计往往涉及到多方面的知识,从最基本的元器件的选用到硬件线路的设计,程序的编制,各种芯片的选用,相应的驱动程序的编写,系统调试等。本模块中的任务应用前面所学知识,制作一个简易的数字频率计。任务14简易数字频率计的设计电子技术中,频率是最基本的参数之一,并且与许多电参量的测量方案、测量结果都有十分密切的关系,因此频率的测量就显得更为重要。测量频率的方法有多种,其中数字式频率计具有精度高、使用方便、测量迅速,以及便于实现测量过程的自动化等优点,是频率测量的重要手段之一。电子计数器测频有两种方式:一是直接测频法,即在一定闸门时间内测量被测信号的脉冲个数;二是间接测频法,如周期测频法。直接测频法适用于高频信号的频率测量,间接测频法适用于低频信号的频率测量。本任务使用51单片机制作一个简易的数字频率计,采用直接测频法。基本思想如下:使用一个定时/计数通道控制测量闸门时间,使用另外一个定时/计数通道计数信号的脉冲个数,从而求出信号频率。这样的设计方案简单易行,但是局限也很明显。由于使用51单片机的定时/计数通道计数信号的脉冲个数,因此被测信号的频率受限于51单片机的工作频率。51单片机的定时/计数通道的最大计数频率等于单片机的工作频率除以24,如果单片机的工作频率为12MHz,则可以测量的信号最大频率不超过12MHz/24,也就是500kHz。由于信号直接输入到单片机的计数引脚(P3.4或P3.5),因而只能测量TTL信号。尽管如此,由于本任务涉及到单片机多方面的技术,因而对于我们熟悉单片机的综合应用是很有帮助的。

1.任务目的全面了解51系列单片机的结构,提高综合应用单片机的能力。

2.任务要求

实现一个小系统,可以测量TTL信号源的频率,其频率不超过500kHz,并在LED灯上显示出来。为了方便实验,另外实现一个小系统,用于产生被测信号。

3.硬件设计硬件上,测量频率的部分相当简单,实际上除了单片机,不再需要其他的附加电路。需要一个6位的LED灯用于显示测量到的频率。频率计部分采用6个LED灯用于显示频率,具体电路设计如图7.1所示,P0口的8个输出引脚分别接到了LED灯的8段引脚上,P2的低6位连接至LED灯的6个位段上。用P1连接了8个流水灯。信号产生部分中,在P3.6和P3.7上分别连接了2个独立按键,用来增加或减少信号频率。为了简洁,电路图中去掉了单片机电源部分的电路。图7.1频率计及信号产生器电路原理图

4.程序设计程序分为两大部分:频率计部分和信号发生部分。

1)频率计部分的程序频率计部分的程序包括LED驱动部分、定时计数器部分和主程序。下面给出的是LED驱动程序。

(1) Led.h头文件。

#ifndef led_h

#define led_h

#defineLed_PinsP0

#defineLed_Controls_PinsP2

voidLed_Show();

voidLed_LongToBeDisplayed(longnum);

voidLed_Delay(unsignedcharnum);

#endif

(2) Led.c代码文件。

#include<reg51.h>

#include"Led.h“

//定义字形码,放在code区。最后一个编码是全灭(不显示)

staticunsignedcharcodecharCodes[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x0};

staticunsignedcharcodecharPointers[]={0xdf,0xef,0xf7,0xfb,0xfd,0xfe};

//显示缓冲,非压缩BCD码,最低位在DisplayBuf[0]

staticunsignedchardisplayBuf[6];

//软件延时子程序

voidDelayMs(unsignedcharms)

{

unsignedchari,j;

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

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

}

//显示数字,在12 MHz的系统上,大约耗时40ms

voidLed_Show()

{

chari,flag=1;//用于标志高位是否为0

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

{

//移动位指针

Led_Controls_Pins|=0x3f;

Led_Controls_Pins&=charPointers[i];

if(displayBuf[i]==0&&flag)

{

Led_Pins=charCodes[10]; //如果高位为0,则不显示

}

else

{

Led_Pins=charCodes[displayBuf[i]];//送字形码

flag=0;

}

DelayMs(2);

}

}

//将一个整数转换成非压缩的BCD码放进显示缓冲,参数num为待显示的整数

voidLed_LongToBeDisplayed(longnum)

{

displayBuf[0]=num %10;

displayBuf[1]=num %100/10;

displayBuf[2]=num /100%10;

displayBuf[3]=num /1000%10;

displayBuf[4]=num /10000%10;

displayBuf[5]=num /100000;

}

//利用显示延时,参数num为延时多少次显示

voidLed_Delay(unsignedcharnum)

{

unsignedchari;

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

Led_Show();

}

LED驱动程序用于将数字显示在LED显示器上,函数Led_Show只能在LED显示器上显示一次数字。本任务采用的是动态数码显示,需要不停地刷新显示,因此必须在一个足够短的时间间隔内调用此函数。调用函数Led_LongToBeDisplayed可以改变要在LED上显示的数字。函数Led_Delay是延时函数,为了不中断LED的显示,这个延时函数内部调用了Led_Show函数。

(3) Counter.h头文件。

#ifndef Counter_h

#define Counter_h

voidCounter_Init();

longCounter_GetFrequency();

#endif

(4) Counter.c代码文件。

#include<reg51.h>

staticlongfrequency;

//初始化2个定时计数通道

voidCounter_Init()

{

TMOD=0x15; // t0计数,t1定时

TH1=-50000/256; //每5000次中断一次

TL1=-50000%256;

TR0=1;

TR1=1;

ET1=1;

EA=1;

}

staticvoidtimer1()interrupt3

{

staticunsignedchartimes=0; //计数中断次数

EA=0;

TR1=0;

//每5000次中断一次,为实现精确中断,补偿18个机器周期

TH1=(-50000+18)/256;

TL1=(-50000+18)%256;

TR1=1;

EA=1;

if(++times>=10) //每10次(半秒)处理一次

{

TR0=0;

frequency=TH0<<8|TL0;//半秒频率

TH0=0; //重新计数频率

TL0=0;

TR0=1;

frequency<<=1; //每秒频率

times=0;

}

}

longCounter_GetFrequency()

{

returnfrequency;

}函数Counter_Init是用来初始化2个定时计数通道的,程序在运行之前应该调用此函数。T0通道用来计数信号的个数,而T1用来提供闸门时间控制。此处将闸门时间定为半秒,当时间到了之后,计算出信号频率,存放到变量frequency中,然后重新开始计数。调用Counter_GetFrequency可以获取当前计算到的频率。最后是主程序。

(5)主程序文件Main.c。

#include<reg51.h>

#include<intrins.h>

#include"Led.h"

#include"Counter.h"

voidmain()

{

longfrequency=0;

Counter_Init();

P1=0xfe;

while(1)

{

if(frequency!=Counter_GetFrequency()) Led_LongToBeDisplayed(frequency=Counter_GetFrequency());

P1=_crol_(P1,1);

Led_Delay(5);

}

}在主函数里面,首先初始化定时计数通道,然后进入无限循环。循环中,反复调用计数模块的Counter_GetFrequency函数,以获取当前读到的频率,如果频率改变了,则调用函数Led_LongToBeDisplayed以刷新显示的频率。为了让实验看起来生动一些,添加了一个流水灯。最后调用Led_Delay延时一段时间,这样既达到了延时的目的,又不会中断LED的显示。

2)信号发生器部分

(1) Timer.h头文件。

#ifndef Timer_h

#define Timer_h

//通过P3.2引脚产生信号源

sbitgenerator_Pin=P3^2;

voidTimer_SetCount(unsignedcharcounter);

#endif

(2) Timer.c代码文件。

#include<reg51.h>

#include"Timer.h"

//设定方波频率

voidTimer_SetCount(unsignedcharcounter)

{

TR0=0;

TMOD=2;// t0定时,方式2

TH0=counter;

TL0=counter;

TR0=1;

ET0=1;

EA=1;

}

staticvoidtimer0()interrupt1

{

generator_Pin=!generator_Pin;

}定时器部分用来产生不同频率的方波信号,调用函数Timer_SetCount可以改变方波产生的频率。此函数设定定时器工作于方式2,所以计数255-counter次后中断一次,每计数一次需要一个机器周期,中断2次就是方波的一个周期,这样方波信号的频率可以这样计算:

fosc÷24÷(255-count)定时器中断处理程序翻转信号产生引脚的电平以输出方波信号。为了方便修改方波频率,提供了键盘处理程序,包含2个按键的处理。

(3) Keyboard.h头文件。

#ifndef Keyboard_h

#define Keyboard_h

sbitUpKey_Pin=P3^6;

sbitDownKey_Pin=P3^7;

unsignedcharKeyboard_KeyPressed();

#endif

(4) Keyboard.c代码文件。

#include<reg51.h>

#include"Keyboard.h"

voidDelayMs(intms)

{

inti,j;

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

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

}

//读按键。如果按下键,则返回1;否则,0</returns>

unsignedcharKeyboard_KeyPressed()

{

if(UpKey_Pin==1&&DownKey_Pin==1)return0;

DelayMs(8);

if(UpKey_Pin==1&&DownKey_Pin==1)return0;

if(UpKey_Pin==0)return1;

return2;

}函数Keyboard_KeyPressed返回按键代码,0表示无键按下,1表示按下“加”键,2

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论