1、设计目的
山景提供的SDK是蓝牙音箱demo,用户使用ADC按键或者IR遥控器,进行人机交互。然而现实很多场景,需要和单片机通信,不管是ADC按键或者IR接口都不适合和单片机通信。这里设计个AT指令用来和BP1048通信。AT指令如下图所示为控制指令。
设计AT指令集
指令 | 功能 |
AT+CA | 指定音量 |
AT+CB | 播放和暂停 |
AT+CC | 下一曲 |
AT+CD | 上一曲 |
AT+CE | 音量+ |
AT+CF | 音量- |
AT+CG | 蓝牙是否开启后台 |
AT+CJ | 单曲播放 循环顺序播放 |
AT+CK | 蓝牙自动后台 |
AT+CN | 提示音 |
AT+CP | 此指令是设置上电自动进入模式 |
AT+CQ | EQ 设置 |
AT+CR | 设置自动回传功能 |
AT+CT | 设置波特率 |
AT+CM | 切换模式 |
AT+CU | 静音 |
AT+CZ | 芯片复位 |
AT+AA | 播放模式 |
AT+AC | 指定播放模式 |
AT+BA | 接挂电话控制指令 |
返回消息包括
M1+0000000E | 当前设备播放的文件为0x0E |
M2+0000000F | 当前设备的文件总数是0x0F,注意是合法的音频文件 |
MT+0000001E | 当前文件的总时间为0x1E 秒 |
MK+00000004 | 当前文件已经播放到了0x04秒 |
MF+XXXXXXX | 当前播放的文件的名称是xxxxxx。这里文件名是完整的 |
上述指令基本能覆盖大部分需求。
2、移植AT指令引擎
a、在SDK中添加AT组件
b、在RTOS系统中添加一个AT处理任务服务
at_task程序如下所示
#include <string.h>
#include "type.h"
#include "app_config.h"
#include "rtos_api.h"
#include "app_message.h"
#include "debug.h"
#include "at_task.h"
#include "uarts.h"
#include "uarts_interface.h"
#include "AT_command.h"
#include "irqn.h"
#include "task.h"
#include "timers.h"
#include "FreeRTOS.h"
#include "timer.h"
#include "timeout.h"
#include "mode_task.h"
#include "bt_play_mode.h"
#define AT_APP_TASK_STACK_SIZE 1024 // 512//1024
#define AT_APP_TASK_PRIO 3
TIMER TimerOut; //
xTaskHandle taskAtHandle;
static uint8_t timeLockFlag = 0;
ATAppContext AtAppCt;
#define UART_RX_LEN 256
#define UART_TX_LEN 300
/**
\brief
*/
typedef struct
{
uint8_t buff[UART_RX_LEN];
uint16_t lenth;
uint8_t flag;
uint8_t busy;
uint8_t u8RxCnt;
} UART_STRUCT;
static UART_STRUCT AtRxBuf;
uint8_t AtTxBuff[UART_TX_LEN] = {0};
static void AtAppInit(void);
static void AtTaskEntrance(void *param)
{
MessageContext msg;
while (1)
{
MessageRecv(AtAppCt.msgHandle, &msg, AT_APP_MSG_TIMEOUT);
if(msg.msgId != MSG_NONE)
{
switch(msg.msgId)
{
case MSG_AT_UDISK_SONG_ALL_MSG:
{
AT_PPRINTF("\n");
sprintf( AtTxBuff, "M1+%08X\r\n",AtAppCt.gMediaPlayer->CurFileIndex ); //当前索引
AT_PPRINTF(AtTxBuff);
vTaskDelay(1);
sprintf( AtTxBuff, "M2+%08X\r\n",AtAppCt.gMediaPlayer->TotalFileSumInDisk ); //当前设备文件总数
AT_PPRINTF(AtTxBuff);
vTaskDelay(1);
sprintf( AtTxBuff, "MK+%08X\r\n",AtAppCt.gMediaPlayer->CurPlayTime ); //当前播放时间
AT_PPRINTF(AtTxBuff);
sprintf( AtTxBuff, "MF+%s\r\n",AtAppCt.gMediaPlayer->file_longname ); //当前播放时间
AT_PPRINTF(AtTxBuff);
}break;
case MSG_AT_UDISK_SONG_SIGNAL_MSG:
{
AT_PPRINTF("\n");
sprintf( AtTxBuff, "M1+%08X\r\n",AtAppCt.gMediaPlayer->CurFileIndex ); //当前索引
AT_PPRINTF(AtTxBuff);
vTaskDelay(1);
sprintf( AtTxBuff, "M2+%08X\r\n",AtAppCt.gMediaPlayer->TotalFileSumInDisk ); //当前设备文件总数
AT_PPRINTF(AtTxBuff);
vTaskDelay(1);
sprintf( AtTxBuff, "MK+%08X\r\n",AtAppCt.gMediaPlayer->CurPlayTime ); //当前播放时间
AT_PPRINTF(AtTxBuff);
sprintf( AtTxBuff, "MF+%s\r\n",AtAppCt.gMediaPlayer->file_longname ); //当前播放时间
AT_PPRINTF(AtTxBuff);
}break;
case MSG_AT_MODE_CON_BTAUDIO_IDEL_MSG: //蓝牙空闲模式
{
AT_PPRINTF("\n");
sprintf( AtTxBuff, "TS+01\r\n"); //蓝牙模式
AT_PPRINTF(AtTxBuff);
sprintf( AtTxBuff, "QM+01\r\n"); //蓝牙模式
AT_PPRINTF(AtTxBuff);
}break;
case MSG_AT_MODE_CON_BTAUDIO_PLAYING_MSG: //蓝牙模式
{
AT_PPRINTF("\n");
sprintf( AtTxBuff, "TS+02\r\n"); //蓝牙播放音乐
AT_PPRINTF(AtTxBuff);
SysModeEnter(ModeBtAudioPlay);
}break;
case MSG_AT_MODE_CON_BTAUDIO_SUSPEND_MSG: //挂起蓝牙
{
AT_PPRINTF("\n");
sprintf( AtTxBuff, "TS+01\r\n"); //蓝牙模式
AT_PPRINTF(AtTxBuff);
}break;
case MSG_AT_MODE_CON_UDISK_MSG: //U盘模式
{
AT_PPRINTF("\n");
sprintf( AtTxBuff, "MU+01\r\n"); //U盘插入
AT_PPRINTF(AtTxBuff);
sprintf( AtTxBuff, "QM+02\r\n"); //U盘模式
AT_PPRINTF(AtTxBuff);
AtStackServiceMsgSend(MSG_AT_UDISK_SONG_SIGNAL_MSG);//发送切换歌曲指令
}break;
case MSG_AT_MODE_CON_UDISK_OUT_MSG: //拔出U盘
{
AT_PPRINTF("\n");
sprintf( AtTxBuff, "MU+02\r\n"); //U盘拔出
AT_PPRINTF(AtTxBuff);
sprintf( AtTxBuff, "QM+01\r\n"); //蓝牙模式
AT_PPRINTF(AtTxBuff);
SysModeEnter(ModeBtAudioPlay);
}break;
case MSG_AT_MODE_CON_AUX_MSG: //AUX模式
{
AT_PPRINTF("\n");
sprintf( AtTxBuff, "QM+05\r\n"); //U盘模式
AT_PPRINTF(AtTxBuff);
SysModeEnter(ModeLineAudioPlay);
}break;
case MSG_AT_MODE_CON_IDEL_MSG: //空闲模式
{
AT_PPRINTF("\n");
sprintf( AtTxBuff, "QM+00\r\n"); //U盘模式
AT_PPRINTF(AtTxBuff);
}break;
}
}
if (timeLockFlag == 0 && IsTimeOut(&TimerOut))
{
timeLockFlag = 1;
AtRxBuf.buff[AtRxBuf.u8RxCnt] = 0;
AT_CMD_Process(AtRxBuf.buff, AtRxBuf.u8RxCnt);
AtRxBuf.u8RxCnt = 0;
}
}
}
static void AtUartReceive(void)
{
AT_CMD_Process(AtRxBuf.buff, AtRxBuf.u8RxCnt);
}
/***************************************************************************************
*
* APIs
*
*/
int32_t AtAppTaskStart(void)
{
AtAppInit();
APP_DBG("AtTask Create\n");
TimeOutSet(&TimerOut, 20);
xTaskCreate(AtTaskEntrance, "AtApp", AT_APP_TASK_STACK_SIZE, NULL, AT_APP_TASK_PRIO, &taskAtHandle);
}
static void AtAppInit(void)
{
memset(&AtAppCt, 0, sizeof(ATAppContext));
AtAppCt.msgHandle = MessageRegister(AT_NUM_MESSAGE_QUEUE);
}
void AtStackServiceMsgSend(uint16_t msgId)
{
MessageContext msgSend;
msgSend.msgId = msgId;
MessageSend(AtAppCt.msgHandle, &msgSend);
}
在主任务中启动at_task任务
3、运行调试
可以看出AT指令任务已经运行。