用EVM_MSPM0L1306开发板制作的音乐键盘
该项目使用了EVM_MSPM0L1306,实现了电子琴的设计,它的主要功能为:可以简单弹琴和调节音量大小。
标签
开发板
RyanYuang
更新2024-07-22
广东东软学院
26

1、任务要求

  • 使用矩阵键盘、蜂鸣器、流水灯和电位器设计音乐键盘
  • 让不同的按键发出不同的音调
  • 电位器用来控制声音大小
  • 流水灯用来显示声音档位。

1.2、实现思路

  • 使用PWM产生不同的PWM频率和占空比来控制蜂鸣器的声音大小和声调。
  • 使用按键来设置不同的预分频系数,从而控制PWM的发生频率。
  • 使用电位器的ADC数值来控制输出的占空比,从而控制蜂鸣器的音量。

2、实现过程

2.1程序流程图

image.png

2.2外设初始化

学习一块新的板子,难点就是在如何使用外设以及这块板子的一些特性,这块板子是TI的,我觉得TI的库让人用起来非常的难懂,因为它无法像ST公司一样,可以跳转到函数的定义,然后根据芯片手册提供的寄存器来查看这个函数的用法,并且,函数解释也是只是说一半。为了节省时间,我还是只能使用sysconfig来对芯片的外设进行初始化,我的初始化是基于矩阵键盘例程进行的。

2.2.1 PWM

image.png

PWM初始化中,我对外设进行了以下的配置:

  1. 定时器分频和预分频系数设置为1,重装载值设置为可以计算出出音调频率的数值。
  2. 然后打开定时器,PWM就开始生成了。

这里我设置的是 通道0,使用的是PA16的引脚。然后使用母对母的杜邦线连接到蜂鸣器的引脚。

64cde5f60a91345b52dce39ffbfa649.jpg

2.2.2 ADC初始化

image.png

2.3程序实现

2.3.1按键实现

  1. 按键读取
uint8_t Key()
{
uint8_t key_num = 0; // 按键值1-16,默认为0
static uint8_t key_flag = 0; // 按下按键标志

if (key_flag)
{
delay_ms(100); // 300ms延迟,防止按下一次按键却被认为按下了多次按键,导致得到了多个相同的按键值
key_flag = 0; // 按下按键标志清零
}

// 行扫描
// ROW 0111
// 0111-1011-1101-1110
DL_GPIO_clearPins(MAT_KEY_PORT, MAT_KEY_ROW0_PIN);
DL_GPIO_setPins(MAT_KEY_PORT, MAT_KEY_ROW1_PIN | MAT_KEY_ROW2_PIN | MAT_KEY_ROW3_PIN);
delay_ms(10); // 按键消抖延迟,一般为10ms,一定要在外界改变时延迟,而不是读取输入后再延迟
// 所谓的外界改变时,即改变行扫描时,如行输出由0111变为1011
// 这里实际上有两个外界改变时,一个是用户刚刚按下时,另一个是改变行扫描时
// 然而由于按键消抖延迟只需10ms,扫描一轮也只需40ms,远小于用户按下的时间
// 因此选择改变行扫描时作为外界改变时,总能涵盖两种外界改变
// 并且在按键消抖例程中提到,无法得知用户刚刚按下的时刻
// 同时不断判断低电平也不能近似这个时刻,因为低电平出现有两种情况
// 一种是用户先按下,然后改变行扫描,另一种是先改变行扫描,用户再按下
// 普遍错误写法如下:
// DL_GPIO_clearPins(MAT_KEY_PORT, MAT_KEY_ROW0_PIN);
// DL_GPIO_setPins(MAT_KEY_PORT, MAT_KEY_ROW1_PIN | MAT_KEY_ROW2_PIN | MAT_KEY_ROW3_PIN);

// if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL0_PIN))//每次改变行扫描后,直接读取并未经过延迟,有可能只能读到抖动中的高电平,从而永远检测不到,如常见的第二行“不灵敏”问题,究其原因是134行过于灵敏导致消抖错误也能检测正确
// {
// delay_ms(10);
// if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL0_PIN))
// {
// key_num = 1;
// key_flag = 1;
// }
// }

if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL0_PIN))
{

key_num = 1;
key_flag = 1; // 按键已按下
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL1_PIN))
{
key_num = 2;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL2_PIN))
{
key_num = 3;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL3_PIN))
{
key_num = 4;
key_flag = 1;
}

// ROW 1011
DL_GPIO_clearPins(MAT_KEY_PORT, MAT_KEY_ROW1_PIN);
DL_GPIO_setPins(MAT_KEY_PORT, MAT_KEY_ROW0_PIN | MAT_KEY_ROW2_PIN | MAT_KEY_ROW3_PIN);
delay_ms(10);

if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL0_PIN))
{
key_num = 5;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL1_PIN))
{
key_num = 6;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL2_PIN))
{
key_num = 7;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL3_PIN))
{
key_num = 8;
key_flag = 1;
}

// ROW 1101
DL_GPIO_clearPins(MAT_KEY_PORT, MAT_KEY_ROW2_PIN);
DL_GPIO_setPins(MAT_KEY_PORT, MAT_KEY_ROW0_PIN | MAT_KEY_ROW1_PIN | MAT_KEY_ROW3_PIN);
delay_ms(10);

if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL0_PIN))
{
key_num = 9;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL1_PIN))
{
key_num = 10;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL2_PIN))
{
key_num = 11;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL3_PIN))
{
key_num = 12;
key_flag = 1;
}

DL_GPIO_clearPins(MAT_KEY_PORT, MAT_KEY_ROW3_PIN);
DL_GPIO_setPins(MAT_KEY_PORT, MAT_KEY_ROW0_PIN | MAT_KEY_ROW1_PIN | MAT_KEY_ROW2_PIN);
delay_ms(10);

// ROW 1110
if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL0_PIN))
{
key_num = 13;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL1_PIN))
{
key_num = 14;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL2_PIN))
{
key_num = 15;
key_flag = 1;
}
else if (!DL_GPIO_readPins(MAT_KEY_PORT, MAT_KEY_COL3_PIN))
{
key_num = 16;
key_flag = 1;
}

return key_num;
}
  1. 按键处理
		//KEY
key_num = Key(); // 读取按键值1-16,默认为0
if(key_num == 0)
{
DL_TimerG_setCaptureCompareValue(PWM_0_INST, 0, DL_TIMER_CC_0_INDEX);
DL_TimerG_initPWMMode(PWM_0_INST, (DL_TimerG_PWMConfig *) &gPWM_0Config);
}
if(key_num != 0)
{
gPWM_0Config.period = Bee_Freq[key_num-1];
DL_TimerG_setCaptureCompareValue(PWM_0_INST, Bee_Freq[key_num-1 ] * gAdcResult * 0.001, DL_TIMER_CC_0_INDEX);
DL_TimerG_initPWMMode(PWM_0_INST, (DL_TimerG_PWMConfig *) &gPWM_0Config);
key_num = 0;
}

2.3.2ADC实现

  1. ADC读取
void ADC12_0_INST_IRQHandler(void)
{
switch (DL_ADC12_getPendingInterrupt(ADC12_0_INST))
{
case DL_ADC12_IIDX_MEM0_RESULT_LOADED:
//结果存储寄存器有更新
gCheckADC = true;
break;
default:
break;
}
}
  1. ADC处理
		//ADC
DL_ADC12_startConversion(ADC12_0_INST);
while (false == gCheckADC)
{
__WFE();
}
gAdcResult = DL_ADC12_getMemResult(ADC12_0_INST, DL_ADC12_MEM_IDX_0);
if(gAdcResult < 224)
{
DL_GPIO_clearPins(LED_PORT, LED_LED0_PIN);
}
else
{
DL_GPIO_setPins(LED_PORT, LED_LED0_PIN);
}

if(gAdcResult < 220)
{
DL_GPIO_clearPins(LED_PORT, LED_LED1_PIN);
}
else
{
DL_GPIO_setPins(LED_PORT, LED_LED1_PIN);
}
if(gAdcResult < 216)
{
DL_GPIO_clearPins(LED_PORT, LED_LED2_PIN);
}
else
{
DL_GPIO_setPins(LED_PORT, LED_LED2_PIN);
}
if(gAdcResult < 212)
{
DL_GPIO_clearPins(LED_PORT, LED_LED2_PIN);
}
else
{
DL_GPIO_setPins(LED_PORT, LED_LED2_PIN);
}
if(gAdcResult < 208)
{
DL_GPIO_clearPins(LED_PORT, LED_LED3_PIN);
}
else
{
DL_GPIO_setPins(LED_PORT, LED_LED3_PIN);
}
if(gAdcResult < 204)
{
DL_GPIO_clearPins(LED_PORT, LED_LED4_PIN);
}
else
{
DL_GPIO_setPins(LED_PORT, LED_LED4_PIN);
}
if(gAdcResult < 200)
{
DL_GPIO_clearPins(LED_PORT, LED_LED5_PIN);
}
else
{
DL_GPIO_setPins(LED_PORT, LED_LED5_PIN);
}
if(gAdcResult < 196)
{
DL_GPIO_clearPins(LED_PORT, LED_LED6_PIN);
}
else
{
DL_GPIO_setPins(LED_PORT, LED_LED6_PIN);
}
if(gAdcResult < 192)
{
DL_GPIO_clearPins(LED_PORT, LED_LED7_PIN);
}
else
{
DL_GPIO_setPins(LED_PORT, LED_LED7_PIN);
}
//ADC12的转换标志位清零
gCheckADC = false;

3.实物展示

image.png

如图是使用了EVM_MSPM0L1306开发板,白色杜邦线是连接了PA16和蜂鸣器的引脚。

image.png

使用PA16作为发生PWM的引脚来控制蜂鸣器。

另外使用跳帽来连接电位器来实现音量变化的控制。

image.png

4. 主要遇到的问题

  1. 对TI的板卡使用并不适合非常熟悉,并且MSP430L1306属于M0系列的芯片,他的资源不是很充足,开发起来非常费劲。
  2. sysconfig工具经常出现问题,但是后续发现这个问题很正常,只要重新打开工程配置文件即可。
团队介绍
广东东软学院
团队成员
RyanYuang
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号