如需要源文件可以添加qq群聊获取:662177587
概要
实际设计图:
设计内容
用单片机产生频率可调的方波信号。输出方波的频率范围为1Hz-200Hz,频率误差比小于0.5%。要求用“增加”、“减小”2个按钮改变方波给定频率,按钮每按下一次,给定频率改变的步进步长为1Hz,当按钮持续按下的时间超过2秒后,给定频率以10次/秒的速度连续增加(减少),输出方波的频率要求在数码管上显示。用输出方波控制一个发光二极管的显示,用示波器观察方波波形。开机默认输出频率为5Hz。
整体架构流程
研究目标
任务分析:方波信号的产生实质上就是在定时器溢出中断次数达到规定次数时,将输出I/O管脚的状态取反。由于频率范围最高为200Hz,即每个周期为5ms(占空比1:1,即高电平2.5ms,低电平2.5 ms),因此,定时器可以工作在8位自动装载的工作模式。
涉及以下几个方面的问题:按键的扫描、功能键的处理、计时功能以及数码管动态扫描显示等。问题的难点在按键连续按下超过2S的计时问题,如何实现计时功能。
系统的整体思路:主程序在初始化变量和寄存器之后,扫描按键,根据按键的情况执行相应的功能,然后在数码显示频率的值,显示完成后再回到按键扫描,如此反复执行。中断程序负责方波的产生、按键连续按下超过2S后频率值以10Hz/s递增(递减)。
选择单片机型号和所需外围器件型号,设计单片机硬件电路原理图。
采用MCS-51系列单片机At89S51作为主控制器,外围电路器件包括数码管驱动、独立式键盘、方波脉冲输出以及发光二极管的显示等。
数码管驱动采用2个四联共阴极数码管显示,由于单片机驱动能力有限,采用74HC244作为数码管的驱动。在74HC244的7段码输出线上串联100欧姆电阻起限流作用。
独立式按键使用上提拉电路与电源连接,在没有键按下时,输出高电平。发光二极管串联500欧姆电阻再接到电源上,当输入为低电平时,发光二极管导通发光。
技术细节
- 主函数.c
#include <STC89C5xRC.H>
#include "Timer0.h"
#include "Nexie.h"
unsigned char freq=5; //ƵÂÊ£¬³õʼֵΪ5
unsigned char long_flag=0,long_flag1=0;//ÓÃÓÚ¼Ó¼õ10µÄÅжϱê־λ
unsigned int comp; //ÓÃÓÚ¶¨Ê±Æ÷µÄ±È½ÏÖµ²úÉúpwm
code unsigned int comper[201]={0,15833,7516,5668,4251,3401,2834,2429,2125,1889,1700,1545,1417,1308,1214,1133,1062,1000,944,894,850,
809,772,739,708,680,654,629,607,586,566,548,531,515,500,485,472,459,447,436,425,
414,404,395,386,377,369,361,354,346,340,333,326,320,314,309,303,298,292,288,284,
283,281,279,277,275,273,271,269,267,265,263,261,259,257,255,253,251,249,247,245,
243,241,239,237,235,233,231,229,227,225,223,221,219,217,215,213,211,209,207,205,
203,201,199,197,195,193,191,189,187,185,183,181,179,177,175,173,171,169,167,165,
164,163,162,161,160,159,158,157,156,155,154,153,152,151,150,149,148,147,146,145,
144,143,142,141,140,139,138,137,136,135,134,133,132,131,130,129,128,127,126,125,
124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,
104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85};
/**
* @brief °´¼üɨÃè
* @param ÎÞ
* @retval ÎÞ
*/
void Key_Loop()
{
static unsigned int count,count1;
if(P30==0)
{
count++;
if(count>200) //˵Ã÷³ÖÐø°´ÏÂ
{ //Ö´ÐмӼõ10µÄ²Ù×÷
long_flag=1;
count--; //ΪÁ˲»ÈüÆÊýÖµ³¬¹ý·¶Î§
}
}
if(P30==1)
{
if(count>2) //˵Ã÷Ö»Êǵ¥»÷
{ //Ö´ÐмӼõ1µÄ²Ù×÷
freq++;
if(freq>200) //ÏÞÖÆƵÂÊ·¶Î§Îª1-200hz
{freq=1;}
}
long_flag=0;
count=0;
}
if(P31==0)
{
count1++;
if(count1>200) //˵Ã÷³ÖÐø°´ÏÂ
{ //Ö´ÐмӼõ10µÄ²Ù×÷
long_flag1=2;
count1--; //ΪÁ˲»ÈüÆÊýÖµ³¬¹ý·¶Î§
}
}
if(P31==1)
{
if(count1>2) //˵Ã÷Ö»Êǵ¥»÷
{ //Ö´ÐмӼõ1µÄ²Ù×÷
freq--;
if(freq<1) //ÏÞÖÆƵÂÊ·¶Î§Îª1-200hz
{freq=200;}
}
long_flag1=0;
count1=0;
}
}
/**
* @brief ƵÂÊÏÔʾº¯Êý
* @param ÎÞ
* @retval ÎÞ
*/
void Fre_show()
{
Nixie_SetBuf(1,freq/100%10);
Nixie_SetBuf(2,freq/10%10);
Nixie_SetBuf(3,freq%10);
}
void main()
{
Timer0_Init(); //¶¨Ê±Æ÷0³õʼ»¯
Timer1_Init(); //¶¨Ê±Æ÷1³õʼ»¯
while(1)
{
Fre_show(); //Ë¢ÐÂÏÔʾƵÂÊÖµ
comp=comper[freq]; //»ñµÃ±È½ÏÖµ1000/2/frequence=¼ÆʱºÁÃë·×ªÊý
}
}
/**
* @brief ¶¨Ê±Æ÷1µÄÏà¹Ø²Ù×÷
* @brief ¶¨Ê±Æ÷1Ϊģʽ8λ²»×Ô¶¯ÖØÔØ,1msÖжÏ
* @param ÎÞ
* @retval ÎÞ
*/
void Timer1_Routine() interrupt 3
{
static unsigned int T1Count0;//¶¨Ê±Æ÷Ïà¹Ø±äÁ¿
T1Count0++;
if(T1Count0>=comp)//Êä³ö·½²¨
{
T1Count0=0;
P20=!P20;
}
}
/**
* @brief ¶¨Ê±Æ÷0µÄÏà¹Ø²Ù×÷
* @brief ¶¨Ê±Æ÷0Ϊģʽ1,16Ϊ²»×Ô¶¯ÖØÔØ,1msÖжÏ
* @param ÎÞ
* @retval ÎÞ
*/
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count0,T0Count1,T0Count2;//¶¨Ê±Æ÷Ïà¹Ø±äÁ¿
TL0 = 0x18; //ÉèÖö¨Ê±³õʼֵ
TH0 = 0xFC; //ÉèÖö¨Ê±³õʼֵ
T0Count0++;T0Count1++;T0Count2++;//ÿ1ms½øÐÐÒ»´Î++£»
if(T0Count0>=10)//10msµ÷ÓÃÒ»´ÎKey_Loop()º¯Êý
{
T0Count0=0;
Key_Loop();
}
if(T0Count1>=2)//2msµ÷ÓÃÒ»´ÎNixie_Loop()º¯Êý
{
T0Count1=0;
Nixie_Loop();
}
if(T0Count2>=250)//µ÷½Ú¸ÃÖµ¿É¸Ä±ä¼Ó¼õ10µÄËÙ¶È
{
T0Count2=0;
if(long_flag==1)
{
freq+=10;
if(freq>200) //ÏÞÖÆƵÂÊ·¶Î§Îª1-200hz
{freq=1;}
}
if(long_flag1==2)
{
freq-=10;
if(freq>200) //ÏÞÖÆƵÂÊ·¶Î§Îª1-200hz
{freq=200;}
}
}
}
- 定时器.c
#include <STC89C5xRC.H>
/**
* @brief ¶¨Ê±Æ÷0³õʼ»¯
* @param ÎÞ
* @retval ÎÞ
*/
void Timer0_Init(void) //100us@12.000MHz
{
TMOD &= 0xF0; //¶¨Ê±Æ÷ʱÖÓ12Tģʽ
TMOD |= 0x01; //ÉèÖö¨Ê±Æ÷ģʽ
TL0 = 0x18; //ÉèÖö¨Ê±³õʼֵ
TH0 = 0xFC; //ÉèÖö¨Ê±³õʼֵ
TF0 = 0; //Çå³ýTF0±êÖ¾
TR0 = 1; //¶¨Ê±Æ÷0¿ªÊ¼¼Æʱ
ET0=1;
EA=1;
PT0=0;
}
/**
* @brief ¶¨Ê±Æ÷1³õʼ»¯
* @param ÎÞ
* @retval ÎÞ
*/
void Timer1_Init(void) //10΢Ãë@12.000MHz
{
TMOD &= 0x0F; //ÉèÖö¨Ê±Æ÷ģʽ
TMOD |= 0x20; //ÉèÖö¨Ê±Æ÷ģʽ
TL1 = 0xF6; //ÉèÖö¨Ê±³õʼֵ
TH1 = 0xF6; //ÉèÖö¨Ê±ÖØÔØÖµ
TF1 = 0; //Çå³ýTF1±êÖ¾
TR1 = 1; //¶¨Ê±Æ÷1¿ªÊ¼¼Æʱ
ET1=1;
EA=1;
}
- 定时器.h
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0_Init(void);
void Timer1_Init(void); //10΢Ãë@12.000MHz
#endif
- 数码管.c
#include <STC89C5xRC.H>
#include "Delay.h"
unsigned char Nixie_Buf[4]={0,10,10,10};//0ÊÇΪÁËÕÕÓ¦loopÖÐi=1
unsigned char NixieNumb[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
/**
* @brief Íⲿµ÷ÓöÔÊý×éNixie_Buf[4]¸³Öµ
* @brief ʹµÃloopº¯ÊýÑ»·¶Ôscanº¯Êý¸³ÖµÊ±¶Áµ½ÏàÓ¦Êý¾Ý
* @brief δ¸³ÖµµÄÊý×éλ¼´Îª10£»¶ÔÓ¦NixieNumb[]ÖеÄ0£»
* @param Table,NumberÔÚNixie_BufÊý×éµÄÏÂ±ê ¸³µÄÖµ£¨¸ÃÖµ¼´¶ÔÓ¦NixieNumb[]ÖеÄÖµ£©
* @retval ÎÞ
*/
void Nixie_SetBuf(unsigned char Table,Number)
{
Nixie_Buf[Table]=Number;
}
/**
* @brief ÊýÂë¹ÜÏÔʾ
* @param Table,NumberÏÔʾµÄλÖà ÏÔʾµÄÊý×Ö
* @param Á½²ÎÊýÓɶ¨Ê±Æ÷°´ÖÜÆÚɨÃèʱ¸ø¶¨
* @retval ÎÞ
*/
void Nixie_Scan(unsigned char Table,Number)
{
P0=0x00;//ÏûÒþ
switch(Table)
{// P2_4=C-4,P2_3=B-2;P2_2=A-1
case 1:P24=1;P23=1;P22=1;break;
case 2:P24=1;P23=1;P22=0;break;
case 3:P24=1;P23=0;P22=1;break;
}
P0=NixieNumb[Number];//²»ÓÃdelayÔÙÏûÒþ£¬ÒòΪ¶¨Ê±Æ÷½øÀ´ÓÐʱ¼ä¼ä¸ô
}
/**
* @brief ¶¨Ê±Æ÷µ÷Óõĺ¯Êý
* @param ÎÞ
* @retval ÎÞ
*/
void Nixie_Loop(void)//¶¨Ê±Æ÷ÿ½øÒ»´Î¾Íµ÷ÓÃÒ»´Îscanº¯Êý
{ //ʹµÃ3¸öÊýÂë¹ÜÒÀ´Î¿ìËÙÏÔʾ
static unsigned char i=1;
Nixie_Scan(i,Nixie_Buf[i]);
i++;
if(i>=4)i=1;
}
- 数码管.h
#ifndef __NEXIE_H__
#define __NEXIE_H__
void Nixie_Scan(unsigned char Table,Number);
void Nixie_Loop(void);
void Nixie_SetBuf(unsigned char Table,Number);
#endif
小结
用单片机产生频率可调的方波信号。输出方波的频率范围为1Hz-200Hz,频率误差比小于0.5%。
如需要源文件可以添加qq群聊获取:662177587
希望对你有所帮助!