[AT32F403/403A] AT32学习记录——通用定时器(三)

[复制链接]
2893|1
 楼主| zexin 发表于 2024-9-2 09:54 | 显示全部楼层 |阅读模式
本帖最后由 zexin 于 2024-9-2 10:54 编辑

AT32F403A通用定时器03
一、输出部分
3107166d46e7484f13.png
比较通道的输出部分
TMR的输出部分由比较器输出控制构成, 输出可编程周期占空比极性的信号。
1.PWM模式A
4809166d46eea594b5.png
PWM_ModeA(向上计数)
PWM模式A向上计数时:
如果CVAL(计数值)<CxDT(比较值),CxROW(输出信号)为有效电平
如果CVAL(计数值) ≥ CxDT(比较值),CxROW(输出信号)为无效电平
9557766d46f6fd58a5.png
PWM_ModeA(向下计数)
PWM模式A向下计数时:
如果CVAL(计数值)>CxDT(比较值),CxROW(输出信号)为无效电平
如果CVAL(计数值) ≤ CxDT(比较值),CxROW(输出信号)为有效电平
2.PWM模式B
6405966d46fd94ed0c.png
PWM_ModeB(向上计数)
PWM模式B向上计数时:
如果CVAL(计数值)<CxDT(比较值),CxROW(输出信号)为无效电平
如果CVAL(计数值) ≥ CxDT(比较值),CxROW(输出信号)为有效电平
2652166d4703cd7f79.png
PWM_ModeB(向下计数)
PWM模式B向下计数时:
如果CVAL(计数值)>CxDT(比较值),CxROW(输出信号)为有效电平
如果CVAL(计数值) ≤ CxDT(比较值),CxROW(输出信号)为无效电平
3.强制输出模式
此时,CxROW(输出信号)的电平被强制输出为所配置的电平,与计数值无关。
注:输出信号不依赖与比较结果,但通道标志位和DMA请求仍依赖于比较结果。
4.输出比较模式
当CVAL(计数值)与CxDT(比较值)匹配时,CxROW(输出信号)可强制输出有效电平、无效电平或进行电平翻转。
4671366d514fd6e43d.png
输出比较模式(电平翻转)
以“电平翻转”为例,当CVAL(计数值) = CxDT(比较值)时,CxROW(输出信号)进行一次翻转
注:此时,当CVAL(计数值)达到TMR_PR(周期值)时,CxROW(输出信号)的电平保持不变
5.单周期模式
8909766d51580dc78c.png
单周期模式
仅在当前周期内进行比较,完成当前计数后,TMREN清零,因此仅输出一个脉冲
6.快速输出模式
CxROW(输出信号)的电平在计数周期开始时发生变化,CVAL(计数值)与CxDT(比较值)的结果将提前决定CxROW(输出信号)的电平状态。
二、案例
1.TMR联合DMA
(1)功能
产生一个100kHz的PWM波,占空比按照{10%,10%,20%,20%,30%,30%,40%,40%,50%,50%,60%,60%,70%,70%,80%,80%,90%,90%}变化。
(2)配置
介绍

使用TMR1的通道1产生PWM,利用DMA向C1DT传输不同的比较值
步骤

①启用TMR1,选择通道1输出;
2910466d516eed8ad8.png
②根据频率(100kHz)设置周期值为2399,并根据第一个占空比(10%)设置比较值为240;
7318966d5175762305.png
③使能DMA请求,方向为内存到外设
④生成代码。
(3)代码
main.c
  1. #include "at32f403a_407_wk_config.h"
  2. #include "wk_system.h"

  3. /* 定义不同占空比对应的比较值 */
  4. uint16_t src_buffer[18] = {240, 240, 480, 480, 720, 720, 960, 960, 1200, 1200, 1440, 1440, 1680, 1680, 1920, 1920, 2160, 2160};

  5. int main(void)
  6. {
  7.   wk_system_clock_config();
  8.   wk_periph_clock_config();
  9.   wk_nvic_config();
  10.   wk_timebase_init();
  11.   wk_dma1_channel5_init();
  12.   wk_dma_channel_config(DMA1_CHANNEL5,
  13.                         (uint32_t)&TMR1->c1dt, //外设地址
  14.                         DMA1_CHANNEL5_MEMORY_BASE_ADDR,
  15.                         DMA1_CHANNEL5_BUFFER_SIZE);
  16.   dma_channel_enable(DMA1_CHANNEL5, TRUE);
  17.   wk_tmr1_init();

  18.   while(1)
  19.   {

  20.   }
  21. }
at32f403a_407_wk_config.c
  1. #include "at32f403a_407_wk_config.h"

  2. void wk_system_clock_config(void)
  3. {
  4.   crm_reset();
  5.   crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);
  6.   while(crm_flag_get(CRM_LICK_STABLE_FLAG) != SET)
  7.   {
  8.   }
  9.   crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE);
  10.   while(crm_flag_get(CRM_HICK_STABLE_FLAG) != SET)
  11.   {
  12.   }
  13.   crm_pll_config(CRM_PLL_SOURCE_HICK, CRM_PLL_MULT_60, CRM_PLL_OUTPUT_RANGE_GT72MHZ);
  14.   crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);
  15.   while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
  16.   {
  17.   }
  18.   crm_ahb_div_set(CRM_AHB_DIV_1);
  19.   crm_apb2_div_set(CRM_APB2_DIV_2);
  20.   crm_apb1_div_set(CRM_APB1_DIV_2);
  21.   crm_auto_step_mode_enable(TRUE);
  22.   crm_sysclk_switch(CRM_SCLK_PLL);
  23.   while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
  24.   {
  25.   }
  26.   crm_auto_step_mode_enable(FALSE);
  27.   system_core_clock_update();
  28. }

  29. void wk_periph_clock_config(void)
  30. {
  31.   crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
  32.   crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
  33.   crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  34.   crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
  35.   crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
  36. }

  37. void wk_nvic_config(void)
  38. {
  39.   nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  40.   NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
  41. }

  42. void wk_tmr1_init(void)
  43. {
  44.   gpio_init_type gpio_init_struct;
  45.   tmr_output_config_type tmr_output_struct;
  46.   tmr_brkdt_config_type tmr_brkdt_struct;

  47.   gpio_default_para_init(&gpio_init_struct);

  48.   gpio_init_struct.gpio_pins = GPIO_PINS_8;
  49.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  50.   gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  51.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  52.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  53.   gpio_init(GPIOA, &gpio_init_struct);

  54.   tmr_base_init(TMR1, 2399, 0);
  55.   tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);
  56.   tmr_clock_source_div_set(TMR1, TMR_CLOCK_DIV1);
  57.   tmr_repetition_counter_set(TMR1, 0);
  58.   tmr_period_buffer_enable(TMR1, FALSE);

  59.   tmr_sub_sync_mode_set(TMR1, FALSE);
  60.   tmr_primary_mode_select(TMR1, TMR_PRIMARY_SEL_RESET);

  61.   tmr_overflow_request_source_set(TMR1, TRUE);

  62.   tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
  63.   tmr_output_struct.oc_output_state = TRUE;
  64.   tmr_output_struct.occ_output_state = FALSE;
  65.   tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  66.   tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  67.   tmr_output_struct.oc_idle_state = FALSE;
  68.   tmr_output_struct.occ_idle_state = FALSE;
  69.   tmr_output_channel_config(TMR1, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
  70.   tmr_channel_value_set(TMR1, TMR_SELECT_CHANNEL_1, 240);
  71.   tmr_output_channel_buffer_enable(TMR1, TMR_SELECT_CHANNEL_1, FALSE);

  72.   tmr_output_channel_immediately_set(TMR1, TMR_SELECT_CHANNEL_1, FALSE);

  73.   tmr_brkdt_struct.brk_enable = FALSE;
  74.   tmr_brkdt_struct.auto_output_enable = FALSE;
  75.   tmr_brkdt_struct.brk_polarity = TMR_BRK_INPUT_ACTIVE_LOW;
  76.   tmr_brkdt_struct.fcsoen_state = FALSE;
  77.   tmr_brkdt_struct.fcsodis_state = FALSE;
  78.   tmr_brkdt_struct.wp_level = TMR_WP_OFF;
  79.   tmr_brkdt_struct.deadtime = 0;
  80.   tmr_brkdt_config(TMR1, &tmr_brkdt_struct);

  81.   tmr_dma_request_enable(TMR1, TMR_OVERFLOW_DMA_REQUEST, TRUE);
  82.   tmr_output_enable(TMR1, TRUE);

  83.   tmr_counter_enable(TMR1, TRUE);
  84. }

  85. void wk_dma1_channel5_init(void)
  86. {
  87.   dma_init_type dma_init_struct;

  88.   dma_reset(DMA1_CHANNEL5);
  89.   dma_default_para_init(&dma_init_struct);
  90.   dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
  91.   dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
  92.   dma_init_struct.memory_inc_enable = TRUE;
  93.   dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
  94.   dma_init_struct.peripheral_inc_enable = FALSE;
  95.   dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
  96.   dma_init_struct.loop_mode_enable = TRUE;
  97.   dma_init(DMA1_CHANNEL5, &dma_init_struct);

  98.   dma_flexible_config(DMA1, FLEX_CHANNEL5, DMA_FLEXIBLE_TMR1_OVERFLOW);
  99.   
  100. }

  101. void wk_dma_channel_config(dma_channel_type* dmax_channely, uint32_t peripheral_base_addr, uint32_t memory_base_addr, uint16_t buffer_size)
  102. {

  103.   dmax_channely->dtcnt = buffer_size;
  104.   dmax_channely->paddr = peripheral_base_addr;
  105.   dmax_channely->maddr = memory_base_addr;
  106. }
at32f403a_407_wk_config.h
  1. #ifndef __AT32F403A_407_WK_CONFIG_H
  2. #define __AT32F403A_407_WK_CONFIG_H

  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. #include "at32f403a_407.h"

  7. #define DMA1_CHANNEL5_BUFFER_SIZE   18
  8. #define DMA1_CHANNEL5_MEMORY_BASE_ADDR   (uint32_t)src_buffer  //内存地址

  9. void wk_system_clock_config(void);
  10. void wk_periph_clock_config(void);
  11. void wk_nvic_config(void);
  12. void wk_tmr1_init(void);
  13. void wk_dma1_channel5_init(void);
  14. void wk_dma_channel_config(dma_channel_type* dmax_channely, uint32_t peripheral_base_addr, uint32_t memory_base_addr, uint16_t buffer_size);

  15. #ifdef __cplusplus
  16. }
  17. #endif

  18. #endif
(4)现象
6052266d5187909879.png
使用逻辑分析仪测量输出波形为100kHz的PWM,占空比从10%到90%变化。
2.正交输出
(1)功能
输出相位差为90°的PWM波。
(2)配置
介绍

利用输出比较模式的电平翻转功能使TMR3的通道1通道2输出相互正交的PWM波:
PA6---PWM 500kHz 50%;
PA7---PWM 500kHz 50%。
步骤
①启用TMR3,选择“通道1输出”和“通道2输出”;

6981766d5191938d52.png
②根据所需频率占空比设置周期值和通道数据,输出模式选择“切换CxROW”;
4609466d519bd19096.png
③PA6和PA7选择复用功能模式;
8905866d519fbddee5.png
④生成代码。
(3)代码
main.c
  1. #include "at32f403a_407_wk_config.h"

  2. int main(void)
  3. {
  4.   wk_system_clock_config();
  5.   wk_periph_clock_config();
  6.   wk_nvic_config();
  7.   wk_timebase_init();
  8.   wk_tmr3_init();

  9.   while(1)
  10.   {
  11.    
  12.   }
  13. }
at32f403a_407_wk_config.c
  1. #include "at32f403a_407_wk_config.h"

  2. void wk_system_clock_config(void)
  3. {
  4.   crm_reset();
  5.   crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);
  6.   while(crm_flag_get(CRM_LICK_STABLE_FLAG) != SET)
  7.   {
  8.   }
  9.   crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE);
  10.   while(crm_flag_get(CRM_HICK_STABLE_FLAG) != SET)
  11.   {
  12.   }
  13.   crm_pll_config(CRM_PLL_SOURCE_HICK, CRM_PLL_MULT_60, CRM_PLL_OUTPUT_RANGE_GT72MHZ);
  14.   crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);
  15.   while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
  16.   {
  17.   }
  18.   crm_ahb_div_set(CRM_AHB_DIV_1);
  19.   crm_apb2_div_set(CRM_APB2_DIV_2);
  20.   crm_apb1_div_set(CRM_APB1_DIV_2);
  21.   crm_auto_step_mode_enable(TRUE);
  22.   crm_sysclk_switch(CRM_SCLK_PLL);
  23.   while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
  24.   {
  25.   }
  26.   crm_auto_step_mode_enable(FALSE);
  27.   system_core_clock_update();
  28. }

  29. void wk_periph_clock_config(void)
  30. {
  31.   crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
  32.   crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  33.   crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
  34.   crm_periph_clock_enable(CRM_TMR3_PERIPH_CLOCK, TRUE);
  35. }

  36. void wk_nvic_config(void)
  37. {
  38.   nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  39.   NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
  40. }

  41. void wk_tmr3_init(void)
  42. {
  43.   gpio_init_type gpio_init_struct;
  44.   tmr_output_config_type tmr_output_struct;

  45.   gpio_default_para_init(&gpio_init_struct);
  46.   gpio_init_struct.gpio_pins = GPIO_PINS_6;
  47.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  48.   gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  49.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  50.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  51.   gpio_init(GPIOA, &gpio_init_struct);

  52.   gpio_init_struct.gpio_pins = GPIO_PINS_7;
  53.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  54.   gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  55.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  56.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  57.   gpio_init(GPIOA, &gpio_init_struct);

  58.   tmr_base_init(TMR3, 9, 23);
  59.   tmr_cnt_dir_set(TMR3, TMR_COUNT_UP);
  60.   tmr_clock_source_div_set(TMR3, TMR_CLOCK_DIV1);
  61.   tmr_period_buffer_enable(TMR3, FALSE);

  62.   tmr_sub_sync_mode_set(TMR3, FALSE);
  63.   tmr_primary_mode_select(TMR3, TMR_PRIMARY_SEL_RESET);
  64.   tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_SWITCH;
  65.   tmr_output_struct.oc_output_state = TRUE;
  66.   tmr_output_struct.occ_output_state = FALSE;
  67.   tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  68.   tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  69.   tmr_output_struct.oc_idle_state = FALSE;
  70.   tmr_output_struct.occ_idle_state = FALSE;
  71.   tmr_output_channel_config(TMR3, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
  72.   tmr_channel_value_set(TMR3, TMR_SELECT_CHANNEL_1, 0);
  73.   tmr_output_channel_buffer_enable(TMR3, TMR_SELECT_CHANNEL_1, FALSE);

  74.   tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_SWITCH;
  75.   tmr_output_struct.oc_output_state = TRUE;
  76.   tmr_output_struct.occ_output_state = FALSE;
  77.   tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  78.   tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
  79.   tmr_output_struct.oc_idle_state = FALSE;
  80.   tmr_output_struct.occ_idle_state = FALSE;
  81.   tmr_output_channel_config(TMR3, TMR_SELECT_CHANNEL_2, &tmr_output_struct);
  82.   tmr_channel_value_set(TMR3, TMR_SELECT_CHANNEL_2, 5);
  83.   tmr_output_channel_buffer_enable(TMR3, TMR_SELECT_CHANNEL_2, FALSE);

  84.   tmr_counter_enable(TMR3, TRUE);
  85. }
(4)现象
2443366d51a6824350.png
逻辑分析仪测量PA6和PA7,产生相位差为90°的正交PWM。
由于作者水平有限,文中如有错误之处,恳请读者批评指正。
参考资料:
《RM_AT32F403A_407_CH_V2.06》的14.2通用定时器(TMR2到TMR5)https://www.arterytek.com/file/download/1995

1625066d517c9bb89d.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

17

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部