📄 111.c
字号:
/*
模块功能:键盘控制ISD录音和放音,并在每段放音结束后,显示下一段起始地址。
完成日期:2007年8月30日
备注: PR端接1为录音,接0为放音。
AN按控制录放音。
STOP控制复位。
*/
//--------------------------------------------函数声明-----------------------------------------------
#include <reg52.h>
#include <absacc.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define LINE1 0
#define LINE2 1
#define LINE1_HEAD 0x80
#define LINE2_HEAD 0xC0
#define LCD_DELAY_TIME 40
#define DATA_MODE 0x38
#define OPEN_SCREEN 0x0C
#define DISPLAY_ADDRESS 0x80
#define CLEARSCREEN LCD_en_command(0x01)
//common part
#define HIGH 1
#define LOW 0
#define TRUE 1
#define FALSE 0
#define ZERO 0
#define MSB 0x80
#define LSB 0x01
/*******************************************************************/
#define LCDIO P2
sbit LCD1602_RS=P1^4;
sbit LCD1602_RW=P1^5;
sbit LCD1602_EN=P1^6;
//--------------------------------------------变量定义-----------------------------------------------
sbit SS = P3^0; //片选
sbit SCLK = P3^1; //ISD4004时钟
sbit MOSI = P3^2; //数据输入
sbit MISO = P3^3; //数据输出
sbit INT = P3^4; //中断
sbit AN = P1^0; //执行
sbit STOP = P1^1; //复位
sbit PR = P1^2; //PR=1录音,PR=0放音
sbit LED = P1^3; //指示灯
sbit E_CLK =P3^7; //同步时钟输入端
sbit RW_SID=P3^6; //串行数据输入、输出端
unsigned char code tab[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
/******************** LCD PART *************************************/
void LCD_delay(void)
{
unsigned char i;
for(i=LCD_DELAY_TIME;i>ZERO;i--)//be sure lcd reset
;
}
/********************************************************************/
void LCD_en_command(unsigned char command)
{
LCDIO=command;
LCD1602_RS=LOW;
LCD1602_RW=LOW;
LCD1602_EN=LOW;
LCD_delay();
LCD1602_EN=HIGH;
}
/********************************************************************/
void LCD_en_dat(unsigned char dat)
{
LCDIO=dat;
LCD1602_RS=HIGH;
LCD1602_RW=LOW;
LCD1602_EN=LOW;
LCD_delay();
LCD1602_EN=HIGH;
}
/********************************************************************/
void LCD_set_xy( unsigned char x, unsigned char y )
{
unsigned char address;
if (y == LINE1)
address = LINE1_HEAD + x;
else
address = LINE2_HEAD + x;
LCD_en_command(address);
}
/********************************************************************/
void LCD_write_char( unsigned x,unsigned char y,unsigned char dat)
{
LCD_set_xy( x, y );
LCD_en_dat(dat);
}
/********************************************************************/
void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s)
{
LCD_set_xy( X, Y ); //set address
while (*s) // write character
{
LCDIO=*s;
LCD_en_dat(*s);
s ++;
}
}
/********************************************************************/
void LCD_init(void)
{
CLEARSCREEN;//clear screen
LCD_en_command(DATA_MODE);//set 8 bit data transmission mode
LCD_en_command(OPEN_SCREEN);//open display (enable lcd display)
LCD_en_command(DISPLAY_ADDRESS);//set lcd first display address
CLEARSCREEN;//clear screen
}
/********************************************************************/
/*********************** OTHER PART *********************************/
void delay_nms(unsigned int n)
{
unsigned int i=0,j=0;
for (i=n;i>0;i--)
for (j=0;j<1140;j++);
}
/********************************************************************/
//--------------------------------------------------------------------------------------------------
// 函数名称: delaynms
// 入口参数: n:延时的毫秒数
// 函数功能: 延时N毫秒
//--------------------------------------------------------------------------------------------------
void delaynms(uchar n)
{
uchar i,j;
for(i=0;i<n;i++)
for(j=0;j<120;j++)
;
}
//===========================================ISD驱动模块============================================//
//--------------------------------------------------------------------------------------------------
// 函数名称: YS50
// 入口参数: 无
// 函数功能: 延时25ms,ISD4003上电后需要延时
//--------------------------------------------------------------------------------------------------
void YS50()
{
delaynms(25);
/*
TMOD=1;
TH0=0x3C; //50mS延时初值置入
TL0=0xB0;
TR0=1;
while(!TF0);
TF0=0;
TR0=0;*/
}
//--------------------------------------------------------------------------------------------------
// 函数名称: ISDX
// 入口参数: d:要发送的命令
// 函数功能: 向ISD发送单字节命令
//--------------------------------------------------------------------------------------------------
void ISDX(unsigned char d)
{
unsigned char i,j;
SS=0; //开片选
SCLK=0; //时钟SCLK=0
j=d;
for(i=0;i<8;i++)
{
if(j&0x01) //数据写 MOSI
MOSI=1;
else
MOSI=0;
SCLK=1; //时钟SCLK=1
j=j>>1;
SCLK=0; //时钟SCLK=0
}
SS=1;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: ISDX1
// 入口参数: d:要发送的指令字
// 函数功能: 向ISD发送2字节命令
//--------------------------------------------------------------------------------------------------
void ISDX1(unsigned int d)
{
unsigned char i;
unsigned int j;
SS=0; //开片选
SCLK=0; //时钟SCLK=0
j=d;
for(i=0;i<16;i++)
{
if(j&0x0001) //数据写 MOSI
MOSI=1;
else
MOSI=0;
SCLK=1; //时钟SCLK=1
j=j>>1;
SCLK=0; //时钟SCLK=0
}
SS=1;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: UP
// 入口参数: 无
// 函数功能: ISD上电
//--------------------------------------------------------------------------------------------------
void UP()
{
ISDX(0x20); //发00100XXXXXXXXXXX
SS=1; //关片选
YS50(); //50mS延时
YS50(); //50mS延时
}
//--------------------------------------------------------------------------------------------------
// 函数名称: STOPP
// 入口参数: 无
// 函数功能: ISD停止当前操作
//--------------------------------------------------------------------------------------------------
void STOPP()
{
ISDX(0x30); //发 0X110XXX
SS=1; //关片选
YS50(); //50mS延时
YS50(); //50mS延时
}
//--------------------------------------------------------------------------------------------------
// 函数名称: DSTOP
// 入口参数: 无
// 函数功能: ISD停止当前操作并掉电
//--------------------------------------------------------------------------------------------------
void DSTOP()
{
ISDX(0x10); //发0X010XXXXXXXXXX
SS=1; //关片选
YS50(); //50mS延时
YS50(); //50mS延时
}
//--------------------------------------------主函数-----------------------------------------------
void main(void)
{
bit key_flag=1; //延时参数
uchar i,ad[4]; //ISD高低位
uint isd_addr,temp; //ISD地址,j
unsigned int Seg_Addr=0,seg_addr;
SP=0x10; //初始化
P0=0xFF;
P1=0xFF;
P2=0xFF;
P3=0xFF;
EA=0;
LCD_init();
CLEARSCREEN;
delay_nms(2);
lab:
LED=1; //关指示灯
DSTOP(); //ISD掉电
while(key_flag) //等待AN按下
{
if (AN == 0)
delaynms(10);
if (AN == 0)
{
key_flag=0;
}
;
}
key_flag=1;
UP(); //ISD上电
isd_addr=0x0000; //ISD高低位地址置0
if(PR) //PR=1 录音
{
UP();
temp = isd_addr & 0x07ff ;
isd_addr = temp | 0xa000 ;
ISDX1(isd_addr); //SETREC
rec:
for (i=0; i<6; i++)
{
YS50();
}
LED=0;
ISDX(0xb0); // REC
while(AN == 0) //等待按键放开
{
if (INT == 0) //遇到OVF
{
LED=1;
while(AN == 0) ; //等待按键放开
SCLK=0;
SS=1;
STOPP();
goto lab;
}
;
}
LED=1;
STOPP();
while(AN) //等待AN按键按下
{
if (STOP == 0)
delaynms(10);
if (STOP == 0) //复位
{
SCLK=0;
SS=1;
STOPP();
goto lab;
}
}
STOPP();
goto rec; //按键按下返回录下一段
}
else //PR=0 放音
{
while(AN == 0);
temp = isd_addr & 0x07ff ;
isd_addr = temp | 0xe000 ;
ISDX1(isd_addr); //SETPLAY
play:
LED=0;
ISDX(0xf0); //PLAY
while(INT)
{
if (STOP == 0)
delaynms(10);
if (STOP == 0)
{
SCLK=0;
SS=1;
STOPP();
goto lab;
}
}
LED=1; //遇到EOM或者OVF
STOPP();
//检测OVF --_--
SCLK=1;
SS=0;
for(i=0; i<16; i++) //读当前状态。EOM OVF 和 下一段起始地址
{
_nop_();
_nop_();
SCLK=0;
_nop_();
_nop_();
Seg_Addr = Seg_Addr >> 1;
if(MISO)
{
Seg_Addr = Seg_Addr | 0x8000;
}
SCLK=1;
}
SS=1;
SCLK=0;
STOPP();
if(Seg_Addr & 0x0001)
{
goto lab; //ISD溢出,则复位
}
else //当前段结束
{
seg_addr = Seg_Addr / 4;
ad[0]=tab[(uchar)((seg_addr&0xf000)>>12)];
ad[1]=tab[(uchar)((seg_addr&0x0f00)>>8)];
ad[2]=tab[(uchar)((seg_addr&0x00f0)>>4)];
ad[3]=tab[(uchar)(seg_addr&0x000f)];
LCD_write_char(0,LINE1,ad[0]);
LCD_write_char(1,LINE1,ad[1]);
LCD_write_char(2,LINE1,ad[2]);
LCD_write_char(3,LINE1,ad[3]);
while(AN) //等待AN键按下
{
if (STOP == 0)
delaynms(10);
if (STOP == 0)
{
SCLK=0; //复位
SS=1;
STOPP();
goto lab;
}
}
goto play; //返回播放下一段
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -