【AT-START-F425 Review】 5. Brief analysis of timer interrupt code and implementation of breathing light
[Copy link]
The Atria AT32 provides a relatively complete demo routine, among which the tmr routine is very rich. There is a 7_pwm_output routine, which outputs PWM on the 7 pins. There is an English description in the Readme file
- tmr1_ch1 ---> pa8
- tmr1_ch1c ---> pb13
- tmr1_ch2 ---> pa9
- tmr1_ch2c ---> pb14
- tmr1_ch3 ---> pa10
- tmr1_ch3c ---> pb15
- tmr1_ch4 ---> pa11
Check the manual to see the multiplexing of each timer pin.
As you can see, multiplexing uses MUX2.
The specific code part is
int main(void)
{
uint8_t dir = 0;
system_clock_config();
at32_board_init();
/* get system clock */
crm_clocks_freq_get(&crm_clocks_freq_struct);
/* turn led2/led3/led4 on */
at32_led_on(LED2);
at32_led_on(LED3);
at32_led_on(LED4);
/* enable tmr1/gpioa/gpiob clock */
crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
// crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
/* timer1 output pin Configuration */
gpio_init_struct.gpio_pins = GPIO_PINS_8 | GPIO_PINS_9 | GPIO_PINS_10 |GPIO_PINS_11;
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
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_13 | GPIO_PINS_14 | GPIO_PINS_15;
// gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
// 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(GPIOB, &gpio_init_struct);
gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE8, GPIO_MUX_2);
gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE9, GPIO_MUX_2);
gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE10, GPIO_MUX_2);
gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE11, GPIO_MUX_2);
// gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE13, GPIO_MUX_2);
// gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE14, GPIO_MUX_2);
// gpio_pin_mux_config(GPIOB, GPIO_PINS_SOURCE15, GPIO_MUX_2);
/* tmr1 configuration generate 7 pwm signals with 4 different duty cycles:
prescaler = 0, tmr1 counter clock = system_core_clock
the objective is to generate 7 pwm signal at 17.57 khz:
- tim1_period = (system_core_clock / 17570) - 1
the channel 1 and channel 1c duty cycle is set to 50%
the channel 2 and channel 2c duty cycle is set to 37.5%
the channel 3 and channel 3c duty cycle is set to 25%
the channel 4 duty cycle is set to 12.5%
the timer pulse is calculated as follows:
- channelxpulse = duty_cycle * (tim1_period - 1) / 100 */
//类似stm32的ARR,自动重新装载寄存器
/* compute the value to be set in arr regiter to generate signal frequency at 17.57 khz */
//timer_period = (crm_clocks_freq_struct.sclk_freq / 17570 ) - 1;
//一下分别根据周期计算占空比
/* compute c1dt value to generate a duty cycle at 50% for channel 1 and 1c */
// channel1_pulse = (uint16_t)(((uint32_t) 5 * (timer_period - 1)) / 10);
/* compute c2dt value to generate a duty cycle at 37.5% for channel 2 and 2c */
//channel2_pulse = (uint16_t)(((uint32_t) 375 * (timer_period - 1)) / 1000);
/* compute c3dt value to generate a duty cycle at 25% for channel 3 and 3c */
//channel3_pulse = (uint16_t)(((uint32_t) 2 * (timer_period - 1)) / 100);
/* compute c4dt value to generate a duty cycle at 12.5% for channel 4 */
//channel4_pulse = (uint16_t)(((uint32_t) 125 * (timer_period- 1)) / 1000);
//原代码直接用系统主频进行计数,不分频
//tmr_base_init(TMR1, timer_period, 0);
//更改为分频96,及定时器主频为 96Mhz / (95 +1) = 1Mhz
//更改Arr 为 500, 实际计数为501个
tmr_base_init(TMR1, 500, 95);
tmr_cnt_dir_set(TMR1, TMR_COUNT_UP); //向上计数方式
tmr_clock_source_div_set(TMR1, TMR_CLOCK_DIV1); //采用预分频的频率
/* channel 1, 2, 3 and 4 configuration in output mode */
tmr_output_default_para_init(&tmr_output_struct);
tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_B;
tmr_output_struct.oc_output_state = TRUE;
tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_LOW;
tmr_output_struct.oc_idle_state = TRUE;
tmr_output_struct.occ_output_state = TRUE;
tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
tmr_output_struct.occ_idle_state = FALSE;
// channel 1 通道1配置,以及设置占空比
tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_1, channel1_pulse);
// channel 2 通道2配置,以及设置占空比
tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_2, &tmr_output_struct);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_2, channel2_pulse);
// channel 3 通道3配置,以及设置占空比
tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_3, &tmr_output_struct);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_3, channel3_pulse);
// channel 4 通道4配置,以及设置占空比
tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_4, &tmr_output_struct);
tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_4, channel4_pulse);
/* output enable */
tmr_output_enable(TMR1, TRUE);
/* enable tmr1 */
tmr_counter_enable(TMR1, TRUE);
channel3_pulse = 100;
while(1)
{
//设置呼吸方式,最大值时递减,最小值时递增
if(dir)channel3_pulse++;
else channel3_pulse--;
if(channel3_pulse>=500)dir=0;
if(channel3_pulse==0)dir=1;
//赋值占空比
TMR1->c3dt = channel3_pulse;
delay_ms(2);
}
}
It is implemented using the advanced timer TMR1.
During the evaluation, it was found that PA11 had no duty cycle signal. Through the multimeter test, it was found that the pin header (PA11) and the MCU pin were disconnected. I don’t know what the reason is. I have protected the development board quite well during use. It can be inferred that the pins were not fully tested at the factory. This is also a reminder to the manufacturer.
|