最近忙得很,估计这是今年参加的最后一个活动了,有始有终。
于是前些天花了点时间继续把东西完善了一下,距离最初的目标又更接近了一步:现在开始,用小狼播放SD卡中的歌曲。
当然了,播放MP3还是有点天方夜谭,我们来播放些简单的:单声道8k8bit的Wav文件。
要想播放声音出来,不外加DA的情况下,就要把小狼的定时器合理分配好,另外由于性能有限,在实际播放的时候,我实际上只利用了声音数据8位中的高7位,所以也就是播放8K7位的声音。经过试验,这样的音质算是比较好的(相对其他参数设定来说)。以下列举了实际需要的和硬件有关的操作:
- #define PwmInit()\
- {\
- PwmStop();\
- P1DIR |= BIT2;\
- P1SEL0 |= BIT2;\
- P1SEL1 &= ~BIT2;\
- TA1CCR0 = 0xFF >> BIT_ABANDON;\
- TA1CCR1 = 0xFF >> BIT_ABANDON;\
- TA1CCTL1 = OUTMOD_3;\
- }
- #define PwmStart() (TA1CTL = TASSEL__SMCLK + TACLR + MC_1)
- #define PwmStop() (TA1CTL = MC_0)
- #define IsPwmStop() (!TA1CTL)
- #define PwmSetDuty(duty) (TA1CCR1 = (duty >> BIT_ABANDON))
- #define SampleClockInit()\
- {\
- TA0CCTL0 = CCIE;\
- TA0CCR0 = 3000;\
- TA0CCTL1 = OUTMOD_3;\
- }
- #define SampleClockStart() (TA0CTL = TASSEL__SMCLK + TACLR + MC_1)
- #define SampleClockStop() (TA0CTL = MC_0)
另一方面,要播放的内容在SD卡上,文件系统自然不多说了,用的是我一向使用的fatfs的精简版。所以就需要用SPI通信对SD卡进行读取。在加上读到的数据,很快就会用在定时器上进行声音的输出,所以一定要协调好SPI通信和定时器的关系,特别是计算好读取的速率——要远大于声音的码率。
- /*******************************************************************************
- * 函数名: xSpiInit
- * 描 述: SPI初始化
- *******************************************************************************/
- void SpiInit(u8_t brcr)
- {
- EUSCI_A_SPI_masterInit(EUSCI_A1_BASE,
- EUSCI_A_SPI_CLOCKSOURCE_SMCLK,
- 24000000,
- 4000000,
- EUSCI_A_SPI_MSB_FIRST,
- EUSCI_A_SPI_PHASE_DATA_CAPTURED_ONFIRST_CHANGED_ON_NEXT,
- EUSCI_A_SPI_CLOCKPOLARITY_INACTIVITY_LOW,
- EUSCI_A_SPI_3PIN
- );
-
- GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4, GPIO_SECONDARY_MODULE_FUNCTION);
- GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN5, GPIO_SECONDARY_MODULE_FUNCTION);
- GPIO_setAsPeripheralModuleFunctionInputPin (GPIO_PORT_P2, GPIO_PIN6, GPIO_SECONDARY_MODULE_FUNCTION);
-
- EUSCI_A_SPI_enable(EUSCI_A1_BASE);
- }
- /*******************************************************************************
- * 函数名: xSpiSend
- * 描 述: SPI收发函数
- *******************************************************************************/
- u8_t SpiSend(const u8_t data)
- {
- volatile u8_t ret;
- EUSCI_A_SPI_transmitData(EUSCI_A1_BASE, data);
- while(EUSCI_A_SPI_isBusy(EUSCI_A1_BASE) == EUSCI_A_SPI_BUSY);
- ret = EUSCI_A_SPI_receiveData(EUSCI_A1_BASE);
- return ret;
- }
最后,即便是这样繁忙的进行计算和处理,也不要忘了经常忙里偷闲扫描一下按键——不能接受外界输出的系统,八成是个,B系统。
- /*******************************************************************************
- * 段 落: Key扫描
- * 描 述: 主要进行按键扫描检测
- *******************************************************************************/
- void key_scan(void)
- {
- static u8_t keyRecord = 0x0A;
-
- keyRecord = (keyRecord << 1) | ((P4IN & 0x20) ? 1 : 0);
-
- if((keyRecord & 0x0F) == 0x0C)
- {
- spf_call_proc(PROC_MAIN, 4, PROC_CALL_SINGLE);
- }
- }
- u8_t key_proc(arg_t arg)
- {
- if(arg == PROC_INIT)
- {
- P4DIR &= ~0x20;
- P4REN |= 0x20;
- P4OUT |= 0x20;
- set_timer(PROC_KEY, TIMER_MS(32), key_scan, CYCLE);
- }
-
- return TRUE;
- }
以上也就是整个系统的麻烦之处了,我已实现完毕,不再过多解释了。只是,非常不谦虚的说,我在硬件方面是个出类拔萃的白痴,所以不能搞出有效的硬件来为这个系统进一步降噪,我表示非常遗憾。
录个视频来看看,可以看到,结构还是很简单的,成本很低的……我用线很乱。切换歌曲的时候,那个是语音报数——果然是屌丝程序员,报数都从0开始,好吧,不让它报0!
后面的话,需要继续实现和时间有关的部分了。不知道有效的时间内,我还能不能完成我的全部想法。总之,先好好去做一下。