本文介绍 注:本文所有程序均基于 IAR EWARM 开发 1.官网下载 MM32-FDS 开发套件,支持 MM32 全系列版本,与Cortex-M微控制器软件接口标准(CMSIS)兼容。 2.官网下载相应 IAR_PACK 文件,支持 MM32 全系列芯片在 IAR v7.6 及以上版本的手动安装。 * 本文使用的复用功能引脚,不代表该脚的全部复用功能,下同。 重点说明: 实例化代码: 说明: 说明: 以兰花草为例: 说明: 配置定时器重载值配置、定时器关闭功能。 说明 篇幅有限,LED 状态闪烁及 RV 调整 LED 亮度参见 《MM32 eMiniBoard 之 PWM 驱动无源蜂鸣器+ ADC 调整 LED 亮度 参考例程(下)》。MindMotion
前言
MM32 Insight-Series 开发板 eMiniBoard 第二批出厂程序(基于 MM32-FDS 底层库开发)主要功能
4:控制对应 4 首内置歌曲的播放与暂停;4:显示当前的播放状态(处于播放状态时对应的 LED 慢闪);3:调节相应 LED * 3 (LED2、LED3、LED4)的亮度,调节过程显示其余两路 LED 状态。准备工作
兼容版型
板级基础模块
硬件
LED & Key 模块

LED
对应IO
* 对应 Timer 通道
LD1
PA_15
*
LD2
PB_3
TIM2_CH2
LD3
PB_4
TIM3_CH1
LD4
PB_5
TIM3_CH2
Key
对应IO
K1
PB_1
K2
PB_2
K3
PB_10
K4
PB_11
Beep 模块

Beep
对应IO
对应 Timer 通道
BUZ
PA_8
TIM1_CH1
RV模块

RV
对应IO
对应AD通道
RV1
PA_1
ADC_Channel_1
RV2
PA_4
ADC_Channel_4
RV3
PA_5
ADC_Channel_5
软件
LED/Key 初始化代码
//////////////////////////////////////////////////////////////////////////////// void BSP_LED_Configure(void); void BSP_KEY_Configure(void); //////////////////////////////////////////////////////////////////////////////// void led2on() { TIM_SelectOCxM (TIM2, TIM_Channel_2, TIM_OCMode_PWM1); TIM_CCxCmd (TIM2, TIM_Channel_2, TIM_CCx_Enable); } void led2off() { TIM_SelectOCxM (TIM2, TIM_Channel_2, TIM_OCMode_Inactive); TIM_CCxCmd (TIM2, TIM_Channel_2, TIM_CCx_Enable); } void led3on() { TIM_SelectOCxM (TIM3, TIM_Channel_1, TIM_OCMode_PWM1); TIM_CCxCmd (TIM3, TIM_Channel_1, TIM_CCx_Enable); } void led3off() { TIM_SelectOCxM (TIM3, TIM_Channel_1, TIM_OCMode_Inactive); TIM_CCxCmd (TIM3, TIM_Channel_1, TIM_CCx_Enable); } void led4on() { TIM_SelectOCxM (TIM3, TIM_Channel_2, TIM_OCMode_PWM1); TIM_CCxCmd (TIM3, TIM_Channel_2, TIM_CCx_Enable); } void led4off() { TIM_SelectOCxM (TIM3, TIM_Channel_2, TIM_OCMode_Inactive); TIM_CCxCmd (TIM3, TIM_Channel_2, TIM_CCx_Enable); } //////////////////////////////////////////////////////////////////////////////// void closeLED() { LD6_off(); led2off(); led3off(); led4off(); } //////////////////////////////////////////////////////////////////////////////// void initLEDPWM(u16 psc, u16 arr) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructInit; COMMON_EnableIpClock(emCLOCK_GPIOB); COMMON_EnableIpClock(emCLOCK_TIM2); COMMON_EnableIpClock(emCLOCK_TIM3); GPIO_Mode_AF_PP_20MHz_Init(GPIOB, GPIO_Pin_3, EXTI_MAPR_TIM2_PARTIAL1, GPIO_AF_2); GPIO_Mode_AF_PP_20MHz_Init(GPIOB, GPIO_Pin_4, EXTI_MAPR_TIM3_PARTIAL, GPIO_AF_1); GPIO_Mode_AF_PP_20MHz_Init(GPIOB, GPIO_Pin_5, EXTI_MAPR_TIM3_PARTIAL, GPIO_AF_1); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = arr; TIM_TimeBaseStructure.TIM_Prescaler = psc; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_RepetitionCounter=0; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_OCStructInit(&TIM_OCInitStructInit); TIM_OCInitStructInit.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructInit.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructInit.TIM_Pulse = arr >> 1; TIM_OCInitStructInit.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OC2Init(TIM2, &TIM_OCInitStructInit); TIM_OC1Init(TIM3, &TIM_OCInitStructInit); TIM_OC2Init(TIM3, &TIM_OCInitStructInit); TIM_Cmd(TIM2, ENABLE); TIM_Cmd(TIM3, ENABLE); }
__MM32_MINIBOARD(Miniboard与eMiniboard部分资源不兼容,后续开发将升级为对应开发板型号 宏定义 MBxxx),即可开启板载资源 LED/KEYLD6_off(); 为 Miniboard 原有配置函数,开启LED1void initLEDPWM(u16 psc, u16 arr) 为配置LED对应定时器PWM通道。实例化代码如下:RCC_ClocksTypeDef rcc_clocks; //////////////////////////////////////////////////////////////////////////////// void main() { RCC_GetClocksFreq(&rcc_clocks); initLEDPWM(rcc_clocks.SYSCLK_Frequency / 1000000 - 1, 4096); //........... } Beep 初始化代码
//////////////////////////////////////////////////////////////////////////////// void initBuzzer(u16 prescaler) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructInit; COMMON_EnableIpClock(emCLOCK_GPIOA); COMMON_EnableIpClock(emCLOCK_TIM1); GPIO_Mode_AF_PP_20MHz_Init(GPIOA, GPIO_Pin_8, NO_REMAP, GPIO_AF_2); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_TimeBaseStructure.TIM_Period = 999; 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_OCStructInit(&TIM_OCInitStructInit); 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_Low; TIM_OC1Init(TIM1, &TIM_OCInitStructInit); TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable); TIM_CtrlPWMOutputs(TIM1, ENABLE); } RCC_ClocksTypeDef rcc_clocks; //////////////////////////////////////////////////////////////////////////////// void main() { RCC_GetClocksFreq(&rcc_clocks); initBuzzer(rcc_clocks.SYSCLK_Frequency / 2000000 - 1); //........... } RV 初始化代码
//////////////////////////////////////////////////////////////////////////////// void initGPIO_ADC() { GPIO_InitTypeDef GPIO_InitStructure; COMMON_EnableIpClock(emCLOCK_GPIOA); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); } //////////////////////////////////////////////////////////////////////////////// void initADC() { ADC_InitTypeDef ADC_InitStructure; DMA_InitTypeDef DMA_InitStructure; COMMON_EnableIpClock(emCLOCK_ADC1); COMMON_EnableIpClock(emCLOCK_DMA1); initGPIO_ADC(); DMA_DeInit(DMA1_ch1); DMA_InitStructure.PeripheralBaseAddr = (u32)&(ADC1->DR); DMA_InitStructure.MemoryBaseAddr = (u32)&ADCtemp[0]; DMA_InitStructure.DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.BufferSize = 3; DMA_InitStructure.PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.MemoryDataSize = DMA_MemoryDataSize_Word; DMA_InitStructure.Mode = DMA_Mode_Circular; DMA_InitStructure.Priority = DMA_Priority_High; DMA_InitStructure.M2M = DMA_M2M_Disable; DMA_Init(DMA1_ch1, &DMA_InitStructure); DMA_Cmd(DMA1_ch1, ENABLE); ADC_InitStructure.ADC_Mode = ADC_CR_CONTINUE; ADC_InitStructure.ADC_PRESCARE = ADC_PCLK2_PRESCARE_16; ADC_InitStructure.ADC_ExternalTrigConv = ADC1_ExternalTrigConv_T1_CC1; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_Init(ADC1, &ADC_InitStructure); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_Samctl_1_5); ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 2, ADC_Samctl_1_5); ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 3, ADC_Samctl_1_5); ADC_ITConfig(ADC1, ADC_IT_EOC, DISABLE); ADC_Cmd(ADC1, ENABLE); ADC_DMACmd(ADC1, ENABLE); ADC1->CFGR |= 0x04; ADC_SoftwareStartConvCmd(ADC1, ENABLE); } 蜂鸣器播放音频
单音频率计算

本文根据上图的单音频率配置频谱表,如下所示:
音符
选定频率
定时器重载值
1
262
7633
2
294
6802
3
330
6060
4
349
5076
5
392
5102
6
440
4545
7
494
4048
·1
523
3824
·2
587
3407
·3
*
3034
·4
*
2865
·5
*
2550
·6
*
2273
·7
*
2024
1·
131
15267
2·
147
13605
3·
*
12121
4·
*
11429
5·
*
10204
6·
*
9090
7·
*
8097
··1
1047
1910
··2
*
1702
··3
*
1516
··4
*
1432
··5
*
1276
··6
*
1136
··7
*
1012
系统主频:
定时器分频后频率: 2MHz
单音对应定时器重载值 = 2MHz / 单音频率const u16 tonetime[] = { 1000, // 1: do 7633, 6802, 6060, 5076, 5102, 4545, 4048,1000,1000,1000, //11: `do 3824, 3407, 3034, 2865, 2550, 2273, 2024,1000,1000,1000, //21: do` 15267, 13605, 12121, 11429, 10204, 9090, 8097,1000,1000,1000, //31: ``do 1910, 1702, 1516, 1432, 1276, 1136, 1012,1000,1000,1000, };
1000 为空白/占位,调度算法会将小于等于 1000 的数值屏蔽发音。谱曲

根据 简谱 编写music音调、time节拍 数组,如下所示:u8 music[]={ 6,3,3,3,3,2, 1,2,1,27,26, 6,6,6,6,6,5, 3,5,5,4,3, 3,6,6,5,3,2, 1,2,1,27,26,23, 23,1,1,27,26,3, 2,1,27,25,26 }; u8 time[] = { 2,2,2,2,6,2, 3,1,2,2,8, 2,2,2,2,6,2, 2,2,2,2,8, 2,2,2,2,6,2, 2,2,2,2,4,4, 2,2,2,2,6,2, 3,1,2,2,8 };
定时器设置
//////////////////////////////////////////////////////////////////////////////// void setBuzzerFreq(u16 Period) { TIM_SetAutoreload(TIM1, Period); TIM_SetCompare1(TIM1, Period / 2); } //////////////////////////////////////////////////////////////////////////////// void setBuzzerEn(FunctionalState NewState) { TIM_Cmd(TIM1, NewState); } 调度算法
//////////////////////////////////////////////////////////////////////////////// void PlayMusic(void) { u16 tonetemp; switch(sPlayMusic.PlayStep){ //////////////////////////////////////////////////////////////////////// case PLAYSTEP1: setBuzzerEn(DISABLE); if(true == sPlayMusic.PlayFlag){ setBuzzerFreq(tonetime[music[sPlayMusic.ToneNumCount]]); sPlayMusic.PlayStep = PLAYSTEP2; } break; //////////////////////////////////////////////////////////////////////// case PLAYSTEP2: if(true == sPlayMusic.PlayFlag){ // play music 0 if(sPlayMusic.MusicNum == 0) { if(sPlayMusic.ToneNumCount < sizeof(music)/sizeof(u8)){ sPlayMusic.ToneCount++; if(sPlayMusic.ToneCount <= (time[sPlayMusic.ToneNumCount] * 10 / 2)){ setBuzzerEn(ENABLE); } else { setBuzzerEn(DISABLE); if(sPlayMusic.ToneCount >= (time[sPlayMusic.ToneNumCount] * 10)){ sPlayMusic.ToneCount =0; sPlayMusic.ToneNumCount ++; tonetemp = tonetime[music[sPlayMusic.ToneNumCount]]; if(tonetemp <= 1000) setBuzzerEn(DISABLE); else { setBuzzerFreq(tonetemp); setBuzzerEn(ENABLE); } } } } else{ sPlayMusic.PlayStep = PLAYSTEP3; setBuzzerEn(DISABLE); } } //....................... else{ setBuzzerEn(DISABLE); } } break; //////////////////////////////////////////////////////////////////////// case PLAYSTEP3: sPlayMusic.PlayFlag = false; sPlayMusic.CurrentPlayFlag = false; sPlayMusic.MusicNum = 0; sPlayMusic.ToneCount = 0; sPlayMusic.ToneNumCount = 0; sPlayMusic.PlayStep = PLAYSTEP1; break; } } 系统调度
//////////////////////////////////////////////////////////////////////////////// void AppTaskTick(void) { if(ready){ if (tickCnt++ >= 20) { tickCnt = 0; tickFlag = true; PlayMusic(); } //..... } }
1.本文配置的发音单元 发音短促,留有大约 50% 的空白,保持蜂鸣器短促悦耳。
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算
官方软件产品操作指南 (170)