目录
树莓派模块
1-wiringPi库的安装
2-串口相关API函数说明
3-代码的编写
LD3320模块
1-代码分析
本项目所用到的树莓派型号是3B,烧写的固件是官方的固件。固件版本是:2019-04-08-raspbian-stretch.img。也可以从官网或百度云下载。百度云下载地址,提取码:fdnb。下载后用烧写工具烧写好后,插入树莓派即可。
可以通过以下方式登录树莓派:
以上第3,第4种方式都是基于第一或者第二种方式登录之后进行设置才可以的。由于串口登录和SSH登录比较常见,下面我们简单说下这两种登录方式。
1-串口方式登录
1-1:修改配置:用读卡器打开SD卡根目录的"config.txt"文件,将以下内容添加在文件的最后并保存
dtoverlay=pi3-miniuart-bt
1-2:然后再修改根目录的"cmdline.txt",将里面的内容全部替换成以下内容,为了安全起见,请先备份好这个文件的原内容,再将里面的内容替换成下面的内容。
dwc_otg.lpm_enable=0 console=tty1 console=serial0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
1-3:修改好上面的配置文件后,把内存卡插入树莓派上电后即可用串口方式登录。
1-4:下载软件 SecureCRT或MobaXterm 。
1-5:USB -TTL 转换模块的VCC,GND分别连接到树莓派的VCC和GND,USB -TTL 转换模块的RXD,TXD分别和树莓派的RXD和TXD进行交叉连接。
1-6:打开安装好的SecureCRT软件,选择串口连接。波特率默认115200,选择自己的USB-TTL模块对应的com口即可。用户名默认为:pi 密码默认为:raspberry
2-SSH方式登录
2-1:在树莓派的Linux命令终端输入以下命令:
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
2-2:在文件末尾添加以下内容,并替换掉ssid_name以及password (需要连接的无线名称和密码)
network={
ssid="ssid_name"
psk="password"
key_mgmt=WPA-PSK //加密方式,可不写
}
2-3:保存并退出:Ctrl + o 保存 Ctrl + x 退出。
2-4:重启树莓派让上面的修改生效,输入命令即可重启:sudo reboot
2-5:由于路由器默认开启了DHCP模式,每次开启树莓派ip地址可能会变掉,所以我们应该固定ip地址,这样保证每次开机ip地址都是不变的,保证了第一次设置的SSH登录方式不会失效。
2-6:输入以下命令:
sudo nano /etc/rc.local
2-7:在 exit 0 上面添加:
ifconfig wlan0 192.168.3.18 红色字段为你想要固定的ip地址,根据自己的网段进行修改
2-8:保存并退出:Ctrl + o 保存 Ctrl + x 退出。
2-9:这样设置并不能登录树莓派,我们还要进行下一步的设置。
2-10: 输入命令 : sudo raspi-config 回车按下。
选择第5项-回车
选择第2项-回车
选择Yes-回车
选择Ok-回车
选择Finsh-回车-退出
至此SSH登录就设置好了,如果觉得默认登录密码记不住可以选择第一项:Change User Password进行修改登录密码。
wringpi在raspbian系统中都有预装,如果想要重新安装和更新可以执行以下命令:
sudo apt-get install wringpi
sudo apt-get upgrade wiringpi
安装成功后可以通过:gpio -v来查看wiringPi库的版本信息。
还可以通过命令:gpio readall 来查看树莓派的外部引脚
函数原型 | 返回值 | 说明 |
---|---|---|
int serialOpen(char* device, int baud); |
成功返回串口文件描述符,失败返回-1 |
device:串口的地址,在Linux中就是设备所在的目录。 默认一般是"/dev/ttyAMA0"。 baud:波特率 |
void serialClose(int fd); |
无 |
关闭fd关联的串口 |
void serialPutchar(int fd, unsigned char c); |
无 |
fd:serialOpen()函数返回的文件描述符 c:要发送的数据 发送一个字节的数据到串口 |
void serialPuts(int fd, char* s); |
无 |
fd:serialOpen()函数返回的文件描述符 s:发送的字符串,字符串要以'\0'结尾。 发送一个字符串到串口 |
void serialPrintf(int fd,char*message, …); |
无 |
fd:serialOpen()函数返回的文件描述符 message:格式化的字符串 像使用C语言中的printf一样发送数据到串口 |
int serialDataAvail(int fd); |
串口缓存中已经接收的,可读取的字节数,-1代表错误 |
fd:serialOpen()函数返回的文件描述符 获取串口缓存中可用的字节数。 |
int serialGetchar(int fd); |
返回:读取到的字符 |
从串口读取一个字节数据返回。 如果串口缓存中没有可用的数据,则会等待10秒,如果10秒后还有没,返回-1 所以,在读取前,最好通过serialDataAvail判断下。 |
void serialFlush(int fd); |
无 |
刷新,清空串口缓冲中的所有可用的数据。 |
*size_t write (int fd,const void * buf, size_t count); |
返回:实际写入的字符数,错误返回-1 |
fd:文件描述符,buf:需要发送的数据缓存数组,count:发送buf中的前count个字节数据。 这个是Linux下的标准IO库函数,需要包含头文件#include 当要发送到的数据量过大时,wiringPi建议使用这个函数。 |
*size_t read(int fd,void * buf ,size_t count); |
返回:实际读取的字符数。 |
fd:文件描述符,buf:接受的数据缓存的数组,count:接收的字节数。 这个是Linux下的标准IO库函数,需要包含头文件#include 当要发送到的数据量过大时,wiringPi建议使用这个函数。 |
下面列出常用的硬件初始化函数和GPIO初始化函数,更多关于wiringPi库函数请参考:http://wiringpi.com/reference/
函数原型 | 返回值 | |
---|---|---|
int wiringPiSetup (void) ; |
成功:返回执行状态 失败:返回 -1 |
①使用这个函数初始化树莓派引脚时,程序使用的是wiringPi引脚编号,引脚编号为0~16。需要root权限 |
int wiringPiSetupGpio(void); |
成功:返回执行状态 失败:返回 -1 |
①当使用这个函数初始化树莓派引脚时,程序中使用的是BCM GPIO 引脚编号表。 需要root权限 |
void pinMode(int pin, int mode); |
无 | ①pin:所配置的引脚,mode:指定引脚的I/O模式 引脚的模式有:INPUT、OUTPUT、PWM_OUTPUT或GPIO_CLOCK。注意只有wiringPi引脚1 (BCM_GPIO 18)支持PWM输出,只有wiringPi引脚7 (BCM_GPIO 4)支持CLOCK输出模式。 ②在Sys模式下,此功能无效。如果需要更改pin模式,那么可以在启动程序之前在脚本中使用gpio程序进行更改。 |
void digitalWrite (int pin,int value); |
无 | ①pin:所配置的引脚,value:配置引脚的电平。(可取的值为HIGH(高电平)或LOW(低电平))。 ②在这之前该引脚必须配置为输出模式。 |
int digitalRead (int pin) ; |
引脚上的电平值(0或1) |
pin:所要读取的引脚。 |
void pwmWrite (int pin, int value) ; |
无 | ①pin:所配置的引脚,value:配置引脚的PWM值。 ②将给定引脚的值写入PWM寄存器。树莓派有一个板载PWM引脚。pin只能是wiringPi 引脚编号下的1脚(BCM下的18脚)。 |
void pullUpDnControl (int pin, int pud) ; |
无 | ①pin:所配置的引脚(该引脚应被置为输入),pud:拉电阻模式。 拉电阻的模式有:PUD_OFF(不设置上拉/下拉)、PUD_DOWN(引脚电平拉到地面)、PUD_UP(引脚电平拉到3.3V)。 ②与Arduino不同的是,BCM2835(支持上拉和下拉更丰富)有上拉和下拉的内部电阻(约50KΩ)。 ③该函数在Sys模式下对树莓派的GPIO管脚没有影响。如果您需要激活上拉/下拉,那么您可以在启动程序之前在脚本中使用gpio程序。 |
#include
#include
#include
#include
#include
#include
#define SWITCH 7
int main()
{
int fd;
int nRead = 0;
char *getString = NULL;
getString = (char *)malloc(sizeof(char)*25);
memset(getString,'\0',25);
if(wiringPiSetup() == -1)
{
printf("Setup wiringPi fail\n");
exit(-1);
}
if((fd = serialOpen("/dev/ttyAMA0",9600)) == -1)
{
printf("Open seial fail\n");
exit(-1);
}
pinMode(SWITCH,OUTPUT);
while(1)
{
nRead = read(fd,getString,25);
if(nRead > 0 && (strcmp(getString,"Received")) != 0)
{
if((strcmp(getString,"CODE_DKD")) == 0)
{
digitalWrite(SWITCH,HIGH);
printf("Open successfully\n");
}
if((strcmp(getString,"CODE_GBD")) == 0)
{
digitalWrite(SWITCH,LOW);
printf("Closed successfully\n");
}
memset(getString,'\0',25);
nRead = 0;
}
else
{
memset(getString,'\0',25);
}
}
return 0;
}
LD3320是非特定人语音识别芯片,即语音声控芯片。最多可以识别50条预先内置的指令。
工作模式
普通模式:直接说话,模块直接识别。
按键模式:按键触发开始ASR进程。
口令模式:需要一级唤醒词(类似于苹果手机中的唤醒Siri,“嗨,Siri”。)
sRecog[DATE_A][DATE_B]中的二维数组就是要添加的口令,所说的口令,拼音打出用空格隔开即可,而pCode[DATA_A]数组中存放的是宏定义,在User_handle(nAsrRes);函数中能用到,可以根据,添加的口令,进行修改宏定义。
根据口令识别的结果可通过串口进行打印,用户可以自己修改 。
最后要说明的几点:
1-树莓派在读取串口缓冲区的字符时,如果超过8个字符时,会造成判断失误。
解决方案有两种:
1.修改User_handle()函数发送到串口缓冲区中字符的长度应<=8个字符
2.树莓派代码中调用strstr()函数进行判断
2-使用read函数读取时(串口的文件描述符),缓冲区中没有数据时并不会发生阻塞,大概8秒左右就会有返回值,这个读者自己验证。
3-通过串口进行通信,需要修改树莓派中的配置文件
输入 :sudo vim /boot/cmdline.txt
删掉里面的 console=serial1,115200 和 kgdboc=serial1,115200 ,这样你才能正常地使用串口,不然后面会出现Permission denied
最终变为:
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
下面是项目展示
基于树莓派和LD3320的语音识别控制
水平有限,错误地方,还请不吝指出。