校园短号号码的接收与显示电路的软硬件设计
- 这次的实验是我的课程设计
课题的内容:话机通过解码电路把按键值输入到单片机中,在通过单片机显示在数码管上,要求话机按下时,数码管显示该数值,按下一次时,数码管之前的数值向前移,同时显示当前的按键值,相当于模拟拨号过程,本次实验,模拟6位号码即可
硬件电路部分
解码电路
解码电路就是把话机按下按键的号码以二进制的形式传给单片机
- MT8870芯片
- 输入与解码表
- 解码电路原理图
原理图中红点的地方焊接时要放置排针,以便检测和连线接电。
芯片的15脚是DTMF信号检测输出,当芯片接收到双音多频信号时,15脚输出高电平,15脚通过反相器接到单片机的外部中断0引脚。
- 电路分析
我们主要分析的电路时基于MT8870的接收器部分电路,对AT89S52最小系统不作分析。电路P3模块接话机两端,作为话机的信号输入端。而12V则为话机的供电,我们在实验室采取的为15V的稳压直流电源。C4,C5两电容为隔只电容,以减小话机信号的输入干扰。2脚为话机信号的输入端。7,8脚为晶振输入端,我们采用的晶振是3.58M的晶振,此电路晶振没接接地电容,最小系统版的晶振的接地电容起到的作用是反馈,稳定振荡的作用。引脚5,6:IC为内部连接点,应接至VSS端;引脚15:DV为延迟控制输出,当一组有效的双音频信号被接收时输出“1”;否则输出“0”。当有信号输出时,15脚高电平,基极与发射极正偏,集电极低电平,基极与集电极正偏,三极管进入饱和状态,中断发生。J2针脚连P3.2口,以作为中断源输入口。 11脚—14脚为16种DTMF信号所对应的4位二进制并行码数据输出端,分别姐AT89C52的P1口的低四位;具体的真值表图如下图。而最小系统所起的作用的是接收输入的四位二进制数据,之后对应DTMF信号的真值表,译出按键值,因为数码管显示限制,数码管只能显示数字0-9,不能显示*和#,而显示的位数只能显示8位,话机输入信号,数码管将显示其按键值,随着信号输入,显示数字不断左移。
单片机部分
开发板我们实验室是采用 STC15F2K16S2 芯片的开发板
STC15F2K16S2管脚图
- MT8870芯片的D1~D4分别连接至开发板的P10~P13 IO口,①处则接开发板的外部中管口,即P32口
数码管显示
- 实验室开发板上的数码管为8段8位的共阳极数码管,P0口控制数码管的段码,P2口控制数码管的位码;数码管的显示原理之前就有写过
软件编程
编程思路
首先观察MT8870的解码表,话机的按键值的二进制即是D1~D4的输出值,而这个值我们刚好可以当数码管显示的段码;而每次按键时,显示位数都要+1,这里就可以设置个变量控制数码管显示的位数,因为是按下按键时才变化,所以这个变量可以放在中断里来控制;而要显示6个不同的数字,可以设6个变量来储存按键按下的数值,作数码管显示的缓冲区
流程图
程序编写
#include <STC15F2K60S2.H>
#include "intrins.h"
#define u8 unsigned char //定义一个全局常量
u8 code smgduan[]={0xff,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xc0};//共阴 段码表 P0
u8 code smgwei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40};//位码表 P2
//u8 code smgbuff[]={0x10,0x10,0x10,0x10,0x10,0x10}; //数码管缓冲区,初值0x10是为了让数码管右下角的点不亮
u8 Number1,Number2,Number3,Number4,Number5,Number6; // 用来存储号码
u8 k = 0; //定义全局变量
void Delay1ms(); //声明延时程序
void Delay20ms();
/*数码管显示函数*/
void smg_display()
{
Number1 = P1&0x0f; //读取电话输入的数值,并把高四位置0
if(k >= 1) P0 = smgduan[Number1]; P2 = smgwei[0]; Delay1ms(); P0 = 0xff; //
if(k >= 2) P0 = smgduan[Number2]; P2 = smgwei[1]; Delay1ms(); P0 = 0xff;
if(k >= 3) P0 = smgduan[Number3]; P2 = smgwei[2]; Delay1ms(); P0 = 0xff;
if(k >= 4) P0 = smgduan[Number4]; P2 = smgwei[3]; Delay1ms(); P0 = 0xff;
if(k >= 5) P0 = smgduan[Number5]; P2 = smgwei[4]; Delay1ms(); P0 = 0xff;
if(k >= 6) P0 = smgduan[Number6]; P2 = smgwei[5]; Delay1ms(); P0 = 0xff;
}
/*主函数*/
void main()
{
EA =1 ; //中断总开关打开
EX0 = 1; //外部中断0中断允许位打开
IT0 = 1; //设置外部中断0为下降沿触发
while(1)
{
smg_display(); //循环数码管显示函数
}
}
/*外部中断0函数*/
void exint0() interrupt 0
{
if(!P32) //检测中断请求
{
Delay20ms(); //延时消抖
if(!P32)
{
k++; //k自加
if(k > 6)
{
k = 1; //重置k
}
Number6=Number5;Number5=Number4;Number4=Number3; //把已经读取的按键值传递到下一个变量让数码管显示
Number3=Number2;Number2=Number1;
}
while(!P32); //等待按键松开
}
}
/*延时函数*/
void Delay1ms() //@12.000MHz 延时程序1ms
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void Delay20ms() //@12.000MHz 延时程序20ms
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 1;
j = 234;
k = 113;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
之前的调试
测试时,发现第一个数码管不亮,而是从第二个数码管开始亮的
u8 code smgwei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40};
后发现调用数组第一个数据[]里是从0开始的,所以最后我把
smgwei[]
里的第一位放一个0xff
让它跳过
拨号时,第一位显示正常,但在按下第二位时,数码管是显示了两位,但之前显示的数值也变成当前按键值,在拨号时,又全都显示为按的那个号
if(k >= 1) P0 = smgduan[Number1]; P2 = smgwei[0]; Delay1ms(); P0 = 0xff; //Number2=Number1; if(k >= 2) P0 = smgduan[Number2]; P2 = smgwei[1]; Delay1ms(); P0 = 0xff; //Number3=Number2;
后发现是我变量赋值的位置放错了,因为数码管显示程序一直在while(1)里循环,所以它一直在移位赋值,导致全都显示为最新的拨号值,而我们预想结果的是拨一次号时,才让变量移位赋值一次,所以该语句应放在中断程序里面。
最终效果
上传不了视频。。。。。。GIF又太大。。。