上午写了开发板的环境搭建和开箱评测,中午调试了下板卡上的Key和Buzzer,想着先把板卡上的资源都测试下,下面看这部分:
1、Key部分先看了例程,例程这部分按键程序很简单,自己测试了下例程的按键,到也没发现误按的情况,比我想象中好用些,不过Key部分我也自己的处理方式
typedef struct
{
unsigned char KeyEnable;
unsigned char KeyValue;
unsigned char EnableContinue;
unsigned char ValidFlag;
unsigned char Counter1;
}s_Key;
extern s_Key sKey[KEY_TOTALNUM];
上面这个结构体是我经常使用的,很多项目上也用过,好用,这次也不例外,将这部分代码移植上去,在sKey[KEY_TOTALNUM]中就可以查看Key的状态
2、板载有蜂鸣器,这部分准备用蜂鸣器实现一首很简单的歌曲,网上红尘情歌的谱比较多,这里也选择这首歌,省的自己再进行谱子的转化
u8 music[]={ 5,5,6,8,7,6,5,6,13,13,
5,5,6,8,7,6,5,3,13,13,
2,2,3,5,3,5,6,3,2,1,
6,6,5,6,5,3,6,5,13,13,
5,5,6,8,7,6,5,6,13,13,
5,5,6,8,7,6,5,3,13,13,
2,2,3,5,3,5,6,3,2,1,
6,6,5,6,5,3,6,1,
13,8,9,10,10,9,8,10,9,8,6,
13,6,8,9,9,8,6,9,8,6,5,
13,2,3,5,5,3,5,5,6,8,7,6,
6,10,9,9,8,6,5,6,8};
u8 time[] = { 2,4,2,2,2,2,2,8,4,4,
2,4,2,2,2,2,2,8,4,4,
2,4,2,4,2,2,4,2,2,8,
2,4,2,2,2,2,2,8,4,4,
2,4,2,2,2,2,2,8,4,4,
2,4,2,2,2,2,2,8,4,4,
2,4,2,4,2,2,4,2,2,8,
2,4,2,2,2,2,2,8,
4,2,2,2,4,2,2,2,2,2,8,
4,2,2,2,4,2,2,2,2,2,8,
4,2,2,2,4,2,2,5,2,6,2,4,
2,2,2,4,2,4,2,2,12};
const uint16_t tone[] = {247,262,294,330,349,392,440,494,523,587,659,698,784,1000};
const uint16_t tonetime[] = {8097,7633,6802,6060,5076,5102,4545,4048,3824,3407,3034,2865,2550,2000}; //0.5us
tone中为对应的频率,为了简单我将频率转变为tonetime中的时间,单位0.5us
3、由于蜂鸣器连接了A8 pin 为TIM1的复用输出pin,所以这里配置TIM1
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
GPIO_PinAFConfig(GPIOA, GPIO_Pin_8, GPIO_AF_2);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //PA8
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
上面RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);这个刚开始忘了,结果 哈哈。。。
定时器部分直接贴code,和STM32差不多,没啥好说的
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructInit;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
TIM_TimeBaseStructure.TIM_Period = Period;
TIM_TimeBaseStructure.TIM_Prescaler =Prescaler;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM1, TIM_FLAG_Update);
TIM_OCStructInit(&TIM_OCInitStructInit);
// TIM_OCInitStructInit.TIM_OCMode = TIM_OCMode_Toggle;
TIM_OCInitStructInit.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructInit.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructInit.TIM_Pulse = 0;
// TIM_OCInitStructInit.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructInit.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM1, &TIM_OCInitStructInit);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
下面实现调频率
void Buzzer_Set_Freq(u16 Period)
{
TIM_SetAutoreload(TIM1,Period);
TIM_SetCompare1(TIM1,Period/2);
}
下面开启关闭定时器,实现蜂鸣器发声
void Buzzer_Set_En(FunctionalState NewState)
{
TIM_Cmd(TIM1, NewState);
}
准备工作结束,下面就是播放控制,先看下控制结构体
typedef struct
{
unsigned char PlayFlag;
unsigned char CurrentPlayFlag;
unsigned char PlayStep;
unsigned char MusicNum;
unsigned char ToneCount;
unsigned char ToneNumCount;
}_sPlayMusic;
蜂鸣在函数PlayMusic函数中实现,次函数由定时调度器调用,我这里是100ms调用一次,code如下
void PlayMusic(void)
{
unsigned int tonetemp;
switch(sPlayMusic.PlayStep)
{
case PLAYSTEP1:
if(TRUE == sPlayMusic.PlayFlag)
{
//Buzzer_Set_Freq(tone[14-music[sPlayMusic.ToneNumCount]]);
Buzzer_Set_Freq(tonetime[music[sPlayMusic.ToneNumCount]]);
Buzzer_Set_En(ENABLE);
sPlayMusic.PlayStep = PLAYSTEP2;
}
break;
case PLAYSTEP2:
if(sPlayMusic.ToneNumCount < sizeof(music)/sizeof(u8))
{
sPlayMusic.ToneCount++;
if(sPlayMusic.ToneCount >= time[sPlayMusic.ToneNumCount])
{
sPlayMusic.ToneCount =0;
sPlayMusic.ToneNumCount++;
//Buzzer_Set_Freq(tone[14-music[sPlayMusic.ToneNumCount]]);
tonetemp = tonetime[music[sPlayMusic.ToneNumCount]];
if(tonetemp <= 2000) Buzzer_Set_En(DISABLE);
else {
Buzzer_Set_Freq(tonetemp);
Buzzer_Set_En(ENABLE);
}
}
}
else{
sPlayMusic.PlayStep = PLAYSTEP3;
Buzzer_Set_En(DISABLE);
}
break;
case PLAYSTEP3:
sPlayMusic.PlayFlag = FALSE;
sPlayMusic.CurrentPlayFlag = FALSE;
sPlayMusic.MusicNum = 0;
sPlayMusic.ToneCount = 0;
sPlayMusic.ToneNumCount = 0;
sPlayMusic.PlayStep = PLAYSTEP1;
break;
}
}
然后在主函数中,当检测到Key2按下时,设置sPlayMusic.PlayFlag = TRUE; 即可,蜂鸣器开始演奏,目前程序没有实现演奏过程中停止演奏,演奏结束后,重新按键可以二次演奏。
截止目前,LED和蜂鸣器部分测试基本结束。附件有烧写的Hex文件,按Key2即可演奏红尘情歌,频率没有认真调试,也不是正式产品,效果还行,该有的功能基本都实现了。
|
共2人点赞
|