ISD1760录放音程序
是用模拟SPI实现的,能直接用硬件SPI实现么? 楼主你程序里的I_delay();是多长时间?几个NOP? 我用了18个NOP(),硬件SPI当然可以,我的51单片机不带SPI才模拟的! 谢谢噢,程序很规范,注释简单明了,一看就懂。我用了你的程序硬件,模拟都能PLAY,STOP,接下来弄分段录和放,还没弄懂里面的存储结构。还在看资料。 呵呵!我的也是参考其他的程序,不过自己加上注释了,我的项目就用这个程序的啊,当然能用了。 那裡有卖ISD1760? 价格大概怎样? 25块,随便GOOGLE一下到处都是! 可惜还没有发现邮购网站在卖ISD1760
不知Armok会否考虑一下, 因为语音芯片应用算广泛 有个网站在卖语音芯片的拷贝机,有ISD1700些列的。
叫中青世纪。好像是www.atvoc.com 20RMB左右 不错,正好参考,谢谢 好像不好用 今天我是特意来感谢楼主的,最近本人也在用ISD1740,在楼主提供的这些程序中,我用了一天的时间就把这款语音芯片用会了,自己搭电路进行录音,又把各段的语音地址读出来通过串口输出到电脑,所以现在已实现了通过SPI命令播放指定的语音段,大大方便了实际应用,呵呵,感谢楼主的帮助啊。我的QQ是:564465382,愿与各位同仁交流单片机技术问题。 互相学习,甭客气! 你好!我在用你的程序。
定点播放序我有不明白处 :GetToneAdd函数 中的 caToneAdd是如何定义的
/**************************************************************************
* 函数原型: void SetPLAY(uchar cNum);
* 功 能: 定点播放
**************************************************************************/
void SetPLAY(uchar cNum){
uint Add_ST, Add_ED;
uchar Add_ST_H, Add_ST_L, Add_ED_H, Add_ED_L;
do{
RdStatus();
DogReset();
}while((SR0_L&0x01)||(!(SR1&0x01))); //if(SR0_L^0==1){system Err}<CMD_Err==1>
ClrInt();
GetToneAdd(cNum, &Add_ST, &Add_ED);
Add_ST_L=(uchar)(Add_ST&0x00ff);
Add_ST_H=(uchar)((Add_ST>>8)&0x00ff);
Add_ED_L=(uchar)(Add_ED&0x00ff);
Add_ED_H=(uchar)((Add_ST>>8)&0x00ff);
ISD_SendData(SET_PLAY);
ISD_SendData(0x00);
ISD_SendData(Add_ST_L); //S7:S0开始地址
ISD_SendData(Add_ST_H); //S10:S8
ISD_SendData(Add_ED_L); //E7:E0结束地址
ISD_SendData(Add_ED_H); //E10:E8
ISD_SendData(0x00);
SS=1;
delay_ms(10); //延迟10ms
do{
RdStatus();
DogReset();
}while((SR0_L&0x01)||((SR1&0x04))); //if(SR0_L^0==1){system Err}<CMD_Err==1>
}
/**************************************************************************
* 函数原型: void GetToneAdd(uchar cNum, Uint * ipStartAdd, Uint * ipEndAdd);
* 功 能: 取出当前语音的首末地址
**************************************************************************/
/*
void GetToneAdd(uchar cNum, uint * ipStartAdd, uint * ipEndAdd){
*ipStartAdd=caToneAdd;
*ipEndAdd=caToneAdd;
} 已经很清楚的说明了是首末地址了,就是要根据你的语音时间长度以及所用语音芯片的型号,计算填写录放音的地址。
定义一个数组,往里面连续写上录放音的起始和末尾地址就可以了! 谢谢你的回答:
我清楚了,是要自己用每段语音的首末地址定义一个数组;cNum 代表语音段的序号
我已录好了几段音,怎样获得它门每段的语音的首末地址? 谢谢你的回答:
我清楚了,是要自己用每段语音的首末地址定义一个数组;cNum 代表语音段的序号
我已录好了几段音,怎样获得它门每段的语音的首末地址? 谢谢你的回答:
我清楚了,是要自己用每段语音的首末地址定义一个数组;cNum 代表语音段的序号
我已用独立按键模式录好了几段音,怎样获得它门每段的语音的首末地址? 语音的首末地址是依据数据手册规定的范围自己定义的,当然语音的长度以及采样率是决定首末地址长度空间的。 谢谢你,具体的地址我还是的不到。
我已用独立按键模式录好了几段音,怎样获得它门每段的语音的首末地址?
能否把用独立按键模式录好的isd1760装到SPI模式电路里用RD_PLAY_PTR指令读出其地址,
我试了一下不成功,不知为何? 谢谢你,具体的地址我还是得不到。
我已用独立按键模式录好了几段音,怎样获得它门每段的语音的首末地址?
能否把用独立按键模式录好的isd1760装到SPI模式电路里用RD_PLAY_PTR指令读出其地址,
我试了一下不成功,不知为何? 楼主的程序非常好.我是参考该程序,操作1730的.谢谢! 所有楼上的高手们能否发个电路图上来啊,十分感谢... 这也要图纸?好好看看手册,都有标准的图纸。帮楼主上传一下
点击此处下载 ourdev_354690.pdf(文件大小:638K) (原文件名:1700zhongwenshiyongshouce.pdf) 小弟新手,程序中
#definePU 0x01
#defineSTOP 0x02
#defineRESET 0x03
#defineCLI_INT 0x04
#defineRD_STATUS 0x05
#defineRD_PLAY_PTR 0x06
#definePD 0x07
#defineRD_REC_PTR 0x08
#defineRD_DEVID 0x09
#defineG_ERASE 0x43
#defineRD_APC 0x44
#defineWR_APC1 0x45
#defineWR_APC2 0x65
#defineWR_NVCFG 0x46
#defineCHK_MEM 0x49
#defineSET_PLAY 0x80
#defineSET_REC 0x81
#defineSET_ERASE 0x82
这些的依据在哪里啊!我上网查资料好长时间没有搞明白啊,望指点..谢谢 ... 原厂手册
点击此处下载 ourdev_354692.pdf(文件大小:351K) (原文件名:ISD1700h.pdf) 小弟新手,程序中
#definePU 0x01
#defineSTOP 0x02
#defineRESET 0x03
#defineCLI_INT 0x04
#defineRD_STATUS 0x05
#defineRD_PLAY_PTR 0x06
#definePD 0x07
#defineRD_REC_PTR 0x08
#defineRD_DEVID 0x09
#defineG_ERASE 0x43
#defineRD_APC 0x44
#defineWR_APC1 0x45
#defineWR_APC2 0x65
#defineWR_NVCFG 0x46
#defineCHK_MEM 0x49
#defineSET_PLAY 0x80
#defineSET_REC 0x81
#defineSET_ERASE 0x82
这些的依据在哪里啊!我上网查资料好长时间没有搞明白啊,望指点..谢谢 ...
依据在这里,好好看看阿,真的看资料了吗?
http://www2.ourdev.cn/bbs/bbs_upload83560/files_10/ourdev_354690.pdf 谢谢,还在研究中,希望以后多多指点.. 能否解释一下,子函数unsigned char isd_send data(uchar buf_isd)的过程
谢谢, 还用就是,返回值为unsigned char,那这些值都返回哪里去了啊... http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_355090.jpg
赚阿莫一条裤子穿真是不容易啊! (原文件名:未命名.jpg) 我已经从原来公司离职了,原理图是随便画的,ISD1760周围期间是要参照手册接,我就省略了。 【30楼】 yangxu0703
具体操作过程请查看数据手册的SPI操作时序。
谢谢:【28楼】 pulan 普兰
上传原厂数据手册 uchar ISD_SendData(uchar BUF_ISD){
uchar i,
dat=BUF_ISD;//要发送给ISD1760的数据
SCLK=1;
SS=0;
for(i=0;i<8;i++){//8位数据逐位发送
SCLK=0;
I_delay();
if(dat&0x01){
MOSI=1;
}
else{
MOSI=0;
}
dat>>=1;
if(MISO){
dat|=0x80;
}
SCLK=1;
I_delay();
}
MOSI=0;
// SS=1;
return(dat); //返回给MCU数据
} 谢谢楼主的精心讲解,十分的感谢...以后还多向你学习..谢谢 http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_355550.jpg
(原文件名:未命名.jpg) http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_355551.jpg
(原文件名:未命名.jpg) 多谢,最近在搞这个,一直没有弄明白,谢谢你的资料.. 还想问一下,这个要是用抵挡点的,比如AT89S52能实现吗!谢谢! 以下蓝色文字由站长:armok 于:2008-07-21,19:56:13 加入。
--------------------------------------------------------------------------------
贴子很好,但需要补充一些材料才能置成酷贴
谢谢你的共享。只是一堆源代码,没有电路图会大幅降低帖子的交流效果。
请将电路图也上传上来,这样本贴就能置COOL,会有更多的人关注,并且能获得本论坛的专家分数(迟些会实施)
你可以编辑本贴上传电路图,或在后面的回复里上传。谢谢对我们网站的支持。
-------------------------------------------------------------------------------------------------------
现在有图了.
阿莫加发裤子啊. 完全可以用89S52实现。 不错。有空搞搞。 楼主你好``我有很多地方不懂,希望多多请教
我才接触单片机 C语言不久
“以下是SPI.H
#ifndef _SPIEX_
#define _SPIEX_ ”
这两个定义是什么意思?
“#include "typedef.h" ”
这个头文件是什么?
怎么我在keil uVison里面查找不到
我是想用AT89S51实现,这里是用STC的,这里应该注意哪些问题? 楼主你好:
我正在做一语音报温计,如何用AT89S51实现下面功能
功能:用ISD1700来实现读温度,比如27.5摄氏度,先分段录制声音:1,2,3,4,5,6,7,8,9,十,点,温度,摄氏度。读27.5摄氏度时,再分段找地址,读出相应的数。
我把SPI.H中的sbit SS = P4^3;
sbit SCLK = P4^2;
sbit MOSI = P4^1;
sbit MISO = P4^0;改为
sbit SS = P2^3;
sbit SCLK = P2^2;
sbit MOSI = P2^1;
sbit MISO = P2^0;
还有用KEIL调试时出错,要caToneAdd[]的大小,SetPLAY(),SetREC()有类型错误,
用80C51时,P3^0,P3^1应注意什么?
谢谢楼主! 还有一点,怎样分段寻址呀,望楼主给写主函数main()的思路 caToneAdd[]里面就是定义语音段的起始和结束地址,必须要结合语音长度以及采样频率还有数据手册,用人工计算的方法填上,你最好仔细看看手册介绍。 语音段的起始和结束地址到底怎么求能不能举个例子来说呢?
比如说用的是1760,第一段露了10s,第二段录了5s
怎么求得它们的起始和结束地址``?
谢谢 电路图里面的倒三角是接地的意思吗? 我有一点明白了:手册说,“芯片存储地址从第一个提示音的地址0X0000开始计算,但是0x000-0x00F地址平均保留给了4个提示音。从0x010地址开始,才是非保留的存储区域,即真正的录音区。”
也就是从0x010到0xFF 共有0x0FF-0x010+1=240位地址
如果用的是1760,60s的芯片,一共60s,也就是每s就对应4位地址
如果第一段录了10s,那么第一段的开始地址是0x010,
结束地址是0x010+10*4=0x010+0x028=0x038
是不是这样??(也就是芯片默认的可录的60s是不包括提示音的吧?) 手册说:“芯片存储地址从第一个提示音的地址0X0000开始计算,但是0x000-0x00F地址平均保留给了4个提示音。从0x010地址开始,才是非保留的存储区域,即真正的录音区。”
从0x010地址开始,应该在0x07FF结束吧?地址有11位呀(S0-S10,E0-E10) 请问楼主extern voidI_delay(void);
extern void DogReset(void) reentrant;
这俩子函数的内容是什么呀?谢谢 我当时看的是手册里面的存储结构
它里面画的是010到FF,所以我就理所当然那样认为
不过你那么一说也有道理呢,可是这样一来就除不尽了。。。。怎么办呢
7FF-10+1=2032
除60除不尽了嘛
到底怎么回事~
http://cache.amobbs.com/bbs_upload782111/files_10/ourdev_359070.jpg
存储结构图 (原文件名:未命名.jpg) 关于前面也有人问uchar ISD_SendData(uchar BUF_ISD)函数
我有一个地方不明白,就是
if(MISO){
dat|=0x80;
}
这是什么意思呢?
根据循环应该是8位,也就是SR0低8位的内容,也就是
这8位从低到高是: CMD-ERR, FULL, POWER, EOM, INT,A0,A1,A2;
解释是“这些数据中如果有‘1’,就执行括号的内容。。“
为什么要这样执行呢`
括号内的按位或又有什么意义呢?请指教呀 今天试验了一下,
真正的录音区就是从0x010到0xFF 共有0x0FF-0x010+1=240位地址 ,但不知道extern void DogReset(void) reentrant;是什么意思?内容是什么? 那是清看门狗子程序。 看了楼主的的模拟SPI时序,来发一个纯硬件SPI的ISD17xx驱动,由于我只用到了其中放音功能,所以录音,及擦除功能没有使用,所以这些函数没有加上去,如果你要用加起来应该很简单的. 程序用M8做的实验,我的电路中有一个LED和一个按键,实际产品用的M64,编译器用的IAR(希望发此贴不会引起关于什么版权问题,所在公司小买不起正版).关于播放地址的表格是实际产品的表格,你要自己修改以适应你的语音内容,电路图参考楼主的,没什么东西,通讯接口连好就OK,通讯速率250k(示波器上测量的,不是计算结果)不知能否再快点
//***************************************************************************************************
//MYDECLARE.H
#ifndef __MYDECLARE__
#define __MYDECLARE__
#include <avr_macros.h> //引用宏定义
#include <intrinsics.h> //引用本征库函数
#include <stdbool.h> //引用BOOL变量
//简化本征库函数的书写
#define NOP __no_operation //空操作
#define SLEEP__sleep //休眠
#define CLI __disable_interrupt //禁止中断
#define SEI __enable_interrupt //充许中断
#define WDR __watchdog_reset //看门狗复位
//==============================================================================
#define CPU_F 8000000ULL//8M的晶振
#define DELAY_US(USCNT) __delay_cycles(((CPU_F)*(USCNT)/1000000))
typedef unsigned char UCHAR;
typedef unsigned intUINT;
typedef unsigned long ULONG;
typedef unsigned char BYTE;
typedef unsigned intWORD;
typedef unsigned long DWORD;
#endif
//***************************************************************************************************
//ISD1700.H
#ifndef __ISD1700__
#define __ISD1700__
//==============================================================================
//语音段干起始地址
#define VOICE_SEGMENT10x10 //声音片断1地址
#define VOICE_SEGMENT20x1E
#define VOICE_SEGMENT30x26
#define VOICE_SEGMENT40x2F
#define VOICE_SEGMENT50x38
#define VOICE_SEGMENT60x49
#define VOICE_SEGMENT70x51
#define VOICE_SEGMENT80x58
#define VOICE_SEGMENT90x61
#define VOICE_SEGMENT10 0x72
#define VOICE_SEGMENT11 0x7B
#define MAX_SOUND_ID 0x0A//最大声音索引,数组中最后一位为结束地址
#define INVALID_SOUND_ID 0xFF//无效声音ID
//==============================================================================
//语音芯片控制命令
#define ISD_PWRUP 0x01 //ISD芯片上电
#define ISD_PU 0x01
#define ISD_STOP 0x02 //停止当前操作
#define ISD_RESET 0x03 //ISD芯片复位
#define ISD_CLRINT 0x04 //清除EOM标志和中断信号
#define ISD_RDSTATUS 0x05 //返回状态寄存器的内容
#define ISD_RDPLAYPTR0x06 //返回状态和放音指针
#define ISD_PWRDOWN 0x07 //芯片下电
#define ISD_PD 0x07
#define ISD_RDRECPTR 0x08 //返回状态和录音指针
#define ISD_RDDEVID 0x09 //读取芯片ID
#define ISD_PLAY 0x40 //从当前地址放音
#define ISD_REC 0x41 //从当前地址录音
#define ISD_ERASE 0x42 //擦除当前段
#define ISD_ERASEALL 0x43 //擦除所有当前段
#define ISD_RDAPC 0x44 //返回状态寄存器和
#define ISD_WRAPC 0x45 //将<D11:D0>写入APC寄存器
#define ISD_WRAPCVOL 0x65 //将<D11:D0>写入APC寄存器,并由<D2:D0>控制音量
#define ISD_WRNVCFG 0x46 //将APC的内容写非易失存储器
#define ISD_LDNVCFG 0x47 //将NVCFG的内容装入APC中
#define ISD_FWD 0x48 //将放音指针指向下一段语音起始地址
#define ISD_CHKMEM 0x49 //检测环形存储
#define ISD_ENEXTCLK 0x4A //使能外部时钟
#define ISD_SETPLAY 0x80 //按指定地址放音
#define ISD_SETREC 0x81 //按指定地址录音
#define ISD_SETERASE 0x82 //按指定地址擦除
//==============================================================================
struct ISD_STATUS
{
unsigned char SR0_L;
unsigned char SR0_H;
unsigned char SR1;
};
//==============================================================================
void isd_init(void); //芯片初始化
void isd_setapc2(void); //设置APC(带音量)
void isd_reset(void); //芯片复位
void isd_pu(void); //芯片上电
UCHAR isd_senddata(UCHAR data); //发送一个字节
bool isd_is_free(void); //返回当前是否为空闲状态
bool isd_is_done(void); //当前操作是否完成
void isd_play(void); //播放当前段;
void isd_wrnvcfg(void); //APC配置写入永久记录
void isd_clearint(void); //清除中断
UCHAR isd_readid(void); //读芯片ID
void isd_stop(void); //停止
void isd_pd(void); //芯片掉电
void isd_setplay(UINT st_addr, UINT end_addr); //播放指定段
struct ISD_STATUS isd_rdstatus(void); //读取状太,返回在一个全局结构中
void isd_playid(UCHAR SoundID); //播放指定片断
void isd_forward(void); //播放指针跳到下一首
//==============================================================================
#endif
//***************************************************************************************************
//ISD1700.C
#include <iom8.h>
#include "mydeclare.h"
#include "isd1700.h"
#define SpiSS PORTB_Bit2 //定义SS端口
//static struct ISD_STATTUS isd_status; //ISD 状诚返回结果
//==============================================================================
//语音片断地址表
__flash static unsigned char isd_seg_addr=
{
//存放播放地址起始位置,结束位置定为上一位置结束位置
0x10, 0x1E, 0x26, 0x2F,
0x38, 0x49, 0x51, 0x58,
0x61, 0x72, 0x7B, 0xFF
};
//==============================================================================
void isd_init(void) //初始化ISD1700
{
isd_reset();
while(!isd_is_free());
isd_pu();
while(!isd_is_free());
isd_setapc2();
while(!isd_is_free());
isd_clearint();
}
//==============================================================================
//ISD1700发送一字节的数据
UCHAR isd_senddata(UCHAR data) //要在外部保证SS = 0
{
SPDR = data;
while((SPSR & 0x80) == 0);
data = SPDR;
return data;
}
//==============================================================================
//检测ISD1700当前是否为空闲状态
bool isd_is_free() //
{
UCHAR status;
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_RDSTATUS);
isd_senddata(0x00);
status = isd_senddata(0x00);
SpiSS = 1;
if((status & 0x01) == 0x01)
return true;
else
return false;
}
//==============================================================================
void isd_setapc2(void)
{
//初始化APC寄存器,音量最大,关模拟输出,遇到EOM标志自动结束
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_WRAPCVOL);
isd_senddata(0xA0); //音量最大
isd_senddata(0x00);
SpiSS = 1;
}
//==============================================================================
void isd_reset(void) //复位MCU
{
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_RESET);
isd_senddata(0x00);
SpiSS = 1;
}
//==============================================================================
void isd_pu(void) //芯片上电
{
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_PU);
isd_senddata(0x00);
SpiSS = 1;
}
//==============================================================================
void isd_wrnvcfg(void) //写APC寄存器到非易失存储器
{
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_WRNVCFG);
isd_senddata(0x00);
SpiSS = 1;
}
//==============================================================================
void isd_play() //播放当前段
{
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_PLAY);
isd_senddata(0x00);
SpiSS = 1;
}
//==============================================================================
void isd_clearint(void)
{
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_CLRINT);
isd_senddata(0x00);
SpiSS = 1;
}
//==============================================================================
UCHAR isd_readid(void)
{
unsigned char isd_id;
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_RDDEVID);
isd_senddata(0x00);
isd_id = isd_senddata(0x00);
SpiSS = 1;
return isd_id;
}
//==============================================================================
void isd_stop(void) //停止当前操作
{
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_STOP);
isd_senddata(0x00);
SpiSS = 1;
}
//==============================================================================
void isd_pd(void) //芯片下电
{
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_PD);
isd_senddata(0x00);
SpiSS = 1;
}
//==============================================================================
bool isd_is_done(void)
{
unsigned char SR0_L;
SpiSS = 0;
DELAY_US(5);
SR0_L = isd_senddata(ISD_RDSTATUS);
isd_senddata(0x00);
isd_senddata(0x00);
SpiSS = 1;
if((SR0_L & 0x10) != 0) //SR0_L_bit4 为INT位表示操作是否完成
return true;
else
return false;
}
//==============================================================================
struct ISD_STATUS isd_rdstatus(void)
{
struct ISD_STATUS status;
SpiSS = 0;
DELAY_US(5);
status.SR0_L = isd_senddata(ISD_RDSTATUS);
status.SR0_H = isd_senddata(0x00);
status.SR1 = isd_senddata(0x00);
SpiSS = 1;
return status;
}
//==============================================================================
void isd_forward(void)
{
SpiSS = 0;
DELAY_US(5);
isd_senddata(ISD_FWD);
isd_senddata(0x00);
SpiSS = 1;
}
//==============================================================================
void isd_setplay(UINT st_addr, UINT end_addr) //播放指定地址
{
SpiSS = 0;
DELAY_US(5);
//isd_clearint();
//while(!isd_is_free()); //等待空闲
isd_senddata(ISD_SETPLAY);
isd_senddata(0x00);
isd_senddata(st_addr & 0xFF);
isd_senddata(st_addr >> 8);
isd_senddata(end_addr & 0xFF);
isd_senddata(end_addr >> 8);
SpiSS = 1;
}
//==============================================================================
void isd_playid(UCHAR SoundID)
{
unsigned int start_addr, end_addr;
if(SoundID > MAX_SOUND_ID)
{
SoundID = MAX_SOUND_ID;
}
start_addr = isd_seg_addr;
end_addr = isd_seg_addr -1;
SpiSS = 0;
DELAY_US(5);
//isd_clearint();
//while(!isd_is_free()); //等待空闲
isd_senddata(ISD_SETPLAY);
isd_senddata(0x00);
isd_senddata(start_addr & 0xFF);
isd_senddata(start_addr >> 8);
isd_senddata(end_addr & 0xFF);
isd_senddata(end_addr >> 8);
SpiSS = 1;
}
//***************************************************************************************************
//MAIN.C
/*通讯过程中缓冲区处理方法
*/
#include <iom8.h> //引用端口及SFR的位定义
#include "MyDeclare.h" //引用自定义头文件
#include "ISD1700.h"
#define LED PORTD_Bit0 //LED
#define KEY PINB_Bit0 //按键
//==============================================================================
//信息
__root unsigned char __flash VerInfo[]@0x1FE0={"Ver 1.0 tomhe666 "__DATE__};
static unsigned char SoundID; //当前需播放的声音片断ID
static unsigned char keylock=0;
//==============================================================================
void main( void )
{
__disable_interrupt(); //禁止中断
DDRB = 0x2C;//SPI端口初始化
PORTB = 0x15; //开启按键上拉
DDRD = 0x01;
PORTD = 0x01; //亮灯
TCCR0 = 0x05; //系统时钟1024分频
TCNT0 = 0;
SPCR = 0x7E; //SPI使能,SCK空闲保持为高电平,数据在上升沿采样,速率为1:128(FOSC/128)
SPSR = 0x01; //使能倍速
DELAY_US(500000);
isd_init(); //初始化语音芯片
while(!isd_is_free());
isd_playid(2);
while(1)
{
TCNT0 = 0;
if((KEY) == 1)
{
keylock = 0;
LED = 0;
}
else
{
LED = 1;
if(keylock != 1)
{
//process key
SoundID++;
if(SoundID > MAX_SOUND_ID)SoundID = 0;
while(!isd_is_free());
isd_playid(SoundID);
keylock = 1;
}
}
while(TCNT0 < 78);
}
} 清看门狗子程序具体内容是什么啊,需不需要硬件支持?谢谢,急用, /**************************************************************************
* 函数原型: void DogReset(void)
* 功 能: 重新设置看门狗
**************************************************************************/
void DogReset(void) reentrant{
WDT_CONTR|=0x10;
} 楼主 为什么我用你的 ISD_Init();都不能运行完,一直在里面循环 还请楼主多多指教 mark TO:
【60楼】 627236799
说明你的程序一直在这里面循环,系统一直出错。
while((SR0_L&0x01)||(!(SR1&0x01))); //if(SR0_L^0==1){system Err}<CMD_Err==1> 谢谢楼主,能不能具体帮我分析一下,是不是硬件那方面的问题 我独立按键模式能运行 顶啊 /**************************************************************************
* 函数原型: void ISD_Init(void);
* 功 能: 初始化
**************************************************************************/
void ISD_Init(void){
ISD_Reset();
do{
ISD_PU();
RdStatus();
DogReset();
}while((SR0_L&0x01)||(!(SR1&0x01))); //if(SR0_L^0==1){system Err}<CMD_Err==1>
SBUF=RD_DevID();//读取芯片ID,----1760为0xa0
ClrInt();
ISD_WR_APC2(0xaf);
RdAPC();
}
要严格按芯片的工作流程来操作。
先复位---上电---读取状态寄存器。注意每一步都要有一定的延时,可能是你操作后的延时时间不够,导致操作失败。
你先确认一下你的晶振频率对应的延时时间够不够。 mark 谢谢楼主 想问下楼主的程序对应的晶振是多少的 我用的是11.0592m stc89c52 11.0592 郁闷了
void ISD_Init(void){
ISD_Reset();
do{
ISD_PU();
RdStatus();
DogReset();
}while((SR0_L&0x01)||(!(SR1&0x01))); //if(SR0_L^0==1){system Err}<CMD_Err==1>
有时间的话请楼主帮我分析下这些数据(是上面的函数对应的数据)
03 00 |01 00| 05 00 00 |05 00 00
复位|上电 |读取状态|读取状态
返回结果
01 80 |01 80| 01 80 00 |01 80 00
我用的是1720的,是不是我硬件有问题 但是独立操作又没问题 SR0_L = 0x01;---> CMD_Err =1;(出错),检查一下上电复位的时间够不够?
SR0_H = 0x80;
SR1 = 0x00;
void ISD_Init(void){
ISD_Reset();
do{
ISD_PU();
//插入100ms延时看看;
RdStatus();
DogReset();
}while((SR0_L&0x01)||(!(SR1&0x01))); //if(SR0_L^0==1){system Err}<CMD_Err==1> /**************************************************************************
* 函数原型: void ISD_SendData(uchar BUF_ISD);
* 功 能: 发送数据
**************************************************************************/
uchar ISD_SendData(uchar BUF_ISD){
uchar i,dat=BUF_ISD;
SCLK=1;
SS=0;
for(i=0;i<8;i++){
SCLK=0;
I_delay();
if(dat&0x01){
MOSI=1;
}
else{
MOSI=0;
}
dat>>=1;
if(MISO){
dat|=0x80;
}
SCLK=1;
I_delay();
}
MOSI=0;
// SS=1;
return(dat);
搂主能把上面的程序详细注释一下吗?我看不懂啊 35楼有说明,你要仔细看啊!
uchar ISD_SendData(uchar BUF_ISD){
uchar i,
dat=BUF_ISD;//要发送给ISD1760的数据
SCLK=1;
SS=0;
for(i=0;i<8;i++){//8位数据逐位发送
SCLK=0;
I_delay();
if(dat&0x01){//逐位发送数据
MOSI=1;
}
else{
MOSI=0;
}
dat>>=1; //右移一位,发送下一位
if(MISO){ //同时读取ISD1760返回的数据
dat|=0x80;
}
SCLK=1;
I_delay();
}
MOSI=0;
// SS=1;
return(dat); //返回给MCU数据
} 多谢楼主的详细解答!
我还想请教一下楼主,在SPI模式下怎么实现录音的?是不是调用函数 SetREC(uchar cNum)后,ISD有录音提示的? markup! 是的,调用SetREC(uchar cNum)后,就直接送语音就可以了。 这两天对照PDF资料仔细看了楼主的程序,明白了不少呀
我也打算选用这个语音芯片了
不过还是想下楼主,如果单用SPI模式录音后,怎么查看每段录音的地址呀
还有我想问下,把按键模式跟SPI模式电路一起用,可以兼容吗?
谢谢楼主了! 录音地址是自己设定好的,你可以通过播放来验证一下!
按键模式跟SPI模式电路一起用,可以兼容 楼主,我还想问一下,资料上的模拟地和数字地在连接的时候有什么要注意的啊?
我想把电脑里已经录好的.wmv文件烧录到芯片里,如果不用拷贝机的话,是不是通过ANA IN引脚输入呀?但它只有一根线怎么跟电脑相连呢,是不是再加跟地线呀?
小弟是新手,还请楼主多指点指点,感谢万分! 好东西,一直想做的,先顶~~~~ 你好! 楼主。我用的是ISD1760参考你的程序,怎么我发送所有的命令好像都在执行RdStatus();这条命令,复位命令也是一样根本不能复位我的程序是这样写的
/*****************************************
语音芯片ISD1760PY程序
*****************************************/
#include <iom128v.h>
#include <macros.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <eeprom.h>
#include <math.h>
/**************宏定义***************************/
#definextal 8 //晶振8MHZ
#define uchar unsigned char // 0~255
#define uintunsigned int // 0~65535
#define ISD_PU 0x01 //ISD芯片上电
#define ISD_STOP 0x02 //停止当前操作
#define ISD_RESET 0x03 //ISD芯片复位
#define ISD_CLR_INT 0x04 //清除EOM标志和中断信号
#define ISD_RD_STATUS 0x05//返回状态寄存器的内容
#define ISD_RD_PLAY_PTR0x06 //返回状态和放音指针
#define ISD_PD 0x07 //芯片下电
#define ISD_RD_REC_PTR 0x08 //返回状态和录音指针
#define ISD_DEVID 0x09 //读取芯片ID
#define ISD_PLAY 0x40 //从当前地址放音
#define ISD_REC 0x41 //从当前地址录音
#define ISD_ERASE 0x42 //擦除当前段
#define ISD_ERASE_ALL 0x43 //擦除所有当前段
#define ISD_RD_APC 0x44 //返回状态寄存器和APC
#define ISD_WR_APC1 0x45 //将<D11:D0>写入APC寄存器
#define ISD_WR_APC2 0x65 //将<D11:D0>写入APC寄存器,并由<D2:D0>控制音量
#define ISD_WR_NVCFG 0x46 //将APC的内容写非易失存储器
#define ISD_LD_NVCFG 0x47 //将NVCFG的内容装入APC中
#define ISD_FWD 0x48 //将放音指针指向下一段语音起始地址
#define ISD_CHK_MEM 0x49 //检测环形存储
#define ISD_EXTCLK 0x4A //使能外部时钟
#define ISD_SET_PLAY 0x80 //按指定地址放音
#define ISD_SET_REC 0x81 //按指定地址录音
#define ISD_SET_ERASE 0x82 //按指定地址擦除
/***********************************************************************/
void InitMCU( void )
{
//MCUCSR&=0x7F;//使能JTAGR接口
MCUCR|=BIT(SRE);//使能外部存储器
XMCRA|=BIT(SRW11);//读写插入两个等待周期
XMCRB|=BIT(XMBK)|BIT(XMM2)|BIT(XMM1)|BIT(XMM0);//使能总线保持功能,屏蔽高位地址
//InitPort(); /* ATmega128的I/O口初始化 */
TIMSK|=BIT(TOIE1)|BIT(TOIE0);//定时器0、1溢出中断使能
//EIFR=0xFF;//INT0--INT7中断标志清零
//EIMSK=BIT(INT1)|BIT(INT4)|BIT(5)|BIT(6);//使能INT1 4
EICRA=0x0F;//INT0 INT1上升沿触发中断
EICRB=0xFF;//INT4--INT7上升沿触发中断
//InitUART0();
//InitLcd();
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;
PORTE=0x00;
DDRE=0x00;
PORTF=0x00;
DDRF=0x00;
DDRG=0x00;
PORTG=0x00;
return;
}
/*****************************************************************/
void delay_1ms(void)
{ uinti;
for (i=0;i<(uint)(xtal*143-2);i++) ;
}
void delay_nms(uint n)
{uint i=0;
for (i=0;i<n;i++)
delay_1ms();
}
/******************************************************************/
voidspi_init(void) //初始化SPI
{
// DDRB=0x87;
DDRB|=BIT(7)|BIT(1)|BIT(2)|BIT(0);
// SPCR=0x51; //工作在主模式下SPCR=BIT(SPE)|BIT(MSTR)|BIT(SPR1)
SPCR=BIT(SPE)|BIT(MSTR)|BIT(SPR1);//使能SPI为主机模式,16分频
PORTB=0x07;
//PORTB=BIT(1)|BIT(7);
// PORTB&=~BIT(2);
//DDRB=0x87;
delay_nms(2);//延迟2ms
}
uchar isd_senddata(uchar senddata) //数据串行传送(统一的读取和发送一个字节操作)
{
uchar i;
i=senddata;
SPDR=i;
while(!(SPSR&(1<<SPIF))); //如果SPIF=1,表示SPI传输一个字节操作完成
senddata=SPDR;
return senddata;
}
/**********************************************************************/
uchar isd_is_free(void) //isd是否空闲
{
uchar status0=0, status1=0, status2=0;
//PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
status0=isd_senddata(ISD_RD_STATUS);
status1=isd_senddata(0x00);
status2=isd_senddata(0x00);
PORTB|=BIT(7);
PORTB=0x07;
if(status2&0x01==0x01) //检测RDY是否为1 表示空闲可以接受SPI命令
return1;
else
return0;
}
void isd_reset(void) //isd复位
{
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_RESET);
isd_senddata(0x00);
PORTB|=BIT(7);
PORTB=0x07;
delay_nms(10);
}
void isd_setapc2(void)
{
PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_WR_APC2);
isd_senddata(0xa0); //设置音量开到最大,关模拟输出,遇到EOM标志自动结束
isd_senddata(0x0c);
PORTB|=BIT(7);
}
void isd_pu(void) //ISD上电
{
PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_PU);
isd_senddata(0x00);
PORTB|=BIT(7);
}
void isd_fwd(void) //ISD上电
{
PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_FWD);
isd_senddata(0x00);
PORTB|=BIT(7);
}
void isd_rd_play_ptr(void)
{
PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_RD_PLAY_PTR);
isd_senddata(0x00);
isd_senddata(0x00);
isd_senddata(0x00);
PORTB|=BIT(7);
}
void isd_clr_int(void) //清楚isd的EOM和中断标志
{
PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(10);//延迟2ms
isd_senddata(ISD_CLR_INT);
isd_senddata(0x00);
PORTB|=BIT(7); //串行SS口置高,SPI命令处理完毕
}
void isd_init(void) //初始化ISD1700
{
isd_reset();
do
{
isd_pu();
} while(!isd_is_done());
isd_clr_int();
}
/************************************************************************/
void isd_erase_all(void)
{
PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_ERASE_ALL);
isd_senddata(0x00);
PORTB|=BIT(7); //串行SS口置高,SPI命令处理完毕
}
void isd_chk_mem(void) //清楚isd的EOM和中断标志
{
PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_CHK_MEM);
isd_senddata(0x00);
PORTB|=BIT(7); //串行SS口置高,SPI命令处理完毕
}
void isd_devid(void) //清楚isd的EOM和中断标志
{
while(!isd_is_free());
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_DEVID);
isd_senddata(0x00);
isd_senddata(0x00);
PORTB|=BIT(7); //串行SS口置高,SPI命令处理完毕
PORTB=0x07;
}
uchar isd_is_done(void)
{
uchar status;
PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
status=isd_senddata(ISD_RD_STATUS);
isd_senddata(0x00);
isd_senddata(0x00);
PORTB|=BIT(7);
if(!(status&0x01==0x01)) // 检测INT是否为1,CMD_ERR是否为0
return1;
else
return0;
}
/*****************************************************************************/
void isd_play(void) //清楚isd的EOM和中断标志
{
while(!isd_is_free());
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_PLAY);
isd_senddata(0x00);
PORTB|=BIT(7); //串行SS口置高,SPI命令处理完毕
PORTB=0x07;
}
void gettoneadd(uchar num, uint * ipstartadd, uint * ipendadd)
{
*ipstartadd=0x10+num*24; //第NUM段语音段开始地址
*ipendadd=0x10+num*24+23; //第NUM段语音段结束地址
}
voidisd_set_rec(uchar num)
{
uint Add_ST=0, Add_ED=0,num1;
uchar Add_ST_H, Add_ST_L, Add_ED_H, Add_ED_L;
num1=num;
while(!isd_is_free()); //等待空闲,可以接收SPI命令
gettoneadd(num1, &Add_ST, &Add_ED);
Add_ST_L=(uchar)(Add_ST&0x00ff);
Add_ST_H=(uchar)((Add_ST>>8)&0x00ff);
Add_ED_L=(uchar)(Add_ED&0x00ff);
Add_ED_H=(uchar)((Add_ST>>8)&0x00ff);
PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_SET_REC);
isd_senddata(0x00);
isd_senddata(0x10); //S7:S0开始地址
isd_senddata(0x00); //S10:S8
isd_senddata(0xff); //E7:E0结束地址
isd_senddata(0x00); //E10:E8
isd_senddata(0x00);
PORTB|=BIT(7);
while(!isd_is_done()); //等待SPI命令正确处理完毕
isd_clr_int();
}
voidisd_set_play(uchar num)
{
uint Add_ST=0, Add_ED=0,num1;
uchar Add_ST_H, Add_ST_L, Add_ED_H, Add_ED_L;
num1=num;
while(!isd_is_free());
gettoneadd(num1, &Add_ST, &Add_ED);
Add_ST_L=(uchar)(Add_ST&0x00ff);
Add_ST_H=(uchar)((Add_ST>>8)&0x00ff);
Add_ED_L=(uchar)(Add_ED&0x00ff);
Add_ED_H=(uchar)((Add_ST>>8)&0x00ff);
PORTB=0x03;
PORTB&=~BIT(7);
delay_nms(2);//延迟2ms
isd_senddata(ISD_SET_PLAY);
isd_senddata(0x00);
isd_senddata(0x10); //S7:S0开始地址
isd_senddata(0x00); //S10:S8
isd_senddata(0x00);
isd_senddata(0x1D); //E7:E0结束地址
isd_senddata(0x01); //E10:E8
PORTB|=BIT(7);
while(!isd_is_done());
isd_clr_int();
}
/*******************************************************************/
void main(void)
{
CLI();
InitMCU();
spi_init();
isd_init();
isd_devid();
isd_play();
//isd_clr_int();
//isd_erase_all();
//isd_init();
//isd_set_play(0);
while(1);
} 请帮我指点一下 谢谢! cool了恭喜楼主啊 和ISD2560差别大不?
好像ISD2560是并行接口的 TO:【78楼】 xirut
楼主,我还想问一下,资料上的模拟地和数字地在连接的时候有什么要注意的啊?
我想把电脑里已经录好的.wmv文件烧录到芯片里,如果不用拷贝机的话,是不是通过ANA IN引脚输入呀?但它只有一根线怎么跟电脑相连呢,是不是再加跟地线呀?
小弟是新手,还请楼主多指点指点,感谢万分!
------------------------------------------------------------------------------------------------------
模拟地和数字地之间可以串联一个磁珠。
通过ANA IN引脚输入可能效果比较好一点吧,当然要和电脑的音频接口的地线连接啦。 楼主,请问电脑音频接口的地线是在哪呀
你做的板子当时是怎么录音的呢,请教! 耳麦的插头不是有三段吗?最后一段(根部)就是地线,我是通过串口控制的! 恩我已经找到地线了,不过还是有点不明白
ANA IN只有一个线,它应该是信号线呀,那耳麦的地线怎么跟它共起来呢
楼主,可以加你QQ请教一下吗? 耳麦的地线直接连接到1760的模拟地就对了 楼主真是热心人啊,不用2500的了,直接用这个了!
谢谢楼主! 楼主 你好 请问一下为什么用SPI模式录音的时候声音会很小 你碰到过这样的问题吗?各位如果知道的麻烦告诉我一下,谢谢! 声音大小可以设置的,看这儿:
/**************************************************************************
* 函数原型: void ISD_WR_APC2(uchar voiceValue);
* 功 能: 设置APC2
**************************************************************************/
void ISD_WR_APC2(uchar voiceValue){
ISD_SendData(WR_APC2);
ISD_SendData(0xa8|voiceValue); //0xa8声音最大,0xaf声音最小
ISD_SendData(0x0c); //D11=1,在SETPLAY模式下,执行到EOM自动结束。或者在连续两个SET_PLAY命令后,执行到第一个EOM自动跳到第二段开始
SS=1;
delay_ms(10); //延迟10ms
ISD_WR_NVCFG(); //永久写入寄存器
} void ISD_WR_APC2(uchar voiceValue){
ISD_SendData(WR_APC2);
ISD_SendData(0x00);
ISD_SendData(0x00);
SS=1;
delay_ms(10);
ISD_WR_NVCFG(); }
我是这样写的 声音还是很小 实在不行你选择SPK+输出,还不行就再加一级运放吧! 我想找出原因,因为,独立模式下声音很大的 请叫楼主:用at 89s52时只需要把地址改一下就行了吗?还有没有其他要修改的地方? /**************************************************************************
* 函数原型: void ISD_SendData(uchar BUF_ISD);
* 功 能: 发送数据
**************************************************************************/
uchar ISD_SendData(uchar BUF_ISD){
uchar i,dat=BUF_ISD;
SCLK=1;
SS=0;
for(i=0;i<8;i++){
SCLK=0;
I_delay();
if(dat&0x01){
MOSI=1;
}
else{
MOSI=0;
}
dat>>=1;
if(MISO){
dat|=0x80;
}
SCLK=1;
I_delay();
}
MOSI=0;
// SS=1;
return(dat);
}
这段发送数据函数,有点问题想请教:
为什么最后要把MOSI拉低?
还有传送完后为什么不把SS拉高? http://cache.amobbs.com/bbs_upload782111/files_11/ourdev_422685.jpg
(原文件名:未命名.jpg)
本贴被 qxs5264 编辑过,最后修改时间:2008-09-19,11:35:00. 另外传送完后可以将SS拉高! 还有一个问题: 那个时钟 SCLK=1 拉高的时候,
为什么不是放在MISO传送之前?
MOSI的传送在上升沿, MISO 在下降沿。