?? avr.txt
字號:
看了樓主的的模擬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 int UINT;
typedef unsigned long ULONG;
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;
#endif
//***************************************************************************************************
//ISD1700.H
#ifndef __ISD1700__
#define __ISD1700__
//==============================================================================
//語音段干起始地址
#define VOICE_SEGMENT1 0x10 //聲音片斷1地址
#define VOICE_SEGMENT2 0x1E
#define VOICE_SEGMENT3 0x26
#define VOICE_SEGMENT4 0x2F
#define VOICE_SEGMENT5 0x38
#define VOICE_SEGMENT6 0x49
#define VOICE_SEGMENT7 0x51
#define VOICE_SEGMENT8 0x58
#define VOICE_SEGMENT9 0x61
#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_RDPLAYPTR 0x06 //返回狀態和放音指針
#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[12]=
{
//存放播放地址起始位置,結束位置定為上一位置結束位置
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[SoundID];
end_addr = isd_seg_addr[SoundID + 1] -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);
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -