树莓派通过串口驱动SU-03T语音模块
文章目录
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/884611c4bd7040bd9e1fad3e3f2101df.png#pic_center)
一、SU-03T语音模块的配置和烧录
1.1 PIN引脚配置:
1.2 设置唤醒词:
1.3 设置控制详情:
1.4 下载SDK并烧录到语音模块:
下载完之后我们的语音模块就可以和树莓派进行串口通信了,但是不急,我们先测试一下语音模块
二、测试语音模块
将USB-TTL的TXD和RXD分别和语音模块的TXD和RXD交叉相连,然后插到电脑的USB中:
经过测试我们的语音模块工作是OK的,下面我们就可以写代码了
三、树莓派通过串口驱动语音模块控制设备
3.1 硬件连接:
由于我的树莓派供电是电脑USB供电的,所以这些外设它驱动不了,所以我们接了一个我们自己做的外置电源,但是外置电源要和树莓派共地!
3.2 代码实现:
/* mySerialTool.h */
#ifndef __MYSERIALTOOL_H__
#define __MYSERIALTOOL_H__
/*
* @Author: <NAME> 打开指定的串口设备,并设置波特率
*
* @param device 串口设备名称,如"/dev/ttyUSB0"
* @param baud 波特率,如9600、115200等
* @return 成功返回文件描述符,失败返回-1
*/
int mySerialOpen(const char *device, const int baud);
/*
* @Author: 向指定的串口设备发送字符串
*
* @param fd 串口设备文件描述符
* @param str 要发送的字符串
* @return 无
*/
void mySerialSendString(const int fd, const char *str);
/*
* @Author: 从指定的串口设备读取字符串
*
* @param fd 串口设备文件描述符
* @param buffer 读取到的字符串存放的缓冲区
* @return 读取到的字符串的长度,失败返回-1
*/
int mySerialReadString(const int fd, char *buffer);
#endif
/* mySerialTool.c */
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
/*打开指定的串口设备,并设置波特率*/
int mySerialOpen(const char *device, const int baud)
{
struct termios options; // 串口配置参数
speed_t myBaud; // 波特率
int status, fd; // 状态和文件描述符
//根据传入的波特率参数设置相应的波特率
switch(baud){
case 9600:
myBaud = B9600;
break;
case 115200:
myBaud = B115200;
break;
default:
printf("不支持的波特率!\n");
return -2;
}
//打开串口设备
if( (fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY)) == -1){
printf("无法打开串口设备\n");
return -1;
}
// 设置文件描述符的标志为读写模式
fcntl(fd, F_SETFL, O_RDWR);
// 获取当前串口配置
tcgetattr(fd, &options);
// 设置串口为原始模式,无特殊处理
cfmakeraw(&options);
// 设置输入波特率
cfsetispeed(&options, myBaud);
// 设置输出波特率
cfsetospeed(&options, myBaud);
// 清除标志位并设置数据格式
options.c_cflag |= (CLOCAL | CREAD);
options.c_cflag &= ~PARENB; // 无奇偶校验位
options.c_cflag &= ~CSTOPB; // 1个停止位
options.c_cflag &= ~CSIZE; // 清除数据位
options.c_cflag |= CS8; // 设置为8位数据位
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 非规范模式,不执行输入处理
options.c_oflag &= ~OPOST; // 输出处理
// 设置读取时的超时和最小接收字符数
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 100; // 10秒超时
// 应用串口配置
tcsetattr(fd, TCSANOW, &options);
// 使用ioctl设置串口的DTR和RTS信号
ioctl(fd, TIOCMGET, &status);
status |= TIOCM_DTR;
status |= TIOCM_RTS;
ioctl(fd, TIOCMSET, &status);
// 短暂延时
usleep(10000); // 10毫秒延时
return fd; // 返回文件描述符
}
/*向指定的串口设备发送字符串*/
void mySerialSendString(const int fd, const char *str)
{
int ret;
ret = write(fd, str, strlen(str)); // 发送字符串
if(ret == -1){
printf("串口发送失败!\n");
exit(-1); // 发送失败,退出程序
}
}
/*从指定的串口设备读取字符串*/
int mySerialReadString(const int fd, char *buffer)
{
int n_read;
n_read = read(fd, buffer, 32); // 读取串口数据
if(n_read == -1){
printf("串口读取失败!\n");
exit(-1); // 读取失败,退出程序
}
}
/* main.c */
#include <stdio.h>
#include <string.h>
#include <wiringPi.h>
#include "mySerialTool.h"
#define LED1 26 //定义四个LED引脚
#define LED2 27
#define LED3 28
#define LED4 29
void LED_GPIO_Init()
{
pinMode(LED1, OUTPUT); //设置四个LED引脚为输出模式
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
}
int main(int argc, char **argv)
{
int fd;
char deviceName[32] = {'\0'};
int n_read; //读取数据长度
char readBuf[2] = {0x98, 0x00}; //接收数据缓存
if(argc < 2){ //查看命令行参数是否存在
printf("Usage: %s /dev/ttyAMA0\n", argv[0]);
return -1;
}
strcpy(deviceName, argv[1]); //拷贝设备名到deviceName
fd = mySerialOpen(deviceName, 9600); //打开串口
if(fd < 0){
printf("打开串口设备失败\n");
return -1;
}
if(wiringPiSetup() == -1){ //初始化wiringPi
printf("初始化wiringPi失败\n");
return -1;
}
LED_GPIO_Init(); //初始化LED引脚
while(1){
n_read = mySerialReadString(fd, readBuf);
//printf("读到的数据为:%c\n", readBuf[1]);
if(n_read > 0 && readBuf[1] == '1'){
printf("打开一号灯\n");
digitalWrite(LED1, LOW);
}else if(n_read > 0 && readBuf[1] == '2'){
printf("打开二号灯\n");
digitalWrite(LED2, LOW);
}else if(n_read > 0 && readBuf[1] == '3'){
printf("打开三号灯\n");
digitalWrite(LED3, LOW);
}else if(n_read > 0 && readBuf[1] == '4'){
printf("打开四号灯\n");
digitalWrite(LED4, LOW);
}else if(n_read > 0 && readBuf[1] == 'c'){
printf("关闭所有灯\n");
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);
digitalWrite(LED3, HIGH);
digitalWrite(LED4, HIGH);
}
memset(readBuf, '\0', sizeof(readBuf));
}
return 0;
}