目录
在微型信号源智能仪器开发、自动测试、自动控制、通讯、遥感等领域中,很需要一种适用于单片机微机接口的微型可编程智能化的扫频系统。扫频系统为有关电路的频率特性测试、研究、分析或改善电路性能提供了方便的条件。扫频系统大大简化了测量操作,提高了工作效率,达到了测量过程快速、直观、准确、方便的目的,在生产科研教学上得到了广泛的应用[1]。在分析电路中,扫频系统是必不可少的激励信号源,应用十分普遍。
本设计是针对测试、通信广泛应用的低频扫频系统,成本低、重量轻、体积小、显示直观、操作方便,可以很好地完成低频扫频信号的产生。在本设计上按照个人的意图稍加扩展,就可以实现各式各样的函数信号发生器。本课题设计的扫频系统功能较多,操作简单,开机后按下键盘S1到S7,系统开始通过由单片机来控制定时/计数器,对单片机写算法来控制对1MHz方波的分频,另外,再通过显示模块输出相应的频段。
图2.1 系统总体框图
系统采用单片微处理器AT89C51为控制核心,利用有源晶振来实现信号的产生。系统开机后总中断打开,按下键盘S1到S7,系统开始通过单片机来控制8253定时/计数器,对单片机写算法来控制对1MHz方波的分频,另外,再通过显示模块输出相应的显示数字。为了提高单片机和定时/计数器的工作效率,并使扫频系统更加稳定地工作,系统利用了74HC244作为缓冲器。
2.1 MCS-51最小系统
(1)单片机的复位电路:
MCS-51单片机的复位是由外部的复位电路来实现的。复位引脚RST与复位电路相连。复位电路通常采用上电自动复位和按钮复位两种方式。上电自动复位是通过外部复位电路的电容充电来实现的。只要Vcc的上升时间不超过1ms,就可以实现自动上电复位。除了上电复位外,有时还需要按键手动复位。按键手动复位有电平方式和脉冲方式两种[2]。
上电复位:上电复位电路是—种简单的复位电路,只要在RST复位引脚接一个电容到Vcc,接一个电阻到地就可以了。上电复位是指在给系统上电时,复位电路通过电容加到RST复位引脚一个短暂的高电平信号,这个复位信号随着Vcc对电容的充电过程而回落,所以RST引脚复位的高电平维持时间取决于电容的充电时间。为了保证系统安全可靠的复位,RST引脚的高电平信号必须维持足够长的时间。
手动复位:手动复位需要人为在复位输入端加高电平让系统复位。一般采用的方法是在RST端和正电源Vcc之间接一个按键,当按下按键后,Vcc和RST端接通,RST引脚处有高电平,而且按键动作一般是数十毫秒、大于两个机器周期的时间,能够安全的让系统复位[3][4]。
本电路采用的是上电复位方式。复位电路如下图2.2所示:
图2.2 复位电路
(2)单片机的时钟电路:
时钟是单片机的心脏,单片机各功能部件的运行都是以时钟频率为基准,有条不紊的一拍一拍地工作。因此,时钟频率直接影响单片机的速度,时钟电路的质量也直接影响单片机系统的稳定性。常用的时钟电路有两种方式:一种是内部时钟方式,另一种为外部时钟方式[5]。本文用的是内部时钟方式。
MCS-51单片机内部有一个用于构成振荡器的高增益反相放大器,该高增益反向放大器的输入端为芯片引脚XTAL1,输出端为引脚XTAL2。这两个引脚跨接石英晶体振荡器和微调电容,就构成一个稳定的自激振荡器[6]。
时钟电路如下图2.3所示:
图2.3 时钟电路
2.2 扫频源的产生
产生频率周期变化的扫频信号实际上就是由一个单一稳定的频率源进行分频或混频来实现的。因为该系统所产生的扫频信号范围主要集中在低频段,大约在几千赫兹左右,也因为只要输出TTL电平,所以在信号产生方面系统直接采用了有源晶振来实现这个功能。
有源晶振是由石英晶体组成的,石英晶片之所以能当为振荡器使用,是基于它的压电效应:在晶片的两个极上加一电场,会使晶体产生机械变形;在石英晶片上加上交变电压,晶体就会产生机械振动,同时机械变形振动又会产生交变电场,虽然这种交变电场的电压极其微弱,但其振动频率是十分稳定的。当外加交变电压的频率与晶片的固有频率(由晶片的尺寸和形状决定)相等时,机械振动的幅度将急剧增加,这种现象称为“压电谐振”[7]。
有源晶振有4只引脚,是一个完整的振荡器,里面除了石英晶体外,还有晶体管和阻容元件 。有源晶振不需要DSP的内部振荡器,信号质量好,比较稳定,而且连接方式相对简单(主要是做好电源滤波,通常使用一个电容和电感构成的PI型滤波网络,输出端用一个小阻值的电阻过滤信号即可),不需要复杂的配置电路。
有源晶振型号纵多,而且每一种型号的引脚定义都有所不同,接法也不同,下面介绍一下一般有源晶振引脚定义,如图2.4所示。
图2.4 有源晶振引脚图
2.3 按键电路
键盘是人机交互的窗口,通过键盘实现人对设备的控制和设置。每个按键有两个连接端:一端与单片机的相应管脚相连,另一端与单片机另一部分管脚相连,通过按键实现电路的连接与断开,以此来实现单片机引脚电平的变化,通过此变化来实现输入指令。
本系统采用的是矩阵键盘,可以最大限度使用少的引脚来控制更多的按键。
按键电路共使用7个单片机引脚来控制12个按键,使系统可以实现更多的功能。
图2.5 键盘接口电路
2.4 显示模块
显示模块使用8个LED灯和8位数码管来显示不同的状态。系统初始状态LED灯全部熄灭,8个LED灯单独亮分别代表8个状态,8个LED灯全部亮代表状态9;数码管用来同步显示系统输出连续脉冲频率。
2.4.1 LED灯电路
图2.6 LED灯连接电路
LED灯采用共阳接法,与单片机连接处输出为低电平即亮。LED灯与单片机中使用锁存器74HC573控制,可以实现分时控制,实现单片机的数据扩展。
2.4.2 数码管显示电路
数码管显示器成本低,配置灵活,与单片机接口相连,在单片机应用系统中广泛应用。在系统运行期间,单片机要完成一个相对其他微控制更为繁杂的计算输出过程,即如何输入的频率值转换为采样点与点之间输出的时间间隔,并准确控制这个时间间隔的实现[8]。
数码管使用7SEG-MPX8-CA-blue八位共阳极数码管来显示频率,该数码管需要16个引脚来控制,同样采用锁存器来控制,这样AT89C51就可以使用8个引脚来控制8个LED灯与8位数码管。
图2.7 数码管连接电路
2.4.3 74HC573锁存器
锁存器是一种对脉冲电平敏感的存储单元电路,它们可以在特定输入脉冲电平作用下改变状态。锁存,就是把信号暂存以维持某种电平状态。锁存器的最主要作用是缓存,其次完成高速的控制器与慢速的外设的不同步问题,再其次是解决驱动的问题,最后是解决一个 I/O 口既能输出也能输入的问题。锁存器是利用电平控制数据的输入,它包括不带使能控制的锁存器和带使能控制的锁存器。
本系统使用的74HC573锁存器是带使能控制的锁存器。
图2.8 74573逻辑图
图2.9 74HC573真值表
锁存器就是把当前的状态锁存起来,使输入的数据在接口电路的输出端保持一段时间锁存后状态不再发生变化,直到解除锁存。锁存引脚高电平表示直通状态,为低电平表示锁存状态,可以通过控制锁存引脚,控制74HC573后端输出数据。当我们需要改变LED灯或数码管状态时,只需要把锁存器打开传入数据再关闭锁存器即可。
2.5可编程定时∕计数器8253
在数字电路、计算机系统以及实时控制系统中常需要用到定时信号,如函数发生器、计算机中的系统日历时钟、DRAM的定时刷新、实时采样和控制系统等,都要用到定时信号。定时信号可以利用软件编程或硬件的方法得到。
所谓软件定时的方法就是设计一个延时子程序,子程序中全部指令执行时间的总和就是该子程序的延时时间。软件定时的定时时间不太精确,仅适用于延时时间较短、重复次数有限的场合,否则,CPU总是执行延时程序,占用了大量的时间,使CPU得利用率降低。所以在对时间要求严格的实时控制系统和多任务系统中很少采用。
硬件定时就是利用专用的硬件定时/计数器,在简单软件控制下产生准确的延时时间。其基本原理是通过软件确定定时/计数器的工作方式、设置计数初值并启动计数器工作,当计数到给定值时,便自动产生定时信号。8253是一个可编程计数∕定时器芯片,它内部有三个独立的16位计数器,各计数器的工件方式可以独立编程设定,CPU可以随时更改各个计数器的工作方式和定时常数,也可以读取它们的计数状态。当CPU启动8253后8253开始计数,计数到确定值便自动产生一具定时输出。在8253开始计数工作以后,CPU可以去做别的工作,8253的定时器输出信号可作为中2断请求信号,这可以大大提高CPU的利用率[9]。
2.5.1 8253的结构和引脚功能
8253是一个24引脚双列直插式芯片。它的引脚
及功能示意图,内部结构框图如图2.10,图2.11所
示。8253内部结构包括数据总线缓冲器、读∕写控制
逻辑、独立的结构功能完全相同的16位可预置的递减
计数器和控制字寄存器[10]。
图2.10 8253的引脚功能示意图
图2.11 8253内部结构框图
数据总线缓冲器是8253与CPU之间的数据接口,它是一个8位双向三态缓冲器。CPU可以用输出指令将控制字和计数初值写入8253,也可以用输入指令从8253读取计数器中的计数值[22]。
读∕写控制逻辑接受CPU送来的读∕写控制信号,并加以组合完成对8253内部操作的控制。来自CPU控制信号如下:
A1、A0:地址线,作为端口选择信号。当A1、A0分别取00、01、10、11、时,对应选择计数器0、计数器1、计数器2及控制寄存器。
:片选信号,低电平有效。
:读控制信号,低电平有效。
:写控制信号,低电平有效。
上述控制信号的组合功能及操作见表2.1。
表2.1 控制信号的组合功能及操作
A1 | A0 |
| 操作 | ||
0 | 0 | 0 | 0 | 1 | 读计数器0 |
0 | 1 | 0 | 0 | 1 | 读计数器1 |
1 | 0 | 0 | 0 | 1 | 读计数器2 |
0 | 0 | 0 | 1 | 0 | 写入计数器0 |
0 | 1 | 0 | 1 | 0 | 写入计数器1 |
1 | 0 | 0 | 1 | 0 | 写入计数器2 |
1 | 1 | 0 | 1 | 0 | 写方式控制字 |
× | × | 1 | × | × | 禁止(H.Z) |
1 | 1 | 0 | 0 | 1 | 无操作(H.Z) |
× | × | 0 | 1 | 1 | 无操作(H.Z) |
控制字寄存器用来存放由CPU写入8253的方式选择控制字,以便定计数器的操作方式。8253的方式选择控制字的格式如图2.12所示。
|
D7 D6 D5 D4 D3 D2 D1 D0
|
|
|
{}
|
图2.11 8253的方式选择控制字的格式
图2.12 8253控制字介绍
8253内部包含三个独立的结构功能完全相同的16位可预置的递减计数器。每个计数器都有3条引脚线,其作用如下:
CLK:时钟输入端。计数脉冲或定时脉冲由该端引入。
GATA:门控制输入端。它是由外部引入的控制信号,用于控制启动或终止计数∕定时。
OUT:计数器的输出端。它用于指示定时或计数完成规定值。该信号可供CPU查询或作为中断请求信号发向CPU。
8253内部除控制字寄存器位,还有三个初值寄存器,分别储存计数器0、计数器1、计数器2初值,地址有A1,A0端口控制。
2.5.2 8253的工作方式
8253各计数器有6种可供选择的工作方式。因为本系统只使用8253的工作方式3,这里只对其工作工作方式3进行介绍。
方式3的时序如图2.13所示。
图2.13方式3的时序图
当任一计数器工作于方式3时,OUT输出的是方波或近似。该方式具有如下工作特点:
1)写入控制字后,OUT端输出低电平。GATE变成高电平,CPU写计数初值并装入CE后,计数器开始减一计数,装入CE的下降沿使OUT跳变为高电平。当计数到n/2(n为偶数)或(n+1)/2(n为奇数)时,OUT变成低电平,直到计数值为0,OUT又变成高电平,同时自动重装初值开始下一周期的计数。即OUT当初值为n时,OUT在n个周期呈现方波划近似方波的一个输出周期。
2)在计数过程中,若GATE变为低电平,则暂停1计数,当GATE又变成高电平时,计数器从初值开始重新计数。
3)在计数过程中,重新写入新的计数值,不会影响本次计数过程,在下一个计数周期开始按新的计数初值计数。
如果要求改变输出方波的速率, 则CPU可在任何时候重新装入新的计数初值n,并从下一个计数操作周期开始改变输出方波的速率。
2.5.3 8253模块电路
在AT89C51的数据端和定时/计数器的数据端相连的时候,为了使扫频系统更稳定的工作,在这两者之间加一个缓冲器74244,这样不但提高了单片机和定时/计数器的工作效率,还使得系统更加稳定。定时/计数器有三个独立16位定时/计数器,在这里只用到了二个,分别是定时/计数0和定时/计数1,最后定时/计数器会有两个取值结果,分别是OUT0和OUT1,加上了一个数据选择器(由一个非门,两个与门,一个或门构成)来选择合适的输出频率。具体的电路图入下所示:
图2.14 定时/计数模块
图2.15 系统整体电路图
3.1 系统基础模块软件设计
3.1.1 按键模块设计(程序见附录1)
图3.1 按键模块流程图
3.1.2 显示模块设计(程序见附录2)
8253寄存器地址定义及AT89C51内部定时器模块化程序见附录二。
3.2 系统总体设计(程序见附录3)
图3.3 系统总体流程图
- Proteus仿真
图4.1 电路整体连接图
4.1 任务功能仿真
在数码管显示器上,可以显示出要求结果。本文通过对1MHz的时钟进行分频混频,分别产生了1Hz~100Hz,100Hz~500Hz,500Hz~1kHz,1kHz~10kHz,10kHz~100kHz,100kHz~400kHz,先1Hz~400kHz后400kHz~1Hz的扫频信号。
(1)摁下S1后,系统对1Hz~100Hz的信号进行扫频,仿真结果如图4.2所示。
图4.2 1Hz~100Hz输出方波
图4.2中所示信号周期为41.50ms,频率约为24Hz,幅值为5V。数码管显示如图4.3所示。
图4.3 数码管显示频率
(1)摁下S2后,系统对100Hz~500Hz的信号进行扫频,仿真结果如图4.4所示。
图4.4 100Hz~500Hz输出方波
图4.2中所示信号周期为3.64ms,频率约为275Hz,幅值为5V。数码管显示如图4.5所示。
图4.5 数码管显示频率
(1)摁下S3后,系统对500Hz~1kHz的信号进行扫频,仿真结果如图4.6所示。
图4.6 500Hz~1kHz输出方波
图4.2中所示信号周期为1.75ms,频率约为572Hz,幅值为5V。数码管显示如图4.7所示。
图4.7数码管显示频率
仿真结果表面,按下相应按键后,系统会对相应频段进行扫描,数码管显示对应频率。
4.2 拓展功能1仿真
长按s11后,会进入设置界面,s1~s10分别表示数字键盘0~9,如图4.10所示。
图4.10 设置输出频率为1000
再次按下s11,系统输出所设频率矩形波,如图4.11所示。
图4.11 系统输出频率为1000的矩形波
图4.12 数码管显示输出频率
4.3 拓展功能2仿真
长按s12后,系统会进入设置界面,首先设置起始频率,如图4.13所示。
图4.13 设置起始频率
短按s12后,确认起始频率,设置终止频率。
图4.14 设置终止频率
短按s12后,确认终止频率,设置频率间隔。
。
图4.15 设置频率间隔
短按s12后,确认频率间隔,设置时间间隔。单位为ms.
图4.16 设置时间间隔
最后短按s12,系统将会输出,所设置的扫频信号。
五、结论
本文设计了基于定时/计数器8253的数字扫频系统,主要从定时/计数器8253和具体的软硬件设计说明等方面详细进行了阐述。
在技术选用上,本次设计的扫频系统用有源晶振输出方波,保证了系统的高性能,即高精度、高响应速率。
在外围电路设计上,装置配备了矩阵键盘、LED等人机交互设备,方便实用,并遵循一切为减少软件负担为原则,能用硬件实现的功能尽量由硬件实现。如数码管显示部分就用静态显示代替动态显示,节约单片机资源。最后,就本系统的联机和脱机调试过程出现的问题及其解决方法进行了说明。
知识与实践结合才是真正的知识。在整个实践过程中,我学到了很多,不仅学会了一些单片机开发方面的实践经验,更重要的是重新认识了真正的工程实践是怎样一个过程。在实际工程工作中,一方面要在不断地遇到问题、解决问题,然后再遇到问题,再解决问题的过程中不断积累经验;另一方面,也是更为重要的一点就是要学会学习。因为一个人不可能把全部的工程技术都学会,相反,实际工作中往往是要求现学现用、活学活用。在这次毕业设计中我就深切体会到这一点。开始的时候一开题,发现那么多都不懂,也没学过,总觉得太难。后来在老师开导下逐渐进入课题。不会的就学,不懂得就查、就问,在解决问题中提高自己的综合素质。我想,大学期间学会如何自己学习并灵活应用才是最重要的。
参考文献
- 邓中国.天线分析仪与扫频仪功能介绍.2012-2-10.
- 褚人乾. 直接数字频率合成的频谱特性及其改善方法. 通信对抗, 1999,7(4):118~128.
- 孙鹏,胡兵,王育生.基于嵌入式系统便捷式扫频仪的设计[J].2011,《现代电子技术》(2):1~25.
- 何苏勤,吕咸亮,刘勇,王小庆.基于TMS320F2808的音频频率数字扫频仪[J].北京:北京化工大学,信息科学与技术学院.2011:1~25.
- C.F.Tsai. The Function of Direct Digital Synthesis Circuit. ISIJ International, 2001,11(5):108~114.
- 袁振东.一种高性价比数字扫频仪的设计与实现.南京:解放军理工大学通信工程学院[J].2000,《电子工程师》(4):28~30.
- 高克方.一种基于FPGA技术的虚拟数字扫频仪的设计[J].福建农林大学机电学院.2005,《现代电子技术》(17):38~40.
- 褚振勇,翁木云. FPGA设计及应用. 西安:西安电子科技大学出版社,2003,219~263.
- 张连江. 理想直接数字频率合成技术. 舰船电子对抗,1998,2 (5):22~30.
- 谭浩强.微型计算机原理及应用(第4版).北京:清华大学出版社出版社,2013:262-268.
附录1
unsigned char ucKBD_Scan()
{
unsigned char key_val=0xff;
P3=P3&0xc0|0x30;P24=1; //列扫描
if(P24==0) key_val=0x70;
if(P35==0) key_val=0xb0;
if(P34==0) key_val=0xd0;
P3=P3&0xc0|0x0f;P24=0; //行扫描
if(P33==0) key_val=key_val | 0x07;
if(P32==0) key_val=key_val | 0x0b;
if(P31==0) key_val=key_val | 0x0d;
if(P30==0) key_val=key_val | 0x0e;
return key_val;
}
unsigned char Trg_KBD;
unsigned char Cont_KBD;
void vKBD_Read()
{
unsigned char ReadData = ucKBD_Scan() ^ 0xff; /* 0x81 0x41 0x21
Trg_KBD = ReadData & (ReadData ^ Cont_KBD); 0x82 0x42 0x22
Cont_KBD = ReadData; 0x84 0x44 0x24
} 0x88 0x48 0x28 */
附录2
void vDevice_Ctrl(unsigned char p2,unsigned char p1) //LED,数码管外设
{
P1=p1;
P2=P2&0x3f|p2;
P2=P2&0x3f;
}
unsigned char smg_buf[8];//数码管
unsigned char code smg_code[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
void vSmg_Display()
{
static unsigned char i;
vDevice_Ctrl(0x80,0);
vDevice_Ctrl(0xc0,~smg_buf[i]);
vDevice_Ctrl(0x80,0x01<<i);
i=(i+1)%8;
}
//8253寄存器地址定义
void Timer0_8253(unsigned int C)
{
CMD_ADDR=0X36;
TIMER0_ADDR=C%256;
TIMER0_ADDR=C/256;
}
void Timer1_8253(unsigned int C)
{
CMD_ADDR=0X76;
TIMER1_ADDR=C%256;
TIMER1_ADDR=C/256;
}
void Timer2_8253(unsigned int C)
{
CMD_ADDR=0Xb6;
TIMER2_ADDR=C%256;
TIMER2_ADDR=C/256;
}
//AT89C51内部定时器0
void Timer0Init()
{
TMOD=0x01;
TH0=0xfc;
TL0=0x18;
EA=1;
ET0=1;
TR0=1;
}
附录3
//所有定义变量
unsigned long T08;
unsigned char out_mode;
unsigned int A[5];
unsigned char state;
unsigned long fre_out;
bit s11,s12,set0,set1,smg_ss;
unsigned int F1[5]; //大模式3 所用参数
unsigned int F2[5];
unsigned int F_start;
unsigned int F_end;
unsigned char f_1;
unsigned char f_2;
unsigned char F3[3];
unsigned char f_3;
unsigned int F4[5];
unsigned char f_4;
unsigned char f_interval;
unsigned int t_interval;
unsigned char mode3;
//所有定义计时器cnt
unsigned char cnt_kbd;
unsigned char cnt_js;
unsigned char cnt_T0;
unsigned int cnt_T1;
unsigned char cnt_led;
unsigned char cnt_smg;
unsigned int cnt_cont0;
unsigned int cnt_cont1; //大模式3 参数
void v8253_Process8();
void vLED_Process() {vDevice_Ctrl(0x40,~(0x01<<out_mode-1));}//LED
void vLED_Process1() {vDevice_Ctrl(0x40,0); }
//矩阵键盘操作
void vKBD_Process()
{
if(cnt_kbd>=10)
{
cnt_kbd=0;
vKBD_Read();
if(Cont_KBD==0x41){s11=1;} else s11=0; //长按s11
if(Cont_KBD==0x21){s12=1;} else s12=0; //长按s12
if(set1==0&&set0==0)
{
if(Trg_KBD==0x88) {out_mode=1;vLED_Process();fre_out=1; P25=1; }//s1
if(Trg_KBD==0x48) {out_mode=2;vLED_Process();fre_out=100; P25=1; }//s2
if(Trg_KBD==0x28) {out_mode=3;vLED_Process();fre_out=500; P25=0; }//s3
if(Trg_KBD==0x84) {out_mode=4;vLED_Process();fre_out=1000; P25=1; }//s4
if(Trg_KBD==0x44) {out_mode=5;vLED_Process();fre_out=10000; P25=0; }//s5
if(Trg_KBD==0x24) {out_mode=6;vLED_Process();fre_out=100000;P25=0; }//s6
if(Trg_KBD==0x82) {out_mode=7;vLED_Process();fre_out=1; }//s7
if(Trg_KBD==0x42) {out_mode=9;fre_out=100;P25=0; }//s8
}
if(set1==0&&set0==1)
{
if(Trg_KBD==0x88) {A[state]=1;state++;if(state>=5) { state=0;}; }//s1
if(Trg_KBD==0x48) {A[state]=2;state++;if(state>=5) { state=0;}; }//s2
if(Trg_KBD==0x28) {A[state]=3;state++;if(state>=5) { state=0;}; }//s3
if(Trg_KBD==0x84) {A[state]=4;state++;if(state>=5) { state=0;}; }//s4
if(Trg_KBD==0x44) {A[state]=5;state++;if(state>=5) { state=0;}; }//s5
if(Trg_KBD==0x24) {A[state]=6;state++;if(state>=5) { state=0;}; }//s6
if(Trg_KBD==0x82) {A[state]=7;state++;if(state>=5) { state=0;}; }//s7
if(Trg_KBD==0x42) {A[state]=8;state++;if(state>=5) { state=0;}; }//s8
if(Trg_KBD==0x22) {A[state]=9;state++;if(state>=5) { state=0;}; }//s9
if(Trg_KBD==0x81) {A[state]=0;state++;if(state>=5) { state=0;}; }//s10
if(Trg_KBD==0x21) {state--;if(state>=5) state=4;} //s12
if(Trg_KBD==0x41) {set0=0;out_mode=8;P25=0;fre_out=A[4]+A[3]*10+A[2]*100+A[1]*1000+A[0]*10000;v8253_Process8();}//s11
}
if(set1==1)
{
switch(mode3)
{
case 0:
{
if(Trg_KBD==0x88) {F1[f_1]=1;f_1++;if(f_1>=5) { f_1=0;}; }//s1
if(Trg_KBD==0x48) {F1[f_1]=2;f_1++;if(f_1>=5) { f_1=0;}; }//s2
if(Trg_KBD==0x28) {F1[f_1]=3;f_1++;if(f_1>=5) { f_1=0;}; }//s3
if(Trg_KBD==0x84) {F1[f_1]=4;f_1++;if(f_1>=5) { f_1=0;}; }//s4
if(Trg_KBD==0x44) {F1[f_1]=5;f_1++;if(f_1>=5) { f_1=0;}; }//s5
if(Trg_KBD==0x24) {F1[f_1]=6;f_1++;if(f_1>=5) { f_1=0;}; }//s6
if(Trg_KBD==0x82) {F1[f_1]=7;f_1++;if(f_1>=5) { f_1=0;}; }//s7
if(Trg_KBD==0x42) {F1[f_1]=8;f_1++;if(f_1>=5) { f_1=0;}; }//s8
if(Trg_KBD==0x22) {F1[f_1]=9;f_1++;if(f_1>=5) { f_1=0;}; }//s9
if(Trg_KBD==0x81) {F1[f_1]=0;f_1++;if(f_1>=5) { f_1=0;}; }//s10
if(Trg_KBD==0x41) {f_1--;if(f_1>=5) f_1=4;} //s11
if(Trg_KBD==0x21) {mode3++;F_start=F1[4]+F1[3]*10+F1[2]*100+F1[1]*1000+F1[0]*10000;}//s12
}break;
case 1:
{
if(Trg_KBD==0x88) {F2[f_2]=1;f_2++;if(f_2>=5) { f_2=0;}; }//s1
if(Trg_KBD==0x48) {F2[f_2]=2;f_2++;if(f_2>=5) { f_2=0;}; }//s2
if(Trg_KBD==0x28) {F2[f_2]=3;f_2++;if(f_2>=5) { f_2=0;}; }//s3
if(Trg_KBD==0x84) {F2[f_2]=4;f_2++;if(f_2>=5) { f_2=0;}; }//s4
if(Trg_KBD==0x44) {F2[f_2]=5;f_2++;if(f_2>=5) { f_2=0;}; }//s5
if(Trg_KBD==0x24) {F2[f_2]=6;f_2++;if(f_2>=5) { f_2=0;}; }//s6
if(Trg_KBD==0x82) {F2[f_2]=7;f_2++;if(f_2>=5) { f_2=0;}; }//s7
if(Trg_KBD==0x42) {F2[f_2]=8;f_2++;if(f_2>=5) { f_2=0;}; }//s8
if(Trg_KBD==0x22) {F2[f_2]=9;f_2++;if(f_2>=5) { f_2=0;}; }//s9
if(Trg_KBD==0x81) {F2[f_2]=0;f_2++;if(f_2>=5) { f_2=0;}; }//s10
if(Trg_KBD==0x41) {f_2++;if(f_2>=5) f_2=4;} //s11
if(Trg_KBD==0x21) {mode3++;F_end=F2[4]+F2[3]*10+F2[2]*100+F2[1]*1000+F2[0]*10000;}//s12
}break;
case 2:
{
if(Trg_KBD==0x88) {F3[f_3]=1;f_3++;if(f_3>=3) { f_3=0;}; }//s1
if(Trg_KBD==0x48) {F3[f_3]=2;f_3++;if(f_3>=3) { f_3=0;}; }//s2
if(Trg_KBD==0x28) {F3[f_3]=3;f_3++;if(f_3>=3) { f_3=0;}; }//s3
if(Trg_KBD==0x84) {F3[f_3]=4;f_3++;if(f_3>=3) { f_3=0;}; }//s4
if(Trg_KBD==0x44) {F3[f_3]=5;f_3++;if(f_3>=3) { f_3=0;}; }//s5
if(Trg_KBD==0x24) {F3[f_3]=6;f_3++;if(f_3>=3) { f_3=0;}; }//s6
if(Trg_KBD==0x82) {F3[f_3]=7;f_3++;if(f_3>=3) { f_3=0;}; }//s7
if(Trg_KBD==0x42) {F3[f_3]=8;f_3++;if(f_3>=3) { f_3=0;}; }//s8
if(Trg_KBD==0x22) {F3[f_3]=9;f_3++;if(f_3>=3) { f_3=0;}; }//s9
if(Trg_KBD==0x81) {F3[f_3]=0;f_3++;if(f_3>=3) { f_3=0;}; }//s10
if(Trg_KBD==0x41) {f_3--;if(f_3>=3) f_3=2;} //s11
if(Trg_KBD==0x21) {mode3++;f_interval=F3[2]+F3[1]*10+F3[0]*100;}//s12
}break;
case 3:
{
if(Trg_KBD==0x88) {F4[f_4]=1;f_4++;if(f_4>=5) { f_4=0;}; }//s1
if(Trg_KBD==0x48) {F4[f_4]=2;f_4++;if(f_4>=5) { f_4=0;}; }//s2
if(Trg_KBD==0x28) {F4[f_4]=3;f_4++;if(f_4>=5) { f_4=0;}; }//s3
if(Trg_KBD==0x84) {F4[f_4]=4;f_4++;if(f_4>=5) { f_4=0;}; }//s4
if(Trg_KBD==0x44) {F4[f_4]=5;f_4++;if(f_4>=5) { f_4=0;}; }//s5
if(Trg_KBD==0x24) {F4[f_4]=6;f_4++;if(f_4>=5) { f_4=0;}; }//s6
if(Trg_KBD==0x82) {F4[f_4]=7;f_4++;if(f_4>=5) { f_4=0;}; }//s7
if(Trg_KBD==0x42) {F4[f_4]=8;f_4++;if(f_4>=5) { f_4=0;}; }//s8
if(Trg_KBD==0x22) {F4[f_4]=9;f_4++;if(f_4>=5) { f_4=0;}; }//s9
if(Trg_KBD==0x81) {F4[f_4]=0;f_4++;if(f_4>=5) { f_4=0;}; }//s10
if(Trg_KBD==0x41) {f_4--;if(f_4>=5) f_4=4;} //s11
if(Trg_KBD==0x21) {set1=0;out_mode=10;P25=0;fre_out=F_start;t_interval=F4[4]+F3[3]*10+F4[2]*100+F4[1]*1000+F4[0]*10000;}
}break;
}
}
}
}
void vSmg_Process() //数码管操作
{
if(set1==0&&set0==0)
{
unsigned char i=2;
smg_buf[0]=0x71;
smg_buf[1]=0x40;
if(fre_out/100000!=0){smg_buf[2]=smg_code[fre_out/100000];} else{smg_buf[2]=0;}
if(fre_out/10000%10!=0||smg_buf[2]!=0){smg_buf[3]=smg_code[fre_out/10000%10];} else{smg_buf[3]=0;}
if(fre_out/1000%10!=0||smg_buf[3]!=0) {smg_buf[4]=smg_code[fre_out/1000%10];} else{smg_buf[4]=0;}
if(fre_out/100%10!=0||smg_buf[4]!=0) {smg_buf[5]=smg_code[fre_out/100%10];} else{smg_buf[5]=0;}
if(fre_out/10%10!=0||smg_buf[5]!=0) {smg_buf[6]=smg_code[fre_out/10%10];} else{smg_buf[6]=0;}
smg_buf[7]=smg_code[fre_out%10];
}
if(set1==0&&set0==1)
{
smg_buf[0]=0x71;
smg_buf[1]=0;
smg_buf[2]=0;
smg_buf[3]=smg_code[A[0]];
smg_buf[4]=smg_code[A[1]];
smg_buf[5]=smg_code[A[2]];
smg_buf[6]=smg_code[A[3]];
smg_buf[7]=smg_code[A[4]];
if(smg_ss){smg_buf[state+3]=0;}
}
if(set1==1)
{
if(mode3==0)
{
smg_buf[0]=0x71;
smg_buf[1]=smg_code[1];
smg_buf[2]=0;
smg_buf[3]=smg_code[F1[0]];
smg_buf[4]=smg_code[F1[1]];
smg_buf[5]=smg_code[F1[2]];
smg_buf[6]=smg_code[F1[3]];
smg_buf[7]=smg_code[F1[4]];
if(smg_ss){smg_buf[f_1+3]=0;}
}
if(mode3==1)
{
smg_buf[0]=0x71;
smg_buf[1]=smg_code[2];
smg_buf[2]=0;
smg_buf[3]=smg_code[F2[0]];
smg_buf[4]=smg_code[F2[1]];
smg_buf[5]=smg_code[F2[2]];
smg_buf[6]=smg_code[F2[3]];
smg_buf[7]=smg_code[F2[4]];
if(smg_ss){smg_buf[f_2+3]=0;}
}
if(mode3==2)
{
smg_buf[0]=0x71;
smg_buf[1]=smg_code[3];
smg_buf[2]=0;
smg_buf[3]=0;
smg_buf[4]=0;
smg_buf[5]=smg_code[F3[0]];
smg_buf[6]=smg_code[F3[1]];
smg_buf[7]=smg_code[F3[2]];
if(smg_ss){smg_buf[f_3+5]=0;}
}
if(mode3==3)
{
smg_buf[0]=smg_code[5];
smg_buf[1]=0x0e;
smg_buf[2]=0;
smg_buf[3]=smg_code[F4[0]];
smg_buf[4]=smg_code[F4[1]];
smg_buf[5]=smg_code[F4[2]];
smg_buf[6]=smg_code[F4[3]];
smg_buf[7]=smg_code[F4[4]];
if(smg_ss){smg_buf[f_4+3]=0;}
}
}
}
void v8253_Process1() //输出频率 1:1~100Hz
{
if(cnt_T1>=200&&cnt_T1%(1000/fre_out)==0) //cnt_T1>=200
{
cnt_T1=0;
T08=10000/fre_out;
Timer0_8253(100);
Timer1_8253(T08);
fre_out=fre_out+1;
if(fre_out>100){ fre_out=1;}
}
}
void v8253_Process2and3() //输出频率 2:100~500; 3:500~1K
{
if(cnt_T0>=100)
{
cnt_T0=0;
if(out_mode==2)
{ fre_out=fre_out+5;
if(fre_out>500){fre_out=100;}
T08=(500000/fre_out);
}
if(out_mode==3)
{ fre_out=fre_out+5;
if(fre_out>1000){fre_out=500;}
T08=(1000000/fre_out);
}
Timer0_8253(T08);
Timer1_8253(2);
}
}
void v8253_Process4and5() //输出频率 4:1K~10KHZ 5:10K~100KHZ
{
if(cnt_T0>=100)
{
cnt_T0=0;
if(out_mode==4)
{ fre_out=fre_out+10;
if(fre_out>10000){fre_out=1000;}
T08=(100000/fre_out);
}
if(out_mode==5)
{ fre_out=fre_out+100;
if(fre_out>100000){fre_out=10000;}
T08=(100000/fre_out);
}
Timer0_8253(T08);
Timer1_8253(10);
}
}
void v8253_Process6() //输出频率6:100K~400K Hz
{
if(cnt_T0>=100)
{
cnt_T0=0;
fre_out=fre_out+100;if(fre_out>400000) fre_out=100000;
T08=(1000000/fre_out);
Timer0_8253(T08);
}
}
bit jiajian;
void v8253_Process7() //输出频率7:1~400kHZ
{
if(cnt_T0>=100)
{
cnt_T0=0;
if(fre_out>1000000) {fre_out=1;jiajian=0;}
if(fre_out>400000&&fre_out<1000000) {fre_out=400000;jiajian=1;}
if(jiajian==0){fre_out+=10;} else {fre_out-=10;}
if(fre_out>100){P25=0;T08=1000000/fre_out;Timer0_8253(T08);}
if(fre_out<100)
{P25=1;T08=10000/fre_out;Timer0_8253(T08);Timer1_8253(100);}
}
}
void v8253_Process9() //模式7快速测试
{
if(cnt_T0>=100)
{
cnt_T0=0;
if(fre_out>1000000) {fre_out=100;jiajian=0;}
if(fre_out>400000&&fre_out<1000000) {fre_out=400000;jiajian=1;}
if(jiajian==0){fre_out+=1000;} else {fre_out-=1000;}
T08=(1000000/fre_out);
Timer0_8253(T08);
}
}
void v8253_Process8() //自由设定频率 16~35535 Hz
{
T08=1000000/fre_out;
Timer0_8253(T08);
}
void v8253_Process10() //自由设置变换频率 16~65535Hz
{
if(cnt_T1>=t_interval)
{
cnt_T1=0;
fre_out=fre_out+f_interval;
if(fre_out>F_end) {fre_out=F_start;}
T08=1000000/fre_out;
Timer0_8253(T08);
}
}
void v8253_Process()
{
switch (out_mode)
{
case 1: v8253_Process1(); break;
case 2: v8253_Process2and3(); break;
case 3: v8253_Process2and3(); break;
case 4: v8253_Process4and5(); break;
case 5: v8253_Process4and5(); break;
case 6: v8253_Process6(); break;
case 7: v8253_Process7(); break;
case 9: v8253_Process9(); break;
case 10: v8253_Process10(); break;
default: break;
}
}
void main()
{
vDevice_Ctrl(0x40,0xff);
Timer0Init();
while(1)
{
v8253_Process();
if(cnt_js>=100)
{
cnt_js=0;
vKBD_Process();
vSmg_Process();
}
}
}
void vTimer0_ISR() interrupt 1
{
TH0=0xfc;
TL0=0x18;
cnt_kbd++;
cnt_js++;
cnt_T0++;
cnt_T1++;
cnt_led++;
cnt_smg++;
if(cnt_smg>=250)
{
cnt_smg=0; smg_ss=~smg_ss;
}
if(s11==1&&set1==0){cnt_cont0++;if(cnt_cont0>=500){cnt_cont0=0; set0=1; state=0; vLED_Process();}}//长按s11
else cnt_cont0=0;
if(s12==1&&set0==0){ cnt_cont1++; if(cnt_cont1>=500)
{cnt_cont1=0;set1=1;vLED_Process1();mode3=0;f_1=f_2=f_3=f_4=0;}} //长按s12
else cnt_cont1=0;
vSmg_Display();
}