《ARM微控制器与嵌入式系统》慕课---实验四 PWM实验

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 16:30   1212   0

任务:使用PWM驱动蜂鸣器来播放简单音乐

分析:声音的特性可由三个要素来描述,即响度、音调和音色。音调主要与声波的频率有关

音调频率
L1261.6
L2293.7
L3329.6
L4349.2
L5392
L6440
L7493.9
M1523.3
M2587.3
M3659.3
M4698.5
M5784
M6880
M7987.8
H11045.5
H21174.7
H31318.5
H41396.9
H51568
H61760
H71975.5

两只老虎简谱:

如果数字下方有点,代表低音,如果数字上方有点,代表高音,否则默认中音。

音长:一般一节为4拍,如果相邻数字下面有连线,说明两个一起是一拍

实现代码片段如下:

#define PWM0_CLK_FREQ 164*1000 //20.97M / 128

#define L1 M1*2
#define L2 M2*2
#define L3 M3*2
#define L4 M4*2
#define L5 M5*2
#define L6 M6*2
#define L7 M7*2

#define M1 (PWM0_CLK_FREQ/523)
#define M2 (PWM0_CLK_FREQ/587)
#define M3 (PWM0_CLK_FREQ/659)
#define M4 (PWM0_CLK_FREQ/698)
#define M5 (PWM0_CLK_FREQ/784)
#define M6 (PWM0_CLK_FREQ/880)
#define M7 (PWM0_CLK_FREQ/988)

#define H1 M1/2
#define H2 M2/2
#define H3 M3/2
#define H4 M4/2
#define H5 M5/2
#define H6 M6/2
#define H7 M7/2

#define NN 0

static unsigned int During;
static unsigned int num;

struct Music_data {
 unsigned int freq;
 unsigned int During_time;
};

//两只老虎乐谱
static struct Music_data md[] = {
  {M1, 0x2},
  {M2, 0x2},
  {M3, 0x2},
  {M1, 0x2},

  {M1, 0x2},
  {M2, 0x2},
  {M3, 0x2},
  {M1, 0x2},

  {M3, 0x2},
  {M4, 0x2},
  {M5, 0x4},
  
  {M3, 0x2},
  {M4, 0x2},
  {M5, 0x4},

  {M5, 0x1},
  {M6, 0x1},
  {M5, 0x1},
  {M4, 0x1},
  {M3, 0x2},
  {M1, 0x2},

  {M5, 0x1},
  {M6, 0x1},
  {M5, 0x1},
  {M4, 0x1},
  {M3, 0x2},
  {M1, 0x2},

  {M1, 0x2},
  {L5, 0x2},
  {M1, 0x4},

  {M1, 0x2},
  {L5, 0x2},
  {M1, 0x4},

  {0xff, 0x0},
};

void TPM0_init(void)
{
 SIM_SOPT2 |= (1 << 24); //select TPM Clock source
 SIM_SCGC5 |= (1 << 11); //enable portC Clock
 SIM_SCGC6 |= (1 << 24); //enable TPM0 Clock

 PORTC_PCR8 |= (3 << 8); //conifg portc_8 as TPM0_ch4
 
 TPM0_SC |= (1 << 3) | 0x7; //CPWMS and CMOD and PS
 TPM0_CNT = 0;
 TPM0_MOD = 0; // period =  (MOD + 0x0001)
 TPM0_C4SC |= (1 << 5) | (1 << 3); //MSnB:MSnA ELSnB:ELSnA EPWM
 TPM0_C4V = 0; //duty cycle
}

void TPM0_set(int period)
{
 TPM0_MOD = period;
 TPM0_C4V = period / 2;
}

void systick_init(void)
{
 SYST_RVR = 2621250; //1/8s
 SYST_CVR = 0;
 SYST_CSR |= 0x7; 
}

void __enable_irq(void)
{
 asm("CPSIE i");
}

void SysTick_Handler(void)
{
 int i;

 if(During == 0)
 {
  if(md[num].freq == 0xff)
  {
   num = 0;
  }
  TPM0_set(md[num].freq);
  During = md[num].During_time;
  num++;
 }
 During--;
 i = SYST_CSR;
}

int main(void)
{
 int counter = 0;
 
 TPM0_init();
 systick_init();
 __enable_irq();
 for(;;) {    
     counter++;
 }
 
 return 0;
}

至此,该实验就玩完啦,别忘记点赞哦,欢迎大家留言讨论,谢谢!

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP