📄 receivedata.c
字号:
/******************************************************************
* *
* ME500B片机开发系统演示程序 - 接收 DTMF 编码 *
* *
* LCD1602显示 *
* *
* 版本: V1.0 (2006/11/20) *
* 作者: gguoqing (Email: gguoqing@willar.com) *
* 网站: www.willar.com(伟纳电子) www.mcusj.com(伟纳单片机世界) *
* 邮箱: support@willar.com *
* *
*【版权】Copyright(C)伟纳电子 www.willar.com All Rights Reserved *
*【声明】此程序仅用于学习与参考,引用请注明版权和作者信息! *
* *
******************************************************************/
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit BEEP = P3^7; //蜂鸣器驱动线
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit MT_RS = P2^3;
sbit MT_RW = P2^4;
sbit MT_CS = P2^5;
sbit MT_CK = P2^6;
sbit TEL = P2^7; //电话摘挂机控制线
bit zhenling,playflag,tel_on;
uchar dis_buf=0x00; //显示缓存
uchar temp,count;
uchar T0_Count,m;
uchar code cdis1[ ] = {" RECEIVE DTMF "};
uchar code cdis2[ ] = {"NUM: "};
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
/*************************************************************
* *
* 延时子程序 *
* 晶振 11.0592MHz 延时为1ms *
* *
*************************************************************/
void delay(uint x)
{
uchar j;
while((x--)!=0)
{
for(j=0;j<115;j++)
{;}
}
}
/*************************************************************
* *
*检查LCD忙状态 *
*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据 *
* *
*************************************************************/
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
delayNOP();
result = (bit)(P0&0x80);
LCD_EN = 0;
return(result);
}
/*************************************************************
* *
*写指令数据到LCD *
*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 *
* *
*************************************************************/
void lcd_wcmd(uchar cmd)
{
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/************************************************************
* *
*写显示数据到LCD *
*RS=H,RW=L,E=高脉冲,D0-D7=数据。 *
* *
************************************************************/
void lcd_wdat(uchar dat)
{
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
delayNOP();
LCD_EN = 1;
delayNOP();
LCD_EN = 0;
}
/************************************************************
* *
* LCD初始化设定 *
* *
************************************************************/
void lcd_init()
{
delay(15);
lcd_wcmd(0x38); //16*2显示,5*7点阵,8位数据
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x38);
delay(5);
lcd_wcmd(0x0c); //显示开,关光标
delay(5);
lcd_wcmd(0x06); //移动光标
delay(5);
lcd_wcmd(0x01); //清除LCD的显示内容
delay(5);
}
/************************************************************
* *
* 设定显示位置 *
* *
************************************************************/
void lcd_pos(uchar pos)
{
lcd_wcmd(pos | 0x80); //数据指针=80+地址变量
}
/************************************************************
* *
* LCD显示函数 *
* *
************************************************************/
void lcd_play()
{
if(dis_buf>9) //转换为ASCII码
dis_buf = dis_buf+0x37;
else
dis_buf = dis_buf+0x30;
lcd_pos(0x44+T0_Count);
lcd_wdat(dis_buf); //显示编码
}
/************************************************************
* *
* 延时 x*0.14ms *
* *
************************************************************/
void delay0(uchar x)
{
unsigned char i;
while(x--)
{
for (i = 0; i<13; i++) {;}
}
}
/************************************************************
* *
* 蜂鸣器响一声 *
* *
************************************************************/
void beep()
{
unsigned char i;
for (i=0;i<180;i++)
{
delay0(6);
BEEP=!BEEP; //BEEP取反
}
BEEP=1; //关闭蜂鸣器
delay(400); //延时
}
/*************************************************************
* *
* MT8880 写状态函数 *
* RS=1,RW=0,写状态寄存器 *
* *
*************************************************************/
void write_status(uchar value)
{
MT_RS =1;
MT_RW =0;
MT_CK =0;
P1 = value; //写 8880CRA和CRB.
MT_CK =1;
delayNOP();
MT_CK =0;
}
/*************************************************************
* *
* MT8880 读状态函数 *
* RS=1,RW=1,读状态寄存器 *
* *
*************************************************************/
uchar read_status()
{
uchar dat;
P1=0xff; //置P1为输入状态
MT_RS=1;
MT_RW =1;
_nop_();
_nop_();
MT_CK =1;
_nop_();
_nop_();
dat=P1;
_nop_();
_nop_();
MT_CK =0;
return(dat);
}
/*************************************************************
* *
* MT8880 初始化函数 *
* *
*************************************************************/
void MT_INIT()
{
MT_CS=0; //MT8880使能
delayNOP();
write_status(0x10); //写 8880CRA,CRA=0000.
write_status(0x10); //写 8880CRA,CRA=0000.
write_status(0x18); //写 8880CRA,CRA=1000,允许选择CRB.
write_status(0x10); //写 8880CRB,CRB=0000
// MT_CS=1; //禁止MT8880工作
}
/*************************************************************
* *
* MT8880 中断初始化函数 *
* *
*************************************************************/
void MT_IRQ_INIT()
{
// MT_CS=0;
delayNOP();
write_status(0x14); //写8880CRA,8880模式1为DTMF,IRQ
delay(1000);
EX0=1; //允许外部EX0中断
temp=0x00;
dis_buf=0x00;
delay(1000);
}
/***********************************************************
*
* 振铃信号中断函数
*
***********************************************************/
void ex_t1() interrupt 2
{
EX1 =0;
count++;
if(count==0x03)
{
count=0x00;
zhenling=1;
EX1 =0;
}
else
EX1=1;
}
/***********************************************************
*
* 中断接收DTMF函数
* RS=0,RW=1,读接收数据寄存器.
*
***********************************************************/
void ex_t0() interrupt 0
{
EX0=0;
read_status();
P1=0xff;
MT_RS=0;
MT_RW=1;
MT_CK=0;
_nop_();
_nop_();
MT_CK=1;
_nop_();
_nop_();
temp=P1; //读MT8880接收数据寄存器
temp=temp & 0x0f;
MT_CK=0;
playflag=1; //显示标志置1
}
/************************************************************
* *
* 主程序 *
* *
************************************************************/
void main()
{
P0=0xff; //置P0口
P1=0xff; //置P1口
P2=0xff; //置P2口
P3=0xff; //置P3口
delay(100); //上电延时
MT_CS=1; //禁止MT8880工作
lcd_init(); //初始化LCD
lcd_pos(0); //设置显示位置为第一行
for(m=0;m<16;m++)
lcd_wdat(cdis1[m]);
lcd_pos(0x40); //设置显示位置为第二行
for(m=0;m<16;m++)
lcd_wdat(cdis2[m]);
temp=0x00; //有关单元清零
dis_buf=0x00;
playflag=0;
zhenling=0;
count=0;
IT0=1; //设置中断触发方式:下降沿触发
IT1=1; //设置中断触发方式:下降沿触发
EA =1; //总的中断允许
EX1=1; //允许外部中断EX1中断
while(1)
{
while(!zhenling); //等待振铃信号出现
if(zhenling)
{
TEL = 0; //摘机
zhenling=0; //振铃标志
tel_on=1; //摘机标志
delay(2000); //等待电话线路稳定
}
while(tel_on)
{
MT_INIT(); //MT8880初始化
MT_IRQ_INIT();
while(temp!=0x0c)
{
if(playflag)
{
dis_buf=temp;
lcd_play();
playflag=0;
T0_Count++;
if(temp==0x0b) //"*"
{
beep(); //蜂鸣器响2声
beep();
}
EX0=1; //显示完毕开中断
}
if(T0_Count==0x0d) // 一行是否显示完?
{
lcd_pos(0x40); //设置显示位置为第二行
for(m=0;m<16;m++)
lcd_wdat(cdis2[m]);
T0_Count=0x00;
dis_buf=temp;
lcd_play();
T0_Count++;
}
} //end of while(temp!=0x0c)
if(temp==0x0c) //"#"
{
for(m=0;m<4;m++) //蜂鸣器响4声
beep();
TEL = 1; //挂机
lcd_pos(0x40); //设置显示位置为第二行
for(m=0;m<16;m++)
lcd_wdat(cdis2[m]);
T0_Count=0x00;
temp=0x00;
dis_buf=0x00;
playflag=0;
tel_on=0;
MT_CS=1; //禁止MT8880工作
EX0=0;
EX1=1;
}
} //end of while(tel_on)
} //end of while(1)
} //end of main()
/*************************************************************
* RS=1,RW=0,写状态寄存器 *
* RS=1,RW=1,读状态寄存器 *
* RS=0,RW=0,写发送寄存器 *
* RS=0,RW=1,读接收数据寄存器 *
*************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -