将数据写入发送缓冲区内
通过spi控制器向毁晌外发送数据
发送成如竖功后spstat的bit 8会渣余大置为1,表示spi完成
用户空间不需要直接用到spi_device结构体,但是这个结构体和用户空间的程序有密切的关系,理解它的成员有助于理解SPI设备节点的IOCTL命令,所以首先来闹皮介绍。在内核中,每个spi_device代表一个物理的SPI设备:
struct spi_device {
structdevice dev
structspi_master *master
u32 max_speed_hz/* 通信时钟最大频率 */
u8 chip_select/* 片选号 */
u8 mode/*SPI设备的模式,下面的宏是它各bit的含义 */
#define SPI_CPHA 0x01 /* 采样的伍帆时钟相位 */
#define SPI_CPOL 0x02 /* 时钟信号起始相位:高或者是低电平 */
#define SPI_MODE_0 (0|0)
#define SPI_MODE_1 (0|SPI_CPHA)
#define SPI_MODE_2 (SPI_CPOL|0)
#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
#define SPI_CS_HIGH 0x04 /* 为1时片选的有效信号是高电平 */
#define SPI_LSB_FIRST 0x08 /* 发送时低比特在前 */
#define SPI_3WIRE 0x10 /* 输入输出信号使用同一根信号线 */
#define SPI_LOOP 0x20 /* 回环模式 */
u8 bits_per_word/* 每个通信字的字长(比特数) */
int irq/*使用到的中断 */
void *controller_state
void *controller_data
char modalias[32]/* 设备驱动的名字 */
}
扩展资料:
SPI的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于SPI的设备共有的,是MISO(主设备数据输入)、MOSI(主设备数据输出)、SCLK(时钟)、CS(片选)。
(1)MISO– Master Input Slave Output,主设备数据输入,从设备数据输出;
(2)MOSI– Master Output Slave Input,主设备数据输出,腔弯雹从设备数据输入;
(3)SCLK – Serial Clock,时钟信号,由主设备产生;
(4)CS – Chip Select,从设备使能信号,由主设备控制。
参考资料来源:百度百科-SPI
ISD4004 工作于SPI 串行接口。SPI 协议是一个同步串行数据传输协议,协议假定微控制器的SPI 移位寄存器在SCLK 的下降沿动作,因此对ISD4004 而言,在时钟止升沿锁存MOSI 引脚的数据,在下降沿将数据送至MISO 引脚。协议的具体内容为:
1.所有串行数据传输开始于SS 下降沿。
2.SS 在传输期间必须保持为低电平,在两条指令之间则保持为高电平。
3.数据在时钟上升沿移入,在下降沿移出。
4.SS 变低,输入指令和地址后,ISD 才能开始录放 *** 作。
5.指令格式是(8 位控制码)加(16 位地址码)。
6.ISD 的任何 *** 作(含快进)如果遇到EOM 或OVF,则产生一个中断,该中断状态在下一个SPI 周期开始时被清除。
7.使用读指令使中断状态位移出ISD 的MISO 引脚时,控制及地址数据也应同步从MOSI 端移入。因此要注意移入的数据是否与器件当前进行的 *** 作兼容。当然,也允许在一个SPI 周期里,同时执行读状态和开始新的 *** 作(即新移入的数据与器件当前的 *** 作可以不兼容)。
8.所有 *** 作在运行位(RUN)置1 时开始,置0 时结束。
9.所有指令都在SS 端上升沿开始执行。 用户不必知道信息的确切地址,就能快进跳过一条信息。信息快进只用于放音模式。放音速度是正
常的160 倍,遇到EOM 后停止,然后内部地址计数器加1,指向下条信息的开始处。 器件延时TPUD(8kHz 采样时,约为25 毫秒)后才能开始 *** 作。因此陆誉碰,用户发完上电指令后,必须等待
TPUD,才能发出一条 *** 作指令。
例如,从00 从处发音,应遵循如下时序:
1. 发POWERUP 命令
2. 等待TPUD(上电延时)
3. 发地址值为00 的SETPLAY 命令
4. 发PLAY 命令。
器件会从此00 地址开始放音,当出现EOM 时,立即中断,停止放音。
如果从00 处录音,则按以下时序:
1. 发POWER UP 命令
2. 等待TPUD(上电延时)
3. 发POWER UP 命令
4. 等待2 倍TPUD
5. 发地址值为00 的SETREC 命令
6. 发REC 命令。
器件便从00 地址开始录音,一直到出现OVF(存贮器末尾)时,录音停止。
ISD4002/4003/4004芯片参数表 型号 存储时间
(秒) 可分
段数 信息分辩
率(毫秒) 采样频
率(HZ) 滤波器
带宽(HZ) 控制码+地址位 ISD4002-120 120 600 200 8.0K 3.4K 5+11 ISD4002-180 180 600 300 5.3k 2.3k 5+11 ISD4002-240 240 600 400 4.0k 1.7k 5+11 ISD4003-04 240 1200 200 8.0K 3.4K 5+11 ISD4003-06 360 1200 300 5.3K 2.3K 5+11 ISD4003-08 480 1200 400 4.0K 1.7K 5+11 ISD4004-08 480 2400 200 8.0K 3.4K 8+16 ISD4004-16 960 2400 400 4.0K 1.7K 8+16 以上芯片由ISD3340K编程拷贝机编程、拷贝。 ************ // 主程序
//
// 功能:1.录音时,按住AN键,LED点亮开始录音,松开AN即可停止录音
// 再次按下AN键,LED点亮开始录第二段音早谈,依次类推,直到芯片溢出。
// 按stop键芯片复位
// 2.放音虚桥时,按一下AN键,即播放一段语音。 按stop键芯片复位。
//************************************************************************
#include <reg52.h>
sbit SS =P1^0//片选
sbit MOSI=P1^1//数据输入
sbit MISO=P1^2//数据输出
sbit SCLK=P1^3//ISD4004时钟
sbit INT =P1^4//中断
sbit LED =P1^7//指示灯
sbit LED1=P1^6//指示灯:亮是录音/不亮是放音
sbit PR =P3^3//录音和放音选择开关
sbit STOP=P3^4//复位
sbit AN =P3^5//执行
void delay(unsigned int time) //延迟n微秒
{
while(time!=0)
{
time--
}
}
void delayms(unsigned int time) //延迟n毫秒
{
TMOD=0x01
for(timetime>0time--)
{
TH0=0xfc
TL0=0x18
TR0=1
while(TF0!=1)
{}
TF0=0
TR0=0
}
}
void isd_send(unsigned char isdx)//spi串行发送子程序,8位数据
{
unsigned char isx_counter
SS=0//ss=0,打开spi通信端
SCLK=0
for(isx_counter=0isx_counter<8isx_counter++)//先发低位再发高位,依次发送。
{
if((isdx&0x01)==1)
MOSI=1
else
MOSI=0
isdx=isdx>>1
SCLK=1
delay(2)
SCLK=0
delay(2)
}
}
void isd_stop()//stop指令(停止当前 *** 作)
{
delay(10)
isd_send(0x30)
SS=1
delayms(50)
}
void isd_powerup()//发送上电指令
{
delay(10)
SS=0
isd_send(0x20)
SS=1
delayms(50)
}
void isd_stopwrdn()//发送掉电指令
{
delay(10)
isd_send(0x10)
SS=1
delayms(50)
}
void isd_play()//发送play指令
{
LED=0
isd_send(0xf0)
SS=1
}
void isd_rec()//发送rec指令
{
LED=0
isd_send(0xb0)
SS=1
}
void isd_setplay(unsigned char adl,unsigned char adh)//发送setplay指令
{
delayms(1)
isd_send(adl)//发送放音起始地址低位
delay(2)
isd_send(adh)//发送放音起始地址高位
delay(2)
isd_send(0xe0)//发送setplay指令字节
SS=1
}
void isd_setrec(unsigned char adl,unsigned char adh)//发送setrec指令
{
delayms(1)
isd_send(adl)//发送放音起始地址低位
delay(2)
isd_send(adh)//发送放音起始地址高位
delay(2)
isd_send(0xa0)//发送setplay指令字节
SS=1
}
void isd_overflow()//芯片溢出,LED闪烁提醒停止录音
{
while(AN==0)
{
LED=1
delayms(300)
LED=0
delayms(300)
}
}
unsigned char chk_isdovf()//检查芯片是否溢出(读OVF,并返回OVF值)
{
SS=0
delay(2)
SCLK=0
delay(2)
SCLK=1
SCLK=0
delay(2)
if(MISO==1)
{
SCLK=0
SS=1//关闭spi通信端
isd_stop()//发送stop指令
return 1//OVF为1,返回1
}
else
{
SCLK=0
SS=1//关闭spi通信端
isd_stop()//发送stop指令
return 0//OVF为0,返回0
}
}
void main(void)
{
unsigned char ovflog
while(1)
{
if(PR==0) {delayms(8)LED1=~LED1while(PR==0)}
if(LED1==0)//如果PR=0则转入录音部分
{
if(AN==0)
{
isd_powerup()//AN键按下,ISD上电并延迟50ms
isd_stopwrdn()
isd_powerup()
LED1=0//表示录音模式
delayms(500)//延迟500ms录音
isd_setrec(0x00,0x00)//发送0x0000h地址的setplay指令
do
{
isd_rec()//发送rec指令
while(AN==0) //等待录音完毕
{
if(INT==0) //如果芯片溢出,进行LED闪烁提示,
isd_overflow()//如果取消录音(松开AN键)则停止录音,芯片复位
}
if(INT==0)
break
LED=1//录音完毕,LED熄灭
isd_stop()//发送停止命令
while(AN==1) //如果AN再次按下,开始录制下一段语音
{
if(isd_stop==0) //如果按下STOP按键,则芯片复位
break
if(AN==0)
delayms(500)
}
}
while(AN==0)
}
}
if(LED1==1)//如果PR=0则转入放音部分 //如果PR==1则转入放音部分
{
if(AN==0)
{
isd_powerup()//AN键按下,ISD上电并延迟50ms
isd_stopwrdn()
isd_powerup()
LED1=1//表示录音模式
while(AN==0)
{}
isd_setplay(0x00,0x00)//发送setplay指令,从0x0000地址开始放音
do
{
isd_play()//发送放音指令
delay(20)
while(INT==1) //等待放音完毕的EOM中断信号
{}
LED=1
isd_stop()//放音完毕,发送stop指令
if (ovflog=chk_isdovf()) //检查芯片是否溢出 ,如溢出则停止放音,芯片复位
break
while(AN==1) //等待AN键再次按下
{
if(isd_stop==0)
break
if(AN==0)
delayms(20)
}
}
while(AN==0)// AN键再次按下,播放下一段语音
// isd_stop()
// isd_stopwrdn()
}
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)