基于 ESP32-S3 开发的 USB 安全麦克风。让使用者完全避免开会中声音泄露的尴尬。
1.主控是 ESP32-S3,内置USB Device 支持,将自身模拟为一个 USB麦克风
2.使用MSM261S4030H0麦克风,这是一个高灵敏度的单麦克,通过I2S接口直接输出音频信息。
通过国产的 Cherry USB 架构实现了一个简单的 UAC.
关键代码如下:
代码
1.初始化麦克风的 I2S ,特别注意是单声道
// 标准模式配置
i2s_std_config_t std_cfg =
{
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(SAMPLE_RATE),
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(
I2S_DATA_BIT_WIDTH_32BIT,
I2S_SLOT_MODE_MONO
),
//.slot_cfg.slot_mask = I2S_STD_SLOT_LEFT,
.gpio_cfg = {
.bclk = I2S_BCK_GPIO,
.ws = I2S_WS_GPIO,
.din = I2S_DATA_GPIO,
.invert_flags = {
.bclk_inv = false, //时钟空闲时为 High
.ws_inv = false
}
}
};
std_cfg.slot_cfg.slot_mode=I2S_SLOT_MODE_MONO;
std_cfg.slot_cfg.slot_mask=I2S_STD_SLOT_LEFT;
代码
2.Cherry USB架构下,下面的函数中完成 UAC 的初始化,同时创建一个队列用于接收音频数据
void audio_v1_init(uint8_t busid, uintptr_t reg_base)
{
// 创建同步信号
sign_tx = xSemaphoreCreateBinary();
// 数据队列
s_receive_queue = xQueueCreate(10, sizeof(i2c_mic_rx_data_t));
//创建接收任务
xTaskCreatePinnedToCore(task_func, "task", 4096, NULL, 10, NULL, tskNO_AFFINITY);
ESP_ERROR_CHECK(esp_task_wdt_add_user("usb", &twdt_usb));
usbd_desc_register(busid, audio_v1_descriptor);
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, 0x0100, audio_entity_table, 1));
usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, 0x0100, audio_entity_table, 1));
usbd_add_endpoint(busid, &audio_in_ep);
usbd_initialize(busid, reg_base, usbd_event_handler);
}
代码
3.收到的音频数据在如下回调函数中
void usbd_audio_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes)
{
//USB_LOG_RAW("actual in len:%d\r\n", nbytes);
ep_tx_busy_flag = false;
if (0 == tx_flag)
{
printf("usbd_audio_iso_callback tx_flag = 0\n");
}
// 释放信号,让Main那边可以发送了
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(sign_tx, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
代码
4. 最终,在将音频数据发送给PC时,做一个简单的判断,只有指定的 GPIO 拉低才会将数据发送出去,否则送出空数据包
// 如果当前没有发送
if (ep_tx_busy_flag != true)
{
ep_tx_busy_flag = true;
xSemaphoreTake(sign_tx, 0);
if(gpio_get_level(GPIO_NUM_9) == 0) { // 低电平触发
// 发送数据到 USB
usbd_ep_start_write(0, AUDIO_IN_EP, rx_data.buffer, rx_data.size);
} else {
usbd_ep_start_write(0, AUDIO_IN_EP, NullBuffer, AUDIO_IN_PACKET);
}
xSemaphoreTake(sign_tx, 10);
while (ep_tx_busy_flag)
{
if (tx_flag == false)
{
break;
}
}
//发送完成,释放缓冲区
rx_data.size = 0;
free(rx_data.buffer);



返回首页
回到顶部

评论