山景BP1048增加AT指令,实现单片机串口控制播放音乐(一)

   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+CQEQ 设置
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指令任务已经运行。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/940855.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EMC VMAX/DMX 健康检查方法

近期连续遇到2个由于对VMAX存储系统没有做及时的健康检查&#xff0c;出现SPS电池故障没有及时处理&#xff0c;然后同一pair就是同一对的另外一个SPS电池再次出现故障&#xff0c;然后存储系统保护性宕机vault&#xff0c;然后业务系统挂掉的案例。 开始之前&#xff0c;先纠…

51c大模型~合集94

我自己的原文哦~ https://blog.51cto.com/whaosoft/12897659 #D(R,O) Grasp 重塑跨智能体灵巧手抓取&#xff0c;NUS邵林团队提出全新交互式表征&#xff0c;斩获CoRL Workshop最佳机器人论文奖 本文的作者均来自新加坡国立大学 LinS Lab。本文的共同第一作者为上海交通大…

移动魔百盒中的 OpenWrt作为旁路由 安装Tailscale并配置子网路由实现在外面通过家里的局域网ip访问内网设备

移动魔百盒中的 OpenWrt作为旁路由 安装Tailscale并配置子网路由实现在外面通过家里的局域网ip访问内网设备 一、前提条件 确保路由器硬件支持&#xff1a; OpenWrt 路由器需要足够的存储空间和 CPU 性能来运行 Tailscale。确保设备架构支持 Tailscale 二进制文件&#xff0c;例…

Webpack学习笔记(4)

1.缓存 可以通过命中缓存降低网络流量&#xff0c;是网站加站速度更快。 然而在部署新版本时&#xff0c;不更改资源的文件名&#xff0c;浏览器可能认为你没有更新&#xff0c;所以会使用缓存版本。 由于缓存存在&#xff0c;获取新的代码成为问题。 接下来将配置webpack使…

java抽奖系统(八)

9. 抽奖模块 9.1 抽奖设计 抽奖过程是抽奖系统中最重要的核⼼环节&#xff0c;它需要确保公平、透明且⾼效。以下是详细的抽奖过程设计&#xff1a; 对于前端来说&#xff0c;负责控制抽奖的流程&#xff0c;确定中奖的人员 对于后端来说&#xff1a; 接口1&#xff1a;查询完…

VulnHub靶场渗透之:Gigachad

环境搭建 VulnHub是一个丰富的实战靶场集合&#xff0c;里面有许多有趣的实战靶机。 本次靶机介绍&#xff1a;http://www.vulnhub.com/entry/gigachad-1,657/ 下载靶机ova文件&#xff0c;导入虚拟机&#xff0c;启动环境&#xff0c;便可以开始进行靶机实战。 虚拟机无法分…

解决Apache/2.4.39 (Win64) PHP/7.2.18 Server at localhost Port 80问题

配置一下apache里面的配置文件&#xff1a;httpd.conf 和 httpd.vhosts.conf httpd.conf httpd-vhosts.conf 重启服务 展示&#xff1a; 浏览器中中文乱码问题&#xff1a;

.NET重点

B/S C/S什么语言 B/S&#xff1a; 浏览器端&#xff1a;JavaScript&#xff0c;HTML&#xff0c;CSS 服务器端&#xff1a;ASP&#xff08;.NET&#xff09;PHP/JSP 优势&#xff1a;维护方便&#xff0c;易于升级和扩展 劣势&#xff1a;服务器负担沉重 C/S java/.NET/…

Linux下基于最新稳定版ESP-IDF5.3.2开发esp32s3入门任务间的通讯-消息队列【入门四】

继续上一篇任务创建 【Linux下基于最新稳定版ESP-IDF5.3.2开发esp32s3入门任务间的通讯-信号量【入门三】-CSDN博客】 今天要实现消息队列进行任务的通讯 一、从上一篇信号量通讯demo拷贝一份重命名&#xff0c;还是之前的两个任务&#xff0c;重命名了。 xTaskCreatePinned…

【AI日记】24.12.22 容忍与自由 | 环境因素和个人因素

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI日记】 工作 内容&#xff1a;看 OpenAi 这周的发布会和其他 AI 新闻&#xff0c;大佬视频时间&#xff1a;3 小时 读书 书名&#xff1a;富兰克林自传时间&#xff1a;1 小时评估&#xff1a;读完&#xff0c;总体…

穷举vs暴搜vs深搜vs回溯vs剪枝系列一>电话号码的字母组合

题目&#xff1a; 解析&#xff1a; 代码&#xff1a; private String[] hash {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};private StringBuffer p…

设计模式 -- 单例模式

设计模式 -- 单例模式 单例模式C++ 实现饿汉式单例模式懒汉式单例模式使用静态局部变量实现懒汉式单例模式(推荐)使用call_once实现懒汉式单例模式(推荐)使用静态全局部变量和指针的方式实现懒汉式单例模式(不推荐)双重检测懒汉式单例模式单例模式 单例模式:确保在整个程…

CH430N 插上电脑无反应

电路图&#xff0c;此处我用的是3.3V供电&#xff0c;现象就是插上USB,电脑没有反应。搜索也搜索不到 抄板请看自己是多少V供电 后来看到也有类似的 换了芯片后就好了。md新板子第一个芯片就是坏的&#xff0c;服了。

重拾设计模式--状态模式

文章目录 状态模式&#xff08;State Pattern&#xff09;概述状态模式UML图作用&#xff1a;状态模式的结构环境&#xff08;Context&#xff09;类&#xff1a;抽象状态&#xff08;State&#xff09;类&#xff1a;具体状态&#xff08;Concrete State&#xff09;类&#x…

【MySQL】深入了解索引背后的内部结构

目录 索引的认识&#xff1a; 作用&#xff1a; 索引的使用&#xff1a; 索引底层的数据结构&#xff1a; 哈希表 AVL树 红黑树 B树&#xff1a; B树&#xff1a; B树搜索&#xff1a; 索引的认识&#xff1a; 索引是数据库中的一个数据结构&#xff0c;用于加速查询…

【MySQL】--- 数据类型

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; MySQL &#x1f3e0; 数据类型分类 MySQL是一套整体的对外数据存取方案,既然要存取数据,而数据有不同的类型,因此MySQL也存在不同的数据类型,有不同的用…

电商店铺数据集成到金蝶云星辰V2的实践经验分享

电商店铺数据集成到金蝶云星辰V2的技术案例分享 在电商业务快速发展的背景下&#xff0c;如何高效地将聚水潭平台上的电商店铺数据集成到金蝶云星辰V2系统中&#xff0c;成为了许多企业面临的重要挑战。本文将详细探讨一个实际运行的解决方案——“电商店铺->金蝶客户”&am…

在VBA中结合正则表达式和查找功能给文档添加交叉连接

在VBA中搜索文本有两种方式可用&#xff0c;一种是利用Range.Find对象&#xff08;更常见的形式可能是Selection.Find&#xff0c;Selection是Range的子类&#xff0c;Selection.Find其实就是特殊的Range.Find&#xff09;&#xff0c;另一种方法是利用正则表达式&#xff0c;但…

大腾智能CAD:国产云原生三维设计新选择

在快速发展的工业设计领域&#xff0c;CAD软件已成为不可或缺的核心工具。它通过强大的建模、分析、优化等功能&#xff0c;不仅显著提升了设计效率与精度&#xff0c;还促进了设计思维的创新与拓展&#xff0c;为产品从概念构想到实体制造的全过程提供了强有力的技术支持。然而…

实现Python将csv数据导入到Neo4j

目录 一、获取数据集 1.1 获取数据集 1.2 以“记事本”方式打开文件 1.3 另存为“UTF-8”格式文件 1.4 选择“是” 二、 打开Neo4j并运行 2.1 创建新的Neo4j数据库 2.2 分别设置数据库名和密码 ​编辑 2.3 启动Neo4j数据库 2.4 打开Neo4j数据库 2.5 运行查看该数据库…