改了几天,又回归到原来

来源:互联网 发布:淘宝客服电话沟通技巧 编辑:程序博客网 时间:2024/05/19 02:16

这些天改一下音频驱动使其容易理解一点,使用了很多技巧。写完了本机测试也很好,但是上网络就不行了;当有大量数据来时会出现很是奇怪的问题。而且最近有要赶时间了,只好改回原来的。换回来一测发现数据量再大也不怕了,那时的心情太澎湃了。就如走到断头崖,千方百计想怎么爬下去;最终无解,回头时猛然醒悟回头也是可以的。

虽然代码比较乱,还是贴一贴

/*这个文件API接口     这里通过调用于语音相关的函数,构建成钩子函数,提供给RTT使用*/#include"DecoderAPI.h"__IO int16_t OUT_Buffer[2][FRAME_SIZE]; //输出缓冲__IO int16_t *outBuffer = OUT_Buffer[0]; //输出缓冲0指针int enh=1;/* SPEEX PARAMETERS, MUST REMAINED UNCHANGED */ //设置参数void *dec_state;/* Holds the states of the encoder & the decoder */ //空指针struct rt_device Decoder;rt_mailbox_t DecoderMB;//邮箱//struct ReceiveEncodeDataTypedef ReceiveEncodeData[100];struct ReceiveEncodeDataTypedef *pReadEncodeData;struct ReceiveEncodeDataTypedef *pWriteEncodeData;static struct rt_mutex  EDBMutex;static rt_mutex_t EncodeDataBuffermutex=&EDBMutex;//播放缓冲区互斥static SpeexBits DecoderBits;/****************************************************************** Description:  定时器8用作PWM输出初始化*** Author:  lindabell & 欧海*** Date:***************************************************************/static void TIM8_PWM_init(void){  GPIO_InitTypeDef GPIO_InitStructure;    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  TIM_OCInitTypeDef  TIM_OCInitStructure;    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC| RCC_APB2Periph_TIM8 | RCC_APB2Periph_AFIO, ENABLE);//vofi modify to TIM8 ch3 ADC1ch0   TIM_DeInit(TIM8); //将外设 TIMx寄存器重设为缺省值  TIM_OCStructInit(&TIM_OCInitStructure); //把 TIM_OCInitStruct 中的每一个参数按缺省值填入   TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); //把 TIM_TimeBaseInitStruct 中的每一个参数按缺省值填入  GPIO_StructInit(&GPIO_InitStructure);  //把 GPIO_InitStruct 中的每一个参数按缺省值填入 //vofi modify to TIM8 ch3(PC8) ADC1ch0  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //TIM8 CH3(PC8)  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_Init(GPIOC, &GPIO_InitStructure);   //vofi modify to TIM8 ch3(PC8) ADC1ch0  /*设置定时器8用来产生 PWM*/  TIM_TimeBaseStructure.TIM_Prescaler = 0x00; /* TIM8CLK = 72 MHz */ //定时器不分频即为系统时钟????  TIM_TimeBaseStructure.TIM_Period = 0x3FF; /* 10 bits resolution */ //装载值 72Mhz/(0x3FF+1)=70.3125Khz 就是说向上加的ox3FF便满了                             //TIM_Period在TIM_TimeBaseInit中赋给 TIMx->ARR                                         //   自动重装载寄存器周期的值  即是PWM方波的周期  TIM_TimeBaseStructure.TIM_ClockDivision = 0;  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //定时器计数模式:向上计数  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; //??  TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); //初始化TIMx的时间基数单位 //vofi modify to TIM8 ch3(PC8) ADC1ch0  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;         //设置定时器模式:TIM 脉冲宽度调制模式 1  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;     //输出      使能  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //互补输出  使能  TIM_OCInitStructure.TIM_Pulse = 0x200;// Duty cycle: 50%   0x200 / 0x3ff =0.5  (Duty=TIM_Pulse/TIM_Period)  //设置占空比 占空比=CCR3_Val/(TIM_Period +1)  //PS: TIM_Pulse这个值最终赋给TIMx->CCR3,不过只在TIM_OC3Init使用而已  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;   //输出极性      低  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;   //互补输出极性     高  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;   //在空闲时输出     高  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;    //在空闲时互补输出 低  TIM_OC1Init(TIM8, &TIM_OCInitStructure);    TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable);   //使能 TIMx在 CCR3 上的预装载寄存器  TIM_ARRPreloadConfig(TIM8, ENABLE);    //使能TIMx在 ARR 上的预装载寄存器}/****************************************************************** Description: 定时器3初始化 *** Author:  lindabell & 欧海*** Date:***************************************************************/static  void TIM3_init(void){   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;   TIM_OCInitTypeDef  TIM_OCInitStructure;      /* TIM3 clocks enable */  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 , ENABLE);    /* Enable the TIM3 Interrupt */  NVIC_SetPriority(TIM3_IRQn, 0x00); /* 0x00 = 0x01 << 3 | (0x00 & 0x7*/  NVIC_EnableIRQ(TIM3_IRQn);  /* TIM3 configuration -------------------------------------------------------*/    TIM_DeInit(TIM3);  TIM_OCStructInit(&TIM_OCInitStructure);  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  /* TIM3 used for timing, the timing period depends on the sample rate */  TIM_TimeBaseStructure.TIM_Prescaler = 0x00;    /* TIM3CLK = 72 MHz */  TIM_TimeBaseStructure.TIM_Period = TIM3ARRValue;  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);    /* Output Compare Inactive Mode configuration: Channel1 */  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Inactive;  TIM_OCInitStructure.TIM_Pulse = 0x0;  TIM_OC1Init(TIM3, &TIM_OCInitStructure);  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable); //不使能 TIMx在 CCR3 上的预装载寄存器  /* Relaod ARR register */TIM3->ARR = TIM3ARRValue;   //设置TIM3的周期值/* Enable the TIM Counter */TIM3->CR1 |= CR1_CEN_Set;   // TIM 计数寄存器计数    使能/* Clear the IT pending Bit */TIM3->SR = (uint16_t)TIM_INT_Update;//这个属于 rc_w0属性的,所以写0才会清除或读出也可以清除;写1不影响}static ReceiveBufInit(u16 num){u16 i=0;RT_ASSERT(num<65535);//创建缓冲区互斥量rt_mutex_init(EncodeDataBuffermutex,"EDBMutex",RT_IPC_FLAG_FIFO);pReadEncodeData=(struct ReceiveEncodeDataTypedef *)rt_malloc(sizeof(struct ReceiveEncodeDataTypedef)); //申请内存pReadEncodeData->Ready=0;pWriteEncodeData=pReadEncodeData;  //记录链表头for(i=0;i<num-1;i++){pReadEncodeData->next=(struct ReceiveEncodeDataTypedef *)rt_malloc(sizeof(struct ReceiveEncodeDataTypedef));//申请内存pReadEncodeData=pReadEncodeData->next;pReadEncodeData->Ready=0;}pReadEncodeData->next=pWriteEncodeData;   pReadEncodeData=pWriteEncodeData;  //两指针开始指向同一个节点}static rt_err_t  rt_hw_Decoder_init(rt_device_t dev){RT_ASSERT(dev!= RT_NULL);//假时产生断言/* speex decoding intilalization */speex_bits_init(&DecoderBits);dec_state = speex_decoder_init(&speex_nb_mode);   //解码初始化if(dec_state!=0){speex_decoder_ctl(dec_state, SPEEX_SET_ENH, &enh);   //回音消除}ReceiveBufInit(1000);//初始化接收结构体//PWM初始化TIM8_PWM_init();//定时器3初始化TIM3_init();return RT_EOK;}static rt_err_t  rt_hw_Decoder_open(rt_device_t dev,rt_uint16_t oflag){RT_ASSERT(dev!= RT_NULL);//假时产生断言RT_ASSERT(oflag==0);//目前不支持参数TIM_Cmd(TIM8, ENABLE);  //使能定时器8TIM_CtrlPWMOutputs(TIM8, ENABLE);//使能定时器8 PWM输出/* Enable TIM2 update interrupt */TIM3->DIER |= TIM_IT_Update;   //中断更新  使能TIM_Cmd(TIM3, ENABLE);return RT_EOK;}static rt_err_t  rt_hw_Decoder_close(rt_device_t dev){RT_ASSERT(dev!= RT_NULL);//假时产生断言TIM_Cmd(TIM8, DISABLE);  //pwm输出也 失能TIM_CtrlPWMOutputs(TIM8, DISABLE);/* Stop TIM3 */TIM_Cmd(TIM3, DISABLE);/* Disable TIM3 update interrupt */TIM_ITConfig(TIM3, TIM_IT_Update, DISABLE);return RT_EOK;}static rt_size_t rt_hw_Decoder_read(rt_device_t dev,rt_off_t pos, void* buffer,rt_size_t size){RT_ASSERT(dev!= RT_NULL);//假时产生断言return 0;//返回 size}//@dev -> Encoder设备//@value ->参数表示解压到那个缓冲区//@buffer ->要解压的语音数据//@size ->要解压语音数据大小(字节)//@return ->返回解压的字节数static rt_size_t rt_hw_Decoder_write(rt_device_t dev,rt_off_t value, const void* buffer,rt_size_t size){RT_ASSERT(dev!= RT_NULL);//假时产生断言RT_ASSERT((value==1) || (value==2));RT_ASSERT(buffer != RT_NULL);RT_ASSERT(size == ENCODED_FRAME_SIZE);//value==1表示OUT_Buffer[0]里的语音数据已经播放完了,要重新解压到OUT_Buffer[0]//同理value==2也一样//什么时候播放完呢,在TIM3中断中体现,并发送邮件通知线程,线程在调用这个函数if(value==1){/* Copy the encoded data into the bit-stream struct */speex_bits_read_from(&DecoderBits,(char *)buffer, ENCODED_FRAME_SIZE); //从编码缓冲区读出数据/* Decode the data */speex_decode_int(dec_state, &DecoderBits, (spx_int16_t*)OUT_Buffer[0]);//解码}else if(value==2){/* Copy the encoded data into the bit-stream struct */speex_bits_read_from(&DecoderBits, (char *)buffer, ENCODED_FRAME_SIZE);/* Decode the data */speex_decode_int(dec_state, &DecoderBits, (spx_int16_t*)OUT_Buffer[1]);}return ENCODED_FRAME_SIZE;//返回 size}static rt_err_t  rt_hw_Decoder_control(rt_device_t dev,rt_uint8_t cmd, void *args){RT_ASSERT(dev!= RT_NULL);//假时产生断言return RT_EOK;}static rt_err_t rt_hw_Decoder_register(rt_device_t dev, const char* name, rt_uint32_t flag){RT_ASSERT(dev!= RT_NULL);//假时产生断言//RT_ASSERT(flag==0);//目前不支持参数dev->type = RT_Device_Class_Sound;dev->rx_indicate = RT_NULL;dev->tx_complete= RT_NULL;dev->init = rt_hw_Decoder_init;dev->open= rt_hw_Decoder_open;dev->close= rt_hw_Decoder_close;dev->read = rt_hw_Decoder_read;dev->write = rt_hw_Decoder_write;dev->control = rt_hw_Decoder_control;dev->user_data= RT_NULL;   return rt_device_register(dev, name, RT_DEVICE_FLAG_RDWR | flag);  //注册到RTT,并返回   }/****************************************************************** Description: 编码器初始化*** Author:  lindabell & 欧海*** Date:***************************************************************/rt_err_t Decoder_init(rt_device_t dev){RT_ASSERT(dev!= RT_NULL);//假时产生断言//rt_hw_Decoder_init(dev);//rt_hw_Decoder_open(dev,0);rt_hw_Decoder_register(dev,"Decoder",0);dev->flag |= RT_DEVICE_FLAG_ACTIVATED; //设备的状态 为激活状态return RT_EOK;}void Decoder_Register(void){rt_hw_Decoder_register(&Decoder,"Decoder",RT_DEVICE_FLAG_ACTIVATED);}/****************************************************************** Description:把语音数据copy到decoder的缓冲区中 *** Author:  lindabell & 欧海*** Date:***************************************************************///问题:每收到一个语音包copy到播放缓冲来,而只有当溢出的时候在decoder中才会播放//在调用这个函数时并不对返回值进行处理;所以不管溢出和没有溢出产生的效果是一样的rt_err_t CopyToDecoderBuf(u8 *pData){static u8 i;static rt_err_t err=RT_EOK;//RT_ASSERT(pWriteEncodeData->Ready == 0);//decoder没有缓冲区了err=rt_mutex_take(EncodeDataBuffermutex,RT_WAITING_FOREVER);RT_ASSERT(err == RT_EOK);if(pWriteEncodeData->Ready != 0 )   //老是有hard falut 指向这里 在汇编中指向读取Ready的值{rt_kprintf("缓冲区没有空的\r\n");rt_mutex_release(EncodeDataBuffermutex);return RT_ERROR;}for(i=0;i<20;i++)pWriteEncodeData->Data[i]=*pData++;pWriteEncodeData->Ready=1;pWriteEncodeData=pWriteEncodeData->next;err=rt_mutex_release(EncodeDataBuffermutex);RT_ASSERT(err == RT_EOK);//rt_kprintf("Got a new voice data\r\n");rt_mb_send(DecoderMB,3); //发送邮件3到decoder中告诉有新的语言数据到来return RT_EOK;}/****************************************************************** Description: 语音解码器入口函数*** Author:  lindabell & 欧海*** Date:***************************************************************/struct rt_thread Decoder_thread;rt_uint8_t Decoder_stack[Decoder_THREAD_STACK_SIZE];void Decoder_thread_entery(void* parameter){static rt_err_t err=RT_EOK;rt_uint32_t cout=0;rt_uint32_t value;static u8 state=1;rt_device_t device;device=rt_device_find("Decoder");RT_ASSERT(device!= RT_NULL);//假时产生断言DecoderMB=rt_mb_create("DecoderMB",5,RT_IPC_FLAG_FIFO);//邮箱    device->init(device); //初始化硬件device->open(device,0); //打开设备 while(1){rt_mb_recv(DecoderMB,&value,RT_WAITING_FOREVER);   //等待邮箱数据//如果mailbox发来的不是1或2时说明是发来语音数据,1和2是TIM3通知的信号:表示解压下一个缓冲区了,如果是3表示串口收到语音数据if(value==3)  //说明有新的数据从串口进来了{   cout++;  // cout的计数并不准,因为语音缓冲区现在不检查溢出,当有溢出时就不准了if((state==0) & (cout>100) ){    //  rt_kprintf("0x%x\r\n",pWriteEncodeData);//打印出写指针的地址   state=1;   device->open(device,0); //打开Decoder   rt_kprintf("Decoder open\r\n");}continue;//value==3只是通知有数据来了要打开Decoder设备,准备解压并播放,所以打开设备后可以直接返回}else {err=rt_mutex_take(EncodeDataBuffermutex,RT_WAITING_FOREVER);RT_ASSERT(err == RT_EOK);if(pReadEncodeData->Ready ==0) //缓冲区没有就绪的未解压的语音数据{if((state==1)){ // rt_kprintf("0x%x\r\n",pReadEncodeData);//打印出读指针的地址  state=0;  device->close(device); //关闭Decoder  rt_kprintf("Decoder close\r\n"); }err=rt_mutex_release(EncodeDataBuffermutex);RT_ASSERT(err == RT_EOK);continue;}  //假如缓冲区没有就绪好的数据,直接跳过}cout--;  //如果value==1、value==2 表是缓冲区的数据播放完了,需要解压语音数据,注意这里value不能是其他值   device->write(device,value,pReadEncodeData->Data,ENCODED_FRAME_SIZE); //语音解压,并播放pReadEncodeData->Ready=0;pReadEncodeData=pReadEncodeData->next;err=rt_mutex_release(EncodeDataBuffermutex);RT_ASSERT(err == RT_EOK);}  }/**  * @brief  This function handles TIM3 interrupt request.  * @param  None  * @retval : None  */void TIM3_IRQHandler(void) {  /* enter interrupt */    rt_interrupt_enter();  /* Relaod output compare */  TIM3->ARR = TIM3ARRValue;    /* Clear TIM3 update interrupt */  TIM3->SR = TIM_INT_Update;     TIM8->CCR1 = ((*outBuffer>>6)) + 0x200 ;     if(outBuffer == &OUT_Buffer[0][159])    {  rt_mb_send(DecoderMB,(u32)1);      outBuffer++;    }    else if(outBuffer == &OUT_Buffer[1][159])    {      outBuffer = OUT_Buffer[0];  rt_mb_send(DecoderMB,(u32)2);    }    else    {      outBuffer++;    }     /* leave interrupt */    rt_interrupt_leave();}




原创粉丝点击