蜂鸣器实现智能风琴

概要

利用stm32最小系统板制作一个智能风琴,要求使用矩阵键盘,不同键盘按下蜂鸣器会发出不同音调,并用OLED显示音调。实现视频可在主页观看

所需器件:stm32f103c8t6、有源分蜂鸣器、矩阵按键、OLED

整体架构流程

使用模块化编程,所有模块如图:

其中key文件包含矩阵键盘的控制,oled文件包含oled的控制,pwm文件则是蜂鸣器的控制。

1.矩阵键盘模块

本次矩阵键盘采用4x4矩阵键盘,其行列引脚如图所示

详细教程可·看这个大佬:STM32 4*4矩阵键盘实现原理(附程序)_矩阵键盘原理图-CSDN博客

#include "stm32f10x.h"
#ifndef __KEY_H
#define __KEY_H
void Matrix_ssKey_Pin_Init(void);
int Matrix_Key_Scan(void);
#endif
#include "key.h"
#include "stm32f10x.h"                  // Device header
#include "delay.h"


void Matrix_ssKey_Pin_Init(void)
	
{
	GPIO_InitTypeDef GPIO_InitStructure;
 
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ; 
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
}	


int Matrix_Key_Scan(void)
{
	u8 temp = 0;
	int key_val = -1;
	
	GPIO_ResetBits(GPIOB,GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11);			//拉低行线
	delay_us(10);
 
	temp=(GPIO_ReadInputData(GPIOB) >> 8)&0xff;	
	
	//没有按键按下时扫描
	if (temp == 0xf0) 
	{
			delay_ms(50); 
			GPIO_ResetBits(GPIOB,GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11);			//拉低行线
			delay_us(10);
			temp=(GPIO_ReadInputData(GPIOB) >> 8)&0xff;	
		
			if (temp != 0xf0) //按键按下时,对键值进行赋值
			{
				//第一行
				GPIO_Write(GPIOB,0);
				delay_ms(5);
				GPIO_Write(GPIOB,(uint16_t)(0xFE << 8)); 
				
				if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0)
				{
						delay_ms(20);//消抖
 
						if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0)
						{
								temp=((GPIO_ReadInputData(GPIOB) >> 8) & 0XFE);		//对列进行扫描
								switch(temp)
								{
										case 0xEE:  key_val = 1;   break;
										case 0xDE:  key_val = 2;   break;
										case 0xBE:  key_val = 3;   break;
										case 0x7E:  key_val = 4;   break;
										default:    key_val = -1;   break;
								}
						}
				}
				
				//第二行
				GPIO_Write(GPIOB,0);
				delay_ms(5);
				GPIO_Write(GPIOB,(uint16_t)(0xFD << 8));
				
				if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0)!= 0XF0)
				{
						delay_ms(20);
 
						if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0)
						{
								temp=((GPIO_ReadInputData(GPIOB) >> 8) & 0XFD);
								switch(temp)
								{
										case 0xED:  key_val = 5;   break;
										case 0xDD:  key_val = 6;   break;
										case 0xBD:  key_val = 7;   break;
										case 0x7D:  key_val = 8;   break;
										default:    key_val = -1;   break;
								}
						}
				}
				

 
				//第三行
				GPIO_Write(GPIOB,0);
				delay_ms(5);
				GPIO_Write(GPIOB,(uint16_t)(0xFB << 8));
				
				if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0)
				{
						delay_ms(20);
 
						if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0)
						{
								temp=((GPIO_ReadInputData(GPIOB) >> 8) & 0XFB);
								switch(temp)
								{
										case 0xEB:  key_val = 9;   break;
										case 0xDB:  key_val = 10;   break;
										case 0xBB:  key_val = 11;   break;
										case 0x7B:  key_val = 12;   break;
										default:    key_val = -1;   break;
								}
						}
				}
				
				//第四行
				GPIO_Write(GPIOB,0);
				delay_ms(5);
				GPIO_Write(GPIOB,(uint16_t)(0xF7 << 8));
				
				if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) !=0XF0)
				{
						delay_ms(20);
 
						if(((GPIO_ReadInputData(GPIOB) >> 8) & 0XF0) != 0XF0)
						{
								temp=((GPIO_ReadInputData(GPIOB) >> 8) & 0XF7);
								switch(temp)
								{
										case 0xE7:  key_val = 13;   break;
										case 0xD7:  key_val = 14;   break;
										case 0xB7:  key_val = 15;   break;
										case 0x77:  key_val = 16;   break;
										default:    key_val = -1;   break;
								}
						}
					}
				}
			}
	
	return key_val;
 



		

 
}

连线方式:

R1——PB8                          C1——PB12

R2——PB9                          C2——PB13

R3——PB10                        C3——PB14

R4——PB11                        C4——PB15

2.蜂鸣器模块

要控制蜂鸣器输出不同音调,就要改变蜂鸣器输出引脚的输出占空比,即输出PWM波。

本次PWM波输出采用TIME2的CH3通道,即PA2、

I/O——PA2

详细原理可看:STM32 使用STM32F103控制无源蜂鸣器发声播放音乐_stm32 无源蜂鸣器 音阶-CSDN博客

#ifndef _PWM_H
#define _PWM_H
#include "stm32f10x.h"
void Pwm_Gpio_Init(void);
void Tim4_Pwm_Set(int Period, int Pulse);
#endif
#include  "pwm.h"

//PA2
void Pwm_Gpio_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA的时钟
//GPIO配置 PA2 TIM2_CH3
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure); //引脚初始化
}                                                                                 
void Tim4_Pwm_Set(int Period, int Pulse)
{
TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能TIM3的时钟
//TIM2的基本配置
TIM_BaseInitStructure.TIM_Prescaler = 7200-1;//预分频
TIM_BaseInitStructure.TIM_Period = Period;//计数周期
TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数
TIM_BaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分割 输入滤波
TIM_TimeBaseInit(TIM2, &TIM_BaseInitStructure);//初始化TIM3
//配置TIM2的通道1输出PWM脉冲
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//TIM 脉冲宽度调制模式 1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//定时器输出使能
TIM_OCInitStructure.TIM_Pulse = Pulse;//设置装入捕获比较寄存器的脉冲值
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//TIM 输出比较极性:高即周期内低于TIM_Pulse这个阈值的时间,都是高电平,其他时间都是低;
TIM_OC3Init(TIM2,&TIM_OCInitStructure);//初始化TIM3的Channel1
TIM_Cmd(TIM2,ENABLE);//使能TIM2

}
3.oled模块,oled模块大都为封装好的文件,可直接移植调用\

SCL——PA6

SDA——PA7

#ifndef __OLED_H
#define __OLED_H			  	 
#include "sys.h"
#include "stdlib.h"	    	
			  
//-----------------OLED IIC端口定义----------------  					   

#define OLED_SCLK_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_6)//SCL IIC接口的时钟信号
#define OLED_SCLK_Set() GPIO_SetBits(GPIOA,GPIO_Pin_6)

#define OLED_SDIN_Clr() GPIO_ResetBits(GPIOA,GPIO_Pin_7)//SDA IIC接口的数据信号
#define OLED_SDIN_Set() GPIO_SetBits(GPIOA,GPIO_Pin_7)

#define OLED_CMD  0	//写命令
#define OLED_DATA 1	//写数据

//OLED控制用函数
void OLED_WR_Byte(unsigned dat,unsigned cmd);  
void OLED_Display_On(void);
void OLED_Display_Off(void);	   							   		    
void OLED_Init(void);
void OLED_Clear(void);
void OLED_Fill(unsigned char fill_Data);
void OLED_ShowString(u8 x,u8 y, u8 *p,u8 Char_Size);	 
void OLED_Set_Pos(unsigned char x, unsigned char y);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Wait_Ack(void);
void Write_IIC_Command(unsigned char IIC_Command);
void Write_IIC_Data(unsigned char IIC_Data);

#endif  
	 



#include "oled.h"
#include "stdlib.h"
#include "oledfont.h"
#include "delay.h"

//PA6.7

//OLED的显存
//存放格式如下.
//[0]0 1 2 3 ... 127
//[1]0 1 2 3 ... 127
//[2]0 1 2 3 ... 127
//[3]0 1 2 3 ... 127
//[4]0 1 2 3 ... 127
//[5]0 1 2 3 ... 127
//[6]0 1 2 3 ... 127
//[7]0 1 2 3 ... 127
/**********************************************
//IIC Start
**********************************************/
/**********************************************
//IIC Start
**********************************************/
void IIC_Start(void)
{
    OLED_SCLK_Set() ;
    OLED_SDIN_Set();
    OLED_SDIN_Clr();
    OLED_SCLK_Clr();
}

/**********************************************
//IIC Stop
**********************************************/
void IIC_Stop(void)
{
    OLED_SCLK_Set() ;
    OLED_SDIN_Clr();
    OLED_SDIN_Set();
}

void IIC_Wait_Ack(void)
{
    OLED_SCLK_Set() ;
    OLED_SCLK_Clr();
}
/**********************************************
// IIC Write byte
**********************************************/

void Write_IIC_Byte(unsigned char IIC_Byte)
{
    unsigned char i;
    unsigned char m, da;
    da = IIC_Byte;
    OLED_SCLK_Clr();

    for(i = 0; i < 8; i++)
    {
        m = da;
        m = m & 0x80;

        if(m == 0x80)
        {
            OLED_SDIN_Set();
        }
        else OLED_SDIN_Clr();

        da = da << 1;
        OLED_SCLK_Set();
        OLED_SCLK_Clr();
    }


}
/**********************************************
// IIC Write Command
**********************************************/
void Write_IIC_Command(unsigned char IIC_Command)
{
    IIC_Start();
    Write_IIC_Byte(0x78);            //Slave address,SA0=0
    IIC_Wait_Ack();
    Write_IIC_Byte(0x00);			       //write command
    IIC_Wait_Ack();
    Write_IIC_Byte(IIC_Command);
    IIC_Wait_Ack();
    IIC_Stop();
}
/**********************************************
// IIC Write Data
**********************************************/
void Write_IIC_Data(unsigned char IIC_Data)
{
    IIC_Start();
    Write_IIC_Byte(0x78);			//D/C#=0; R/W#=0
    IIC_Wait_Ack();
    Write_IIC_Byte(0x40);			//write data
    IIC_Wait_Ack();
    Write_IIC_Byte(IIC_Data);
    IIC_Wait_Ack();
    IIC_Stop();
}

/***********************Delay****************************************/
//坐标设置

void OLED_Set_Pos(unsigned char x, unsigned char y)
{
    Write_IIC_Command(0xb0 + y);
    Write_IIC_Command(((x & 0xf0) >> 4) | 0x10);
    Write_IIC_Command((x & 0x0f) | 0x01);
}
void OLED_Fill(unsigned char fill_Data)//全屏填充
{
    unsigned char m, n;

    for(m = 0; m < 8; m++)
    {
        Write_IIC_Command(0xb0 + m);		//page0-page1
        Write_IIC_Command(0x02);		//low column start address
        Write_IIC_Command(0x10);		//high column start address

        for(n = 0; n < 128; n++)
        {
            Write_IIC_Data(fill_Data);
        }
    }
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void)
{
    OLED_Fill(0x00);
}
//--------------------------------------------------------------
// Prototype      : void OLED_ON(void)
// Calls          :
// Parameters     : none
// Description    : 将OLED从休眠中唤醒
//--------------------------------------------------------------
void OLED_On(void)
{
    Write_IIC_Command(0X8D);  //设置电荷泵
    Write_IIC_Command(0X14);  //开启电荷泵
    Write_IIC_Command(0XAF);  //OLED唤醒
}
//--------------------------------------------------------------
// Prototype      : void OLED_OFF(void)
// Calls          :
// Parameters     : none
// Description    : 让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
//--------------------------------------------------------------
void OLED_OFF(void)
{
    Write_IIC_Command(0X8D);  //设置电荷泵
    Write_IIC_Command(0X10);  //关闭电荷泵
    Write_IIC_Command(0XAE);  //OLED休眠
}
//--------------------------------------------------------------
// Prototype      : void OLED_ShowChar(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
// Calls          : 
// Parameters     : x,y -- 起始点坐标(x:0~127, y:0~7); ch[] -- 要显示的字符串; TextSize -- 字符大小(1:6*8 ; 2:8*16)
// Description    : 显示codetab.h中的ASCII字符,有6*8和8*16可选择
//--------------------------------------------------------------
void OLED_ShowString(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
	unsigned char c = 0,i = 0,j = 0;
	switch(TextSize)
	{
		case 8:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 122)
						return;

				OLED_Set_Pos(x,y);
				for(i=0;i<6;i++)
					Write_IIC_Data(F6x8[c][i]);
				x += 6;
				j++;
			}
		}break;
		case 16:
		{
			while(ch[j] != '\0')
			{
				c = ch[j] - 32;
				if(x > 120)
						return;

				OLED_Set_Pos(x,y);
				for(i=0;i<8;i++)
					Write_IIC_Data(F8X16[c*16+i]);
				OLED_Set_Pos(x,y+1);
				for(i=0;i<8;i++)
					Write_IIC_Data(F8X16[c*16+i+8]);
				x += 8;
				j++;
			}
		}break;
	}
}
//初始化OLED屏幕
void OLED_Init(void)
{

     GPIO_InitTypeDef  GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PB端口时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7| GPIO_Pin_6;	 //PB6,PB7推挽输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHz
    GPIO_Init(GPIOA, &GPIO_InitStructure);	  //初始化GPIOD3,6

    delay_ms(100); //这里的延时很重要

    Write_IIC_Command(0xAE); //display off
    Write_IIC_Command(0x20);	//Set Memory Addressing Mode
    Write_IIC_Command(0x10);	//00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid
    Write_IIC_Command(0xb0);	//Set Page Start Address for Page Addressing Mode,0-7
    Write_IIC_Command(0xc8);	//Set COM Output Scan Direction
    Write_IIC_Command(0x00); //---set low column address
    Write_IIC_Command(0x10); //---set high column address
    Write_IIC_Command(0x40); //--set start line address
    Write_IIC_Command(0x81); //--set contrast control register
    Write_IIC_Command(0xff); //亮度调节 0x00~0xff
    Write_IIC_Command(0xa1); //--set segment re-map 0 to 127
    Write_IIC_Command(0xa6); //--set normal display
    Write_IIC_Command(0xa8); //--set multiplex ratio(1 to 64)
    Write_IIC_Command(0x3F); //
    Write_IIC_Command(0xa4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content
    Write_IIC_Command(0xd3); //-set display offset
    Write_IIC_Command(0x00); //-not offset
    Write_IIC_Command(0xd5); //--set display clock divide ratio/oscillator frequency
    Write_IIC_Command(0xf0); //--set divide ratio
    Write_IIC_Command(0xd9); //--set pre-charge period
    Write_IIC_Command(0x22); //
    Write_IIC_Command(0xda); //--set com pins hardware configuration
    Write_IIC_Command(0x12);
    Write_IIC_Command(0xdb); //--set vcomh
    Write_IIC_Command(0x20); //0x20,0.77xVcc
    Write_IIC_Command(0x8d); //--set DC-DC enable
    Write_IIC_Command(0x14); //
    Write_IIC_Command(0xaf); //--turn on oled panel
    OLED_Clear();
}





























4.mian函数部分
#include "stm32f10x.h" // Device header
#include "pwm.h"
#include "key.h"
#include "led.h"
#include "oled.h"
#include "stdio.h"
#include "delay.h"
void my_delay(int n);
	 
#define proport 10000 //Tclk/(psc+1)=72000000/(7199+1) Tclk=72MHz 预分频后的频率
//根据 Tout = ((arr+1)*(psc+1))/Tclk Tout为音调频率的倒数, 推出arr值就是define定义的值
#define L1 ((proport/131)-1)//低调 do 的周期
#define L2 ((proport/147)-1)//低调 re 的周期
#define L3 ((proport/165)-1)//低调 mi 的周期
#define L4 ((proport/176)-1)//低调 fa 的周期
#define L5 ((proport/196)-1)//低调 sol的周期
#define L6 ((proport/220)-1)//低调 la 的周期
#define L7 ((proport/247)-1)//低调 si 的周期
#define M1 ((proport/262)-1)//中调 do 的周期
#define M2 ((proport/296)-1)//中调 re 的周期
#define M3 ((proport/330)-1)//中调 mi 的周期
#define M4 ((proport/349)-1)//中调 fa 的周期
#define M5 ((proport/392)-1)//中调 sol的周期
#define M6 ((proport/440)-1)//中调 la 的周期
#define M7 ((proport/494)-1)//中调 si 的周期
#define H1 ((proport/523)-1)//高调 do 的周期
#define H2 ((proport/587)-1)//高调 re 的周期
#define H3 ((proport/659)-1)//高调 mi 的周期
#define H4 ((proport/699)-1)//高调 fa 的周期
#define H5 ((proport/784)-1)//高调 sol的周期
#define H6 ((proport/880)-1)//高调 la 的周期
#define H7 ((proport/988)-1)//高调 si 的周期
#define Z0 0

unsigned int keyValue;

int music[]=
{

		H2,50,H1,25,M6,25,M6,25,H1,50, M6,25,H2,25,H1,25,M6,50,M6,25,H1,50,H1,50, H3,100,H3,25,H4,25,H3,50,H3,25,H2,50,H2,50,Z0,25,
		//我曾将青春翻涌成她 也曾指尖弹出盛夏 心之所动且就随缘去吧
		H1,50,H2,50,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,50, H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H3,50,H3,50, H2,50,H1,25,M6,25,M6,25,H3,50,H3,50, H2,50,H1,25,M6,25,M6,25,H1,50,H1,50,H1,100,H1,100,Z0,10,
		//短短的路走走停停  也有了几分的距离
		M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,25,M3,25,M2,25,M1,25,L6,100,Z0,10,
		//不知抚摸的是故事还是段心情
		M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M3,25,M2,50,M1,50,M2,100,Z0,50,
		//也许期待的不过是与时间为敌
		M2,50,M2,50,M1,25,M2,50,M2,50,M1,25,M2,50,M3,50,M5,50,M3,50, M2,50,M2,50,M3,25,M2,50,M1,50,L6,100,Z0,10,
		//再次见到你 微凉晨光里 笑的很甜蜜
		M3,25,M2,25,M1,25,M2,25,M1,100, M3,25,M2,25,M1,25,M2,25,M1,50,M1,50, M5,25,M3,25,M2,25,M1,25,M2,25,M1,100,M1,150,Z0,30,
		//从前初识这世间 万般留恋 看着天边似在眼前 也甘愿赴汤蹈火去走它一遍
		M1,50,M2,50,M3,50,M1,50,M6,50,M5,25,M6,25,M6,50,M6,50, M1,25,M7,50,M6,25,M7,25,M7,100,Z0,5, M7,50,M6,25,M7,25,M7,50,M3,50,H1,25,H2,25,H1,25,M7,25,M6,50,M5,50, M6,50,M5,25,M6,25,M6,25,M5,25,M6,25,M5,25,M6,50,M5,25,M2,25,M2,25,M5,50,M5,50,M3,100,M3,100,Z0,25,
		//如今走过这世间 万般留恋 翻过岁月不同侧脸 措不及防闯入你的笑颜
		M1,50,M2,50,M3,50,M1,50,M6,50,M5,25,M6,25,M6,50,M6,50, M1,25,M7,50,M6,25,M7,25,M7,100,Z0,5, M7,50,M6,25,M7,25,M7,50,M3,50,H1,25,H2,25,H1,25,M7,25,M6,50,M5,50, M6,50,H3,25,H3,25,H3,50,M5,50,M6,50,H3,25,H3,25,H3,25,M5,50,M6,25,M6,100,M6,100,M6,100,Z0,25,
		//我曾难自拔于世界之大 也沉溺于其中梦话
		H1,50,H2,50,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,25,H3,25,H3,50, H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,25,H3,50,H3,50,
		//不得真假 不做挣扎 不惧笑话
		H2,50,H1,25,M6,25,M6,25,H1,50, M6,25,H2,25,H1,25,M6,50,M6,25,H1,50,H1,50, H3,100,H3,25,H4,25,H3,50,H3,25,H2,50,H2,50,Z0,25,
		//我曾将青春翻涌成她 也曾指尖弹出盛夏 心之所动且就随缘去吧
		H1,50,H2,50,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,50, H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H3,50,H3,50, H2,50,H1,25,M6,25,M6,25,H3,50,H3,50, H2,50,H1,25,M6,25,M6,25,H1,50,H1,50,H1,100,H1,100,Z0,10,
		//逆着光行走任风吹雨打吧
		M6,25,H3,50,H3,50,H2,50,H1,25,M6,25,M6,25,H3,50,H2,50,H1,25,M6,25,M6,25,H1,50,H1,50,H1,50,H1,100,Z0,25,
		//晚风吹起你鬓间的白发 抚平回忆留下的疤
		H1,50,H2,50,H2,25,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,25, H3,25,H3,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,25,H3,50,H3,50,Z0,5,
		//你的眼中明暗交杂 一笑生花 暮色遮住你蹒跚的步伐
		H2,50,H1,25,M6,25,M6,25,H1,50,M6,25,H2,25,H1,25,M6,50,M6,50, H1,50,H1,50,H3,100,H3,25,H4,25,H3,50,H3,25,H2,50,H2,50,H1,100,H2,100,H3,100,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H6,25,H5,25,H5,50,H2,50,
		//走进床头藏起的画 画中的你(低着头说话)
};



int main()
{
	int i = 2000;
 int length = sizeof(music)/sizeof(music[0]);//计算数组长度
 
	 delay_init();
	 
   OLED_Init();
	 OLED_Clear();
	
delay_init();
Matrix_ssKey_Pin_Init();
	while(1)
	{
		keyValue=Matrix_Key_Scan();;//获取按键的键值
		switch(keyValue)			//根据键值确定按下的按钮
		{
			case 1:
				Pwm_Gpio_Init();
				Tim4_Pwm_Set(L1, 25);
				OLED_ShowString(0,0,(u8*)"do",16);
			  
			  delay_ms(200);break;  //按键1
			
			case 2:
				Pwm_Gpio_Init();
				Tim4_Pwm_Set(M2, 25);
				OLED_ShowString(0,0,(u8*)"re",16);
			  
			  delay_ms(200);break;  //按键2
			
			case 3:
				Pwm_Gpio_Init();
			Tim4_Pwm_Set(L3, 25);
				OLED_ShowString(0,0,(u8*)"mi",16);
			  
			  delay_ms(200);break;  //按键3
			
			case 4:
				Pwm_Gpio_Init();
			Tim4_Pwm_Set(L4, 25);
				OLED_ShowString(0,0,(u8*)"fa",16);
			 
			  delay_ms(200);break;  //按键4
			
			case 5:
				Pwm_Gpio_Init();
			Tim4_Pwm_Set(L5, 25);
				OLED_ShowString(0,0,(u8*)"sol",16);
			  
			  delay_ms(200);break;  //按键5
			
			case 6:
				Pwm_Gpio_Init();
			Tim4_Pwm_Set(L6, 25);
				OLED_ShowString(0,0,(u8*)"la",16);
			  
			  delay_ms(200);break;  //按键6
			
			case 7:
				Pwm_Gpio_Init();
			 Tim4_Pwm_Set(L7, 25);
				OLED_ShowString(0,0,(u8*)"xi",16);
			  
			  delay_ms(200);break;  //按键7
			
			case 8:
				 Pwm_Gpio_Init();
      
	       OLED_ShowString(0,0,(u8*)"qifengle  ",16);
		     delay_ms(1000);
	
         for(i=0; i<(length/2); i++)//取数组数据
      {
        Tim4_Pwm_Set(music[2*i], music[2*i]);//PWM波周期
         my_delay(5*music[2*i+1]);//音长的时间都乘以5即一拍为500微秒,此值"5"可调整,只是播放的整个快慢而已,有点类似于视频快进和后退
				
      }
          my_delay(20000); //2S延时
                   
			    break;  //按键8
			
			
			case 9:
			
				OLED_ShowString(0,0,(u8*)"9",16);
		  	delay_ms(2000);break;  //按键9
			
			case 10:
			
				OLED_ShowString(0,0,(u8*)"10",16);
		  	delay_ms(2000);break;  //按键10
			
			case 11:
				
				OLED_ShowString(0,0,(u8*)"11",16);
		  	delay_ms(2000);break;  //按键11
			
			case 12:
			
				OLED_ShowString(0,0,(u8*)"12",16);
		  	delay_ms(2000);break;  //按键12
			
			case 13:
		
				OLED_ShowString(0,0,(u8*)"13",16);
		  	delay_ms(2000);break;  //按键13
			
			case 14:
				
				OLED_ShowString(0,0,(u8*)"14",16);
		  	delay_ms(2000);break;  //按键14
			
			case 15:
				
				OLED_ShowString(0,0,(u8*)"15",16);
		  	delay_ms(2000);break;  //按键15
			
			case 16:
			
				OLED_ShowString(0,0,(u8*)"16",16);
		  	delay_ms(2000);break;  //按键16
			default:break;
			}
}
	

技术细节

特别注意:delay_Init()函数一定要放在所有初始化函数前面!!!!否则整个代码都运行不了!

还有千万不要串口功能重定义!!!

小结

写代码前一定要想好不同模块功能的连接位置,合理规划引脚

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值