📄 mt8880.c
字号:
/*
;00-12-13 16:19
;---------------------------------------------------------------
忙音: 450Hz,350ms有,350ms无
700ms内156次,700ms内计数小于230次,认为忙音
;---------------------------------------------------------------
拨号音: 450Hz,持续
700ms内315次,700ms内计数大于230次,认为拨号音
;---------------------------------------------------------------
回铃音: 450Hz,1s有,4s无
;---------------------------------------------------------------
振铃音判断:
INT1产生中断,开放T0,1s内INT1中断>10次,认为是振铃音
50ms内无第2次INT1中断,延时400ms转入CP模式,探测拨号音(500ms超时)
有,返回B_OCCUPY=1,有人占用电话线
无,判断线上电平,1--正常返回,0--返回断线
回铃音判断:
拨本地电话: 拨号后200ms有回铃音,长1.6s(2段回铃音0.6s+1s)
拨移动电话: 拨号后8.5s有回铃音,长160ms,1.5s后出现第2个回铃音
拨号后立即计数脉冲,延时11s,一旦计数>50,跳出11s循环,等待2s后判断脉冲信号,延时1s,
若1s内无脉冲信号,确认电话拨通
若脉冲信号,确认电话忙音;同样,11s超时也确认为电话忙音.
*/
#include <reg51.h>
#include <intrins.h>
/* MT8880C操作 */
sbit p_MTirq = P3 ^ 2;
sbit p_MTcs = P1 ^ 6;
sbit p_MTrw = P1 ^ 7;
sbit p_MTrs0 = P1 ^ 5;
sbit p_MTclk = P1 ^ 4;
sbit p_MTb0 = P1 ^ 3;
sbit p_MTb1 = P1 ^ 2;
sbit p_MTb2 = P1 ^ 1;
sbit p_MTb3 = P1 ^ 0;
unsigned char bdata MT8880Status;
sbit b_MTSRDIrq = MT8880Status ^ 0; // 低4位为状态位
sbit b_MTSRDTdre = MT8880Status ^ 1;
sbit b_MTSRDRdrf = MT8880Status ^ 2;
sbit b_MTSRDDs = MT8880Status ^ 3; //
sbit b_mtdial = MT8880Status ^ 4;
sbit b_mtburst = MT8880Status ^ 5;
unsigned char data MTDataTemp;
unsigned char b_cpdly;
unsigned char w_buf[10];
unsigned char code Led_Tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,
0xf8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0x27,0x9}; //共阳极数码显示码0-F,c\H.
unsigned char code Led_Sel[]={0xe,0xd,0xb,0x7};//{0x01,0x02,0x04,0x08,0x10,0x20};//{0xe,0xd,0xb,0x7}
unsigned char Led_Buf[4]; //显示缓冲区
char Led_Index;//位选
sbit P1_2 = 0X92;
sbit P1_0 = 0X90;
sbit P1_6 = 0X96;
sbit P3_1 = 0XB1;
sbit P3_6 = 0XB6;
sbit P3_7 = 0XB7;
/* 子函数(子程序)说明
void timer0(void);
void Mt8880Ini (void);
void MtDtmfMode ( void );
void MtBurstMode ( void );
void MtCPMode ( void );
void MtEXBMode ( void );
void MtSDRRead ( void );
void MtREGRead ( void );
void MtSend ( void )
*/
//==============================================================
//数码管扫描
void timer0() interrupt 1 using 1
{
TL0=0x52;
TH0=0xf6; //定时器0设定约2.479ms中断一次,用于数码管扫描描
P0=0xff;
//for(i=0;i<72;i++);
P2=Led_Sel[Led_Index]; //位选
P0=Led_Tab[Led_Buf[Led_Index]]; //段选
if(++Led_Index>3) Led_Index=0; //四个扫描完了,到第一个数码管
}
//=====================================================================
// 初始化,系统上电1s后调用
void Mt8880Ini (void) {
p_MTrs0=1;
p_MTrw=1;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1; //读
_nop_ ();
_nop_ ();
p_MTclk=0;
p_MTcs=1;
p_MTrs0=1; //;1
p_MTrw=0; //;0
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
p_MTb0=0;
p_MTb1=0;
p_MTb2=0;
p_MTb3=0;
_nop_ ();
p_MTclk=0; //;写CRA
p_MTcs=1;
p_MTrs0=1; //;1
p_MTrw=0; //;0
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
p_MTb0=0;
p_MTb1=0;
p_MTb2=0;
p_MTb3=0;
_nop_ ();
p_MTclk=0; //;写CRA
p_MTcs=1;
p_MTrs0=1; //;1
p_MTrw=0; //;0
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
p_MTb3=1;
_nop_ ();
p_MTb0=0;
p_MTb2=0;
p_MTb2=0;
p_MTb3=1;
_nop_ ();
p_MTclk=0; //;写CRA
p_MTcs=1;
p_MTrs0=1; //;1
p_MTrw=0; //;0
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
p_MTb3=0;
_nop_ ();
p_MTb0=0;
p_MTb2=0;
p_MTb2=0;
p_MTb3=0;
_nop_ ();
p_MTclk=0; //写CRB
p_MTcs=1;
p_MTrs0=1; //1
p_MTrw=1; //1
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
_nop_ ();
p_MTclk=0; //读状态寄存器
p_MTcs=1;
MT8880Status=0;
}
// dtmf模式,接收信号,不允许发送
void MtDtmfMode ( void ) {
p_MTrs0=1;
p_MTrw=0;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
//p_MTb0=0;
//p_MTb1=0;
//p_MTb2=1;
//p_MTb3=0;
if(12&0x1) p_MTb0=1;
else p_MTb0=0;
if(12&0x2) p_MTb1=1;
else p_MTb1=0;
if(12&0x4) p_MTb2=1;
else p_MTb2=0;
if(12&0x8) p_MTb3=1;
else p_MTb3=0;
_nop_ ();
p_MTclk=0; //DTMF模式,无输出,IRQ开放,
p_MTcs=1;
p_MTrs0=1;
p_MTrw=0;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
if(0&0x1) p_MTb0=1;
else p_MTb0=0;
if(0&0x2) p_MTb1=1;
else p_MTb1=0;
if(0&0x4) p_MTb2=1;
else p_MTb2=0;
if(0&0x8) p_MTb3=1;
else p_MTb3=0;
_nop_ ();
p_MTclk=0; //BURST模式
p_MTcs=1;
IT0=1; /* 边沿触发 */
EX0=1; //IE=0x81; /* 允许中断,开中断 */
}
// burst模式,发50ms,停50ms,然后送出中断信号
void MtBurstMode ( void ) {
p_MTrs0=1;
p_MTrw=0;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
if(13&0x1) p_MTb0=1;
else p_MTb0=0;
if(13&0x2) p_MTb1=1;
else p_MTb1=0;
if(13&0x4) p_MTb2=1;
else p_MTb2=0;
if(13&0x8) p_MTb3=1;
else p_MTb3=0;
_nop_ ();
p_MTclk=0;
p_MTcs=1;
p_MTrs0=1;
p_MTrw=0;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
if(0&0x1) p_MTb0=1;
else p_MTb0=0;
if(0&0x2) p_MTb1=1;
else p_MTb1=0;
if(0&0x4) p_MTb2=1;
else p_MTb2=0;
if(0&0x8) p_MTb3=1;
else p_MTb3=0;
_nop_ ();
p_MTclk=0;
p_MTcs=1;
}
// cp模式,检测电话拨号音,回铃音
void MtCPMode ( void ) {
p_MTrs0=1;
p_MTrw=0;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
if(14&0x1) p_MTb0=1;
else p_MTb0=0;
if(14&0x2) p_MTb1=1;
else p_MTb1=0;
if(14&0x4) p_MTb2=1;
else p_MTb2=0;
if(14&0x8) p_MTb3=1;
else p_MTb3=0;
_nop_ ();
p_MTclk=0;
p_MTcs=1;
p_MTrs0=1;
p_MTrw=0;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
if(1&0x1) p_MTb0=1;
else p_MTb0=0;
if(1&0x2) p_MTb1=1;
else p_MTb1=0;
if(1&0x4) p_MTb2=1;
else p_MTb2=0;
if(1&0x8) p_MTb3=1;
else p_MTb3=0;
_nop_ ();
p_MTclk=0;
p_MTcs=1;
}
// 扩展burst模式,发送100ms,停100ms,没有中断输出
void MtEXBMode ( void ) {
p_MTrs0=1;
p_MTrw=0;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
if(15&0x1) p_MTb0=1;
else p_MTb0=0;
if(15&0x2) p_MTb1=1;
else p_MTb1=0;
if(15&0x4) p_MTb2=1;
else p_MTb2=0;
if(15&0x8) p_MTb3=1;
else p_MTb3=0;
_nop_ ();
p_MTclk=0;
p_MTcs=1;
p_MTrs0=1;
p_MTrw=0;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
if(0&0x1) p_MTb0=1;
else p_MTb0=0;
if(0&0x2) p_MTb1=1;
else p_MTb1=0;
if(0&0x4) p_MTb2=1;
else p_MTb2=0;
if(0&0x8) p_MTb3=1;
else p_MTb3=0;
_nop_ ();
p_MTclk=0;
p_MTcs=1;
}
// mt8880特殊寄存器读取函数
void MtSDRRead ( void ) {
unsigned char mtbusreg;
if(15&0x1) p_MTb0=1;
else p_MTb0=0;
if(15&0x2) p_MTb1=1;
else p_MTb1=0;
if(15&0x4) p_MTb2=1;
else p_MTb2=0;
if(15&0x8) p_MTb3=1;
else p_MTb3=0;
p_MTrs0=1;
p_MTrw=1;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
mtbusreg <<= 1;
if(p_MTb3) mtbusreg++;
mtbusreg <<= 1;
if(p_MTb2) mtbusreg++;
mtbusreg <<= 1;
if(p_MTb1) mtbusreg++;
mtbusreg <<=1;
if(p_MTb0) mtbusreg++;
_nop_ ();
p_MTclk=0;
p_MTcs=1;
mtbusreg &= 0x0f;
MT8880Status&=0xf0;
MT8880Status+=mtbusreg;
}
// mt8880接收寄存器读取函数
void MtREGRead ( void ) {
p_MTrs0=0;
p_MTrw=1;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
_nop_ ();
MTDataTemp <<= 1;
if(p_MTb3) MTDataTemp++;
MTDataTemp <<= 1;
if(p_MTb2) MTDataTemp++;
MTDataTemp <<= 1;
if(p_MTb1) MTDataTemp++;
MTDataTemp <<=1;
if(p_MTb0) MTDataTemp++;
_nop_ ();
p_MTclk=0;
p_MTcs=1;
MTDataTemp &= 0x0f;
}
// 将数据送入mt8880的发送寄存器
void MtSend ( void ) {
p_MTrs0=0;
p_MTrw=0;
p_MTcs=0;
_nop_ ();
_nop_ ();
p_MTclk=1;
if(MTDataTemp&0x1) p_MTb0=1;
else p_MTb0=0;
if(MTDataTemp&0x2) p_MTb1=1;
else p_MTb1=0;
if(MTDataTemp&0x4) p_MTb2=1;
else p_MTb2=0;
if(MTDataTemp&0x8) p_MTb3=1;
else p_MTb3=0;
_nop_ ();
p_MTclk=0;
p_MTcs=1;
}
/*
//我的思想是:
//mt8880的irq脚接单片机中断,并且需要一个定时器配合。我是用int1,timer1
unsigned char cpdly; // 延时
unsigned int stcount; // 脉冲计数
bit b_mtirq;
void int1_dtmf (void) interrupt 2 using 2 {
stcount++;
b_mtirq=1;
}
#define TL1_VALUE 0x78 // 0xec78=60536 -- 10ms,6MHz晶振
#define TH1_VALUE 0xec
void timer0 (void) interrupt 3 using 2 {
if(cpdly) cpdly--;
TL1 += TL1_VALUE;
TH1 += TH1_VALUE;
}
// 拨号音检测
bit judgestone (void) {
unsigned char i;
MtCPMode();
stcount=0;
cpdly=(1000);
b_cpdly=0;
while (cpdly) { // 等待第一个脉冲,1s延时
if(b_mtirq) {
cpdly=(700); // 接收到第一个脉冲,700ms检测时间
break;
}
}
if(b_mtirq) {
while(cpdly); // 等待延时结束
if(stcount>200) return (1); // 正确
}
else return (0); // 没有中断,无拨号音
}
// 回铃音检测
bit judgesatone (void) {
unsigned char i,j;
MtCPMode();
stcount=0;
for(j=0;j<12;j++) { // 12s延时
cpdly=(1000);
b_cpdly=0;
while (cpdly) { // 等待第一个脉冲,1s延时
if(b_mtirq) {
cpdly=(700); // 接收到第一个脉冲,700ms检测时间
break;
}
}
if(b_mtirq) {
while(cpdly); // 等待延时结束
if(stcount>200) return (1); // 正确
}
}
return (0); // 12s后返回错误
}
*/
void Delay(unsigned char l)
{
unsigned char j;
while(l-- != 0)
{
for(j=0;j<72;j++);
}
}
// 接收中断服务程序
void int0(void) interrupt 0 using 1
{
P3_6=0;
MtREGRead ();//读取接收寄存器
}
void main()
{
Led_Index=1;
TMOD=0x11;//
TL0=0x52;
TH0=0xf6; //定时器0设定约2.479ms中断一次,用于数码管扫描?
EA=1;
ET0=1;
TR0=1;
Led_Buf[0]=0;
Led_Buf[1]=1;
Led_Buf[2]=2;
Led_Buf[3]=3; //显示区设成0
Delay(250);
Mt8880Ini (); //初始化
MtDtmfMode (); //接收
while(1)
{
Led_Buf[0]=MTDataTemp;
Led_Buf[1]=4;
Led_Buf[2]=5;
Led_Buf[3]=6;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -