stm32F103C8T6、4*4矩阵键盘、无源蜂鸣器、OLED(调试用)

4*4矩阵键盘接引脚A0-A7

无源蜂鸣器接引脚B0

1f6094c2dcd44b6c844ad23c2067500c.jpg

 

一、矩阵键盘扫描

Scan.h

#ifndef __SCAN_H
#define __SCAN_H

int Scan(void);

#endif

Scan.c

#include "stm32f10x.h"
#include "Scan.h"
#include "Delay.h"

int Scan(void)
{
	GPIO_SetBits(GPIOA, GPIO_Pin_0 |GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
	
	int Pin_Array_Row[] = {GPIO_Pin_0 , GPIO_Pin_1, GPIO_Pin_2, GPIO_Pin_3};
	int Pin_Array_Col[] = {GPIO_Pin_4 , GPIO_Pin_5, GPIO_Pin_6, GPIO_Pin_7};
	
	char position = 0;
	int i, j;
	
	//行
	for( i = 0; i < 4; i++)
	{
		GPIO_ResetBits(GPIOA, Pin_Array_Row[i]); //从第零行开始置为低电平,依次++
		
		//列
		for( j = 0; j < 4; j++)
		{
		
			if(GPIO_ReadInputDataBit(GPIOA, Pin_Array_Col[j]) == 0) //检验列是否为低电平
			{
				//消抖
				Delay_ms(50);
				
				//计算按键位置
				position = (i + 1) * 4 - (3 - j);  //i*4定位到该行最后一位数,再减去列的偏移量
				return position;
			}
		
		}
		
		
		GPIO_SetBits(GPIOA, Pin_Array_Row[i]); //将该行置为高电平
	}
	
	
	
	

}

 

二、引脚初始化

GPIO_Init.h

#ifndef __GPIO_INIT_H
#define __GPIO_INIT_H

void Init(void);




#endif

GPIO_Init.c

#include "stm32f10x.h"
#include "GPIO_Init.h"

void Init(void)
{
	
	//GPIOA ---- 矩阵键盘
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 
	
	//输出
	GPIO_InitTypeDef GPIO_InitStructureA;       	
	GPIO_InitStructureA.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructureA.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructureA.GPIO_Mode = GPIO_Mode_Out_PP;     
    GPIO_Init(GPIOA, &GPIO_InitStructureA);
	GPIO_SetBits(GPIOA,GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);   
	
	
	//输入
	GPIO_InitStructureA.GPIO_Pin  = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;         
	GPIO_InitStructureA.GPIO_Mode = GPIO_Mode_IPU;       
	GPIO_Init(GPIOA, &GPIO_InitStructureA);
	GPIO_SetBits(GPIOA, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7);
	
	
	
	




}

三、输出PWM

PWM.h

#ifndef __PWM_H
#define __PWM_H

void TIM_Config(uint16_t arr, uint16_t psc);


#endif

PWM.c

#include "stm32f10x.h"

void TIM_Config(uint16_t arr, uint16_t psc)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    TIM_TimeBaseStructure.TIM_Period = arr;
    TIM_TimeBaseStructure.TIM_Prescaler = psc;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = arr / 2; //50%占空比
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OC3Init(TIM3, &TIM_OCInitStructure);

    TIM_Cmd(TIM3, ENABLE);
}

四、蜂鸣器发声

Beep.h

#ifndef __BEEP_H
#define __BEEP_H

void BEEP_Play_Note(uint16_t note);

#endif

Beep.c

#include "stm32f10x.h"                  // Device header

void BEEP_Play_Note(uint16_t note) 
{
    const uint16_t notes[16] = {262, 294, 330, 349, 392, 440, 494, 523, 587, 659, 698, 784, 880, 988, 1046, 1175}; // C4-B4
    uint32_t f = notes[note - 1];                     // note参数为1-7
    uint32_t psc = 71;                                // 预分频器值
    uint32_t arr_val = (SystemCoreClock / (psc + 1)) / f;
    TIM_SetAutoreload(TIM3, arr_val - 1);
    TIM_SetCompare1(TIM3, arr_val / 2); 
}

五、main.c

#include "stm32f10x.h"  // Device header
#include "Delay.h"
#include "GPIO_Init.h"
#include "Scan.h"
#include "OLED.h"
#include "PWM.h"
#include "Beep.h"



int main(void)
{
	Init();

	int position = 0;
	int old_position = 0;
	
	OLED_Init();
	OLED_Clear();
	
	SystemInit();
    TIM_Config(999, 71); // 配置定时器

	
	while(1)
	{
		position = Scan(); //获取键位
		
		if(position == old_position)   //防止数字一直闪,没有更新按键就不显示新数字
			continue;
		
		if(position > 0 && position < 17)
		{
			OLED_ShowNum(1, 1, position, 2);
		}
		
		old_position = position;
		
		
		BEEP_Play_Note(position);
		
	}
	
		
}

 

 

 

 

 

 

作者:debugCpp

物联沃分享整理
物联沃-IOTWORD物联网 » stm32简易电子琴

发表回复