/****************************************************************** //总体电路设计采用总线控制方式 //对外围器件的访问统一采用地址编码方式 //2011-02-18 ******************************************************************/ #include #include #include #include //包含绝对地址定义的头文件 #define ADC XBYTE[0x7FF0] //ADC 0通道地址 #define ADC_CTRL 0xFD //ADC 控制信号 #define DAC XBYTE[0x6FFF] //DAC 地址 #define DAC_CTRL 0xFC //DAC 控制信号 //RAM地址范围为 0x8000~0xffff (共4页) //ADC的地址范围为 0x7ff0~0x7ff7 (共8个通道) //DAC的地址范围为 0x6fff (只要低2位为 ff 即可) static unsigned int RAM_address; //RAM 地址变量,起始地址0x8000 unsigned char count,m,n=1,key = 0xff; //显示字符编码 unsigned char code zifu[]={0x7e, /*0*/ 0x30, /*1*/ 0x6d, /*2*/ 0x79, /*3*/ 0x33, /*4*/ 0x5b, /*5*/ 0x5f, /*6*/ 0x70, /*7*/ 0x7f, /*8*/ 0x7b, /*9*/ 0x0e, /*L*/ 0x47, /*F*/ 0x00, /*无显示*/ }; //ZLG7289接口定义 sbit ZLG7289CS = P1^5; //片选信号,低电平有效 sbit ZLG7289CLK = P1^6; //时钟信号,上升沿有效 sbit ZLG7289DIO = P1^7; //数据信号,双向 sbit ZLG7289INT = P3^2; //键盘中断请求信号,低电平(负边沿)有效 //sbit ADCEOC = P3^3; void delay_us(unsigned char n) //执行一次约为14us { for(;n--;n>0) { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } } //************************************************************************ //短延时 void nNop(unsigned char i) { for(;i>0;i--) ; } //长延时 void LDelay(unsigned int i) { unsigned int j; for(;i>0;i--) { for(j=1000;j>0;j--);} } //************************************************************************ //函数功能:ZLG7289复位指令 #define ZLG7289_Reset() ZLG7289_Instruc(0xa4) //*********************************************************************** //函数:SPI_WriteOneByte() //功能:向SPI总线写数据 //说明:写入的数据长度为1字节 void SPI_WriteOneByte(unsigned char Wdata) { unsigned char i; for(i=0;i<8;i++) { ZLG7289DIO = (bit)(Wdata&0x80); ZLG7289CLK = 1; Wdata <<= 1; nNop(1); ZLG7289CLK = 0; nNop(1); } } //函数:SPI_ReadOneByte() //功能:从SPI总线读数据 //说明:返回1字节数据 unsigned char SPI_ReadOneByte() { unsigned char i,temp; ZLG7289DIO = 1; //将I/O切换到输入状态 for(i=0;i<8;i++) { ZLG7289CLK = 1; nNop(5); temp <<= 1; if(ZLG7289DIO) temp++; ZLG7289CLK = 0; nNop(5); } return temp; } //函数:ZLG7289_Instruc() //功能:执行ZLG7289纯指令 //说明:指令长度为1字节 void ZLG7289_Instruc(unsigned char Instruc) { unsigned char i; i = IE; IE &= 0xfa; //禁止外部中断; ZLG7289CS = 0; nNop(5); SPI_WriteOneByte(Instruc); ZLG7289CS = 1; nNop(5); IE = i; } //函数:ZLG7289_Instruc_Data //功能:执行ZLG7289带数据指令 //说明:指令长度以及数据长度均为1字节 void ZLG7289_Instruc_Data(unsigned char Instruc,unsigned char Data) { unsigned char i; i = IE; IE &= 0xfa; ZLG7289CS = 0; nNop(5); SPI_WriteOneByte(Instruc); nNop(5); SPI_WriteOneByte(Data); ZLG7289CS = 1; nNop(5); IE = i; } //函数:ZLG7289_ReadKey() //功能:执行ZLG7289读键盘指令 //说明:返回1字节的按键号 // 按键号的范围为:0 ~ 63(即0x0 ~ 0x3f) // 若没有按按键被按下了,返回255(即0xff) unsigned char ZLG7289_ReadKey() { unsigned char Key; ZLG7289CS = 0; nNop(10); SPI_WriteOneByte(0x15); nNop(5); Key = SPI_ReadOneByte(); nNop(1); ZLG7289CS = 1; nNop(5); return Key; } //函数:ZLG7289_Download //功能:下载数据 //说明:将要显示的数据下载到ZLG7289内,并译码显示 //参数:数码管编号x,要显示的数据dat void ZLG7289_Download(unsigned char x,unsigned char dat) { x |= 0x90; //以自己编码的方式进行译码 1001 0xxx ZLG7289_Instruc_Data(x,dat); } //ZLG7289初始化函数 void ZLG7289_Init() { LDelay(20); //延时一定时间,以使系统电源稳定 //ZLG7289 I/O 口初始化 ZLG7289CS = 1; ZLG7289CLK = 0; ZLG7289DIO = 1; ZLG7289INT = 1; } //********************普通录音函数************************* void Record() { unsigned char temp,page,page_ctrl; unsigned int i; for(page=0;page<4;page++) //分4页存储 { switch(page) { case 0:page_ctrl=0xF8;break;//RAM 第一页控制信号 case 1:page_ctrl=0xF9;break;//RAM 第二页控制信号 case 2:page_ctrl=0xFA;break;//RAM 第三页控制信号 case 3:page_ctrl=0xFB;break;//RAM 第四页控制信号 default:break; } RAM_address=0x8000; //RAM地址复位 for(i=0;i<32768;i++) //每页32k字 { //***此处的“>=”条件很重要,少了“>”不行*** if(count >= 18) //考虑到指令执行时间,这里并非1s的时间(相差约几十ms) //11.0592MHz 18 22.1184MHz 39 { count = 0; if(m == 10) //先判断后显示,防止显示不符合正常习惯 { m = 0; ZLG7289_Download(1,zifu[n]); n += 1; if(n==10)n=1; } ZLG7289_Download(0,zifu[m]); m += 1; } P1=ADC_CTRL; //ADC控制有效 ADC=0x00; //启动通道0的ADC转换 delay_us(7); //等待转换结束 11.0592MHz 7 temp = ADC; //读ADC的值 P1=page_ctrl; //RAM分页控制有效 XBYTE[RAM_address++] = temp; delay_us(12); } } m = 0; n = 1; ZLG7289_Download(0,zifu[0]); //录音完毕显示“0” ZLG7289_Download(1,zifu[12]); //录音完毕显示“无显示” } //********************普通放音函数************************* void Play() { unsigned char temp,page,page_ctrl; unsigned int i; for(page=0;page<4;page++) //分4页读取 { switch(page) { case 0:page_ctrl=0xF8;break; case 1:page_ctrl=0xF9;break; case 2:page_ctrl=0xFA;break; case 3:page_ctrl=0xFB;break; default:break; } RAM_address=0x8000; //RAM地址复位 for(i=0;i<32768;i++) //每页32k字 { //***此处的“>=”条件很重要,少了“>”不行*** if(count >= 18) //考虑到指令执行时间,这里并非1s的时间(相差约几十ms) { count = 0; if(m == 10) //先判断后显示,防止显示不符合正常习惯 { m = 0; ZLG7289_Download(1,zifu[n]); n += 1; if(n==10)n=1; } ZLG7289_Download(0,zifu[m]); m += 1; } P1=page_ctrl; //RAM分页控制有效 temp = XBYTE[RAM_address++];//读取RAM中的数据 delay_us(8); //输出和采样等时 11.0592MHz 8 P1=DAC_CTRL; //DAC控制有效 DAC = temp; //DAC输出 } } m = 0; n = 1; ZLG7289_Download(0,zifu[0]); //放音完毕显示“0” ZLG7289_Download(1,zifu[12]); //放音完毕显示“无显示” } //**********************串口初始化函数************************** void UART_init() { SCON = 0X50; //串口工作于模式1 TMOD = 0x20; //T1工作于定时模式2 PCON |= 0x80; //电源管理寄存器(此时单片机正常工作) TL1 = TH1=253; //定时器装值(比特率为9600时的值) 11.0592MHz // TH1 = TL1 = 255; //定时器装值(比特率为57600时的值)22.1184MHz TR1=1; //启动定时器T1 ES = 0; //关串口中断,采用查询方式收发数据 } //***********************串口发送函数************************ void UARTSend() { unsigned char temp,page,page_ctrl; unsigned int i; ZLG7289_Download(0,zifu[11]); //开始发送显示“F” for(page=0;page<4;page++) //分4页读取 { switch(page) { case 0:page_ctrl=0xF8;break; case 1:page_ctrl=0xF9;break; case 2:page_ctrl=0xFA;break; case 3:page_ctrl=0xFB;break; default:break; } RAM_address=0x8000; //RAM地址复位 for(i=0;i<32768;i++) //每页32k字 { P1=page_ctrl; //RAM分页控制有效 temp = XBYTE[RAM_address++];//读取RAM中的数据 SBUF=temp; //将RAM中的数据发送出去 while(!TI); //等待数据发送完毕 TI=0; //为下次发送数据做准备 } } ZLG7289_Download(0,zifu[12]); //发送完毕显示“无显示” } //***********************串口接收函数************************ void UARTReceive() { unsigned char temp,page,page_ctrl; unsigned int i; for(page=0;page<4;page++) //分4页存储 { switch(page) { case 0:page_ctrl=0xF8;break;//RAM 第一页控制信号 case 1:page_ctrl=0xF9;break;//RAM 第二页控制信号 case 2:page_ctrl=0xFA;break;//RAM 第三页控制信号 case 3:page_ctrl=0xFB;break;//RAM 第四页控制信号 default:break; } RAM_address=0x8000; //RAM地址复位 for(i=0;i<32768;i++) //每页32k字 { while(!RI); //等待接收数据 RI=0; //为下次接收做准备 temp = SBUF; //读串口发送来的数据 P1=page_ctrl; //RAM分页控制有效 XBYTE[RAM_address++] = temp; } } } void main() { unsigned char k; ZLG7289_Init(); //初始化ZLG7289 ZLG7289_Reset(); //复位ZLG7289 UART_init(); //串口初始化 EA = 0; TMOD |= 0x01; //T0工作于16位定时模式 TH0 = (65536-50000)/256; TL0 = (65536-50000)%256; ET0 = 1; //使能定时/计数器T0中断 TR0 = 1; //启动定时/计数器T0 // IT0 = 1; //外部中断0选择边沿触发方式 EX0 = 1; //打开外部中断0 EA = 1; //开总中断 while(1) { k = key; key = 0xff; switch(k) { case 0: Record();break; case 1: Play();break; case 2: UARTReceive();break; case 3: UARTSend();break; default: break; } } } //外部中断0服务函数 void Int0(void) interrupt 0 { key = ZLG7289_ReadKey(); } //定时计数器0中断服务函数 void T0int() interrupt 1 { TH0 = (65536-48000)/256; TL0 = (65536-48000)%256; count += 1; }