目录
0 前言
① STM32用的是STM32F407ZGT6的核心版。
② SIPEED是之前买的准备做声源定位的。
1 接线与引脚定义
接线方式采用杜邦线接线
SIPEED | STM32 |
LED_CA | GPIOB7 |
LED_DA | GPIOB8 |
MIC_D0 | GPIOB3 |
MIC_D1 | GPIOB4 |
MIC_D2 | GPIOB5 |
MIC_D3 | GPIOB6 |
MIC_WS | GPIOG14 |
MIC_CK | GPIOG15 |
VIN | 3.3V |
GND | GND |
2 SIPEED驱动
软件模拟i2s,MSM261S4030H0数字麦克风采用飞利浦标准的i2s。
① sipeed.c文件:(中心的麦克风数据线为MIC_D3,是单声道,读取的数据为24位)
#include "sipeed.h"
/*
sipeed的sk9822灯珠初始化
GPIOB7: 时钟
GPIOB8: 数据
*/
void Sipeed_Led_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/*
发送字节数据
SIPEED_LED_CLK: 时钟
SIPEED_LED_DAT: 数据
*/
static void Sipeed_Led_SendByte(u8 data)
{
u8 i = 0;
SIPEED_LED_CLK = 1;
delay_us(1);
for (i = 0; i < 8; i++)
{
SIPEED_LED_CLK = 0;
delay_us(1);
SIPEED_LED_DAT = (data>>(7-i)) & 0x01;
delay_us(1);
SIPEED_LED_CLK = 1;
delay_us(1);
}
}
/*
发送帧头
*/
static void Sipeed_Led_SendStart(void)
{
Sipeed_Led_SendByte(0x00);
Sipeed_Led_SendByte(0x00);
Sipeed_Led_SendByte(0x00);
Sipeed_Led_SendByte(0x00);
}
/*
发送帧尾
*/
static void Sipeed_Led_SendEnd(void)
{
Sipeed_Led_SendByte(0xFF);
Sipeed_Led_SendByte(0xFF);
Sipeed_Led_SendByte(0xFF);
Sipeed_Led_SendByte(0xFF);
}
/*
发送数据
参数:point :灯位置 取值:1~12
r :red 取值:0~255
g :green 取值:0~255
b :blue 取值:0~255
bright:亮度 取值:0~31
*/
void Sipeed_Led_SendData(u8 point, u8 r, u8 g, u8 b, u8 bright)
{
u8 i = 1;
Sipeed_Led_SendStart();
for (i = 1; i < point; i++)
{
Sipeed_Led_SendByte(0xE0);
Sipeed_Led_SendByte(0x00);
Sipeed_Led_SendByte(0x00);
Sipeed_Led_SendByte(0x00);
}
Sipeed_Led_SendByte(0xE0 | bright); //bright
Sipeed_Led_SendByte(b); //blue
Sipeed_Led_SendByte(g); //green
Sipeed_Led_SendByte(r); //red
for (i = point+1; i <= 12; i++)
{
Sipeed_Led_SendByte(0xE0);
Sipeed_Led_SendByte(0x00);
Sipeed_Led_SendByte(0x00);
Sipeed_Led_SendByte(0x00);
}
Sipeed_Led_SendEnd();
}
/*
sipeed的MSM26S4030H0麦克风初始化
GPIOG14: 声道选择
GPIOG15: 时钟
GPIOB3 : MIC_D0
GPIOB4 : MIC_D1
GPIOB5 : MIC_D2
GPIOB6 : MIC_D3
*/
void Sipeed_MIC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOG, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/*
sipeed系统初始化
*/
void Sipeed_Init(void)
{
Sipeed_Led_Init();
Sipeed_MIC_Init();
Sipeed_Led_SendData(1, 0, 0, 0, 0);
}
/*
sipeed读数据
SIPEED_MIC_WS
SIPEED_MIC_SCK
SIPEED_MIC_D0
SIPEED_MIC_D1
SIPEED_MIC_D2
SIPEED_MIC_D3
DMIC:第几个麦克风,取值:0 MIC_D0
1 MIC_D1
2 MIC_D2
*/
u32 Sipeed_read_left(u8 DMIC)
{
u8 i = 0;
u32 data = 0;
for (i = 1; i <= 32; i++)
{
SIPEED_MIC_SCK = 0;
SIPEED_MIC_WS = 0;
delay_us(1);
if (i >= 2 && i <= 25)
{
if (DMIC == 0)
{
data |= SIPEED_MIC_D0 << (25-i);
}
else if (DMIC == 1)
{
data |= SIPEED_MIC_D1 << (25-i);
}
else if (DMIC == 2)
{
data |= SIPEED_MIC_D2 << (25-i);
}
}
SIPEED_MIC_SCK = 1;
delay_us(1);
}
return data;
}
/*
sipeed读数据
SIPEED_MIC_WS
SIPEED_MIC_SCK
SIPEED_MIC_D0
SIPEED_MIC_D1
SIPEED_MIC_D2
SIPEED_MIC_D3
DMIC:第几个麦克风,取值:0 MIC_D0
1 MIC_D1
2 MIC_D2
3 MIC_D3
*/
u32 Sipeed_read_right(u8 DMIC)
{
u8 i = 0;
u32 data = 0;
delay_us(1);
for (i = 1; i <= 32; i++)
{
SIPEED_MIC_SCK = 0;
SIPEED_MIC_WS = 1;
delay_us(1);
if (i >= 2 && i <= 25)
{
if (DMIC == 0)
{
data |= SIPEED_MIC_D0 << (25-i);
}
else if (DMIC == 1)
{
data |= SIPEED_MIC_D1 << (25-i);
}
else if (DMIC == 2)
{
data |= SIPEED_MIC_D2 << (25-i);
}
else if (DMIC == 3)
{
data |= SIPEED_MIC_D3 << (25-i);
}
}
SIPEED_MIC_SCK = 1;
delay_us(1);
}
return data;
}
② sipeed.h文件:
#ifndef _SIPEED_H_
#define _SIPEED_H_
#include "stm32f4xx.h"
#include "SysTick.h"
#include "system.h"
#define SIPEED_LED_CLK PBout(7)
#define SIPEED_LED_DAT PBout(8)
#define SIPEED_MIC_WS PGout(14)
#define SIPEED_MIC_SCK PGout(15)
#define SIPEED_MIC_D0 PBin(3)
#define SIPEED_MIC_D1 PBin(4)
#define SIPEED_MIC_D2 PBin(5)
#define SIPEED_MIC_D3 PBin(6)
//LED
extern void Sipeed_Led_Init(void);
extern void Sipeed_Led_SendData(u8 point, u8 r, u8 g, u8 b, u8 bright);
//MSM26S4030H0
extern void Sipeed_MIC_Init(void);
extern u32 Sipeed_read_left(u8 DMIC);
extern u32 Sipeed_read_right(u8 DMIC);
//SYSTEM
extern void Sipeed_Init(void);
#endif
③ main.c文件 (主函数,只接收了一个麦克风的数据)
#include "stm32f4xx.h"
#include "SysTick.h"
#include "sipeed.h"
#include "usart.h"
int main()
{
int data = 0;
SysTick_Init(168);
USART1_Init(115200);
Sipeed_Init();
while(1)
{
data = Sipeed_read_left(0);
data = Sipeed_read_right(0);
if (data > 0xF72000) //0xF87B6F
{
Sipeed_Led_SendData(1, 255, 0, 0, 10);
}
else
{
Sipeed_Led_SendData(1, 0, 255, 0, 10);
}
printf("%d\n", data);
}
}
3 MATLAB上位机
声明:
sipeed读取的数据是24位数据; |
在本人看了一些资料后,还是不太明白数据的值代表什么,搜到的都在普及位深度是啥,留个坑,有机会来补充(MSM261S4030H0给的数据手册,看了个寂寞); |
本人将数据当作声音的振幅,采用24位有符号数表示,并通过MATLAB上位机实时显示。 |
① matlab代码:
classdef voice < matlab.apps.AppBase
% Properties that correspond to app components
properties (Access = public)
UIFigure matlab.ui.Figure
notice matlab.ui.container.Panel
notice_Label matlab.ui.control.Label
notice_confirm matlab.ui.control.Button
uart_Panel matlab.ui.container.Panel
uart_lamp_stop matlab.ui.control.Lamp
plot_clear matlab.ui.control.Button
uart_lamp_notice matlab.ui.control.Lamp
uart_recivestop matlab.ui.control.Button
uart_recive matlab.ui.control.Button
uart_lamp matlab.ui.control.Lamp
uart_open matlab.ui.control.Button
uart_check matlab.ui.control.DropDown
Label_3 matlab.ui.control.Label
uart_data matlab.ui.control.DropDown
Label_2 matlab.ui.control.Label
uart_boud matlab.ui.control.DropDown
DropDownLabel matlab.ui.control.Label
uart_COM matlab.ui.control.DropDown
COMDropDownLabel matlab.ui.control.Label
Label matlab.ui.control.Label
uart_stop matlab.ui.control.DropDown
UIAxes_2 matlab.ui.control.UIAxes
UIAxes matlab.ui.control.UIAxes
end
properties (Access = public)
uart_flag = 0; % 串口状态
uart_scom; % 串口设备
plot_flag = 0; % 绘图状态
x_tick = 0;
uart_recieve_data;
uart_recieve_db;
end
methods (Access = public)
function notice_info(app, info)
app.notice_Label.Text = info;
app.notice.Visible = 'on';
end
end
methods (Access = private)
function data = B2Qw(~, X)
len = strlength(X);
p = str2double(X(1))* (-1) * power(2, len-1);
for i=2:1:len
p = p + str2double(X(i)) * power(2, len-i);
end
data = p;
end
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
% 获取屏幕分辨率
res = get(0, 'ScreenSize');
width = res(3);
height = res(4);
% 设置位置居中
app.UIFigure.Position(1:2) = [(width-app.UIFigure.Position(3))/2, ...
(height-app.UIFigure.Position(4))/2];
app.uart_COM.Items = serialportlist("available");
end
% Button pushed function: uart_open
function uart_openButtonPushed(app, event)
% 查询并显示可用串口
app.uart_COM.Items = serialportlist("available");
% 串口信息
COM = app.uart_COM.Value; % COM口
boudRate = app.uart_boud.Value; % 波特率
data = app.uart_data.Value; % 数据位
check = app.uart_check.Value; % 校验位
stop = app.uart_stop.Value; % 停止位
if app.uart_flag == 1
% 关闭串口
app.uart_flag = 0;
app.plot_flag = 0;
app.uart_open.Text = '打开串口';
app.uart_lamp.Color = [0.15,0.15,0.15];
delete(app.uart_scom);
% 查询并显示可用串口
app.uart_COM.Items = serialportlist("available");
else
% 打开串口
try
app.uart_scom = serialport(COM, ...
str2double(boudRate),...
'DataBits', str2double(data),...
'Parity', check,...
'StopBits',str2double(stop));
app.uart_lamp.Color = [0 1 0];
app.uart_open.Text = '关闭串口';
app.uart_flag = 1;
app.plot_flag = 1;
catch
notice_info(app, '打开失败');
end
end
end
% Button pushed function: notice_confirm
function notice_confirmButtonPushed(app, event)
% 关闭提示
app.notice.Visible = 'off';
end
% Drop down opening function: uart_COM
function uart_COMDropDownOpening(app, event)
if app.uart_flag == 0
% 查询并显示可用串口
app.uart_COM.Items = serialportlist("available");
end
end
% Button pushed function: uart_recive
function uart_reciveButtonPushed(app, event)
% 判断串口是否打开
if app.uart_flag == 0
notice_info(app, "请先打开串口");
return;
end
app.uart_lamp_stop.Visible = 'off';
app.plot_flag = 1;
i = 1;
data = 0;
while app.plot_flag
i = i + 1;
% 接收数据
if i == 1000
app.uart_lamp_notice.Color = [1 0 0];
pause(0.00001);
end
temp = read(app.uart_scom, 1, "char");
if temp ~= 10
data = data * 10 + temp - 48;
else
app.uart_recieve_db = [app.uart_recieve_db; 20*log10(data)];
if data > 0x800000
data = B2Qw(app, dec2bin(data));
end
app.uart_recieve_data = [app.uart_recieve_data; data];
app.x_tick = [app.x_tick; app.x_tick(end)+0.01];
plot(app.UIAxes, app.x_tick(2:end), app.uart_recieve_data);
plot(app.UIAxes_2, app.x_tick(2:end), app.uart_recieve_db);
data = 0;
end
if i == 2000
app.uart_lamp_notice.Color = [0 1 0];
pause(0.00001);
i = 1;
end
pause(0.001);
end
end
% Button pushed function: uart_recivestop
function uart_recivestopButtonPushed(app, event)
app.plot_flag = 0;
app.uart_lamp_notice.Color = [0.15,0.15,0.15];
app.uart_lamp_stop.Visible = 'on';
end
% Button pushed function: plot_clear
function plot_clearButtonPushed(app, event)
app.x_tick = 0;
app.uart_recieve_data = [];
app.uart_recieve_db = [];
cla(app.UIAxes);
cla(app.UIAxes_2);
end
end
% Component initialization
methods (Access = private)
% Create UIFigure and components
function createComponents(app)
% Create UIFigure and hide until all components are created
app.UIFigure = uifigure('Visible', 'off');
app.UIFigure.AutoResizeChildren = 'off';
app.UIFigure.Position = [100 100 1153 763];
app.UIFigure.Name = 'MATLAB App';
app.UIFigure.Resize = 'off';
% Create UIAxes
app.UIAxes = uiaxes(app.UIFigure);
app.UIAxes.XGrid = 'on';
app.UIAxes.YGrid = 'on';
app.UIAxes.Position = [192 384 963 380];
% Create UIAxes_2
app.UIAxes_2 = uiaxes(app.UIFigure);
app.UIAxes_2.XGrid = 'on';
app.UIAxes_2.YGrid = 'on';
app.UIAxes_2.Position = [192 1 963 380];
% Create uart_Panel
app.uart_Panel = uipanel(app.UIFigure);
app.uart_Panel.AutoResizeChildren = 'off';
app.uart_Panel.ForegroundColor = [1 0 0];
app.uart_Panel.TitlePosition = 'centertop';
app.uart_Panel.Title = '串口设置';
app.uart_Panel.BackgroundColor = [0.651 0.651 0.651];
app.uart_Panel.FontName = '宋体';
app.uart_Panel.FontWeight = 'bold';
app.uart_Panel.FontSize = 20;
app.uart_Panel.Position = [1 1 191 764];
% Create uart_stop
app.uart_stop = uidropdown(app.uart_Panel);
app.uart_stop.Items = {'1', '2', '1.5'};
app.uart_stop.Position = [73 517 107 22];
app.uart_stop.Value = '1';
% Create Label
app.Label = uilabel(app.uart_Panel);
app.Label.HorizontalAlignment = 'right';
app.Label.Position = [5 517 57 22];
app.Label.Text = '停止位:';
% Create COMDropDownLabel
app.COMDropDownLabel = uilabel(app.uart_Panel);
app.COMDropDownLabel.HorizontalAlignment = 'right';
app.COMDropDownLabel.FontName = 'Times New Roman';
app.COMDropDownLabel.Position = [5 705 57 22];
app.COMDropDownLabel.Text = 'COM口:';
% Create uart_COM
app.uart_COM = uidropdown(app.uart_Panel);
app.uart_COM.Items = {};
app.uart_COM.DropDownOpeningFcn = createCallbackFcn(app, @uart_COMDropDownOpening, true);
app.uart_COM.Position = [73 705 107 22];
app.uart_COM.Value = {};
% Create DropDownLabel
app.DropDownLabel = uilabel(app.uart_Panel);
app.DropDownLabel.HorizontalAlignment = 'right';
app.DropDownLabel.Position = [5 658 57 22];
app.DropDownLabel.Text = '波特率:';
% Create uart_boud
app.uart_boud = uidropdown(app.uart_Panel);
app.uart_boud.Items = {'9600', '115200'};
app.uart_boud.Position = [73 658 107 22];
app.uart_boud.Value = '115200';
% Create Label_2
app.Label_2 = uilabel(app.uart_Panel);
app.Label_2.HorizontalAlignment = 'right';
app.Label_2.Position = [5 611 57 22];
app.Label_2.Text = '数据位:';
% Create uart_data
app.uart_data = uidropdown(app.uart_Panel);
app.uart_data.Items = {'8', '7', '6', '5'};
app.uart_data.Position = [73 611 107 22];
app.uart_data.Value = '8';
% Create Label_3
app.Label_3 = uilabel(app.uart_Panel);
app.Label_3.HorizontalAlignment = 'right';
app.Label_3.Position = [5 564 57 22];
app.Label_3.Text = '校验位:';
% Create uart_check
app.uart_check = uidropdown(app.uart_Panel);
app.uart_check.Items = {'none', 'odd', 'even', 'mark', 'space'};
app.uart_check.Position = [73 564 107 22];
app.uart_check.Value = 'none';
% Create uart_open
app.uart_open = uibutton(app.uart_Panel, 'push');
app.uart_open.ButtonPushedFcn = createCallbackFcn(app, @uart_openButtonPushed, true);
app.uart_open.FontName = '宋体';
app.uart_open.FontWeight = 'bold';
app.uart_open.Position = [95 469 86 31];
app.uart_open.Text = '打开串口';
% Create uart_lamp
app.uart_lamp = uilamp(app.uart_Panel);
app.uart_lamp.Position = [42 473 20 20];
app.uart_lamp.Color = [0.149 0.149 0.149];
% Create uart_recive
app.uart_recive = uibutton(app.uart_Panel, 'push');
app.uart_recive.ButtonPushedFcn = createCallbackFcn(app, @uart_reciveButtonPushed, true);
app.uart_recive.FontName = '宋体';
app.uart_recive.FontWeight = 'bold';
app.uart_recive.Position = [95 116 86 31];
app.uart_recive.Text = '接收数据';
% Create uart_recivestop
app.uart_recivestop = uibutton(app.uart_Panel, 'push');
app.uart_recivestop.ButtonPushedFcn = createCallbackFcn(app, @uart_recivestopButtonPushed, true);
app.uart_recivestop.FontName = '宋体';
app.uart_recivestop.FontWeight = 'bold';
app.uart_recivestop.Position = [95 63 86 31];
app.uart_recivestop.Text = '停止接收';
% Create uart_lamp_notice
app.uart_lamp_notice = uilamp(app.uart_Panel);
app.uart_lamp_notice.Position = [43 121 20 20];
app.uart_lamp_notice.Color = [0.149 0.149 0.149];
% Create plot_clear
app.plot_clear = uibutton(app.uart_Panel, 'push');
app.plot_clear.ButtonPushedFcn = createCallbackFcn(app, @plot_clearButtonPushed, true);
app.plot_clear.FontName = '宋体';
app.plot_clear.FontWeight = 'bold';
app.plot_clear.Position = [96 11 86 31];
app.plot_clear.Text = '清空窗口';
% Create uart_lamp_stop
app.uart_lamp_stop = uilamp(app.uart_Panel);
app.uart_lamp_stop.Visible = 'off';
app.uart_lamp_stop.Position = [43 68 20 20];
app.uart_lamp_stop.Color = [1 0 0];
% Create notice
app.notice = uipanel(app.UIFigure);
app.notice.AutoResizeChildren = 'off';
app.notice.Title = 'Notice!';
app.notice.Visible = 'off';
app.notice.FontName = 'Algerian';
app.notice.FontWeight = 'bold';
app.notice.FontSize = 15;
app.notice.Position = [458 292 240 180];
% Create notice_confirm
app.notice_confirm = uibutton(app.notice, 'push');
app.notice_confirm.ButtonPushedFcn = createCallbackFcn(app, @notice_confirmButtonPushed, true);
app.notice_confirm.FontName = '宋体';
app.notice_confirm.FontWeight = 'bold';
app.notice_confirm.Position = [180 10 50 30];
app.notice_confirm.Text = '确定';
% Create notice_Label
app.notice_Label = uilabel(app.notice);
app.notice_Label.HorizontalAlignment = 'center';
app.notice_Label.FontName = '宋体';
app.notice_Label.FontSize = 15;
app.notice_Label.FontWeight = 'bold';
app.notice_Label.FontColor = [1 0 0];
app.notice_Label.Position = [1 50 240 100];
app.notice_Label.Text = '';
% Show the figure after all components are created
app.UIFigure.Visible = 'on';
end
end
% App creation and deletion
methods (Access = public)
% Construct app
function app = voice
% Create UIFigure and components
createComponents(app)
% Register the app with App Designer
registerApp(app, app.UIFigure)
% Execute the startup function
runStartupFcn(app, @startupFcn)
if nargout == 0
clear app
end
end
% Code that executes before app deletion
function delete(app)
% Delete UIFigure when app is deleted
delete(app.UIFigure)
end
end
end
4 效果
上面显示的就是振幅,下面是想显示分贝的,但是有点问题,待我去学习一下基础知识再说吧,还有就是这玩意为啥我制造声音,没反应啊。
5 坑
① 第一个坑就是那个数据是啥,咋处理的问题,本人目前也懵逼ing
② MATLAB上位机,之前做过一个MATLAB的上位机,使用的虚拟串口进行的调试,收发都没问题,这次用STM32串口通信的时候,MATLAB一直收不到数据(发没有试)。
首先,matlab可以正常打开串口,但是收数据一直显示超时;
其次,重新以管理员身份运行MATLAB,无解;
最后,换了串口连接方式。开始使用的是右边白色的数据线,MATLAB接收一直超时(原因未知),后续换了下图,并用杜邦线直接连接TX、RX到STM32(注意交叉连接)。