大家好,又见面了,我是你们的朋友全栈君。
main.c
#include "config.h"
//矩阵按键扫描头文件
#include "anjian.h"
//1602显示头文件
#include "1602.h"
#include "music.h"
sbit LED=P1^0;
u8 code key[]={
'0','1','2','3','4','5','6','7','8','9','*','#'};//3*4手机拨号键盘号码
u8 code title[]="- phone number -";
u8 keynum=12;
//数字缓冲区
u8 Number_Str[]={
" "};
u8 i=0,j;
//设定工作方式
void port()
{
TMOD=0x21; //(定时器T0工作方式1、软启动、定时,驱动蜂鸣器);(T1工作方式2、软启动,设置串口波特率)
//串口初始化
TH1=0xfd; //波特率9600
TL1=0xfd;
TR1=1;
PCON=0x00;
SCON=0X40;//串口工作方式1,8位异步收发,(REN=0)不允许接收
//定时器初始化,驱动蜂鸣器发声
TH0=63628/256;
TL0=63628%256; //根据蜂鸣器频率设置计数初值
}
void init()
{
EA=1;
EX0=1;//允许外部中断0
IT0=1;//下降沿引发外部中断
EX1=1;//允许外部中断1
IT1=1;//下降沿引发外部中断
}
void main()
{
port();
LCD_Init();//使用前初始化
display_char(title,0x00);
while(1)
{
keynum=keyscan();//扫描按键
init();
if(keynum<12)
{
EA=0;//关键:两个定时器同时使用时,在串口收发时,最好把EA关掉,处理完后在将EA打开。
SBUF=key[keynum];
while(!TI);//检测发送标志位TI, TI=0,未发送完
TI=0;//一个字节发送完,TI清0
//打开蜂鸣器
EA=1;
ET0=1; //允许计数器T0中断
TR0=1; //启动计数器T0驱动蜂鸣器
sound(keynum);
delay(300);
BEEP=1; TR0=0;//停止定时器,关闭蜂鸣器
if(keynum==0xFF) continue;
if(++i == 12) //超过十一位时清空
{
for(j=0;j<16;j++)
Number_Str[j]=' ';
i=0;
}
Number_Str[i]=key[keynum];
display_char(Number_Str,0x40);
}
}
}
//外部中断0
void EX_INT0() interrupt 0 /*INT0中断服务程序*/
{
LED=~LED;
for(j=0;j<16;j++)
Number_Str[j]=' ';
i=0;
display_char(Number_Str,0x40);
}
//外部中断1
void EX_INT1() interrupt 2 /*INT0中断服务程序*/
{
PlayMusic(); //播放生日快乐
}
void Time0() interrupt 1//定时器T0中断
{
TH0 = TH00;
TL0 = TL00;
BEEP = ~BEEP;
}
anjian.h
#include "config.h"
u8 keyscan()//手机拨号盘按键扫描函数:要去抖,若有按键按下,返回对应的按键值(0-9,*-10,#-12),否则返回16
{
unsigned char i,key=16,row,temp;//初值设置为16,目的是:没有按键按下时返回16;若不设初值(默认值为0),没有按键按下时,将返回0,会误认为0被按下
row=0xef;
for(i=0;i<4;i++)
{
P2=0xff;
P2=row;
row=_crol_(row,1);
temp=P2;
temp=temp&0x0f;
if(temp!=0x0f)
{
delay(20);
temp=P2;
temp=temp&0x0f;
if(temp!=0x0f)
{
switch(temp)
{
case 0x0e:key=1+i*3;break;
case 0x0d:key=2+i*3;break;
case 0x0b:key=3+i*3;
}
do{
temp=P2;
temp=temp&0x0f;
}while(temp!=0x0f); //等待按键释放
}
}
}
if(key==11) key=0;
if(key==12) key=11;
return(key);//没找到
}
//按键音
void sound(u8 keynum)
{
switch(keynum)
{
case 0:TH00=0xf3;TL00=0x07;break; //低3
case 1:TH00=0xf3;TL00=0xc8; break; //低4
case 2:TH00=0xf5;TL00=0x1e; break; //低5
case 3:TH00=0xf6;TL00=0x4c; break; //低6
case 4:TH00=0xf7;TL00=0x5a; break; //低7
case 5:TH00=0xf7;TL00=0xd8; break; //中1
case 6:TH00=0xf8;TL00=0xbd; break; //中2
case 7:TH00=0xf9;TL00=0x87; break; //中3
case 8:TH00=0xf9;TL00=0xe4; break; //中4
case 9:TH00=0xfa;TL00=0x90; break; //中5
case 10:TH00=0xfb;TL00=0x29; break; //中6
case 11:TH00=0xfb;TL00=0xb1; break; //中7
case 12:TH00=0xfb;TL00=0xef; break; //高1
case 13:TH00=0xfc;TL00=0x62; break; //高2
case 14:TH00=0xfc;TL00=0xc7; break; //高3
case 15:TH00=0xfc;TL00=0xf6; break; //高4
}
TH0=TH00;
TL0=TL00;
// TR0=1;
}
music.h
#include "config.h"
//生日快乐歌的音符频率表,不同频率由不同的延时来决定
u8 code SONG_TONE[]={
201,212,190,212,159,169,212,212,190,212,142,159,
212,212,106,126,159,169,190,119,119,126,159,142,159,0};
//生日快乐歌节拍表,节拍决定每个音符的演奏长短
u8 code SONG_LONG[]={
9,3,12,12,12,24,9,3,12,12,12,24,9,3,12,12,12,12,12,9,3,12,12,12,24,0};
void PlayMusic()
{
u16 i=0,j,k;
while(SONG_LONG[i]!=0||SONG_TONE[i]!=0)
{ //播放各个音符,SONG_LONG为拍子长度
for(j=0;j<SONG_LONG[i]*20;j++)
{
BEEP=~BEEP;
//SONG_TONE延时表决定了每个音符的频率
for(k=0;k<SONG_TONE[i]/3;k++);
}
delay(10);
i++;
}
}
1602.h
/*****************************显示输入文本数字等*********************************************/
void display_char(u8 *point, u8 address)
{
unsigned char i;
WrComLCD(0x80 + address);
for (i=0;i<16;i++)
{
WrDatLCD(*point);
point++;
}
}
/*****************************显示变量(三位数)*********************************************/
void display(int number, unsigned char address)
{
unsigned char b,c,d;
b = (number/100);
c = (number/10)%10;
d = (number/1)%10;
WrComLCD(0x80+address);
WrDatLCD(b+48);
WrDatLCD(c+48);
WrDatLCD(d+48);
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/132195.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...