打印
[数据转换器-信号链]

【转】在单片机上运行USB Audio实现MATLAB简单虚拟示波器

[复制链接]
805|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
焚琴煮鹤|  楼主 | 2016-12-25 13:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

传统上有个实现简单示波器的方式是用电脑的声卡来采集信号。通常这种方法有两个毛病:一是并不知道具体的电压值;二是声卡输入级是有滤波器的,对低频信号影响尤其明显。

现在用单片机来实现一个USB声卡已经很容易了,上面两个问题都可以克服。

USB Audio 的实现

简单的方法是用mbed。

mbed基本操作不细谈,当下的开发者起码应该了解一下mbed能做什么吧。因为虽然mbed能实现的并不多,但只要能实现,基本就是秒写。

首先需要一个支持USB Device的mbed兼容的板子。最基本的包括LPC1768系、LPC11Uxx系、FRDM系和EFM32系,其他可以在这里看到列表:
https://developer.mbed.org/platforms/?connectivity=10
这里安利一下LPC11U35,这货自带USB ISP所以配合mbed下程序很方便,同时基本的外设和ADC、USB Device都是有的。

我用的是mbed LPC1768。

直接导入这个工程:
https://developer.mbed.org/users/K_O_Carnivist/code/USBAudioOscilloscope/

代码也就20行,没有理解难度。

加载mbed基本库和USB Device:

#include "mbed.h"#include "USBAudio.h"
  • 1
  • 2
  • 1
  • 2

定义音频接口的采样率、通道数,定义缓冲大小:

#define FREQ                    48000#define NUMBER_CHANNEL          2#define LENGTH_AUDIO_PACKET     (FREQ / 500) * NUMBER_CHANNEL
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

建立一个USBAudio对象:

USBAudio audio(FREQ, NUMBER_CHANNEL, FREQ, NUMBER_CHANNEL, 0xab45, 0x0378);
  • 1
  • 1

建立两个AnalogIn对象,用于ADC输入模拟量,这里构造函数的参数是引脚号,根据板子的不同要做对应的修改:

AnalogIn pot0(p17);AnalogIn pot1(p18);
  • 1
  • 2
  • 1
  • 2

为音频数据开缓冲:

int16_t buf_in[LENGTH_AUDIO_PACKET/sizeof(int16_t)][2];int16_t buf_out[LENGTH_AUDIO_PACKET/sizeof(int16_t)][2];
  • 1
  • 2
  • 1
  • 2

主函数中只有一个大循环,里面的程序是读取两个ADC的值,将这个值赋给输出缓冲区的左、右声道的所有变量,再把USB数据流的地址指定到缓冲区上:

int main() {    while (1) {        int16_t analog_input[2] = {pot0.read_u16() / 64, pot1.read_u16() / 64};        for (int i = 0; i < LENGTH_AUDIO_PACKET/sizeof(int16_t); i++) {            buf_out[0] = analog_input[0];            buf_out[1] = analog_input[1];        }        audio.readWrite((uint8_t *)buf_in, (uint8_t *)buf_out);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

完。成。了。

烧写到单片机后连接USB线,电脑端显示一个名叫“Mbed Audio”的USB声卡。

这段程序的缺点还是很明显的:缓冲区刷新和USB发包不同步,会造成帧撕裂。因此它只适合看直流和低频变化,及其长时间采集存储。
实际上我也经常用另外一个用ST库写的严谨的USB音频设备程序^_^。
电脑端数据的读取

电脑端读取声卡数据的方式就很多了。各种录音软件,另外也有不少做成示波器界面的专用软件。
这里我想把数据读到MATLAB里后续还要存储处理。

其实32位Windows系统里的MATLAB是有个softscope可以用的,可惜我是64位……

这里需要装Data Acquisition Toolbox,并用Support Package Installer装一个DirectSound的扩展包。

全部代码如下,运行于MATLAB 2015a和Windows 7 64位:

%% Plot Continuous Data from Audio Input% This program acquire data from an audio input (e.g. Mbed Audio) and% display them on an axis continuously.% Data Acquisition Toolbox and DirectSound Support Package are needed.%% Select a Sound Device% List all sound devices available in the system.d = daq.getDevices%% % Search for mbed sound card.for dev_index = 1:length(d)    if strcmp(d(dev_index).Model, 'Microphone (2- Mbed Audio)')        dev = d(dev_index)        break;    endend%% Create an Audio Session% Create a session with directsound as the vendor and add an audio input% channel to it.% Prepare session for continuous operation.s = daq.createSession('directsound');addAudioInputChannel(s, dev.ID, 1:2);s.IsContinuous = true%% Set up the Plot for Live Input.hf = figure;hp = plot(zeros(1000,2));T = title('Audio Plot');xlabel('Time (ms)');ylabel('Voltage');axis([0 1000 0 3.3]);legend('Channel 1', 'Channel 2');grid on;%% Add DataAvailable listener% Listener updates the figure with the live input signal.plotData = @(src, event) ({ ...        set(hp(1), 'ydata', event.Data(:, 1) * 3.3, 'xdata', (1:length(event.Data))' / src.Rate * 1000), ...        set(hp(2), 'ydata', event.Data(:, 2) * 3.3, 'xdata', (1:length(event.Data))' / src.Rate * 1000), ...        axis([0 length(event.Data)/src.Rate*1000 -5 5]), ...        drawnow ...    });hl = addlistener(s, 'DataAvailable', plotData);%% Start acquisition% Observe that the figure updates.startBackground(s);%% Stop the Session% Wait for 10 seconds while continuing to acquire data.pause(10);% Stop the session.stop(s);s.IsContinuous = false;delete(hl);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

中间'Microphone (2- Mbed Audio)'那一段可能需要根据实际设备名做改动。

总体来说这段代码的执行效果是利用DirectSound连续采集音频数据,每隔100ms(默认值)触发DataAvailable事件,事件执行plotData那段匿名函数,更新图线的数据。共执行10秒后停止更新。我对匿名函数不太熟悉,如果这里报错的话,可以把它拉出来单独一个m文件。

d = daq.getDevices之后如果没有列出DirectSound设备,说明需要安装支持包,详见这段开头。

这段代码可以用MATLAB的publish功能的哈,很好玩。

结果

单片机引脚输入周期为10ms的方波,得到的连续刷新的图形。

进一步可以在每次事件触发时保存数据,并做更长时间的绘图及数据处理。


相关帖子

沙发
chuntian2016| | 2016-12-25 20:04 | 只看该作者
matlab具有非常强大的数据处理功能的,,结合开发使用的很有帮助的

使用特权

评论回复
板凳
baiyunpiapia| | 2016-12-25 20:17 | 只看该作者
这个看起来好高端的样子;

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

63

主题

106

帖子

3

粉丝