定时器计数器功能
以AT32F403A雅特力芯片为基础:
定时时间:T = 1/f
频率 f :f = 系统频率/预分频/重装载值
#include "time.h"
void clkout_config(void)
{
gpio_init_type gpio_init_struct;
crm_clocks_freq_type crm_clocks_freq_struct = {0};
/* enable gpio port clock */
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
/* set default parameter */
gpio_default_para_init(&gpio_init_struct);
/* clkout gpio init */
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_MUX;
gpio_init_struct.gpio_pins = GPIO_PINS_8;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(GPIOA, &gpio_init_struct);
/* 获取系统时钟*/
crm_clocks_freq_get(&crm_clocks_freq_struct);
/* enable tmr1 clock */
crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
/* systemclock/24000/10 = 1000hz = 1/1000 s = 1ms ,freq = sysfrq/((div+1)*(pr+1))*/
//预分频就是 将此时的系统频率分频。分频后得到的频率就是 计一个数的频率对应的时间 = 频率的倒数
//那么周期就是计多少个数产生中断溢出 分频后计一个数的时间 * 周期 = 定时时间----》周期值可以这样算:分频后的频率倒数 (单位s) / 定时的时间 = 等于填入的周期值
tmr_base_init(TMR1, 24-1, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
//总线上240mhz , 1ms进入 (crm_clocks_freq_struct.ahb_freq / 10000) - 1)是分频
// 24是重装载值 。。。所以计算是系统时钟频率(240mhz/分频系数)/ 重装载值 = 定时器频率 //定时时间 = 频率倒数单位s
tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);
/* 溢出中断使能*/
tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);
/* 中断分组 */
nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 0, 0);
/* 开始计数 */
tmr_counter_enable(TMR1, TRUE);
}
int timer_count = 0;
uint16_t temp_pro_count_0_1s = 0;
uint16_t temp_down_count_0_1s = 0;
void TMR1_OVF_TMR10_IRQHandler(void)
{
if(tmr_flag_get(TMR1, TMR_OVF_FLAG) != RESET)
{
timer_count++;
temp_pro_count_0_1s++;
temp_down_count_0_1s++;
tmr_flag_clear(TMR1, TMR_OVF_FLAG);
}
}
配置一个pwm 频率2.5k 占空比50%
void pwm_tmr8_config(void)
{
gpio_init_type gpio_init_struct;
tmr_output_config_type tmr_oc_init_structure;
/* peripheral clocks configuration */
crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_TMR8_PERIPH_CLOCK, TRUE);
/* gpio configuration */
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_pins = GPIO_PINS_9;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(GPIOC, &gpio_init_struct);
/* 初始化 TMR8 的基本时间基数,设置自动重装载寄存器(ARR)和预分频器(PSC) */
tmr_base_init(TMR8, 1000-1, 96 - 1); //预分频为96,周期给个1000, 频率2.5k=240000000/(1000*96)
tmr_output_enable(TMR8, TRUE);
tmr_output_default_para_init(&tmr_oc_init_structure);
tmr_oc_init_structure.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A; // 设置为 PWM 模式 A
tmr_oc_init_structure.oc_idle_state = FALSE; // PWM 模式下,空闲状态输出低电平
tmr_oc_init_structure.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH; // 输出极性为高电平有效
tmr_oc_init_structure.oc_output_state = TRUE; // 输出状态使能
// 配置 TMR8 的第四个通道,设置捕获比较寄存器(CCR)的值和输出比较模式
tmr_output_channel_config(TMR8, TMR_SELECT_CHANNEL_4, &tmr_oc_init_structure);
tmr_channel_value_set(TMR8, TMR_SELECT_CHANNEL_4, 500);
/* tmr enable counter */// 启动 TMR8 计数器
tmr_counter_enable(TMR8, FALSE);
}
呼吸灯例程
#include "Breath.h"
#define LED_PIN GPIO_PINS_13
#define LED_GPIO_PORT GPIOD
uint16_t period = 1000; // 定时器周期
uint8_t pwm_duty = 0; // PWM占空比
uint8_t pwm_direction = 1; // 0表示减小,1表示增大
////// 定时器中断服务例程
void TMR3_GLOBAL_IRQHandler(void)
{
// 检查更新中断标志
if(tmr_flag_get(TMR3, TMR_OVF_FLAG) != RESET)
{
tmr_flag_clear(TMR3, TMR_OVF_FLAG); // 清除更新标志
pwm_duty += pwm_direction; // 调整占空比
printf("pwm_duty=%d\r\n",pwm_duty);
if(pwm_duty >=100) // 达到最大占空比
{
pwm_duty = 100;
pwm_direction = -1; // 改变方向
}
else if(pwm_duty <= 0) // 达到最小占空比
{
pwm_duty = 0;
pwm_direction = 1; // 改变方向
}
// 更新PWM占空比
tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_2, (uint16_t)(period * pwm_duty / 100.0f));
}
}
// 初始化呼吸灯 ///PD13是灯的,想pwm控制灯电平,需要找到对应的pwm通道 这个是 定时器4的通道2 在寄存器手册查找,同时不要忘记复用
void breathing_led_init(void)
{
gpio_init_type gpio_init_struct;
tmr_output_config_type tmr_oc_init_structure;
TMR3INIT();
// 启用GPIO和定时器时钟以及复用时钟
crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_TMR4_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
// 配置LED引脚为复用功能
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pins = LED_PIN;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init(LED_GPIO_PORT, &gpio_init_struct);
/* GPIO PIN remap */ //寄存器手册中PD13要复用才可以使用
gpio_pin_remap_config(TMR4_MUX, TRUE);
// 配置定时器TMR4
tmr_base_init(TMR4, 1000, 240); // 预分频为240,周期也就是重装在职1000。重装载计数值1000。频率240MHZ/(1000*240)
tmr_cnt_dir_set(TMR4, TMR_COUNT_UP); // 向上计数
tmr_clock_source_div_set(TMR4, TMR_CLOCK_DIV1);
tmr_period_buffer_enable(TMR4, TRUE);
//tmr_output_enable(TMR4, TRUE);//高级定时器有的
/* configure primary mode settings */
tmr_sub_sync_mode_set(TMR4, FALSE);
tmr_primary_mode_select(TMR4, TMR_PRIMARY_SEL_RESET);
// 配置PWM输出 channel 2 output settings
tmr_output_default_para_init(&tmr_oc_init_structure);
tmr_oc_init_structure.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A; // PWM模式A
tmr_oc_init_structure.oc_idle_state = FALSE;
tmr_oc_init_structure.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH; // 高电平有效
tmr_oc_init_structure.oc_output_state = TRUE; // 使能输出
tmr_output_channel_config(TMR4, TMR_SELECT_CHANNEL_2, &tmr_oc_init_structure);
tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_2, 50); //设置初始值比较值CCR,CCR<重装载值输出高电平,相反输出低电平
tmr_output_channel_buffer_enable(TMR4, TMR_SELECT_CHANNEL_2, TRUE);
// 启用PWM输出和定时器
tmr_counter_enable(TMR4, TRUE);
}
void TMR3INIT(void)
{
crm_periph_clock_enable(CRM_TMR3_PERIPH_CLOCK, TRUE);
//配置定时器TMR3
tmr_base_init(TMR3, 1000, 2400); // 10ms,周期为1000
tmr_cnt_dir_set(TMR3, TMR_COUNT_UP); // 向上计数
tmr_clock_source_div_set(TMR3, TMR_CLOCK_DIV1);
tmr_interrupt_enable(TMR3, TMR_OVF_INT, TRUE); // 启用更新中断
tmr_counter_enable(TMR3, TRUE);
}