本次目标新建工程,将I2S驱动麦克风,串口助手可以查看当前环境的声音质量大小。新建工程

软件配置配置设备树NRF的工程都是在zerphy上建立的,其中使用引脚,要引入一个设备树的概念


vscode选择创建新的工程,选择copy sample

选择helloworld工程

设置配置文件,直接选择板卡点击最下面的build,其他可以不用选择
软件配置配置设备树NRF的工程都是在zerphy上建立的,其中使用引脚,要引入一个设备树的概念在目录下创建 app.overlay,系统会识别到这个作为我们的默认引脚配置

选择i2s20,这里L5引脚只支持其中i2s这个引脚位
#include <zephyr/dt-bindings/pinctrl/nrf-pinctrl.h>
&pinctrl {
i2s20_default: i2s20_default {
group1 {
psels = <NRF_PSEL(I2S_SCK_M, 1, 12)>,
<NRF_PSEL(I2S_LRCK_M, 1, 13)>,
<NRF_PSEL(I2S_SDIN, 1, 11)>;
};
};
};
&i2s20 {
status = "okay";
pinctrl-0 = <&i2s20_default>;
pinctrl-names = "default";
};开启配置宏,通过宏的方式将我们需要的功能使能

这里我们这3个配置使能
# 启用日志系统 CONFIG_LOG=y #I2S CONFIG_I2S=y CONFIG_CBPRINTF_FP_SUPPORT=y测试是否成功驱动软件
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/i2s.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/nrf_clock_control.h>
#define I2S_NODE DT_NODELABEL(i2s20)
#define SAMPLE_FREQUENCY 16000
#define WORD_SIZE 16 /* 16-bit */
#define CHANNELS 1
#define BLOCK_SIZE (1024)
#define NUM_BLOCKS 4
K_MEM_SLAB_DEFINE(rx_mem_slab, BLOCK_SIZE, NUM_BLOCKS, 4);
int main(void)
{
const struct device *i2s_dev = DEVICE_DT_GET(I2S_NODE);
int ret;
printk("--- Starting I2S INMP441 Ultimate Test ---\n");
/* 开启给I2S的时钟 */
const struct device *clk_dev = DEVICE_DT_GET(DT_NODELABEL(clock));
if (device_is_ready(clk_dev)) {
clock_control_on(clk_dev, CLOCK_CONTROL_NRF_SUBSYS_HF);
printk("HF Clock forced ON.\n");
} else {
printk("Warning: Clock device not ready.\n");
}
if (!device_is_ready(i2s_dev)) {
printk("I2S device not ready!\n");
return 0;
}
/* 2. 配置 I2S 硬件参数 */
struct i2s_config config;
config.word_size = WORD_SIZE;
config.channels = CHANNELS;
config.format = I2S_FMT_DATA_FORMAT_I2S;
config.options = I2S_OPT_BIT_CLK_MASTER | I2S_OPT_FRAME_CLK_MASTER;
config.frame_clk_freq = SAMPLE_FREQUENCY;
config.mem_slab = &rx_mem_slab;
config.block_size = BLOCK_SIZE;
config.timeout = 2000; /* 设置 2000ms 超时 */
ret = i2s_configure(i2s_dev, I2S_DIR_RX, &config);
if (ret < 0) {
printk("Failed to configure I2S RX: %d\n", ret);
return 0;
}
/* 3. 【最关键的扳机】:启动 I2S 数据流传输 */
ret = i2s_trigger(i2s_dev, I2S_DIR_RX, I2S_TRIGGER_START);
if (ret < 0) {
printk("Failed to trigger I2S RX START: %d\n", ret);
return 0;
}
printk("I2S stream triggered successfully! Waiting for data...\n");
/* 4. 无限循环读取数据 */
while (1) {
void *mem_block;
size_t block_size_out;
/* 读取音频数据块 */
ret = i2s_read(i2s_dev, &mem_block, &block_size_out);
if (ret < 0) {
printk("I2S read error: %d (Timeout or DMA fault)\n", ret);
k_msleep(1000);
continue;
}
//音量大小
int16_t *samples = (int16_t *)mem_block;
int num_samples = block_size_out / sizeof(int16_t);
int16_t max_amplitude = 0;
for (int i = 0; i < num_samples; i++) {
int16_t val = samples[i];
if (val < 0) {
val = -val; /* 取绝对值 */
}
if (val > max_amplitude) {
max_amplitude = val;
}
}
/* 打印读取到的字节数和音量大小 */
printk("Read %zu bytes | Max Amplitude: %d\n", block_size_out, max_amplitude);
k_mem_slab_free(&rx_mem_slab, mem_block);
}
return 0;
}这里的配置是16采样率,16位,然后其中将音频获取,通过计算到字节数和音频,是否在串口助手上打印,则代表硬件通路搭建完成。
我要赚赏金
