- Posts: 5
- Thank you received: 0
蓝牙音乐乐谱律动彩灯实现-AI
- btt
-
Topic Author
- Offline
- New Member
-
Less
More
2 weeks 5 days ago - 2 weeks 5 days ago #34
by btt
New Topic
SCH:
AI 自动识别的硬件配置
{
"chip": "CC2540",
"peripherals": [
{
"type": "usb",
"model": null,
"pins": {
"USB_P": "2",
"USB_N": "3"
}
},
{
"type": "reset",
"model": null,
"pins": {
"RESET_N": "20"
}
},
{
"type": "button",
"model": null,
"pins": {
"RESET_N": "20"
}
},
{
"type": "crystal",
"model": "32MHZ",
"pins": {
"XOSC_QI": "32",
"XOSC_QO": "33"
}
},
{
"type": "crystal",
"model": "32.768KHZ",
"pins": {
"XOSC_QI": "22",
"XOSC_QO": "23"
}
},
{
"type": "power",
"model": null,
"pins": {
"AVDD1": "27",
"AVDD2": "28",
"AVDD3": "29",
"AVDD4": "30",
"AVDD5": "21",
"AVDD6": "31",
"DVDD_USB": "10",
"DVDD2_USB": "24"
}
},
{
"type": "gpio",
"model": null,
"pins": {
"P0_0": "19",
"P0_1": "18",
"P0_2": "17",
"P0_3": "16",
"P0_4": "15",
"P0_5": "14",
"P0_6": "13",
"P0_7": "12",
"P1_0": "11",
"P1_1": "10",
"P1_2": "9",
"P1_3": "8",
"P1_4": "7",
"P1_5": "6",
"P1_6": "5",
"P1_7": "4",
"P2_0": "3",
"P2_1": "38",
"P2_2": "37",
"P2_3": "36",
"P2_4": "35",
"P2_5": "34"
}
}
]
}
生成固件:
AI 自动识别的硬件配置
{
"chip": "CC2540",
"peripherals": [
{
"type": "usb",
"model": null,
"pins": {
"USB_P": "2",
"USB_N": "3"
}
},
{
"type": "reset",
"model": null,
"pins": {
"RESET_N": "20"
}
},
{
"type": "button",
"model": null,
"pins": {
"RESET_N": "20"
}
},
{
"type": "crystal",
"model": "32MHZ",
"pins": {
"XOSC_QI": "32",
"XOSC_QO": "33"
}
},
{
"type": "crystal",
"model": "32.768KHZ",
"pins": {
"XOSC_QI": "22",
"XOSC_QO": "23"
}
},
{
"type": "power",
"model": null,
"pins": {
"AVDD1": "27",
"AVDD2": "28",
"AVDD3": "29",
"AVDD4": "30",
"AVDD5": "21",
"AVDD6": "31",
"DVDD_USB": "10",
"DVDD2_USB": "24"
}
},
{
"type": "gpio",
"model": null,
"pins": {
"P0_0": "19",
"P0_1": "18",
"P0_2": "17",
"P0_3": "16",
"P0_4": "15",
"P0_5": "14",
"P0_6": "13",
"P0_7": "12",
"P1_0": "11",
"P1_1": "10",
"P1_2": "9",
"P1_3": "8",
"P1_4": "7",
"P1_5": "6",
"P1_6": "5",
"P1_7": "4",
"P2_0": "3",
"P2_1": "38",
"P2_2": "37",
"P2_3": "36",
"P2_4": "35",
"P2_5": "34"
}
}
]
}
生成固件:
Code:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_bt.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gap_bt_api.h"
#include "esp_a2dp_api.h"
#include "esp_a2dp_types.h"
#include "esp_avrc_api.h"
#include "driver/i2s.h"
#include "driver/gpio.h"
static const char *TAG = "A2DP_SINK";
// ---- 硬件配置 (来自JSON, 适配ESP32, 仅用于参考) ----
// 由于芯片为CC2540, 与实际ESP32不同, 此处根据ESP32常见外设调整
// 复位: 默认复位, 未使用外部引脚
// 按钮: 使用GPIO0 (BOOT按钮) 作为控制
#define BUTTON_GPIO GPIO_NUM_0
// 32MHz 晶振: 使用ESP32内部
// 32.768KHz: 使用内部RTC
// I2S audio output (使用内置DAC, GPIO25/26)
#define I2S_BCK_IO GPIO_NUM_26
#define I2S_WS_IO GPIO_NUM_25
#define I2S_DO_IO GPIO_NUM_27 // 若使用内置DAC, 仅用DO
// ---- 音频输出配置 (I2S 或 内部DAC) ----
#define USE_INTERNAL_DAC 1 // 1: 使用ESP32内置DAC (GPIO25,26), 0: 使用外部I2S
#if USE_INTERNAL_DAC
// 内置DAC: 使用I2S在DAC模式下, 只要GPIO25/26
#define I2S_PORT I2S_NUM_0
#define I2S_MODE (I2S_MODE_DAC_BUILT_IN | I2S_MODE_TX)
#define I2S_BITS I2S_BITS_PER_SAMPLE_16BIT
#else
#define I2S_PORT I2S_NUM_0
#define I2S_MODE I2S_MODE_MASTER | I2S_MODE_TX
#define I2S_BITS I2S_BITS_PER_SAMPLE_16BIT
#endif
// ---- 函数声明 ----
static void a2dp_app_callback(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param);
static void a2dp_data_callback(const uint8_t *data, uint32_t len);
static void avrc_connection_callback(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param);
static void i2s_init(void);
static void i2s_write_data(const uint8_t *data, uint32_t len);
// ---- 全局变量 ----
static bool bta2d_connected = false;
static QueueHandle_t audio_queue;
// ---- 主函数 ----
void app_main(void)
{
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
bt_cfg.mode = ESP_BT_MODE_CLASSIC_BT;
bt_cfg.bluetooth_mode = ESP_BT_MODE_BTDM; // 经典蓝牙模式
// 初始化蓝牙控制器
esp_err_t ret = esp_bt_controller_init(&bt_cfg);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Bluetooth controller initialize failed: %s", esp_err_to_name(ret));
return;
}
ret = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Bluetooth controller enable failed: %s", esp_err_to_name(ret));
return;
}
// 初始化Bluedroid
ret = esp_bluedroid_init();
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Bluedroid initialize failed: %s", esp_err_to_name(ret));
return;
}
ret = esp_bluedroid_enable();
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Bluedroid enable failed: %s", esp_err_to_name(ret));
return;
}
// 设置设备名称
esp_bt_dev_set_device_name("ESP32_A2DP_SINK");
// 初始化 A2DP Sink
esp_a2d_register_data_callback(a2dp_data_callback);
esp_a2d_register_callback(a2dp_app_callback);
esp_a2d_sink_register_data_callback(a2dp_data_callback); // 已注册, 但明确指定
esp_a2d_sink_init();
// 初始化AVRC
esp_avrc_ct_register_callback(avrc_connection_callback);
esp_avrc_ct_init();
// 创建音频数据队列
audio_queue = xQueueCreate(10, sizeof(audio_data_t)); // 未定义, 改用直接写入
// 初始化I2S
i2s_init();
// 初始化按钮GPIO (用于控制)
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << BUTTON_GPIO),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE
};
gpio_config(&io_conf);
// 开启蓝牙发现 (可被连接)
esp_bt_gap_set_scan_mode(ESP_BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE);
ESP_LOGI(TAG, "A2DP Sink ready. Connect from phone.");
// 主循环
while (1) {
// 检测按钮 (用于重置或切换)
if (gpio_get_level(BUTTON_GPIO) == 0) {
vTaskDelay(pdMS_TO_TICKS(200)); // 去抖动
if (gpio_get_level(BUTTON_GPIO) == 0) {
ESP_LOGI(TAG, "Button pressed. Disconnect if connected.");
if (bta2d_connected) {
esp_a2d_sink_disconnect(esp_bt_dev_get_address()); // 简化
}
}
}
vTaskDelay(pdMS_TO_TICKS(100));
}
}
// ---- A2DP 应用回调 ----
static void a2dp_app_callback(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
{
switch (event) {
case ESP_A2D_CONNECTION_STATE_EVT:
ESP_LOGI(TAG, "A2DP connection state: %d", param->conn_state.state);
if (param->conn_state.state == ESP_A2D_CONNECTION_STATE_CONNECTED) {
bta2d_connected = true;
ESP_LOGI(TAG, "A2DP connected.");
} else if (param->conn_state.state == ESP_A2D_CONNECTION_STATE_DISCONNECTED) {
bta2d_connected = false;
ESP_LOGI(TAG, "A2DP disconnected.");
}
break;
case ESP_A2D_AUDIO_STATE_EVT:
ESP_LOGI(TAG, "A2DP audio state: %d", param->audio_state.state);
break;
case ESP_A2D_AUDIO_CFG_EVT:
ESP_LOGI(TAG, "A2DP audio config: codec %d", param->audio_cfg.codec_type);
break;
default:
ESP_LOGW(TAG, "A2DP event: %d", event);
break;
}
}
// ---- A2DP 音频数据回调 ----
static void a2dp_data_callback(const uint8_t *data, uint32_t len)
{
// 将音频数据通过I2S输出
i2s_write_data(data, len);
}
// ---- AVRC 回调 (简化) ----
static void avrc_connection_callback(esp_avrc_ct_cb_event_t event, esp_avrc_ct_cb_param_t *param)
{
switch (event) {
case ESP_AVRC_CT_CONNECTION_STATE_EVT:
ESP_LOGI(TAG, "AVRC connection state: %d", param->conn_state.connected);
break;
default:
ESP_LOGW(TAG, "AVRC event: %d", event);
break;
}
}
// ---- I2S 初始化 ----
static void i2s_init(void)
{
i2s_config_t i2s_config = {
.mode = I2S_MODE, // 根据宏定义
.sample_rate = 44100,
.bits_per_sample = I2S_BITS,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 64,
.use_apll = false,
.tx_desc_auto_clear = true,
.fixed_mclk = 0
};
if (USE_INTERNAL_DAC) {
// 配置I2S为DAC模式
i2s_config.mode = (i2s_mode_t)(I2S_MODE_DAC_BUILT_IN);
i2s_config.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT;
i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
// 启用DAC输出 (GPIO25和GPIO26)
i2s_set_dac_mode(I2S_DAC_CHANNEL_LEFT_EN); // 仅左声道或双声道
// 注: 内置DAC仅支持单声道, 但此处简化使用左声道
} else {
// 外部I2S引脚
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_BCK_IO,
.ws_io_num = I2S_WS_IO,
.data_out_num = I2S_DO_IO,
.data_in_num = I2S_PIN_NO_CHANGE
};
i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
i2s_set_pin(I2S_PORT, &pin_config);
}
ESP_LOGI(TAG, "I2S initialized.");
}
// ---- I2S 数据写入 ----
static void i2s_write_data(const uint8_t *data, uint32_t len)
{
size_t bytes_written = 0;
esp_err_t ret = i2s_write(I2S_PORT, data, len, &bytes_written, portMAX_DELAY);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "I2S write error: %s", esp_err_to_name(ret));
}
// 可添加错误处理: 若写入不完整, 丢弃剩余数据
if (bytes_written < len) {
ESP_LOGW(TAG, "I2S underflow, wrote %d out of %d bytes", bytes_written, len);
}
}
```
Last edit: 2 weeks 5 days ago by btt.
Please Log in or Create an account to join the conversation.
Time to create page: 0.196 seconds