基于stm32不使用pwm实现利用1/0口产生一定频率的方波,驱动蜂鸣器,发出不同的音调,从而演奏乐曲(最少三首乐曲):(2)采用数码管显示歌曲序号;(3)可通过功能键选择乐曲,暂停,播放。
时间: 2024-03-13 07:43:57 浏览: 99
以下是基于STM32使用GPIO输出实现利用1/0口产生一定频率的方波,驱动蜂鸣器,发出不同的音调,从而演奏乐曲的代码,同时添加了数码管显示歌曲序号和通过功能键选择乐曲,暂停,播放的功能:
```c
#include "stm32f10x.h"
#include "delay.h"
#include "tm1637.h"
#define BUZZER_PIN GPIO_Pin_0
#define BUZZER_PORT GPIOB
#define SWITCH_PIN GPIO_Pin_1
#define SWITCH_PORT GPIOB
#define SONG_NUMER 3
int song[SONG_NUMER][100] = {
{262, 294, 330, 349, 392, 440, 494, 523, 0},
{262, 262, 294, 294, 330, 330, 294, 262, 262, 0},
{392, 392, 440, 440, 494, 494, 440, 392, 349, 349, 330, 330, 294, 294, 262, 0}
};
int noteLength[SONG_NUMER][100] = {
{4, 4, 4, 4, 4, 4, 4, 4, 4},
{4, 4, 4, 4, 4, 4, 8, 4, 4, 8},
{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8}
};
int songIndex = 0;
int playFlag = 0;
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 配置蜂鸣器引脚
GPIO_InitStructure.GPIO_Pin = BUZZER_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BUZZER_PORT, &GPIO_InitStructure);
// 配置拨动开关引脚
GPIO_InitStructure.GPIO_Pin = SWITCH_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(SWITCH_PORT, &GPIO_InitStructure);
}
void PlaySong(int songIndex)
{
int i, noteDuration;
for (i = 0; i < 100; i++) {
if (song[songIndex][i] == 0) {
break;
}
noteDuration = 500 / noteLength[songIndex][i];
int freq = song[songIndex][i];
int time = noteDuration / 2;
// 产生方波
for (int j = 0; j < time; j++) {
GPIO_SetBits(BUZZER_PORT, BUZZER_PIN);
delay_us(freq);
GPIO_ResetBits(BUZZER_PORT, BUZZER_PIN);
delay_us(freq);
}
// 暂停
delay_ms(noteDuration);
// 检测播放标志
if (playFlag == 0) {
break;
}
}
}
void DisplaySongIndex(int index)
{
int i, digit;
int digitArr[4] = {0};
for (i = 0; i < 4; i++) {
digit = index % 10;
digitArr[i] = digit;
index = index / 10;
if (index == 0) {
break;
}
}
TM1637_Display(digitArr);
}
void PlayPauseSwitch(void)
{
// 延时去抖动
delay_ms(50);
if (GPIO_ReadInputDataBit(SWITCH_PORT, SWITCH_PIN) == RESET) {
// 切换播放状态
playFlag = !playFlag;
if (playFlag) {
// 播放歌曲
PlaySong(songIndex);
}
}
}
void SongSwitch(void)
{
// 延时去抖动
delay_ms(50);
if (GPIO_ReadInputDataBit(SWITCH_PORT, SWITCH_PIN) == RESET) {
// 切换歌曲
songIndex++;
if (songIndex >= SONG_NUMER) {
songIndex = 0;
}
// 数码管显示歌曲序号
DisplaySongIndex(songIndex);
// 延时去抖动
delay_ms(200);
}
}
int main(void)
{
GPIO_Configuration();
TM1637_Init();
DisplaySongIndex(songIndex);
while (1) {
// 检测拨动开关状态
if (GPIO_ReadInputDataBit(SWITCH_PORT, SWITCH_PIN) == RESET) {
PlayPauseSwitch();
SongSwitch();
}
}
}
```
该代码在基于原先的代码的基础上,添加了数码管显示歌曲序号和通过功能键选择乐曲,暂停,播放的功能。其中,`DisplaySongIndex`函数用于将歌曲序号显示在数码管上,`PlayPauseSwitch`函数用于切换播放状态,`SongSwitch`函数用于切换歌曲。在`main`函数中,使用拨动开关实现歌曲的切换、播放和暂停,同时数码管显示当前歌曲序号。
阅读全文