4338 views|1 replies

58

Posts

0

Resources
The OP
 

[Atria Development Board AT32F421 Review] Timer PWM Output [Copy link]

 This post was last edited by eew_Violet on 2021-4-28 00:34

Some places need to output PWM with a certain phase difference. For chips without asynchronous PWM, the PWM1 and PWM2 modes of the timer can be used to achieve this, like this.

The maximum duty cycle is generally not more than 48%, otherwise the tube will explode. I have already ruined two D209L . Next, let's see how to implement it. The TIM initialization code is still placed in at32_board.c.

/*TIM1初始化*/
void TIM_Init()
{
	TMR_TimerBaseInitType           TIM_TimerBaseStructure;
    TMR_OCInitType  				TMR_OCInitStructure;
    GPIO_InitType 					GPIO_InitStructure;
	
	/* 启用 TIM clock 和 GPIO 时钟  */
  RCC_APB2PeriphClockCmd(AT32_TIM_FUNC , ENABLE);
  RCC_AHBPeriphClockCmd(AT32_TIM_GPIO_RCC , ENABLE);
	

  /* Configure tim_pins: CH1   CH4
	 *	CH1-->PA8
	 *	CH4-->PA11
	 */
  //GPIO初始化
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pins = AT32_TIM_CH1_PIN|AT32_TIM_CH4_PIN ;
  GPIO_InitStructure.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
  GPIO_InitStructure.GPIO_OutType = GPIO_OutType_PP; 
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Pull = GPIO_Pull_NOPULL;
  GPIO_Init(AT32_TIM_GPIO, &GPIO_InitStructure);
	//GPIO复用到定时器
  GPIO_PinAFConfig(AT32_TIM_GPIO, GPIO_PinsSource8, GPIO_AF_2);
  GPIO_PinAFConfig(AT32_TIM_GPIO, GPIO_PinsSource11, GPIO_AF_2);
	
  /* 定时器时基配置 为了便于观察先频率调的低些--------------------------------------*/
  TMR_TimeBaseStructInit(&TIM_TimerBaseStructure);
  TIM_TimerBaseStructure.TMR_Period = 65535-1;
  TIM_TimerBaseStructure.TMR_DIV = 6553-1;
  TIM_TimerBaseStructure.TMR_ClockDivision = TMR_CKD_DIV2;
  TIM_TimerBaseStructure.TMR_CounterMode = TMR_CounterDIR_CenterAligned1;

  TMR_TimeBaseInit(AT32_TIM, &TIM_TimerBaseStructure);
	
  /* PWM模式配置: Channe8 */
  TMR_OCStructInit(&TMR_OCInitStructure);
  TMR_OCInitStructure.TMR_OCMode = TMR_OCMode_PWM1;
  TMR_OCInitStructure.TMR_OutputState = TMR_OutputState_Enable;
  TMR_OCInitStructure.TMR_Pulse = 0;
  TMR_OCInitStructure.TMR_OCPolarity = TMR_OCPolarity_High;
  TMR_OCInitStructure.TMR_OCIdleState = TMR_OCIdleState_Reset ;

  TMR_OC1Init(AT32_TIM, &TMR_OCInitStructure);

  TMR_OC1PreloadConfig(AT32_TIM, TMR_OCPreload_Enable);

  /* PWM2模式配置: Channe11 */
  TMR_OCInitStructure.TMR_OCMode = TMR_OCMode_PWM2;
  TMR_OCInitStructure.TMR_OutputState = TMR_OutputState_Enable;
  TMR_OCInitStructure.TMR_Pulse = 0;

  TMR_OC4Init(AT32_TIM, &TMR_OCInitStructure);

  TMR_OC4PreloadConfig(AT32_TIM, TMR_OCPreload_Enable);
	//使能定时器
	TMR_Cmd(AT32_TIM,ENABLE);
    //使能输出
	TMR_CtrlPWMOutputs(TMR1, ENABLE);
}

In order to facilitate transplantation, the macro definition in at32_board.h

/**************** TIM ****************/
#define AT32_TIM               	   TMR1

#define AT32_TIM_GPIO_RCC    	   RCC_AHBPERIPH_GPIOA
#define AT32_TIM_FUNC  			   RCC_APB2PERIPH_TMR1

/*TIM1_CH1*/
#define AT32_TIM_CH1_PIN           GPIO_Pins_8
#define AT32_TIM_GPIO              GPIOA

/*TIM1_CH4*/
#define AT32_TIM_CH4_PIN           GPIO_Pins_11
#define AT32_TIM_GPIO              GPIOA

/**************** End TIM****************/

Channel 2 and channel 3 are occupied by the serial port, so channel 1 and channel 4 are used here.

Call the initialization function in board.c to complete the initialization.

void rt_hw_board_init()
{
    /* System Clock Update */
    SystemCoreClockUpdate();
    
    /* System Tick Configuration */
    _SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND);
	
	  /* 串口1初始化*/
	  UART_Print_Init(115200);
	  /* SPI2初始化 */
	  SPI2_Init();

	  OLED_Init();
	  TIM_Init();
	
    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get());
#endif
}

Write the test code in while(1)

The comparison register is incremented every 100 milliseconds to change the duty cycle, and then the OLED obtains and displays the value of the comparison register.

uint16_t Pulse;
uint8_t  dir = 1;

 while (1)
  {

		if(dir == 1)
			Pulse++;
		if(Pulse>31456)
			dir = 0;
			
		if(dir == 0)
			Pulse--;
		if(Pulse==0)
			dir = 1;
        //设置比较寄存器
		TMR_SetCompare1(AT32_TIM, Pulse);
		TMR_SetCompare4(AT32_TIM, 65535-Pulse);
		OLED打印寄存器值
		OLED_ShowString(5,0,(uint8_t*)"CC1",16);
		OLED_ShowNum(5,16,TMR_GetCapture1(AT32_TIM),5,16);
		OLED_ShowString(5,30,(uint8_t*)"CC4",16);
		OLED_ShowNum(5,46,TMR_GetCapture4(AT32_TIM),5,16);
		OLED_Refresh();
		rt_thread_mdelay(100);
  }

WeChat_20210428000856.mp4 (1.77 MB, downloads: 4)

This is when the duty cycle is relatively small

WeChat_20210428002619.mp4 (2.32 MB, downloads: 2)

This is when the duty cycle is relatively large. The blue and green colors may not be easy to see just now, so let's change the color this time.

You can see that the code has run successfully

This post is from Domestic Chip Exchange

Latest reply

[attach]536177[/attach]It’s ok if you see the green light   Details Published on 2021-4-29 21:59
 
 

1662

Posts

0

Resources
2
 

It’s ok if you see the green light

This post is from Domestic Chip Exchange
 
 
 

Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list