⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avr.txt

📁 单片机的I2C通信协议
💻 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 + -