本帖最后由 zexin 于 2024-9-2 10:51 编辑
#申请原创# AT32F403A通用定时器02 一、输入部分
通道1输入部分 1.输入捕获 当触发信号被检测到时,通道x的数据寄存器(TMRx_CxDT)会记录当前计数器的计数值,并将捕获中断标志(CxIF)置1。如果有使能中断或者DMA请求,则还会进入到相应的中断或DMA。
注:如果在发生捕获后又立即检测到触发信号,此时计数器的计数值会覆盖之前的计数值,同时通道再捕获标志(CxRF)置1。 2.多输入异或
多输入异或 通道1的输入端可以通过TMRx_CH1、TMRx_CH2和TMRx_CH3经过异或逻辑后输入,可用于连接霍尔传感器,进而计算出电机的转速。 3.PWM输入
PWM输入 使用PWM输入模式时需要将C1IN和C2IN同时映射到同一个TMRx_CHx,同时通道1(或通道2)配置成次定时器的复位模式。 PWM输入时序图 如图,通道1(CH1)输入信号的上升沿会触发捕获,并将捕获值(0xA)储存到通道1的数据寄存器(C1DT),同时复位定时器,使之从0开始计数;
接着,通道1(CH1)输入信号的下降沿会触发捕获,并将捕获值(0x4)储存到通道2的数据寄存器(C2DT);
则输入信号的周期:T = C1DT ÷ TMR_CLK;
输入信号的占空比:D = C2DT ÷ C1DT。 二、案例 1.多输入异或
(1)功能
对三路霍尔输入信号进行异或输出。
(2)配置
介绍
使用PA3、PA6、PA7产生三路霍尔信号,将其输入到PA0、PA1、PA2进行异或,PA8根据异或结果输出方波。
步骤
①启用定时器(以TMR2为例),选择“异或/HALL模式”;
②选择触发极性(以上升沿为例); ③开启中断; ④设置PA3、PA6、PA7、PA8为输出模式; ⑤生成代码。 (3)代码
main.c
#include "at32f403a_407_wk_config.h"
#include "wk_system.h"
int main(void)
{
wk_system_clock_config();
wk_periph_clock_config();
wk_nvic_config();
wk_timebase_init();
wk_tmr2_init();
wk_gpio_config();
tmr_counter_enable(TRM2, TRUE);
while(1)
{
/* 产生三路霍尔信号 */
gpio_bits_set(GPIOA, GPIO_PINS_3);
delay_us(10)
gpio_bits_set(GPIOA, GPIO_PINS_6);
delay_us(10)
gpio_bits_set(GPIOA, GPIO_PINS_7);
delay_us(10)
gpio_bits_reset(GPIOA, GPIO_PINS_3);
delay_us(10)
gpio_bits_reset(GPIOA, GPIO_PINS_6);
delay_us(10)
gpio_bits_reset(GPIOA, GPIO_PINS_7);
delay_us(10)
}
}
at32f403a_407_wk_config.c
#include "at32f403a_407_wk_config.h"
void wk_system_clock_config(void)
{
crm_reset();
crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);
while(crm_flag_get(CRM_LICK_STABLE_FLAG) != SET)
{
}
crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE);
while(crm_flag_get(CRM_HICK_STABLE_FLAG) != SET)
{
}
crm_pll_config(CRM_PLL_SOURCE_HICK, CRM_PLL_MULT_60, CRM_PLL_OUTPUT_RANGE_GT72MHZ);
crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);
while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
{
}
crm_ahb_div_set(CRM_AHB_DIV_1);
crm_apb2_div_set(CRM_APB2_DIV_2);
crm_apb1_div_set(CRM_APB1_DIV_2);
crm_auto_step_mode_enable(TRUE);
crm_sysclk_switch(CRM_SCLK_PLL);
while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
{
}
crm_auto_step_mode_enable(FALSE);
system_core_clock_update();
}
void wk_periph_clock_config(void)
{
crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE);
}
void wk_nvic_config(void)
{
nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
nvic_irq_enable(TMR2_GLOBAL_IRQn, 0, 0);
}
void wk_gpio_config(void)
{
gpio_init_type gpio_init_struct;
gpio_default_para_init(&gpio_init_struct);
gpio_bits_set(GPIOA, GPIO_PINS_3 | GPIO_PINS_6 | GPIO_PINS_7 | GPIO_PINS_8);
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_3 | GPIO_PINS_6 | GPIO_PINS_7 | GPIO_PINS_8;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(GPIOA, &gpio_init_struct);
}
void wk_tmr2_init(void)
{
gpio_init_type gpio_init_struct;
tmr_input_config_type tmr_input_struct;
tmr_output_config_type tmr_output_struct;
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_pins = GPIO_PINS_0;
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(GPIOA, &gpio_init_struct);
gpio_init_struct.gpio_pins = GPIO_PINS_1;
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(GPIOA, &gpio_init_struct);
gpio_init_struct.gpio_pins = GPIO_PINS_2;
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(GPIOA, &gpio_init_struct);
tmr_base_init(TMR2, 65535, 0);
tmr_cnt_dir_set(TMR2, TMR_COUNT_UP);
tmr_clock_source_div_set(TMR2, TMR_CLOCK_DIV1);
tmr_period_buffer_enable(TMR2, FALSE);
tmr_sub_sync_mode_set(TMR2, FALSE);
tmr_primary_mode_select(TMR2, TMR_PRIMARY_SEL_RESET);
tmr_input_struct.input_channel_select = TMR_SELECT_CHANNEL_1;
tmr_input_struct.input_mapped_select = TMR_CC_CHANNEL_MAPPED_STI;
tmr_input_struct.input_polarity_select = TMR_INPUT_RISING_EDGE;
tmr_input_struct.input_filter_value = 0;
tmr_input_channel_init(TMR2, &tmr_input_struct, TMR_CHANNEL_INPUT_DIV_1);
tmr_channel1_input_select(TMR2, TMR_CHANEL1_2_3_CONNECTED_C1IRAW_XOR);
tmr_trigger_input_select(TMR2, TMR_SUB_INPUT_SEL_C1INC);
tmr_sub_mode_select(TMR2, TMR_SUB_RESET_MODE);
tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_B;
tmr_output_struct.oc_output_state = TRUE;
tmr_output_struct.occ_output_state = FALSE;
tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
tmr_output_struct.oc_idle_state = FALSE;
tmr_output_struct.occ_idle_state = FALSE;
tmr_output_channel_config(TMR2, TMR_SELECT_CHANNEL_2, &tmr_output_struct);
tmr_output_channel_immediately_set(TMR2, TMR_SELECT_CHANNEL_4, FALSE);
tmr_channel_value_set(TMR2, TMR_SELECT_CHANNEL_2, 0);
tmr_output_channel_buffer_enable(TMR2, TMR_SELECT_CHANNEL_2, FALSE);
tmr_primary_mode_select(TMR2, TMR_PRIMARY_SEL_RESET);
//tmr_counter_enable(TMR2, TRUE);
/* 使能定时器中断 */
tmr_interrupt_enable(TMR2, TMR_TRIGGER_INT, TRUE);
}
at32f403a_407_int.c
#include "at32f403a_407_int.h"
#include "wk_system.h"
void SysTick_Handler(void)
{
wk_timebase_handler();
}
void TMR2_GLOBAL_IRQHandler(void)
{
if(tmr_interrupt_flag_get(TMR2, TMR_TRIGGER_FLAG) != RESET)
{
tmr_flag_clear(TMR2, TMR_TRIGGER_FLAG);
GPIOA->odt ^= GPIO_PINS_8; //PA8根据异或结果翻转电平
}
}
(4)现象
连接PA0和PA3、PA1和P6、PA2和PA7,逻辑分析仪测量PA0(霍尔1)、PA1(霍尔2)、PA2(霍尔3)和PA8(异或结果)的波形。
当霍尔信号 = “001”时,异或结果为“1”;
当霍尔信号 = “011”时,异或结果为“0”;
当霍尔信号 = “111”时,异或结果为“1”;
……
即只有当霍尔信号中“1”的个数为奇数时,异或结果才为“1”,其余情况都为“0”。 2.PWM输入
(1)功能
使用32位计数器测量输入PWM的频率和占空比。(以测量频率20Hz以上的信号为例)
(2)配置
介绍
PA6产生PWM方波(有条件的可以使用信号发生器),输入到PA0进行测量,在Debug模式下查看所测频率与占空比与逻辑分析所测结果是否一致。
步骤
①TMR2选择“通道1PWM输入”模式,开启“增强模式”(32bit);
② 可通过所测信号的频率范围来设置周期值(以最小20Hz为例),配置通道1极性为上升沿,并且次定时器模式为复位模式,配置通道2极性为下降沿; ③开启中断; ④配置PA6为输出模式用于产生PWM; ⑤ 生成代码。 (3)代码
main.c
#include "at32f403a_407_wk_config.h"
#include "wk_system.h"
uint16_t duty_cycle = 0; //占空比
uint32_t frequency = 0; //频率
int main(void)
{
wk_system_clock_config();
wk_periph_clock_config();
wk_nvic_config();
wk_timebase_init();
wk_tmr2_init();
wk_gpio_config();
while(1)
{
/* 产生PWM波 */
gpio_bits_set(GPIOA, GPIO_PINS_6);
delay_us(30);
gpio_bits_reset(GPIOA, GPIO_PINS_6);
delay_us(10);
}
}
at32f403a_407_wk_config.c
#include "at32f403a_407_wk_config.h"
void wk_system_clock_config(void)
{
crm_reset();
crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);
while(crm_flag_get(CRM_LICK_STABLE_FLAG) != SET)
{
}
crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE);
while(crm_flag_get(CRM_HICK_STABLE_FLAG) != SET)
{
}
crm_pll_config(CRM_PLL_SOURCE_HICK, CRM_PLL_MULT_60, CRM_PLL_OUTPUT_RANGE_GT72MHZ);
crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);
while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
{
}
crm_ahb_div_set(CRM_AHB_DIV_1);
crm_apb2_div_set(CRM_APB2_DIV_2);
crm_apb1_div_set(CRM_APB1_DIV_2);
crm_auto_step_mode_enable(TRUE);
crm_sysclk_switch(CRM_SCLK_PLL);
while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
{
}
crm_auto_step_mode_enable(FALSE);
system_core_clock_update();
}
void wk_periph_clock_config(void)
{
crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE);
}
void wk_nvic_config(void)
{
nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
nvic_irq_enable(TMR2_GLOBAL_IRQn, 0, 0);
}
void wk_gpio_config(void)
{
gpio_init_type gpio_init_struct;
gpio_default_para_init(&gpio_init_struct);
gpio_bits_set(GPIOA, GPIO_PINS_6);
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_6;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(GPIOA, &gpio_init_struct);
}
void wk_tmr2_init(void)
{
gpio_init_type gpio_init_struct;
tmr_input_config_type tmr_ic_init_struct;
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_pins = GPIO_PINS_0;
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(GPIOA, &gpio_init_struct);
/* 使能32位计数器 */
tmr_32_bit_function_enable(TMR2, TRUE);
tmr_base_init(TMR2, 11999999, 0);
tmr_cnt_dir_set(TMR2, TMR_COUNT_UP);
tmr_clock_source_div_set(TMR2, TMR_CLOCK_DIV1);
tmr_period_buffer_enable(TMR2, FALSE);
tmr_sub_sync_mode_set(TMR2, FALSE);
tmr_primary_mode_select(TMR2, TMR_PRIMARY_SEL_RESET);
tmr_ic_init_struct.input_filter_value = 0;
tmr_ic_init_struct.input_channel_select = TMR_SELECT_CHANNEL_1;
tmr_ic_init_struct.input_mapped_select = TMR_CC_CHANNEL_MAPPED_DIRECT;
tmr_ic_init_struct.input_polarity_select = TMR_INPUT_RISING_EDGE;
tmr_pwm_input_config(TMR2, &tmr_ic_init_struct, TMR_CHANNEL_INPUT_DIV_1);
tmr_trigger_input_select(TMR2, TMR_SUB_INPUT_SEL_C1DF1);
tmr_sub_mode_select(TMR2, TMR_SUB_RESET_MODE);
tmr_counter_enable(TMR2, TRUE);
/* 开启中断 */
tmr_counter_enable(TRM2, TMR_C1_INT, TRUE)
}
at32f403a_407_int.c
#include "at32f403a_407_int.h"
#include "wk_system.h"
extern uint16_t duty_cycle;
extern uint32_t frequency;
uint32_t ic1value = 0;
void SysTick_Handler(void)
{
wk_timebase_handler();
}
void TMR2_GLOBAL_IRQHandler(void)
{
if(tmr_interrupt_flag_get(TMR2, TMR_C1_FLAG) != RESET)
{
tmr_flag_clear(TMR2, TMR_C1_FLAG);
ic1value = tmr_channel_value_get(TMR2, TMR_SELECT_CHANNEL_1);//获取上升沿时的计数值
if(ic1value != 0)
{
/* 计算占空比(上升沿时的计数值/下降沿时的计数值) */
duty_cycle = (tmr_channel_value_get(TMR2, TMR_SELECT_CHANNEL_2) * 100) / ic1value;
/* 计算频率(定时器时钟/上升沿时的计数值) */
frequency = system_cor_clock / ic1value;
}
else
{
duty_cycle = 0;
frequency = 0;
}
}
}
(4)现象
先用逻辑分析仪测量PA6所产生的PWM的频率和占空比;
再连接PA6与PA0,进入Debug(调试模式),对比Watch 1中变量duty_cycle和frequency的值与逻辑分析仪的结果基本一致。
由于作者水平有限,文中如有错误之处,恳请读者批评指正。
参考资料:
《RM_AT32F403A_407_CH_V2.06》的14.2通用定时器(TMR2到TMR5)https://www.arterytek.com/file/download/1995 |
感谢大佬分享!二姨家的原创奖励文章需首发于21ic论坛哦~由于您在其他平台发布早于21ic,由此本篇文章不审核原创~希望大佬下次可以先发布在21ic~ ps:大佬的文章排版用心啦!