文章目录
全网首发!大众奥迪DIY数码碟盒增加USB和蓝牙播放音乐功能
前言
1、之前写过两篇关于车机增加音频输入的方法,第一种方式:车载音频处理芯片一般和主CPU之间是IIC通信协议,而IIC总线物理层运行在总线上挂载多个设备,通过监听IIC总线发现,只有音频信号发生改变的时候主芯片才会控制音频处理芯片,根据这个原理,卡硬件bug模拟主CPU 的指令,强制控制音频处理器切换输入信号源切换到碟盒音频上,这时主机即可播放碟盒信道的音频了。链接如下:
07宝来经典车机CD收音机(RC668)改装增加蓝牙播放音乐
2、在这之后虽然可以听音乐了,但是当时选择的蓝牙音质一般,而且蓝牙输出带载能力较弱,导致输出声音小。为了解决这问题,所以研究了碟盒的和主机的通信协议,通过抓取之间的数据,分析出了通信格式,进而可以通过单片机模拟碟盒和主机通信,当主机按下按钮时,单片机根据协议解析出内容,就可以知道哪个按钮按下,然后控制蓝牙动作。链接如下
全网首发!老大众奥迪碟盒通信协议破解,可以模拟数码碟盒,外接AUX蓝牙U盘等音频设备
3、我以为我的教程写的和通俗易懂了,但是有一些朋友找到我,让我教他们怎么改装,这时我意识到一个问题,我认为简单的事,对于爱好者来说还是很难,所以综合了一些朋友的意见,觉得做一个可以使用蓝牙和U盘播放音乐的模块。
1、设计指标
和一些朋友聊天,又调查了一番发现,有此需求的人大多是喜欢折腾有一定动手能力的人,但是老车嘛,又不想投入太多的资金改装,毕竟现在也有成熟产品在卖。我个人喜欢用蓝牙听音乐,导航啥的,可是有些朋友又喜欢用U盘听歌,AUX也有一些再用。
因为我很少用AUX听歌所以决定把AUX砍掉,这样就可以减小电路板体积和系统复杂度(喜欢AUX的朋友 不要着急 有时间会出AUX版本的)。高音质高性能意味着高成本,大家都希望功能多成本少,体积还小,但是现实是做不到的,性能和是成本正比的。在结合朋友的意见,最终要实现如下功能。
模块规格如下:
输入电压 | 11V-14.6V/DC |
---|---|
工作电流 | 200mA |
工作温度 | -40℃~+80℃ |
信噪比 | 95dB |
频率响应 | 20HZ-20KHZ |
2、方案设计
2.1、外壳选择
经过几天筛选找到了下面这个外壳 ,长x宽x高 = 6x4x2 CM 还算小巧,上面有一个按键孔和一个5mmLED孔,安排一些功能将这两个孔堵上,侧面是MINIUSB和10PIN牛角座。
2.2、蓝牙方案
蓝牙选用的是定制款WR201蓝牙双模音频芯片,音频程序深度优化,减少底噪。片内集成USB 2.0主站,可以读取U盘内的音频文件进行播放,真是性能小钢炮,性价比特别高。
2.3、MCU方案
数码碟盒和主机通信频率并不高,所以IO模拟输出时序,用定时器捕获分析输入的时序,加加上串口,IO口就可以了,根据这个需求,选择了WR32F202,至于为啥选这个呢,因为最近申请了一批样片正好这个芯片符合要求,顺道帮厂家宣传下。
3、原理图设计
根据以上需求,绘制原理图,放个 按钮 放个LED指示灯,把外壳上的窟窿堵上。
要注意的事,这里面使用78l05线性稳压降压, 由于压差比较大,78l05发热会很严重所以串联一个功率电阻,分担耗散功能,提供系统的稳定性。
4、PCB设计
要想音质好,地分割隔离少不了,再打上多多的过孔,特批是射频部分一定要多打孔。
放上伪3D效果图。
5、程序设计
1、移植OSAL系统框架到NV32F102上,如图所示。替换timer.c定时器的内容。移植基本工作完成。
void PIT1_IRQHandler(void)
{
PIT_ChannelClrFlags(PIT_CHANNEL1);
osal_update_timers();
}
/**
* @brief 硬件定时器初始化,设定系统时钟
*/
void OSAL_TIMER_TICKINIT(void)
{
uint32_t u32LoadValue0;
PIT_ConfigType sPITConfig;
PIT_ConfigType *pPIT_Config =&sPITConfig;
u32LoadValue0 = 48000 - 1; //定时器时钟为总线时钟48M,定时1S
pPIT_Config->u32LoadValue = u32LoadValue0;
pPIT_Config->bFreeze = FALSE;
pPIT_Config->bModuleDis = FALSE;
pPIT_Config->bInterruptEn = TRUE;
pPIT_Config->bChainMode = FALSE;
pPIT_Config->bETMerEn = TRUE; // 打开定时器
PIT_Init(PIT_CHANNEL1, pPIT_Config);
}
2、移植底层驱动
根据上一篇博文的时序编写底层驱动程序,使用NV32f102 ETM2模块用来捕获输入脉冲。
初始化
SIM->SCGC |= SIM_SCGC_ETM2_MASK;//选通ETM1门控时钟
ETM2->CONTROLS[5].CnSC |= ETM_CnSC_ELSB_MASK; //下降沿沿捕捉
ETM_ClockSet(ETM2, ETM_CLOCK_SYSTEMCLOCK, ETM_CLOCK_PS_DIV16); //ETM1时钟设置-48M /16 = 3M
NVIC_EnableIRQ(ETM2_IRQn);
ETM2->CONTROLS[5].CnSC |= ETM_CnSC_CHIE_MASK;//使能中断
ETM_EnableOverflowInt(ETM2); //开启TOF溢出中断
捕获脉冲
/*捕捉中断*/
void ETM2_IRQHandler(void)
{
if(ETM2->SC & ETM_SC_TOF_MASK) //清除溢出标志位
{
ETM2->SC &= ~ETM_SC_TOF_MASK;
TIM_ICUserValueStructure.Capture_Period ++;
}
if(ETM2->CONTROLS[5].CnSC & ETM_CnSC_CHF_MASK )//输入信号边沿变化
{
ETM2->CONTROLS[5].CnSC &= ~ETM_CnSC_CHF_MASK;
if ( TIM_ICUserValueStructure.Capture_StartFlag == 0 ) // 第一次捕获下降沿捕获
{
// 计数器清0
ETM2->CNT=0; //清零计数器
// 自动重装载寄存器更新标志清0
TIM_ICUserValueStructure.Capture_Period = 0;
// 存捕获比较寄存器的值的变量的值清0
TIM_ICUserValueStructure.Capture_CcrValue = 0;
// 当第一次捕获到下降沿之后,就把捕获边沿配置为上升沿
ETM2->CONTROLS[5].CnSC &= ~ETM_CnSC_ELSB_MASK; //去除下降沿沿捕捉
ETM2->CONTROLS[5].CnSC |= ETM_CnSC_ELSA_MASK; //上升沿沿捕捉
// 开始捕获标准置1
TIM_ICUserValueStructure.Capture_StartFlag = 1;
}
// 上升沿捕获中断
else // 第二次捕获
{
// 获取捕获比较寄存器的值,这个值就是捕获到的低电平的时间的值
TIM_ICUserValueStructure.Capture_CcrValue = ETM2->CONTROLS[5].CnV;
capturedLowPulse(TIM_ICUserValueStructure.Capture_CcrValue/3); //3M /3 = 1us
// 当第二次捕获到上升沿之后,就把捕获边沿配置为上升沿,好开启新的一轮捕获
ETM2->CONTROLS[5].CnSC &= ~ETM_CnSC_ELSA_MASK; //去除上升沿捕捉
ETM2->CONTROLS[5].CnSC |= ETM_CnSC_ELSB_MASK; //下降沿沿捕捉
// 开始捕获标志清0
TIM_ICUserValueStructure.Capture_StartFlag = 0;
// 捕获完成标志置1
TIM_ICUserValueStructure.Capture_FinishFlag = 1;
}
}
if(ETM2->CONTROLS[5].CnSC & ETM_CnSC_CHF_MASK )//输入信号上升沿
{
ETM2->CONTROLS[5].CnSC &= ~ETM_CnSC_CHF_MASK;
}
}
定义结构体 用于保存车机播放音乐相关信息。
/**
* @brief U盘发送报文状态结构体定义
*/
typedef struct
{
uint8 currentTruck; /*!< 当前曲目*/
uint8 playMode; /*!< 播放模式 循环 随机*/
uint16 fileNum; /*!< 有效音频文件数量*/
uint16 trickTime; /*!< 当期音频总时间*/
uint16 trickRunTime; /*!< 当期音频播放了时间*/
}UDISK_STRUCT;
/**
* @brief muxVwcdc发送报文状态结构体定义
*/
typedef struct
{
UDISK_STRUCT musicDisk;
uint8 btCarPower; /*!< 汽车电源*/
uint8 btReset; /*!< bt复位*/
uint8 btPlay; /*!< 播放/停止*/
uint8 btNext; /*!< 下一曲*/
uint8 btPre; /*!< 上一曲*/
uint8 btMode; /*!< u盘 蓝牙模式*/
uint8 fpoweren; /*!< 电源使能*/
uint8 frst; /*!< 复位*/
uint8 fPlay; /*!< 播放/停止*/
uint8 fnext; /*!< 下一曲*/
uint8 fpre; /*!< 下一曲*/
uint8 fbutton_flag; /*!< 按键标志*/
uint8 fbutton_value; /*!< 当前处理键值*/
}AUDIO_BLE_STRUCT;
定义按键事件
#define U_COMMEND_RST 0
#define U_COMMEND_POWER 1
#define U_COMMEND_PLAY 2
#define U_COMMEND_PUSE 3
#define U_COMMEND_NEXT 4
#define U_COMMEND_PRE 5
#define U_COMMEND_UDISK 6 //U盘模式
#define U_COMMEND_BLE 7 //蓝牙模式
#define U_COMMEND_REPEAT 8 //循环播放
#define U_COMMEND_SHUFFLE 9 //随机播放
编写接接收到cd按钮事件后向主线程发送按键消息函数
void sendVwcdcMsg( uint8 button)
{
general_msg_data_t *msg;
//向统计任务发送消息
msg = (general_msg_data_t*)osal_msg_allocate(sizeof(general_msg_data_t) + sizeof(int));
if(msg != NULL)
{
//消息结构体的data数据指针偏移至申请到的内存的数据段
//msg->data = (unsigned char*)( msg + sizeof(osal_event_hdr_t) );
msg->data = (unsigned char*)(msg + 1);
msg->hdr.event = button;
msg->hdr.status = 0;
*msg->data = button;
osal_msg_send(userApp_task_id, (uint8*)msg);
}
}
按键消息处理函数
/***********用户处理消息函数***********/
void uCommend_ProcessOSALMsg( uint8 task_id,osal_sys_msg_t *msg_pkt )
{
uint8 *pda;
static uint8 tap_count = 0;
static uint8 tap_flag = 0;
while(msg_pkt)
{
switch(msg_pkt->hdr.event) //判断该消息事件类型
{
case U_COMMEND_RST:
{
btReset();
} break;
case U_COMMEND_PLAY:
{
btPlayPuse();
} break;
case U_COMMEND_PUSE:
{
btPlayPuse();
} break;
case U_COMMEND_NEXT:
{
printf("next \n");
btNext();
} break;
case U_COMMEND_PRE:
{
btPre();
} break;
case U_COMMEND_UDISK:
{
btUdiskMode();
setVwcdcTrack(0x00); // U盘模式 显示00
setVwcdcTime(0); // 时间归零
} break;
case U_COMMEND_BLE:
{
btBleMode();
setVwcdcTrack(0x88); // 蓝牙模式 显示88
setVwcdcTime(0); // 时间归零
} break;
case U_COMMEND_REPEAT:
{
btRepeat();
} break;
case U_COMMEND_SHUFFLE:
{
btShuffle();
} break;
default:
break;
}
osal_msg_deallocate((uint8 *)msg_pkt); //释放消息内存
msg_pkt = (osal_sys_msg_t *)osal_msg_receive(task_id); //读取下一条消息
}
}
在系统中起两个任务,一个是用户线程,实现业务逻辑功能,另外一个任务是用来和车机进行通信监听车机按键事件的,有按键按下,就将按键消息发送到住任务里。
osal_add_Task(vwcd_task_init, vwcd_task_event_process, 4); //车机任务
osal_add_Task(userApp_task_init, userApp_task_event_process, 5); // 用户主任务
启动OSAL系统抽象层
//添加的任务统一进行初始化
osal_Task_init();
osal_mem_kick();
//允许中断
HAL_ENABLE_INTERRUPTS();
//设置初始任务事件,上电就需要自动轮询的任务事件可在此添加
//启动osal系统,不会再返回
osal_start_system();
用户任务
/**
* @brief 当前任务的事件回调处理函数
* @param task_id [任务ID]
* @param task_event [收到的本任务事件]
* @return uint16 [未处理的事件]
*/
uint16 userApp_task_event_process(uint8 task_id, uint16 task_event)
{
if(task_event & SYS_EVENT_MSG) //判断是否为系统消息事件
{
osal_sys_msg_t *msg_pkt;
msg_pkt = (osal_sys_msg_t *)osal_msg_receive(task_id); //从消息队列获取一条消息
uCommend_ProcessOSALMsg(task_id,msg_pkt);
// return unprocessed events
return (task_event ^ SYS_EVENT_MSG);
}
if(task_event & USERAPP_INIT_EVENT)
{
osal_start_reload_timer(userApp_task_id, USERAPP_EVENT, 20 / TICK_PERIOD_MS);
return task_event ^ USERAPP_INIT_EVENT; //处理完后需要清除事件位
}
if(task_event & BLE_UART_RX_EVENT)
{
BLE_UART_Rx.lenth = BLE_UART_Rx.u8RxCnt;
BLE_UART_Rx.flag = 1;
BLE_UART_Rx.u8RxCnt = 0;
bleBtReceiveServer(1);
return task_event ^ BLE_UART_RX_EVENT; //处理完后需要清除事件位
}
if(task_event & USERAPP_EVENT)
{
key_function_sever();
#ifndef WDEBUG
WDOG_Feed(); // 喂狗
#endif
return task_event ^ USERAPP_EVENT; //处理完后需要清除事件位
}
if(task_event & USERAPP_BUTTON_EVENT)
{
return task_event ^ USERAPP_BUTTON_EVENT; //处理完后需要清除事件位
}
return 0;
}
车机任务函数
/**
* @brief 当前任务的事件回调处理函数
* @param task_id [任务ID]
* @param task_event [收到的本任务事件]
* @return uint16 [未处理的事件]
*/
uint16 vwcd_task_event_process(uint8 task_id, uint16 task_event)
{
static unsigned char led_flag = 0;
if(task_event & VWCD_RECE_EVENT)
{
flag_50ms = TRUE;
vwcdSever();
PTC5_OUT_TOGGLE;
sendPacketSever(NULL);
return task_event ^ VWCD_RECE_EVENT; //处理完后需要清除事件位
}
return 0;
}
6、打板焊接调试
测试开关电源不稳定加个680uF电容滤波。
7、模块引脚及功能
7.1、模块引脚定义
模块引脚对照表
引脚名称 | 引脚功能 |
---|---|
L | 音频左声道输出 |
R | 音频右声道输出 |
AG | 音频模拟地 |
AG | 音频模拟地 |
IN | 模块数据输入 |
CLK | 模块时钟输出 |
HU | 开关机检测输入 |
OUT | 模块数据输出 |
12V | 模块电源输入 |
DG | 数字地 需要搭铁在车机外壳上 |
备注:数字地和模拟地不能连接到一起
7.2、模块连接到车机方法
大众系车机常见有两种接头,8针 MINI-ISO接口和12针ISO接口。
8针插座接口定义如图所示。
7.4、模块与8针车机连接方法
车机与模块引脚连接对应关系表
模块引脚 | 车机引脚 | 模块引脚 | 车机引脚 |
---|---|---|---|
L | 19脚 左声道 | R | 20脚 右声道 |
AG | 18 模拟地 | AG | 18脚 模拟地 |
IN | 14脚数据输出 | CLK | 15脚 时钟 |
HU | 17脚开机信号 | OUT | 13脚数据输入 |
12V | 16脚12V电源 | DG | 搭铁到车机壳上 |
备注: 数字地和模拟地不能连接到一起
12针如图所示。
7.5、模块与12车机连接方法
车机与模块引脚连接对应关系表
模块引脚 | 车机引脚 | 模块引脚 | 车机引脚 |
---|---|---|---|
L | 8脚 左声道 | R | 9脚 右声道 |
AG | 2 模拟地 | AG | 2脚 模拟地 |
IN | 6脚数据输出 | CLK | 12脚 时钟 |
HU | 10脚开机信号 | OUT | 11脚数据输入 |
12V | 4脚12V电源 | DG | 搭铁到车机壳上 |
备注: 数字地和模拟地不能连接到一起
8、安装方法
1、将汽车停在安全地方熄火,拔下车钥匙;
2、根据实际情况取出汽车CD车机;
3、使用配套的线束或者根据上文接口定义自己DIY线束,通过线束将模块和车机连起来;
4、将数字地与车机外壳牢固搭铁;
5、插入钥匙打开钥匙 按车上(CD、CDC、DISC、SOURCE、SRC、MODE等按钮进入碟盒模式开始播放音乐;
6、调试没有问题后,如果不使用蓝牙,可以将模块放在车机的后方放回去,或者将模块放到手套箱中,自己喜欢放到哪都行。然后将车机放回即可安装完成;
注意:改装有风险,下手需谨慎,因车型的不同,难易程度不同,当你选择下手的时候,强烈建议找个老司机带你。
9、 使用方法
9.1 CD车机按钮功能定义
由于有些大众车型车机没有mix按钮,而车机都有CD-Cd6这六个按钮,为了保证通用性,将按钮功能做了如下映射。
车机按钮映射表
车机按钮 | 模块功能 |
---|---|
CD1 | 空置 |
CD2 | 播放/停止 |
CD3 | 随机播放/顺序播放 |
CD4 | U盘模式 |
CD5 | 蓝牙模式 |
CD6 | 复位 |
上一曲 | 上一曲 |
下一曲 | 下一曲 |
MIX | 随机播放/顺序播放(不是所有车型都有) |
注意事项:大众系车机上的CD1-CD6按钮,是相互锁定和自锁的关系,比如默认是CD1模式,此时按CD1按钮是不好使的,因为在当前模式下CD1被自己锁定状态不能被改变,再次按下CD1按钮CD车机不会有动作。比如我想停止播放,那么按下CD2按钮,此时停止播放,如果想要继续播放,就有先跳入别的CD模式 由于CD2-CD6都被分配了功能,而CD1按钮没有功能,所以如果想重复进入一直CD模式,可以按下CD1在按对应的按钮就可以了。比如 停止 CD2 播放 CD+CD2 其他按钮功能类似。
9.2 模块指示灯定义
红灯为U盘蓝牙状态指示灯,蓝灯为模块运行状态指示灯。
指示灯状态表
灯闪烁方式 | 模块状态 |
---|---|
蓝灯熄灭 | 不可以和车机通信 |
蓝灯快闪 | 可以和车机通信 |
红灯快闪 | 进入蓝牙 |
红灯常亮 | 连接成功 |
红灯慢闪 | 正在播放 |
红灯关闭 | 进入关机模式 |
9.3 模块工作原理
模块上电后会优先检查是否插入U盘,插入则屏幕会显示TRACK77如果有音乐文件则开始播放音乐,屏幕显示当前正在播放的音乐序号。否则自动进入蓝牙模式等待连接。第一次进入蓝牙模式屏幕会显示TRACK88.总得来说蓝牙模式的优先级高于U盘模式。
状态改变说明表
条件 | 动作 |
---|---|
正在播放音乐,此时连接蓝牙 | 音乐停止播放,进入蓝牙模式等待播放音乐 |
蓝牙模式,按下U盘模式按钮 | 开始播放音乐 |
蓝牙连接上,正在播放U盘音乐 | 蓝牙发出声音自动切换到蓝牙模式 |
9.4 示例演示
以迈腾CD300为例进行升级改造。
第一步 准备好改装套件。
第二步 关闭车机电源,将插头插入对应的接口中,并将负极搭铁到车机外壳上,然后通过排线将车机和模块连接起来。
第三步 检测连接没有问题后,打开电源,按下CD切换按钮,如果是开机状态(不建议开机安装)安装,需要按电源按钮关机5s以上,重新打开电源,按下CD切换按钮即可进入CD模式。TRACK 77 显示当前进入了U盘模式,播放音乐后TRACK XX 即为当前正在播放音乐的序号。模式切换后显示TRACK 88则是进入了蓝牙模式。在使用车机按钮控制手机播放音乐前,要通过手机先播放音乐,否则车机不能控制。在蓝牙模式播放音乐,TRACK XX和播放的音乐序号无关。
第四步 之后既可正常操作车机了,按钮CD1-CD6功能可以参考5.1按钮功能定义。
支持的一些车机照片
奥迪A4 C5卡带机
大众帕萨特领驭车机,支持方向盘控制
奥迪森林里车机
大众领驭帕萨特NV2428支持方向盘控制
宝来高尔夫亮线CD
进口领驭帕萨特德尔塔6
10、常见问题集锦
1. 问题 为什么按CD切换按钮,显示“NO DISC”,不能进入CD播放模式?
答疑:1、请尝试关闭电源5s以上重新打开电源,在按CD切换按钮
2、请检查状态指示灯是否正确
3、请检查线缆是否损坏
2. 问题 为什么车机上一曲、下一曲、停止/播放按钮,不能控制手机播放音乐?
答疑:1、重新连接蓝牙车机是没有控制权,这是蓝牙协议规定的,必须用在手机端操作播放,之后才能用车机面板控制
3. 问题 是否支持接挂电话?
增加接挂电话方法
11、 联系我
下面准备好了DIY套件,感觉动手吃力的朋友可以下单购买。
模块链接: 数码碟盒专用大众奥迪斯柯达蓝牙改装DIY U盘无损FLAC音乐播放
升级服务
产品定制升级
商务合作
汽车电子开发
电子产品开发
联系方式