秦天qintian0303 发表于 2022-8-10 20:56

【AT32WB415测评】02时钟配置+LED操作

<div class='showpostmsg'> 本帖最后由 秦天qintian0303 于 2022-8-10 20:59 编辑

<p><strong><span style="font-size:16px;">02时钟配置+LED操作</span></strong></p>

<p><strong><span style="font-size:16px;">前言</span></strong></p>

<p><span style="font-size:16px;">&nbsp; &nbsp; &nbsp; &nbsp;在上文中我们选择对应的开发工程,下面就将在AT32WB415_Firmware_Library_V2.0.2\project\at_start_wb415\templates\iar_v8.2进行咱们的软件开发。</span></p>

<p><strong><span style="font-size:16px;">目标</span></strong></p>

<p><span style="font-size:16px;">&nbsp; &nbsp; &nbsp; &nbsp;熟悉芯片时钟配置,并进行LED操作,本次将通过按键方式改变LED展示模式。</span></p>

<p><strong><span style="font-size:16px;">实现</span></strong></p>

<p><span style="font-size:16px;">&nbsp; &nbsp; &nbsp; &nbsp;芯片时钟的配置主要依托时钟树中各种时钟配置的选择,直观高效:</span></p>

<p><span style="font-size:16px;"></span></p>

<p><span style="font-size:16px;">&nbsp; &nbsp; &nbsp; &nbsp;本软件工程目前就是开发板自带的例程,关于时钟的配置,其实在头文件中 EXTERN SystemInit就是执行的的时钟配置,在system_at32wb415.c的SystemInit如下:</span></p>

<p><span style="font-size:16px;"></span></p>

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

<p>&nbsp;</p>

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

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面进行具体的配置:</span></p>

<p><span style="font-size:16px;">LED对应IO口初始化:</span></p>

<pre>
<code>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(&amp;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, &amp;gpio_init_struct);
}</code></pre>

<p>&nbsp;</p>

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;进行IO口操作宏定义:</span></p>

<pre>
<code>/************************************宏定义************************************/

#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);</code></pre>

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意:IO低电平时点亮</span></p>

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;对IO口赋初值:</span></p>

<pre>
<code>void LED_init(void)
{
LEDRed_on;
LEDYellow_on;
LEDGreen_on;
}</code></pre>

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面进行基本定时器配置:</span></p>

<pre>
<code>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);
}</code></pre>

<p><span style="font-size:16px;">基本定时器是用定时器10,注意分频的计算,Period对应定时ms;</span></p>

<p>&nbsp;</p>

<p><span style="font-size:16px;">进行外部中断配置:</span></p>

<pre>
<code>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(&amp;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(&amp;exint_init_struct);

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

}</code></pre>

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;按键的判断通过外部中断+定时器的方式进行,为此定义了一个结构体。</span></p>

<pre>
<code>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;
externkey key_Ok;</code></pre>

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在外部中断中只进行EXIT_flag的置位,最主要是通过定时器中进行防抖和按键识别;</span></p>

<pre>
<code>    if(key_Ok.EXIT_flag == 1)//防抖判断
    {
      key_Ok.EXIT_Data++;
      if(key_Ok.EXIT_Data == 2 &amp;&amp; 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 &gt; 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 &gt;= 100)
      {
          key_Ok.LongPress_flag = 1;
      }
      else if(key_Ok.Press_Data &lt; 100)
      {
          key_Ok.ShortPress_flag = 1;
      }
      key_Ok.Press_flag = 0;
      }
      else
      {
      if(key_Ok.Press_Data &gt;= 120)
      {
          key_Ok.LongPress_flag = 1;
          key_Ok.Press_flag = 0;
      }
      }
    }</code></pre>

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过原理图及数据手册判断出,PWM的输出对应的是TIM4的2、3、4通道,配置如下:</span></p>

<pre>
<code>if(key_Ok.EXIT_flag == 1)//防抖判断
    {
      key_Ok.EXIT_Data++;
      if(key_Ok.EXIT_Data == 2 &amp;&amp; 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 &gt; 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 &gt;= 100)
      {
          key_Ok.LongPress_flag = 1;
      }
      else if(key_Ok.Press_Data &lt; 100)
      {
          key_Ok.ShortPress_flag = 1;
      }
      key_Ok.Press_flag = 0;
      }
      else
      {
      if(key_Ok.Press_Data &gt;= 120)
      {
          key_Ok.LongPress_flag = 1;
          key_Ok.Press_flag = 0;
      }
      }
    }</code></pre>

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以下将呼吸灯的频率设置为2s,并定义了LED控制结构体:</span></p>

<pre>
<code>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;
}

}
</code></pre>

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LED操作的表现形式有很多种,这里就实现了3个比较有代表性的,大家也可以发散思维实现不同的唯美的体现。</span></p>

<p><span style="font-size:16px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;视频如下:</span></p>

<p></p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>

<p>&nbsp;</p>
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

常见泽1 发表于 2022-8-10 22:59

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

秦天qintian0303 发表于 2022-8-11 08:34

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

<p>这是必然啊,根是一样的,但是穿的衣裳不一样,所有的都会改一点</p>
页: [1]
查看完整版本: 【AT32WB415测评】02时钟配置+LED操作