02时钟配置+LED操作
前言
在上文中我们选择对应的开发工程,下面就将在AT32WB415_Firmware_Library_V2.0.2\project\at_start_wb415\templates\iar_v8.2进行咱们的软件开发。
目标
熟悉芯片时钟配置,并进行LED操作,本次将通过按键方式改变LED展示模式。
实现
芯片时钟的配置主要依托时钟树中各种时钟配置的选择,直观高效:
本软件工程目前就是开发板自带的例程,关于时钟的配置,其实在头文件中 EXTERN SystemInit就是执行的的时钟配置,在system_at32wb415.c的SystemInit如下:
是直接进行的寄存器初始赋值,这样其实是不适合我们直接修改操作的,不易理解还容易出错,所以在这之外雅特力在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个比较有代表性的,大家也可以发散思维实现不同的唯美的体现。
视频如下:
本帖最后由 秦天qintian0303 于 2022-8-10 20:59 编辑
引用: 常见泽1 发表于 2022-8-10 22:59 这个时钟寄存器的名字 感觉故意和ST区分 名字看起来有点奇怪
这是必然啊,根是一样的,但是穿的衣裳不一样,所有的都会改一点