STM32 RDS解码
来源:互联网 发布:java aop 日志记录 编辑:程序博客网 时间:2024/06/14 17:14
RDS(Radio Data System)无线数据广播系统是在调频广播发射信号中利用副载波把电台名称、节目类型、节目内容及其它信息以数字形式发送出去。通过具有RDS功能的调谐器就可以识别这些数字信号,变成字符显示在显示屏上。在收到节目的同时,通过RDS可知道接收到的是那个电台,它的发射频率,并给出该电台其余的频率,由此再使用“切换频率”钮来保证所接收的信号为最强的频率。RDS无线数据广播文件可显示接收到的节目名称及其它资料。RDS功能可按节目类型决定取舍,寻找到符合你要求的电台。RDS还能用来自动控制接收机,使流动工作的汽车收音机一直保持最佳接收状态,及时收到紧急交通报告,有利交通安全。
最近需要在我们的车载设备中集成RDS功能,这里需要用到一个专门的RDS解码芯片(这里使用ST的TDA7478), 通过RDS解码芯片,可以将空中的RDS广播信号解调出来输出给STM32,共有3路输出,分别是QUAL(信号质量)、RDCL(时钟信号)、RDDA(RDS数据)输出,STM32在RDS时钟到来是读取RDS数据并存入到buffer中,当buffer中的数据校验成功时,认为收到正确的RDS数据。
STM32具体操作流程如下:
1.配置QUAL、RDCL、RDDA为输入端口,并设置RDCL为上升沿中断;
2.在RDCL产生中断时,读取RDDA数据,并将数据存入到buffer中;
3.每收到一块(26位)RDS数据后,做一次同步校验,若同步失败,则继续做同步,若同步成功,则继续接收下一块数据;
4.当接收到连续的ABCD四块数据并校验无误后,将四块数据拼接成一组,发送给主CPU做进一步的解析处理(需参考RDS标准,如国标、欧洲标准,美洲标准)。
参考代码如下:
//********************************************************************//filename: RDS.cpp//created: 2012-04-24//author: firehood//purpose: RDS解码//*********************************************************************#include "RDS.h"// 同步校验码(由偏置字*H矩阵计算得到)const static int32u SYNCODE_A = 0x03D8;const static int32u SYNCODE_B = 0x03D4;const static int32u SYNCODE_C = 0x025C;const static int32u SYNCODE_C2 = 0x03CC;const static int32u SYNCODE_D = 0x0258;static Boolean g_bRDSExist = FALSE; // RDS是否存在static Boolean g_bRDSEnable = FALSE; // RDS功能使能标志static BLOCK g_block = 0; // RDS数据块static BLOCK g_blockA = 0,g_blockB = 0,g_blockC = 0,g_blockD = 0;static int32u g_bRevBitCount = 0; static Boolean g_bSyncFlag = FALSE; // 是否同步标志static Boolean g_nSyncLevel = 0; // 同步级数static Boolean g_bGroupFlag = FALSE;static int8u g_RDSGroup[16] = {0}; // 每组信息包含A、B、C、D四块; // 每块信息占26bit,以四个字节存放(存在低26位) // RDS初始化void dev_RDS_init(void){GPIO_InitTypeDef GPIO_InitStructure;// 配置GPIOA15为RDS时钟输入,GPIOA8为RDS数据输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_8;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置GPIOD2为RDS信号质量输入GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOD, &GPIO_InitStructure);// 打开GPIOA、GPIOD时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD, ENABLE);}// RDS使能void dev_RDS_Enable(Boolean bEnable){ EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitStructure; if(g_bRDSEnable == bEnable) return;// 配置GPIOA15(RDS时钟信号)上升沿中断GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);EXTI_ClearITPendingBit(EXTI_Line15);EXTI_InitStructure.EXTI_Line = EXTI_Line15;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising;EXTI_InitStructure.EXTI_LineCmd = bEnable ? ENABLE : DISABLE;EXTI_Init(&EXTI_InitStructure);// 配置中断向量NVIC_ClearIRQChannelPendingBit(EXTI15_10_IRQChannel);NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;NVIC_InitStructure.NVIC_IRQChannelCmd = bEnable ? ENABLE : DISABLE;NVIC_Init(&NVIC_InitStructure); g_bRDSEnable = bEnable;}/******************************************************************************** Function Name : main* Description : Main program.* Input : None* Output : None* Return : None*******************************************************************************/int main(void){/* Configure the system clocks */RCC_Configuration();/* NVIC Configuration */NVIC_Configuration();/* RDS initialization */dev_RDS_init();/* Enable RDS */dev_RDS_Enable(TRUE);/* RDS decode*/dev_RDS_decode();}// RDS解码void dev_RDS_decode(void){ int32u nSynCode = 0; Boolean bReSync = FALSE;// 是否重新同步标志 if(!g_bRDSExist) return; //dbgprt("g_bRevBitCount = %d...\n",g_bRevBitCount); if(!g_bSyncFlag) // 是否同步 {if(g_bRevBitCount<BLOCK_COUNT)return;// 计算同步校验码nSynCode = CacluSyncCode(g_block);//dbgprt("g_block = 0x%x,SynCode = 0x%x\n",g_block,nSynCode);if(nSynCode == SYNCODE_A){g_bSyncFlag = TRUE; g_blockA = g_block;g_nSyncLevel = 1;g_bRevBitCount = 0;dbgprt("RDS sync success!!!!!!!!!!\n");}}else // RDS已同步{if(g_bRevBitCount >= BLOCK_COUNT){ nSynCode = CacluSyncCode(g_block); //dbgprt("g_block = 0x%x,SynCode = 0x%x\n",g_block,nSynCode);switch(nSynCode){case SYNCODE_A:if(g_nSyncLevel != 0){bReSync = TRUE;break;}g_blockA = g_block;g_nSyncLevel = 1;g_bRevBitCount = 0;dbgprt("rev BlockA[0x%04x] success...\n",g_blockA);break;case SYNCODE_B:if(g_nSyncLevel != 1){bReSync = TRUE;break;}g_blockB = g_block;g_nSyncLevel = 2;g_bRevBitCount = 0;dbgprt("rev BlockB[0x%04x] success...\n",g_blockB);break;case SYNCODE_C:case SYNCODE_C2:if(g_nSyncLevel != 2){bReSync = TRUE;break;}g_blockC = g_block;g_nSyncLevel = 3;g_bRevBitCount = 0;dbgprt("rev BlockC[0x%04x] success...\n",g_blockC);break;case SYNCODE_D:if(g_nSyncLevel != 3){bReSync = TRUE;break;}g_blockD = g_block;g_nSyncLevel = 0;g_bGroupFlag = TRUE;g_bRevBitCount = 0;dbgprt("rev BlockD[0x%04x] success...\n",g_blockD);break;default: // 同步校验失败,需重新同步bReSync = TRUE;break; } }if(bReSync){// 重新同步dbgprt("ReSync RDS...\n");g_bSyncFlag = FALSE;g_nSyncLevel = 0;}if(g_bGroupFlag) // 接收到一组RDS数据,发送给89{dbgprt("rev RDS group done...\n");g_bGroupFlag = FALSE;memcpy(g_RDSGroup,&g_blockA,4);memcpy(g_RDSGroup+4,&g_blockB,4);memcpy(g_RDSGroup+8,&g_blockC,4);memcpy(g_RDSGroup+12,&g_blockD,4);// 将RDS数据发送给主CPUSendRdsDataToHost(g_RDSGroup,sizeof(g_RDSGroup));}}}// RDS数据接收处理(RDS时钟中断)void dev_RDS_RevDataHandler(void){ static int8u nGoodQualCounts = 0; // 统计RDS信号质量持续有效次数int8u RDSDataBit = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8);// 读取RDS信号质量信号if(!GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_2)) // GPIOD2为RDS信号质量输入{ nGoodQualCounts = 0; g_bRDSExist = FALSE;}else { nGoodQualCounts++;} // 连续N(N=10)次统计RDS信号输出均为高电平,认为存在RDS信号if(nGoodQualCounts>10){ g_bRDSExist = TRUE; nGoodQualCounts = 0;} //if(g_bRDSExist){ g_block <<= 1; g_block |= RDSDataBit; g_block &= 0x3FFFFFF; g_bRevBitCount++;}}// 计算同步校验码int32u CacluSyncCode(BLOCK block){// 同步校验矩阵Hconst int8u H[] = {1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,1,1,0,0,0,1,0,1,1,0,1,1,1,0,0,0,1,0,1,1,0,1,1,1,1,0,1,0,0,0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,0,0,0,1,0,0,1,1,1,1,0,1,0,1,0,1,0,1,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,0,0,0,1,1,1,1,0,1,1,1,0, 0,0,1,1,1,1,0,1,1,1,1,0,1,0,1,0,0,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0,1,1,0,1,1}; int8u synMatrix[10] = {0};int32u nSynCode = 0;int8u i = 0,j = 0; for(i=0;i<10;i++) { for(j=0;j<BLOCK_COUNT;j++) { synMatrix[i]+= ((block>>(BLOCK_COUNT-1-j))&1)*H[i+10*j]; } synMatrix[i] = synMatrix[i]%2; nSynCode <<= 1; nSynCode += synMatrix[i]; } return nSynCode;}/******************************************************************************** Function Name : EXTI15_10_IRQHandler* Description : This function handles External lines 15 to 10 interrupt request.* Input : None* Output : None* Return : None*******************************************************************************/void EXTI15_10_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line15) != RESET){EXTI_ClearITPendingBit(EXTI_Line15); dev_RDS_RevDataHandler(); }}
- STM32 RDS解码
- RDS
- RDS
- STM32+ucos+ucgui+fatfs+bmp解码+JPG解码
- 基于STM32的中文字库解码
- 基于STM32的BMP图片解码
- STM32单片机学习(12) 红外信号接收解码(外部中断)
- STM32学习笔记:gps两种解码的方式
- RDS-TMC
- RDS/RBDS
- AWS RDS Rename DataBase - RDS重命名数据库
- 解码
- 解码
- 解码
- 解码
- 解码
- 单片机 stm32读取ico图标文件 从SD卡中解码显示到LCD
- RDS 编程模型详细资料
- SharedPreference
- 第二章 Ioc的基本概念
- NorthScale Memcached Server的.NET客户端NorthScaleClient使用简介
- 手把手教你用CAB发布OCX的简单办法
- 关于字符串全排
- STM32 RDS解码
- NO.80 从与L君饭间聊天再扯开去……
- Flex 4.5下 mx:TabNavigator 与s:TextInput一起使用的Bug
- sqlserver 递归查询
- inkscape 详解
- FreeMarker 对null值的处理技巧
- this和getApplicationContext区别
- 高级程序员装逼指南
- 将smartform转换成pdf并上传