[原创] 【AT32WB415测评】02时钟配置+LED操作

秦天qintian0303   2022-8-10 20:56 楼主

02时钟配置+LED操作

前言

       在上文中我们选择对应的开发工程,下面就将在AT32WB415_Firmware_Library_V2.0.2\project\at_start_wb415\templates\iar_v8.2进行咱们的软件开发。

目标

       熟悉芯片时钟配置,并进行LED操作,本次将通过按键方式改变LED展示模式。

实现

       芯片时钟的配置主要依托时钟树中各种时钟配置的选择,直观高效:

204305rda3g3el0zxs703g.jpg

       本软件工程目前就是开发板自带的例程,关于时钟的配置,其实在头文件中 EXTERN SystemInit就是执行的的时钟配置,在system_at32wb415.c的SystemInit如下:

204305px02lwz0lk8xy820.jpg

       是直接进行的寄存器初始赋值,这样其实是不适合我们直接修改操作的,不易理解还容易出错,所以在这之外雅特力在main中有进行了一遍时钟配置system_clock_config();可以通过修改里面的寄存器配置。AT32WB415CCU7-7目前不考虑功耗,由于USB的存在必须能够通过PLLCLK分频得到48M,所以PLLCLK在150M的限值下最大可以设计成144,HEXT通过18倍频后得到PLLCLK。

 

       下面进行LED的操作设计,首先咱们先规划一下LED的模式,一种是所有LED全开全关,第二种是LED循环点亮,这两种都是对IO的基本操作;第三种就是循环呼吸灯,这里面涉及的主要是定时的PWM输出功能。模式的切换采用按键操作进行,这里面涉及的就是外部中断操作,防抖操作使用定时器中进行。

       下面进行具体的配置:

LED对应IO口初始化:

void LED_GPIO_init(void)
{
  gpio_init_type gpio_init_struct;
  crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);/* enable the led clock */
  gpio_default_para_init(&gpio_init_struct);/* set default parameter */
  /* configure the led gpio */
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_pins = GPIO_PINS_7|GPIO_PINS_8|GPIO_PINS_9;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOB, &gpio_init_struct);
}

 

        进行IO口操作宏定义:

/************************************宏定义************************************/

#define LEDRed_on gpio_bits_reset(GPIOB,GPIO_PINS_7);
#define LEDRed_off gpio_bits_set(GPIOB,GPIO_PINS_7);
#define LEDRed_Toggle gpio_bits_TogglePin(GPIOB,GPIO_PINS_7);

#define LEDYellow_on gpio_bits_reset(GPIOB,GPIO_PINS_8);
#define LEDYellow_off gpio_bits_set(GPIOB,GPIO_PINS_8);
#define LEDYellow_Toggle gpio_bits_TogglePin(GPIOB,GPIO_PINS_8);

#define LEDGreen_on gpio_bits_reset(GPIOB,GPIO_PINS_9);
#define LEDGreen_off gpio_bits_set(GPIOB,GPIO_PINS_9);
#define LEDGreen_Toggle gpio_bits_TogglePin(GPIOB,GPIO_PINS_9);

        注意:IO低电平时点亮

        对IO口赋初值:

void LED_init(void)
{
  LEDRed_on;
  LEDYellow_on;
  LEDGreen_on;
}

        下面进行基本定时器配置:

void Tmr10Base_init(uint16_t Period)
{
  /* enable tmr10 clock */
  crm_periph_clock_enable(CRM_TMR10_PERIPH_CLOCK, TRUE);
  /* tmr1 configuration */
  /* time base configuration */
  /* systemclock/14400/10000 = 1hz */
  tmr_base_init(TMR10, Period * 10 - 1, 14400 - 1);
  tmr_cnt_dir_set(TMR10, TMR_COUNT_UP);
  /* overflow interrupt enable */
  tmr_interrupt_enable(TMR10, TMR_OVF_INT, TRUE);
  /* tmr10 overflow interrupt nvic init */
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 0, 2);
  /* enable tmr10 */
  tmr_counter_enable(TMR10, TRUE);
}

基本定时器是用定时器10,注意分频的计算,Period对应定时ms;

 

进行外部中断配置:

void port_EXIT_init(void)
{
  exint_init_type exint_init_struct;

  crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

  gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE0);

  exint_default_para_init(&exint_init_struct);
  exint_init_struct.line_enable = TRUE;
  exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
  exint_init_struct.line_select = EXINT_LINE_0;
  exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
  exint_init(&exint_init_struct);

  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  nvic_irq_enable(EXINT0_IRQn, 1, 0);

}

        按键的判断通过外部中断+定时器的方式进行,为此定义了一个结构体。

typedef struct 
{
 uint8_t EXIT_flag; //中断触发标志
 uint8_t EXIT_Data; //中断触发防抖计时
 uint8_t Press_flag; //按键触发标志
 uint8_t Press_Data; //按键类型判断计时
 uint8_t ShortPress_flag; //短按触发标志
 uint8_t LongPress_flag; //长按触发标志
 
}key;
extern  key key_Ok;

        在外部中断中只进行EXIT_flag的置位,最主要是通过定时器中进行防抖和按键识别;

    if(key_Ok.EXIT_flag == 1)//防抖判断
    {
      key_Ok.EXIT_Data++;
      if(key_Ok.EXIT_Data == 2 && READ_KEY_OK == 1)
      {
        key_Ok.Press_flag = 1;
        key_Ok.Press_Data = 0;
        key_Ok.ShortPress_flag = 0;
        key_Ok.LongPress_flag = 0;
        key_Ok.EXIT_flag = 0;
      }
      else if(key_Ok.EXIT_Data > 2)
      {
        key_Ok.EXIT_flag = 0;
        key_Ok.EXIT_Data = 0;
      }
    
    }
    if(key_Ok.Press_flag == 1)
    {
      key_Ok.Press_Data++;
      if(READ_KEY_OK == 0) 
      {
        if(key_Ok.Press_Data >= 100)
        {
          key_Ok.LongPress_flag = 1;
        }
        else if(key_Ok.Press_Data < 100)
        {
          key_Ok.ShortPress_flag = 1;
        }
        key_Ok.Press_flag = 0;
      }
      else
      {
        if(key_Ok.Press_Data >= 120)
        {
          key_Ok.LongPress_flag = 1;
          key_Ok.Press_flag = 0;
        } 
      }
    }

        通过原理图及数据手册判断出,PWM的输出对应的是TIM4的2、3、4通道,配置如下:

if(key_Ok.EXIT_flag == 1)//防抖判断
    {
      key_Ok.EXIT_Data++;
      if(key_Ok.EXIT_Data == 2 && READ_KEY_OK == 1)
      {
        key_Ok.Press_flag = 1;
        key_Ok.Press_Data = 0;
        key_Ok.ShortPress_flag = 0;
        key_Ok.LongPress_flag = 0;
        key_Ok.EXIT_flag = 0;
      }
      else if(key_Ok.EXIT_Data > 2)
      {
        key_Ok.EXIT_flag = 0;
        key_Ok.EXIT_Data = 0;
      }
    
    }
    if(key_Ok.Press_flag == 1)
    {
      key_Ok.Press_Data++;
      if(READ_KEY_OK == 0) 
      {
        if(key_Ok.Press_Data >= 100)
        {
          key_Ok.LongPress_flag = 1;
        }
        else if(key_Ok.Press_Data < 100)
        {
          key_Ok.ShortPress_flag = 1;
        }
        key_Ok.Press_flag = 0;
      }
      else
      {
        if(key_Ok.Press_Data >= 120)
        {
          key_Ok.LongPress_flag = 1;
          key_Ok.Press_flag = 0;
        } 
      }
    }

        以下将呼吸灯的频率设置为2s,并定义了LED控制结构体:

typedef struct 
{
 uint8_t Mode_Dis; //LED显示模式
 uint8_t Mode_OidDis; //LED上一次显示模式
 uint8_t PWMcnt; //PWM控制
 uint8_t state; //LED过程
 uint8_t UpFlag; //更新标志
 uint8_t Upcnt; //更新计时
 
}LED_states;

extern LED_states     LED;

void App_LED(void)
{
  if(LED.Mode_OidDis != LED.Mode_Dis)
  {
    LED.Upcnt = 0;
    LED.state = 0;
    LED.UpFlag = 1;
    
    if(LED.Mode_OidDis == 2)
    {
      tmr_counter_enable(TMR4, FALSE);
      LED_GPIO_init();
      
    }
    else
    {
      LEDRed_off;
      LEDYellow_off;
      LEDGreen_off;
    }

    switch(LED.Mode_Dis)
    {
      case 0:
        LEDRed_on;
        LEDYellow_on;
        LEDGreen_on;
        break;
        
      case 1:
        LEDRed_on;
        break;
        
      case 2:
        Tmr4PWM_init(Tmr4PWM);
        LED.Upcnt = 0;
        break;

      default:
        break;
    }
    LED.Mode_OidDis = LED.Mode_Dis;
  }
  
  if(LED.UpFlag == 1)
  {
    if(LED.Mode_Dis == 0)
    {
      LEDRed_Toggle;
      LEDYellow_Toggle;
      LEDGreen_Toggle;
    }
    else if(LED.Mode_Dis == 1)
    {
      switch(LED.state)
      {
        case 0:
          LEDRed_on;
          LEDGreen_off;
          break;
          
        case 1:
          LEDRed_Toggle;
          LEDYellow_Toggle;
          break;
          
        case 2:
          LEDYellow_Toggle;
          LEDGreen_Toggle;
          break;
          
        default:
          break;
      }
    }
    else if(LED.Mode_Dis == 2)
    {
      switch(LED.state)
      {
        case 0:
          tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_2, LED.PWMcnt*50);
          break;
          
        case 1:
          tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_3, LED.PWMcnt*50);
          break;
          
        case 2:
          tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_4, LED.PWMcnt*50);
          break;
          
        default:
          break;
      }
    }
    LED.UpFlag = 0;
  }

}

        LED操作的表现形式有很多种,这里就实现了3个比较有代表性的,大家也可以发散思维实现不同的唯美的体现。

        视频如下:

LED操作.gif 点击上图查看Gif动图

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本帖最后由 秦天qintian0303 于 2022-8-10 20:59 编辑
在爱好的道路上不断前进,在生活的迷雾中播撒光引

回复评论 (2)

这个时钟寄存器的名字 感觉故意和ST区分 名字看起来有点奇怪

点赞  2022-8-10 22:59
引用: 常见泽1 发表于 2022-8-10 22:59 这个时钟寄存器的名字 感觉故意和ST区分 名字看起来有点奇怪

这是必然啊,根是一样的,但是穿的衣裳不一样,所有的都会改一点

点赞  2022-8-11 08:34
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复