600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 基于Arduino IDE开发的LD3320语音识别模块

基于Arduino IDE开发的LD3320语音识别模块

时间:2024-03-20 20:50:36

相关推荐

基于Arduino IDE开发的LD3320语音识别模块

基于Arduino的LD3320语音识别模块设计详解

文章目录

基于Arduino的LD3320语音识别模块设计详解前言一、LD3320驱动编写step 1.0 使用Arduino的SPI库,通过硬件SPI和LD3320通讯,读写寄存器setp 1.1 访问LD3320的三个指定寄存器,检查硬件连接的可靠性setp 1.2 进行驱动程序的编写,驱动LD3320进行语音识别二、第二部分 用模拟SPI编写LD3320的驱动程序模拟SPI通讯程序例程三、IIC修改命令词

前言

本文章为记录本人的学习过程,最终目的是设计一款IIC通讯方式的语音识别模块,该模块的主要功能,就是识别程序中设定的指令词,并返回识别结果,指令词和对应的返回编号可在程序中任意修改,不需要去给语音识别模块烧录固件,支持命令词的动态编辑。

模块硬件包含一块单片机芯片,一块LD3320芯片,以及外围电路。PCB工程已开源,网上到处都有。

基础功能:

1.动态编辑命令词,不需要烧录模块的固件

2.识别成功后返回对应结果

文章将会记录我从零开始的调试步骤以及遇到的问题,还有解决问题的详细思路。

接下来我们开始。

工程已上传(PCB工程+模块固件+Demo),有需要的可以先下载,链接挂在末尾

一、LD3320驱动编写

根据ICroute官方文档所写,想要驱动LD3320进行语音识别,可以使用软硬并口通讯方式对LD3320的寄存器进行读写从而驱动LD3320,也可以使用软硬SPI串行通讯方式对LD3320的寄存器进行读写,也可以驱动LD3320。需要注意的是,模拟并口驱动方式官方并不推荐,不仅速度慢,也会造成通讯不稳定等情况。推荐使用硬件SPI进行驱动,如果MCU没有SPI的硬件接口,也可以使用普通I/O口模拟SPI进行通讯,较为稳定。

回到正题,我手头正好有一块网上买的LD3320模块,是不带单片机的那种,板子上只有LD3320的那种。

直接先拿Arduino UNO开发板和这款LD3320进行原理测试,Let’s go。

直接用杜邦线,按如下方式连接:

5V – VCC

GND – GND

MISO – D12

MOSI – D11

SCK – D13

NSS – D4

RST – D9

IRQ – D2

WR – GND

官方文档所说,LD3320的电压为3V3,通讯引脚耐压也是3V3,超过3V3会使模块使用不稳定,但是在使用Arduino的实际测试中,未使用电压转换模块,反应良好。千万别学我,最好还是用3V3该转压还是得转请注意,引脚电平可以超过3v3,但是!电源只能是3v3

本部分我分为三小步来完成:

step 1.0 使用Arduino的SPI库,通过硬件SPI和LD3320通讯,读写寄存器

setp 1.1 访问LD3320的三个指定寄存器,检查硬件连接的可靠性

setp 1.2 进行驱动程序的编写,驱动LD3320进行语音识别

step 1.0 使用Arduino的SPI库,通过硬件SPI和LD3320通讯,读写寄存器

这一步的主要目的,是确定和LD3320能否进行正常的通讯,众所周知,SPI是一种串行通讯方式,需要至少连接五根线,为什么是五而不是四,因为要公地。

【SCK】 》》同步主机产生的数据传输的时钟脉冲。

【MOSI】 》》用于向外设发送数据的线,主机从这个引脚发送,从机从这个引脚接收。

【MISO】《《用于向主设备发送数据的线,主机从这个引脚接收,从机从这个引脚发送。

【CS】 》》片选信号,主机控制这个引脚来开启和禁用从机,低电平使能。

【GND】 祖传公地。

好了,SPI相关的知识我们就了解这么多,我们只需要知道他是全双工串行通讯,还有这些引脚是干啥的就可以了。继续下一步。

我们要和LD3320进行通讯,首先要让LD3320工作,我们需要先复位芯片,激活内部DSP。

只需要将LD3320芯片的47脚【RSTB*】发一个低电平,就可以复位LD3320到初始状态。然后需要激活DSP,就需要对片选【CS】做一次拉低再拉高的操作。

复位LD3320激活内部dsp的子函数

void LD_reset()//对LD3320复位 对47脚发送低电平 然后反转片选一次 激活DSP:{digitalWrite(RSTB, HIGH);delay(1);digitalWrite(RSTB, LOW);delay(1);digitalWrite(RSTB, HIGH);delay(1);cSLow();delay(1);cSHigh();delay(1);//writeReg(0xb9, 0x00); //寄存器 0xB9 当前添加识别语句的字符串长度 初始化时写入0x00}

激活DSP之后,就可以进行LD3320的寄存器读写了,我们使用的是SPI串行方式,根据官方的文档描述,SPI的通讯参数需要设置如下:

SPI没有官方标准,所以要好好看芯片的datasheet

在Arduino的setup里对SPI参数进行设置

void setup() {......SPI.setClockDivider(SPI_CLOCK_DIV16); //16分频SPI.setDataMode(SPI_MODE2); //时钟极性CPOL 1 时钟相位CPHA 0SPI.setBitOrder(MSBFIRST); //高位在前......}

接下来写一个用于读寄存器的程序,根据官方文档描述,要读寄存器,需要先发送0x05,然后再发送十六进制的寄存器地址,然后再读取芯片返回过来的十六进制数据。

读寄存器的子函数

unsigned char LD_readReg(unsigned char address) {unsigned char result;//局部变量 保存读取的数据cSLow(); //片选使能 低电平有效delay(10);SPI.transfer(0x05);SPI.transfer(address); //发送 寄存器地址result = SPI.transfer(0x00); //读取数据cSHigh(); //片选去使能return (result); //返回数据}

接下来写一个用于写寄存器的程序,根据官方文档描述,要写取寄存器,需要先发送0x04,然后再发送十六进制的寄存器地址,最后发送十六进制数据。

写寄存器的子函数

void LD_writeReg(unsigned char address, unsigned char value) {cSLow();//片选使能delay(10);SPI.transfer(0x04);//发送0x04 是写入模式SPI.transfer(address); //发送 寄存器地址SPI.transfer(value); //发送 数据cSHigh();//片选去使能}

接下来,进行对LD3320寄存器的读写测试。

如果,我们先向可读写的寄存器写入某个数值,再读出来,用来检查寄存器读写是否正常。

每次先向一个寄存器写,再读出来,内容是完全正确,但是在接下来的语音识别操作中,发现LD3320芯片并不会鸟你,这是为什么呢,因为可能你的数据存在SPI的总线上,但是没有Touch到寄存器里面

所以我建议读写寄存器的序列如下:

对寄存器写入再读取的操作顺序

void setup() {......LD_reset();//先复位激活LD3320delay(1);LD_readReg(0x06);//读取一次0X06寄存器delay(1);LD_writeReg(0x35, 0x33);//对寄存器0x35写入0x33LD_writeReg(0x1b, 0x55);//对寄存器0x1b写入0x55LD_writeReg(0xb3, 0xaa);//对寄存器0xb3写入0xaaSerial.print(LD_readReg(0x35),HEX); Serial.print(" ");//读取并打印寄存器0x35的值Serial.print(LD_readReg(0x1b),HEX); Serial.print(" ");//读取并打印寄存器0x1b的值Serial.print(LD_readReg(0xb3),HEX); Serial.println(" ");//读取并打印寄存器0xb3的值}

就是向 3 个寄存器先依次写数据,再依次读数据出来。作为比较。

这样可以有效地验证读写寄存器是否正常。

如果结果是 33 55 aa 那么恭喜你,读写寄存器正常,可以进行下一步操作了。

这一步基本不会出错,如果出错了,请详细比对SPI的参数设置

step1.0 完整代码,在工程文档中,有需要的直接下载即可

setp 1.1 访问LD3320的三个指定寄存器,检查硬件连接的可靠性

既然已经可以正常读写LD3320的寄存器了,那为了保证LD3320稳定工作,再来检查一下硬件之间连接的可靠性。

我们在复位LD3320之后,读取寄存器0x06两次,再读取寄存器0x35和0xb3,将值打印出来。

访问三个指定寄存器的操作

void setup() {......LD_reset();//先复位激活LD3320delay(1);Serial.print(LD_readReg(0x06),HEX); Serial.print(" "); //读取并打印寄存器0x06的值Serial.print(LD_readReg(0x06),HEX); Serial.print(" "); //读取并打印寄存器0x06的值Serial.print(LD_readReg(0x35),HEX); Serial.print(" "); //读取并打印寄存器0x35的值Serial.print(LD_readReg(0xb3),HEX); Serial.println(" ");//读取并打印寄存器0xb3的值}

如果打印出来的值,是87 87 80 FF或者00 87 80 FF则正常。不要把LD3320断电,复位Arduino UNO ,多读取几次,看看值是否稳定,如果稳定,则连接非常稳定。就可以进行语音识别的操作了。

setp 1.2 进行驱动程序的编写,驱动LD3320进行语音识别

现在我们进行完整驱动的编写。首先,先介绍驱动LD3320进行语音识别的流程。

ASR初始化→写入识别列表→开始识别→准备好中断函数→打开中断

然后每次识别到语音,无论是否识别到命令词,就会触发中断,运行你准备好的中断函数,正常情况是只运行一次就结束了,但是你可以在中断函数中添加ASR初始化→开始识别,继续进行下一轮识别,达到循环识别的目的。

接下来,我们按照流程来编写驱动程序。先贴两张寄存器地址的图表。

通用初始化函数,直接抄作业就可以了,都是官方例程,唯一需要注意的,就是晶振频率相关的四个变量

void LD_Init_Common()//通用初始化{LD_readReg(0x06);LD_writeReg(0x17, 0x35);delay(10);LD_readReg(0x06);LD_writeReg(0x89, 0x03);delay(5);LD_writeReg(0xcf, 0x43);delay(5);LD_writeReg(0xcb, 0x02);LD_writeReg(0x11, PLL_11);//和晶振频率有关,注意调整LD_writeReg(0x1e, 0x00);LD_writeReg(0x19, PLL_ASR_19);//和晶振频率有关,注意调整LD_writeReg(0x1b, PLL_ASR_1B);//和晶振频率有关,注意调整LD_writeReg(0x1d, PLL_ASR_1D);//和晶振频率有关,注意调整delay(10);LD_writeReg(0xcd, 0x04);LD_writeReg(0x17, 0x4c);delay(5);LD_writeReg(0xb9, 0x00);LD_writeReg(0xcf, 0x4f);LD_writeReg(0x6f, 0xff);}

ASR初始化函数,一样的,抄作业就完事了,没什么需要注意的

void LD_Init_ASR() /**语音识别初始化**/{LD_Init_Common();LD_writeReg(0xbd, 0x00);LD_writeReg(0x17, 0x48);delay(10);LD_writeReg(0x3c, 0x80);LD_writeReg(0x3e, 0x07);LD_writeReg(0x38, 0xff);LD_writeReg(0x3a, 0x07);LD_writeReg(0x40, 0);LD_writeReg(0x42, 8);LD_writeReg(0x44, 0);LD_writeReg(0x46, 8);delay(1);}

接下来,写入识别列表,也就是把自定义的命令词写入到LD3320里面。需要注意的是,我们在写入识别列表之前,要先读取0xB2寄存器的值,查看芯片的状态是否正常,如果不正常,则需要先复位一次芯片,再重新初始化,再写入。为什么会出现不正常的情况,主要原因,是电压和电流不稳定造成的。

检查0xB2寄存器的函数,返回1则正常,返回0失败

int LD_Check_ASRbusyFlag_b2()/**检查芯片状态**/{for (int j = 0; j < 10; j++){if (LD_readReg(0xb2) == 0x21)//寄存器值0x21为空闲{return 1;}delay(10);}return 0;}

如果检查寄存器结果是正常,那么就可以写入识别词了。

写入识别列表的函数,char *pass也可以用string pass代替

int LD_ASRAddFixed(char *pass, int num) /**添加命令词**/{int i; //局部变量 用来循环写入识别字的数据,并记录字符的长度int flag;//返回添加成功或者失败flag = 1;for (int j = 0; j < 5; j++) {//这个循环没有任何意义if (LD_Check_ASRbusyFlag_b2() == 0) {flag = 0;break;//如果检查到不支持,则退出,并返回添加失败}LD_writeReg(0xc1, num);//添加命令的编号LD_writeReg(0xc3, 0);//识别字添加时写入0x00LD_writeReg(0x08, 0x04);//清除数据缓存器内容delay(1);LD_writeReg(0x08, 0x00);//清除后再次写入0x00delay(1);for (i = 0; i <80; i++)//为什么i<80,因为单个命令词最多支持80字节,最好只写入79字节{if (pass[i] == 0)break;//如果读取到空字符则退出循环写入LD_writeReg(0x5, pass[i]);///将识别字写入寄存器0x05}LD_writeReg(0xb9, i);//在0xb9寄存器写入当前字符长度LD_writeReg(0xb2, 0xff);LD_writeReg(0x37, 0x04);//在0x37寄存器写入 0x04通知DSP 我要写入一条识别词break;//写入完成,退出}return flag;//返回添加成功或者失败}

接下来,就要启动识别了。

启动识别函数,照抄就行,这些变量都在程序头部进行宏定义

int LD_AsrRun()/**启动ASR**/{LD_writeReg(0x35, MIC_VOL);//在0x35寄存器 写入识别灵敏度LD_writeReg(0xb3, speech_endpoint);//在0xb3寄存器 写入语音端点检测功能的灵敏度 0关闭 数值越小越灵敏LD_writeReg(0xb4, speech_start_time);//在0xb4寄存器 写入判断语句开始的时间LD_writeReg(0xb5, speech_end_time);//在0xb5寄存器 写入判断语句结束的时间LD_writeReg(0xb6, voice_max_length);//在0xb6寄存器 写入识别语句的最长长度LD_writeReg(0xb7, noise_time);//在0xb7寄存器 写入初始忽略掉的底噪时间LD_writeReg(0x1c, 0x09);//保留命令字LD_writeReg(0xbd, 0x20);//保留命令字LD_writeReg(0x08, 0x01);//清除缓存器delay( 1);LD_writeReg(0x08, 0x00);//再次写入00delay( 1);if (LD_Check_ASRbusyFlag_b2() == 0) //查看寄存器0xb2的值是否正常{return 0;//不正常返回0 ,启动失败}LD_writeReg(0xb2, 0xff);//更新寄存器0xb2的值LD_writeReg(0x37, 0x06);//通知dsp开始语音识别delay( 5 );LD_writeReg(0x1c, 0x0b);//选择声音输入方式,因为我用双极电容麦,直接写入0x0B,LD_writeReg(0x29, 0x10);//中断开启LD_writeReg(0xbd, 0x00);//启动ASR模块return 1;//成功}

启动之后,我们准备好中断函数,用来响应LD3320发送的中断信号,查询返回值并启动下一轮识别。

中断响应函数

void LD_ASRget()/**中断执行程序**/{/****以下程序对LD3320的运算结果进行分析,取其运算结果****/uint8_t Asr_Count = 0;LD_writeReg(0x29, 0) ;LD_writeReg(0x02, 0) ;if ((LD_readReg(0x2b) & 0x10) && LD_readReg(0xb2) == 0x21 && LD_readReg(0xbf) == 0x35){Asr_Count = LD_readReg(0xba); //读取有几个候选值if (Asr_Count > 0 && Asr_Count < 4){readnum = LD_readReg(0xc5); //得到最佳选项 如果你需要其他选项,可以去另外三个寄存器掏readflag = 1;}else {Serial.println("运算结果是无法识别");}LD_writeReg(0x2b, 0);LD_writeReg(0x1C, 0);}else {Serial.println("运算结果是无法识别");}/****以下程序对LD3320进行初始化,预备进行下一次识别****/LD_readReg(0x06);delay(10);LD_readReg(0x06);LD_writeReg(0x89, 0x03);delay(5);LD_writeReg(0xcf, 0x43);delay(5);LD_writeReg(0xcb, 0x02);LD_writeReg(0x11, PLL_11);LD_writeReg(0x1e, 0x00);LD_writeReg(0x19, PLL_ASR_19);LD_writeReg(0x1b, PLL_ASR_1B);LD_writeReg(0x1d, PLL_ASR_1D);delay(10);LD_writeReg(0xcd, 0x04);LD_writeReg(0x17, 0x4c);delay(5);LD_writeReg(0xcf, 0x4f);LD_writeReg(0xbd, 0x00);LD_writeReg(0x17, 0x48);delay(10);LD_writeReg(0x3c, 0x80);LD_writeReg(0x3e, 0x07);LD_writeReg(0x38, 0xff);LD_writeReg(0x3a, 0x07);LD_writeReg(0x40, 0);LD_writeReg(0x42, 8);LD_writeReg(0x44, 0);LD_writeReg(0x46, 8);delay(1);LD_writeReg(0x1c, 0x09);LD_writeReg(0xbd, 0x20);LD_writeReg(0x08, 0x01);delay( 1);LD_writeReg(0x08, 0x00);delay( 1);LD_writeReg(0xb2, 0xff);LD_writeReg(0x37, 0x06);delay( 5 );LD_writeReg(0x1c, 0x0b);LD_writeReg(0x29, 0x10);LD_writeReg(0xbd, 0x00);}

把这个丢在LOOP里面循环运行

int LD_Read(){if (readflag == 1){readflag = 0;return readnum;}return -1;}

所有的子函数都准备完毕了,接下来,开始识别!

Let’s Go!!!

再来个运行语音识别的子函数,我保证是最后一个了

int RunASR(){int asrflag = 0;for (int z = 0; z < 5; z++) {//循环尝试五轮LD_Init_ASR();//进行ASR初始化delay(100);//延时时间自己控制,可以改5msif (LD_ASRAddFixed("kai deng", 1) == 0) {//添加命令词kai deng,编号是1,注意,两个字的拼音用空格隔开LD_reset(); //如果失败了,复位芯片delay(100);continue; //进行下一轮尝试}if (LD_ASRAddFixed("guan deng", 2) == 0) {//添加命令词guan deng,编号是2LD_reset();//如果失败了,复位芯片delay(100);continue;//进行下一轮尝试}if (LD_AsrRun() == 0) {//启动识别LD_reset();//如果失败了,复位芯片delay(100);continue;//进行下一轮尝试}asrflag = 1;//运行到这里了,说明上面的步骤都成功了break;//退出循环}return asrflag;//返回状态,成功或者失败}

接下来调用RunASR()函数就可以启动语音识别了,当然你也可以这样写

if(RunASR()==0){Serial.println("ASR启动失败");}else Serial.println("ASR启动成功");

然后就可以愉快得尝试了。

二、第二部分 用模拟SPI编写LD3320的驱动程序

模拟SPI通讯程序例程

时隔不知多少日,我又来更新了~~~~~~~~~~

这部分内容来介绍一下模拟SPI通讯,为什么要这样做呢,因为部分的单片机没有硬件SPI的支持,只能通过普通引脚来模拟SPI,达到通讯的目的,不过这样实现的通讯,往往速度较硬件SPI慢的不止一点点,也不够稳定,只能说,勉强够用。

先附上时序图,其实和硬件SPI的时序一毛一样。

和常规的 SPI通讯一样,查看时序图可知这四个引脚的状态。CS引脚(片选引脚SCS),低电平有效,也就是说在开始通讯之前,要先将CS引脚置为低电平,结束通讯之后,将CS引脚置为高电平。CLK引脚(时钟信号引脚SDCK),在开始通讯之后,要送出稳定的时钟信号,下降沿有效,在CLK送出下降沿的时候,MOSI(SDI)或者MISO(SDO)线上的电平信号才被记录为一个位数据。

写寄存器的操作和之前一样,要先写入一个字节0x04(写入寄存器的指令,读出寄存器为0x05),再写入一个字节(地址的值),最后写入数据。如图所示的SDI线上的时序,分为了三个字节位置,分别是指令字节、地址字节、数据字节,每个四节各八位。众所周知,0b1111 1111是0xFF,写寄存器的图中指令字节是0b 0000 0100,也就是0x04,这是8421-BCD码的知识点,不会的同学自己百度哦。

废话不多说,直接上程序。

头部宏定义

nop根据单片机的运行周期自行调整,没有很严格的要求

#define nop 0.07#define CS D4 #define SPI_MOSI_PIN D11#define SPI_SCK_PIN D13#define SPI_MISO_PIN D12

模拟SPI写寄存器的部分程序

程序分成三个部分,分别为写入指令,写入地址,写入数据,三个流程结束,就成功完成了写寄存器的操作

void LD_writeReg(unsigned char address, unsigned char dataout){unsigned char i = 0;unsigned char Command = 0x04;//写寄存器的指令cSLow();//片选使能delayMicroseconds(nop * 3);//延时三个机器周期,如果通讯不正常,调整这里的延时时间可以解决问题//写入 指令for ( i = 0; i < 8; i++)//循环八次 循环结束就完整得写入了 Command {if ((Command & 0x80) == 0x80)//按位与 Command & 0b 1000 0000 判断最高位是否为1digitalWrite(SPI_MOSI_PIN, HIGH);//置为高elsedigitalWrite(SPI_MOSI_PIN, LOW);//置为低delayMicroseconds(nop * 3);//延时三个机器周期digitalWrite(SPI_SCK_PIN, LOW);//时钟信号拉低Command = (Command << 1);//将Command 左移一位 delayMicroseconds(nop * 3);//延时三个机器周期digitalWrite(SPI_SCK_PIN, HIGH);//时钟信号拉高}//写入 地址 (和写入指令的操作一样)for (i = 0; i < 8; i++){if ((address & 0x80) == 0x80)digitalWrite(SPI_MOSI_PIN, HIGH);elsedigitalWrite(SPI_MOSI_PIN, LOW);delayMicroseconds(nop * 3);digitalWrite(SPI_SCK_PIN, LOW);address = (address << 1);delayMicroseconds(nop * 3);digitalWrite(SPI_SCK_PIN, HIGH);}delayMicroseconds(nop * 3);//写入 数据(和写入指令的操作一样)for (i = 0; i < 8; i++){if ((dataout & 0x80) == 0x80)digitalWrite(SPI_MOSI_PIN, HIGH);elsedigitalWrite(SPI_MOSI_PIN, LOW);delayMicroseconds(nop * 3);digitalWrite(SPI_SCK_PIN, LOW);dataout = (dataout << 1);delayMicroseconds(nop * 3);digitalWrite(SPI_SCK_PIN, HIGH);}delayMicroseconds(nop * 3);//延时三个系统周期cSHigh();//片选去使能}

模拟SPI读寄存器的部分程序

程序分成三个部分,分别为写入指令,写入地址,读取数据,三个流程结束,就成功完成了读寄存器的操作

unsigned char LD_readReg(unsigned char address){unsigned char i = 0;unsigned char datain = 0 ;//用于存储读取到字节完整数据unsigned char Temp = 0;//用于存储读取到的字节单个位的数据unsigned char Command = 0x05;//读寄存器的指令cSLow();//片选使能delayMicroseconds(nop * 3);//延时三个系统周期//写入 指令(和之前一样的操作,就不打备注了)for ( i = 0; i < 8; i++){if ((Command & 0x80) == 0x80)digitalWrite(SPI_MOSI_PIN, HIGH);elsedigitalWrite(SPI_MOSI_PIN, LOW);delayMicroseconds(nop * 3);digitalWrite(SPI_SCK_PIN, LOW);Command = (Command << 1);delayMicroseconds(nop * 3);digitalWrite(SPI_SCK_PIN, HIGH);}//写入 地址(和之前一样的操作,就不打备注了)for (i = 0; i < 8; i++){if ((address & 0x80) == 0x80)digitalWrite(SPI_MOSI_PIN, HIGH);elsedigitalWrite(SPI_MOSI_PIN, LOW);delayMicroseconds(nop * 3);digitalWrite(SPI_SCK_PIN, LOW);address = (address << 1);delayMicroseconds(nop * 3);digitalWrite(SPI_SCK_PIN, HIGH);}delayMicroseconds(nop * 3);//读取数据for (i = 0; i < 8; i++){datain = (datain << 1);//将datain 左移一位Temp = digitalRead(SPI_MISO_PIN);//读取到一位数据delayMicroseconds(nop * 3);//延时三个系统周期digitalWrite(SPI_SCK_PIN, LOW);//时钟信号拉低if (Temp == 1) {//如果Temp 为1datain |= 0x01;//或等于 将datain 的最低位变为1}delayMicroseconds(nop * 3);//延时三个系统周期digitalWrite(SPI_SCK_PIN, HIGH);//时钟信号拉高}delayMicroseconds(nop * 3);//延时三个系统周期cSHigh();//片选去使能return datain;//返回最后结果}

这里给不懂 & 和 | 的同学稍微解释一下

& 在C语言里面是位与运算符,| 在C语言里面是位或运算符,例如:

int a=0x03;//0b 0000 0011int b=0x02;//0b 0000 0010int c,d;c=a&b;d=a|b;//c的值为0x02 0&1=0 1&1=1 0&0=0//d的值为0x03 0|1=1 1|1=1 0|0=0

&= 和 |= 的意思就是与等于和或等于,例如:

a&=b 的意思就是,先将a和b按位与,再将结果赋值给a

a|=b 的意思就是,先将a和b按位或,再将结果赋值给a

好了跑题了,回到正题,上述通过模拟SPI读写寄存器的操作就完成了,后面的驱动部分,按照第一部分硬件SPI驱动LD3320的方法移植过来就好了。

补充一点,驱动程序里面的外部中断响应操作不规范,正常情况下,读取到外部中断后,应该先关闭该外部中断,然后去执行一系列中断触发的程序,执行结束后重新打开该外部中断。建议修改。

文章结尾附上源码和PCB的下载链接

/download/qq_40532525/85002112?spm=1001..3001.5503

三、IIC修改命令词

原理很简单,就是通过自己拟定的代码命令,来操控语音识别模块的初始化等等进程,唯一需要注意的是,Arduino的IIC通讯缓存区只有32个字节,所以这边建议将命令词进行切割分块发送,最后发送一个自拟定的结束命令,通知模块我发送完了,你可以装载命令词了,具体方法查看例程3.1。例程2.3里面有切割字符串并载入到3320里面的例程。

祝大家玩的愉快,LD3320的内容就告一段落了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。