当前位置:   article > 正文

用stm32写三首歌曲外加LED每隔1秒切换一次绿灯亮灭

用stm32写三首歌曲外加LED每隔1秒切换一次绿灯亮灭

首先进行LED、按键、定时器和中断的初始化:

LED初始化:

void LED_init(void)
{
    GPIO_InitTypeDef gpio_info;
    //PH0
    //初始化GPIOH时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH,ENABLE);
    
    gpio_info.GPIO_Mode = GPIO_Mode_OUT;
    gpio_info.GPIO_OType = GPIO_OType_PP;
    gpio_info.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12;
    gpio_info.GPIO_PuPd = GPIO_PuPd_UP;
    gpio_info.GPIO_Speed = GPIO_Low_Speed;
    
    GPIO_Init(GPIOH,&gpio_info);
}

按键初始化:

void key1_init(void)
{
    GPIO_InitTypeDef gpio_info;
    EXTI_InitTypeDef exti_info;
    NVIC_InitTypeDef  NVIC_InitStructure;
    //PA0
    //初始化GPIOA的时钟    
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    //初始化中断时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
    
    //配置按键
    gpio_info.GPIO_Mode = GPIO_Mode_IN;
    gpio_info.GPIO_OType = GPIO_OType_PP;
    gpio_info.GPIO_Pin = GPIO_Pin_0;
    gpio_info.GPIO_PuPd = GPIO_PuPd_NOPULL;
    gpio_info.GPIO_Speed = GPIO_Low_Speed;
    GPIO_Init(GPIOA,&gpio_info);
    

    //配置按键的外部中断   
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);
    exti_info.EXTI_Line = EXTI_Line0;
    exti_info.EXTI_LineCmd = ENABLE; //使能
    exti_info.EXTI_Mode = EXTI_Mode_Interrupt;
    exti_info.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_Init(&exti_info);
    
    //配置这个外部中断的优先级
    NVIC_InitStructure.NVIC_IRQChannel =  EXTI0_IRQn;   //PA0 对应的是EXTI0_IRQn
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitStructure);
    
}

定时器初始化:

__IO uint32_t TimingDelay = 0;

//每10us执行一次
void TimingDelay_Decrement()
{
    if(TimingDelay!=0)
        TimingDelay--;
}


void Delay_10us(__IO uint32_t value)
{
    TimingDelay = value;
    
    while(TimingDelay!=0);
}

void Delay_ms(__IO uint32_t value) 
{
    Delay_10us(value*100);
}


void Delay_init(void)
{
    //配置systick定时器每10us产生一次中断
    SysTick_Config(SystemCoreClock/100000);
}

中断初始化:

static void TIM_PWMOUTPUT_Config(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    // 开启TIMx_CLK,x[2,3,4,5,12,13,14] 
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 
        /* 累计 TIM_Period个后产生一个更新或者中断*/        
    //当定时器从0计数到8999,即为9000次,为一个定时周期
    TIM_TimeBaseStructure.TIM_Period = 1000-1; 
    // 通用控制定时器时钟源TIMxCLK = HCLK/2=90MHz 
    // 设定定时器频率为=TIMxCLK/(TIM_Prescaler+1)=100KHz
    TIM_TimeBaseStructure.TIM_Prescaler = 90-1;    
    // 采样时钟分频
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    // 计数方式
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
    // 初始化定时器TIMx, x[2,3,4,5,12,13,14] 
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    /*PWM模式配置*/
    /* PWM1 Mode configuration: Channel1 */
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;     //配置为PWM模式1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;    
    TIM_OCInitStructure.TIM_Pulse = 1000-1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //当定时器计数值小于CCR1_Val时为高电平
    TIM_OC1Init(TIM2, &TIM_OCInitStructure);     //使能通道1
    /*使能通道1重载*/
    TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
    // 使能定时器
    TIM_Cmd(TIM2, ENABLE);    
}

void TIM_PWM_init()
{
    TIMx_GPIO_Config();
    TIM_PWMOUTPUT_Config();
}

void PWM_SetFrequency(uint32_t rate)
{
    uint32_t temp =0;
    if(rate == 0)
            temp = 0;
    else
            temp= 1*1000000/rate;
    TIM_SetCounter(TIM2,0);
    TIM_SetAutoreload(TIM2, temp);
    TIM_SetCompare1(TIM2,temp/2);
}

然后在.h文件中进行定义,在定义在主函数中:

         Delay_init();
         TIM_PWM_init();
         LED_init();
         key1_init();

接下来在定义歌曲的中低高音和节拍频率:

//中音
#define L1 523
#define L2 587
#define L3 659
#define L4 698
#define L5 784     
#define L6 880
#define L7 988
//低音
#define k1 262
#define k2 294
#define k3 330
#define k4 349
#define k5 392
#define k6 440
#define k7 494
//高音
#define h1 1046
#define h2 1175
#define h3 1318
#define h4 1379
#define h5 1568
#define h6 1760
#define h7 1976


#define l0 500
#define l1 l0/2
#define l2 l1/2
#define l3 l0*2

进行三首歌曲的编写:

uint16_t musicical1[][2]=
{
  {h3,l1},{h4,l1},{h3,l1},{h2,l1},
  {h3,l3},{L6,l3},{h2,l3},{L5,l3},
  {h2,l3},{L5,l3},{h1,l3},{h3,l1},
  {h4,l1},{h3,l1},{h2,l1},{h3,l3},
  {h6,l3},{h4,l0},{h3,l1},{h2,l1},
  {h1,l0},{h3,l1},{h3,l3},{h3,l1},
  {h2,l1},{h1,l1},{h2,l1},{h3,l3}, 
  {h6,l3},{h2,l3},{h3,l3},

};//"交换余生"31个字符

uint16_t musicical2[][2]=
{
    
    {L1,l0},{L2,l0},{L3,l0},{L1,l0},
    {L1,l0},{L2,l0},{L3,l0},{L1,l0},
    {L3,l0},{L4,l0},{L5,l3},{L3,l0},
    {L4,l0},{L5,l3},{L5,l1},{L6,l1},
    {L5,l1},{L4,l1},{L3,l0},{L1,l0},
    {L5,l1},{L6,l1},{L5,l1},{L4,l1},
    {L3,l0},{L1,l0},{L1,l0},{k5,l0},
    {L1,l3},{L1,l0},{k5,l0},{L1,l3},
    
};//"两只老虎"32个字符

uint16_t musicical3[][2]=
{
    
    {L3,l0},{L2,l0},{L4,l0},{L3,l0}, 
    {L1,l0},{L5,l0},{L7,l0},{h1,l0},
    {L7,l0},{L1,l0},{L1,l0},{L1,l0},
    {L6,l0},{L6,l1},{L6,l1},{L5,l0},
    {L5,l1},{L5,l1},{L4,l0},{L3,l0},
    {L2,l0},{L3,l0},{L4,l0},{L3,l0},

};//"晴天"24个字符

void play1()
{
    static uint16_t timecnt = 0;
    static uint16_t index = 0;
    
    if(timecnt == 0)
    PWM_SetFrequency(musicical1[index][0]);
    timecnt+=10;
    
    if(timecnt>=musicical1[index][1])
    {
        index++;
        timecnt = 0;
        
    }
    if(index>=31)
        index = 0;
}
  
void play2()
{
    static uint16_t timecnt = 0;
    static uint16_t index = 0;
    
    if(timecnt == 0)
    PWM_SetFrequency(musicical2[index][0]);
    timecnt+=10;
    
    if(timecnt>=musicical2[index][1])
    {
        index++;
        timecnt = 0;
        
    }
    if(index>=32)
        index = 0;
}
void play3()
{
    static uint16_t timecnt = 0;
    static uint16_t index = 0;
    
    if(timecnt == 0)
    PWM_SetFrequency(musicical3[index][0]);
    timecnt+=10;
    
    if(timecnt>=musicical3[index][1])
    {
        index++;
        timecnt = 0;
        
    }
    if(index>=24)
        index = 0;
}

其中重要的一点是要在stm32f4xx_it.c文件中写入一个中断如图所示:

定义变量可自由定义,然后再到主函数定义代码如下:

extern int number;//引用外部变量 number

   int main(void)
{
    //函数初始化
    Delay_init();
    TIM_PWM_init();
      LED_init();
        key1_init();
      //关闭所有LED灯
    LED_Red_Ctrl(LED_OFF);
        LED_Green_Ctrl(LED_OFF);
        LED_Blue_Ctrl(LED_OFF);
    
    while(1)
    {     
      Delay_ms(10);
            music_time = music_time + 10;
            
            switch(number)
            {
                case 1:
                    play1();//播放第一首歌曲
                    break;
                case 2:
                    play2();//播放第二首歌曲
                    break;
                case 3:
                    play3();//播放第三首歌曲
                    break;
                default:
                    break;
            }                                                            
            
              if(music_time%1000 ==0)//表示系统时间除以1000的余数是0,
                {
                    //绿色LED灯一秒钟切换一次亮灭状态。
              if(GREEN ==0)
                            {
                            LED_Green_Ctrl(LED_ON);
                                GREEN = 1;
                            }
                else if(GREEN ==1)
                                {
                             LED_Green_Ctrl(LED_OFF);
                                GREEN = 0;
                                }
                        
               }            
            
    }
}

这样就完成一个简单的八音盒系统。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/790080
推荐阅读
相关标签
  

闽ICP备14008679号