#include <AT892051.H>
//这是中青世纪开发的“PM50语音组合发码板”的单片机程序,设计用AT89C2051与PM50串行模式接口的程序范例,使用晶振11.0592MHZ,单片机管理一个键盘,例如当用户按键"6*12*37*1*63#"时,将控制PM50连续播放第6、第12、第37、第1、第63段,如果只按#号,将播放上一次组合播放的内容。这样以实现语音组合.
//PM50串行模式下,无论一段语音的长度多少,第1段语音在地址80H,第2段在81H,如此,最多128段。PM50的串行时钟为10HZ~100KHZ,建议使用1KHZ。
//以下是“PM50语音组合发码板”的原理图纸:
//以下是AT89C2051的程序设计
//I/O脚的定义
#define key_port P1
#define tx_pin P3_1 //数据脚
#define clk_pin P3_7 //时钟脚
#define busy_pin P3_2 //BUSY脚
#define test_pin P3_3 //测试脚
#define test_clk P3_4
#define low 0
#define high 1
typedef unsigned char byte;
unsigned int key_time;
unsigned int delay_time;
unsigned int input_time;
byte key_buf[21];
byte key_tmp[21];
byte key,last_key;
byte key_input;
byte sound_number;
byte play_number;
bit read;
bit play;
//延时子程序 单位 MS
void delay(byte t)
{
EA = 0;
delay_time = 0;
EA = 1;
while(delay_time < t);
}
void send_play(byte sound_no)
{
byte sd = sound_no + 0x80; //第一段为80H
byte loop;
tx_pin = low;
delay(45); //启动延时 45MS
tx_pin = high;
delay(1);
//now send data
for(loop = 0;loop < 8; loop++) //发送数据 8个
{
clk_pin = low;
tx_pin = sd & 0x01;
sd = sd >> 1;
delay(1); //发送频率 1 KHZ
clk_pin = high;
delay(1);
}
tx_pin = high;
}
//测试程序
void test(byte t)
{
byte loop;
byte sd = t;
for(loop = 0;loop < 8; loop++)
{
test_clk = low;
test_pin = sd & 0x01;
sd = sd >> 1;
delay(1);
test_clk = high;
delay(1);
}
test_pin = high;
}
//键盘处理
byte get_key()
{
byte tmp;
key_port = 0x6f;
for(tmp = 0; tmp <10;tmp++);
tmp = key_port & 0x0f;
if(tmp != 0x0f)
return tmp+0x10;
key_port = 0x5f;
for(tmp = 0; tmp <10;tmp++);
tmp = key_port & 0x0f;
if(tmp != 0x0f)
return tmp+0x20;
key_port = 0x3f;
for(tmp = 0; tmp <10;tmp++);
tmp = key_port & 0x0f;
if(tmp != 0x0f)
return tmp+0x40;
//no key on
return 0;
}
byte proc_key(byte key)
{
switch(key)
{
case 0x1e: return 12; //#
case 0x1d: return 10; //9
case 0x1b: return 7; //6
case 0x17: return 4; //3
case 0x2e: return 1; //0
case 0x2d: return 9; //8
case 0x2b: return 6; //5
case 0x27: return 3; //2
case 0x4e: return 11; //*
case 0x4d: return 8; //7
case 0x4b: return 5; //4
case 0x47: return 2; //1
default: return 0;
}
}
//时钟
void clkint (void) interrupt 1 using 0
{
TR0=0;
TH0=0xfc; /* clk 12mhz */
TL0=0x18; /* set interrupt freq.=1ms */
TR0=1; /* start timer/counter0 */
key_time++;
delay_time++;
input_time++ ;
}
//键盘处理主程序
void do_key()
{
if(key_time > 32) // 32ms to scan key
{
key_time = 0;
key = get_key();
if(key)
key = proc_key(key);
}
else return;
if(input_time > 5000)
{
input_time = 0;
if(sound_number)
{
key_tmp[key_input] = sound_number ;
if(++key_input > 19)
key_input = 19;
}
read = sound_number = 0;
}
if(!key)
{
key = last_key = 0;
return;
}
input_time = 0; //inputing .....
if(key == last_key) return; //rep
last_key = key;
test(key);
switch(key)
{
case 11: // *
if(sound_number)
{
key_tmp[key_input] = sound_number ;
if(++key_input > 19)
key_input = 19;
}
read = sound_number = 0;
break;
case 12: // #
if(sound_number)
{
key_tmp[key_input] = sound_number ;
if(++key_input > 19)
key_input = 19;
}
if(key_input > 0 )
{
for(sound_number = 0; sound_number < 20;sound_number++)
key_buf[sound_number] = 0;
for(sound_number = 0; sound_number < key_input;sound_number++)
key_buf[sound_number] = key_tmp[sound_number];
}
play = 1;
key_input = 0;
sound_number = 0;
play_number = 0;
read = 0;
break;
default:
if(read)
{
sound_number = (sound_number-1) * 10 + key;
read = 0;
}
else
{
sound_number= key;
read = 1;
}
break;
}
}
//主程序
void main(void)
{
//初始化
P1 = 0xff;
P3 = 0xff;
for(key_time = 0; key_time<21;key_time++)
{
key_buf[key_time] = 0;
key_tmp[key_time] = 0;
}
key_time = 0;
input_time = 0;
key_input = 0;
last_key = 0;
sound_number = 0;
read = play = 0;
play_number = 0;
TMOD = TMOD|0x01; // init Timer0 mode
TF0 = 0;
TR0=0;
TH0=0xfe;
TL0=0xc3;
TR0=1; // start timer/counter 0
ET0 = 1;
EA = 1;
//主循环
while(1)
{
do_key();
if(play)
{
if(key_buf[play_number])
{
if(!busy_pin)
send_play(key_buf[play_number++]-2);
}
else
play = 0;
}
}
}
|