前言
最近在学习上海山景公司的BP10_128DBG的开发板,因为网上关于BP10开发板的帖子也比较少,在学习的时候也没有太多的参考资料,基本上都是官方的历程。芯片的相关资料也没有像ST、NXP这些那么全,所以我把我自己的学习收获分享出来,大家有需要的可以参考。
项目场景
我按键控制音量的代码是在官方Demo_Decoder上进行添加的,官方原本的demo可以实现从tf卡读取歌单然后根据不同类型的歌曲,调用相应的解码函数得到PCM数据,最后通过DMA传输到DAC0(一个3.5mm耳机口)输出音频。
官方的历程是通过串口收发数据来控制DAC0输出音频的音量,然后我看板子上有比较多的按键,想着就不用串口了用按键会更方便。
然后开发板上的按键是ADC按键,就是连接了不同阻值的电阻,按下不同的按键IO口被拉低的程度不同。ADC1_KEY连接到的是GPIOA_23,ADC2_KEY连接到的是GPIOA_26。
从原理图可以看出,按键从左到右电平拉低程度越来越低(最左边按下GPIOA_23电平基本为0,最右边按下GPIOA_23电平几乎为VCC)。于是可以将GPIO配置成外部中断模式,读取GPIOA_23, GPIOA_26的电平是否被拉低来判断对应按键是否按下,进而是否触发中断。
配置过程
1:首先设置GPIO中断管脚、配置的是下降沿触发、开启GPIO中断
2:先初始化一个定时器进行延时消抖处理、先不开启定时器
3:按下按键之后进入gpio中断,要清掉中断标志位(一定要清要不然会一直进入GPIO中断)。清除中断标志位的的方式要先调用GPIO_INTFlagGet(GPIO_A_INT)得到一组GPIO的中断标志状态,最后传入GPIO_INTFlagClear函数中,然后开启定时器。
4:然后我用串口打印出两个按键按下GPIO_INTFlagGet(GPIO_A_INT)分别返回的值,通过GPIO_INTFlagGet(GPIO_A_INT)得到不同的返回值,最后就可以确定到底是哪个IO进了中断,即哪个按键按下了。
5:定时10ms之后进入定时器中断,然后根据中断状态的值来判断哪个按键按下了,进而执行相应音量加减的操作,结束的时候要清定时器的中断标志位并且要暂停定时器。
6:以下是每个小模块的代码
GPIO初始化:
//GPIO按键中断控制
GPIO_PortAModeSet(GPIOA26, 0);
GPIO_RegOneBitSet(GPIO_A_IE, GPIO_INDEX26);
GPIO_RegOneBitClear(GPIO_A_OE, GPIO_INDEX26);
GPIO_RegOneBitSet(GPIO_A_PU, GPIO_INDEX26);
GPIO_RegOneBitClear(GPIO_A_PD, GPIO_INDEX26);
GPIO_INTEnable(GPIO_A_INT, GPIO_INDEX26, GPIO_NEG_EDGE_TRIGGER);
GPIO_PortAModeSet(GPIOA23, 0);
GPIO_RegOneBitSet(GPIO_A_IE, GPIO_INDEX23);
GPIO_RegOneBitClear(GPIO_A_OE, GPIO_INDEX23);
GPIO_RegOneBitSet(GPIO_A_PU, GPIO_INDEX23);
GPIO_RegOneBitClear(GPIO_A_PD, GPIO_INDEX23);
GPIO_INTEnable(GPIO_A_INT, GPIO_INDEX23, GPIO_NEG_EDGE_TRIGGER);
NVIC_SetPriority(Gpio_IRQn, 0);
NVIC_EnableIRQ(Gpio_IRQn);
定时器初始化:
//定时器相关配置
Timer_InterruptFlagClear(TIMER2, UPDATE_INTERRUPT_SRC);
Timer_Config(TIMER2, 10000, 0);
NVIC_EnableIRQ(Timer2_IRQn);
GIE_ENABLE(); //开启总中断
外部中断服务函数:
uint32_t gpioPinIndex[2] = {0,0};
__attribute__((section(".driver.isr"))) void GpioInterrupt(void)
{
DBG("ENTER GpioInterrupt\r\n");
gpioPinIndex[0] = GPIO_INTFlagGet(GPIO_A_INT);
DBG("GpioA Int Index:%ld\r\n",gpioPinIndex[0]);
GPIO_INTFlagClear(GPIO_A_INT,gpioPinIndex[0]);
Timer_Start(TIMER2);
}
定时器中断服务函数:
__attribute__((section(".driver.isr"))) void Timer2Interrupt(void)
{
DBG("Enter Timer2Interrupt\r\n");
if(gpioPinIndex[0] == 0x800000){ //K9按下
DBG("ADC1_KEY IS PRESSED GPIOA_23 Vol++\r\n");
if(vol_l < 0xaff){
vol_l += 10;vol_r += 10;
AudioDAC_VolSet(AUDIO_DAC0, vol_l, vol_r);
DBG("Vol+: %d\r\n", vol_l);
}
}
if(gpioPinIndex[0] == 0x4000000){ //K8按下
DBG("ADC2_KEY IS PRESSED GPIOA_26 Vol--\r\n");
if(vol_l > 10){
vol_l -= 10;vol_r -= 10;
AudioDAC_VolSet(AUDIO_DAC0, vol_l, vol_r);
DBG("Vol-: %d\r\n", vol_l);
}
}
Timer_Pause(TIMER2, 1);
Timer_InterruptFlagClear(TIMER2, UPDATE_INTERRUPT_SRC);
}
总结
以上就是本文的内容,非常感谢你能看到这。