Bắt PWM hoạt động trên STM32F4 bằng thư viện HAL của ST


7

Tôi đang cố gắng chuyển sang các thư viện ST HAL và dường như không thể làm cho PWM hoạt động. Biên dịch tốt, chỉ không bắt đầu.

Trong main () của tôi, tôi gọi hàm khởi tạo Timer:

/* TIM3 init function */
void MX_TIM3_Init(void)
{

  TIM_MasterConfigTypeDef sMasterConfig;
  TIM_OC_InitTypeDef sConfigOC;

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 0;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 1300;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_PWM_Init(&htim3);

  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig);

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_SET;
  sConfigOC.Pulse = 650;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;

  HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
  HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2);
  HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3);
  HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4);
  HAL_TIM_PWM_MspInit(&htim3);

} 

GPIO được khởi tạo trong HAL_TIM_PWM_MspInit()chức năng:

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(htim_pwm->Instance==TIM3)
  {
    /* Peripheral clock enable */
    __TIM3_CLK_ENABLE();

    /**TIM3 GPIO Configuration    
    PC9     ------> TIM3_CH4
    PC8     ------> TIM3_CH3
    PC7     ------> TIM3_CH2
    PC6     ------> TIM3_CH1 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_8|GPIO_PIN_7|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

  }

}

cuối cùng, tệp main () của tôi trông như thế này: (Tôi đang gọi SystemInit () từ chính vì tôi đang sử dụng các tệp được tạo STCube với coocox coide)

int main(void)
{

    SystemInit() ;

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_TIM3_Init();
  MX_GPIO_Init();
  MX_LWIP_Init();
  while (1)
  {

  }

}

Cuối cùng tôi đã quay trở lại các thư viện cũ vì tôi thấy chúng không hoạt động - tôi đang làm việc trên một proto-board với stm32F417IG và chỉ muốn làm cho nó hoạt động trở lại! Hy vọng rằng tôi sẽ có thời gian để quay lại vấn đề này và khiến công cụ HAL hoạt động. Cảm ơn tất cả các câu trả lời!
oboist B

Câu trả lời:


6

Tôi đến bữa tiệc muộn, nhưng tôi thấy mình trong một tình huống tương tự và có câu trả lời thực sự, hoặc ít nhất là câu trả lời mà cá nhân tôi đã xác minh để làm việc với bảng STM32 của riêng tôi và trình điều khiển STM32CubeMx.

  1. Hãy chắc chắn rằng bạn khởi tạo (không ra) các cấu trúc được phân bổ ngăn xếp của bạn. ví dụ: memset(&sConfigOC, 0, sizeof(sConfigOC));Biến cục bộ không được tự động khởi tạo và bạn sẽ có cấu hình không mong muốn / ngoài ý muốn vì HAL đưa ra các giả định rất cơ bản về trạng thái ngoại vi dựa trên các biến xử lý này. Điều này đặc biệt điên rồ khi hành vi thay đổi từ biên dịch sang biên dịch hoặc từ lệnh gọi hàm sang gọi hàm khi bộ nhớ ngăn xếp thay đổi.
  2. Đừng gọi HAL_TIM_PWM_MspInit()thủ công. Nó được tự động gọi khi bạn gọi HAL_TIM_PWM_Init(), nhưng bạn phải đảm bảo các biến xử lý của bạn được khởi tạo đúng cách (xem # 1 ở trên).
  3. Bạn không cần gọi HAL_TIMEx_MasterConfigSynchronization()nếu bạn không thay đổi từ cấu hình mặc định (không bị xích / đồng bộ hóa). Nó sẽ không làm tổn thương gì, nhưng nó cũng không cần thiết.
  4. MspInit()Chức năng của bạn là tốt, ngoại trừ bạn cũng nên kích hoạt đồng hồ của thiết bị ngoại vi GPIOC.

Và điều kỳ diệu ngăn nó hoạt động:

  1. Bạn PHẢI gọi HAL_TIM_PWM_Start()sau mỗi cuộc gọi đến HAL_TIM_PWM_ConfigChannel()- việc đầu tiên HAL_TIM_PWM_ConfigChannel()làm là vô hiệu hóa đầu ra bộ hẹn giờ (các CCxEbit trong TIMx_CCER). HAL_TIM_PWM_ConfigChannel()không kích hoạt lại các đầu ra hẹn giờ!

Vì cách duy nhất HAL cập nhật thủ công chu kỳ nhiệm vụ PWM là thông qua HAL_TIM_PWM_ConfigChannel(), bạn phải luôn gọi HAL_TIM_PWM_Start()nếu không bạn sẽ không có đầu ra PWM. Tôi nghĩ điều này được thực hiện bởi vì cách làm việc bình thường với PWM là sử dụng _IT()hoặc _DMA()các biến thể của HAL_TIM_PWM_Start(), và do đó bạn đang cập nhật chu kỳ nhiệm vụ "trong nền" để nói.

Một số câu trả lời khác (bao gồm câu trả lời bạn đánh dấu là được chấp nhận) là sai:

  1. Đừng gọi HAL_TIM_Base_Start() , cũng không HAL_TIM_Base_Init(), cũng không phải bất kỳ cuộc gọi không phải là PWM nào khác; Đầu tiên, HAL sẽ không gọi PWM_MspInit()chức năng của bạn vì tay cầm ngoại vi sẽ không còn ở trạng thái thiết lập lại, nhưng quan trọng hơn, PWM (và OC và các biến thể khác) đều gọi đúng chức năng bên trong mức thấp mà bạn không thực hiện thủ công. Toàn bộ quan điểm của HAL là không phải lo lắng quá nhiều về các chi tiết, nhưng bạn đã có khả năng xử lý tốt những gì HAL đang làm và những gì nó mong đợi. Nguồn đầy đủ có sẵn và được ghi lại khá tốt. Bạn chỉ cần đọc nó.
  2. Bạn không phải gọi HAL_TIMEx_PWMN_Start()hoặc bất kỳ TIMExchức năng nào khác trừ khi bạn đang sử dụng các đầu ra miễn phí. Một lần nữa, đây là tài liệu khá tốt trong nguồn HAL.

Đã thử các đề xuất khác nhưng không có kết quả nào, điều này hiệu quả với tôi, sử dụng bảng Olimex H103. điều này dựa trên STM32F103RBT6. Tôi chỉ cần thêm dòng sau đây giữa MÃ NGƯỜI DÙNG BEGIN 2 VÀ MÃ NGƯỜI DÙNG END 2 trong main.c HAL_TIM_PWM_Start (& htim3, TIM_CHANNEL_1);
Pop24

6

Tôi đang sử dụng STCubeMX và các tệp khởi tạo HAL được tạo. Quá trình xác minh trên Bảng Nucleo F302 của tôi. Tôi thiết lập Timer 1 (TIM1) nâng cao với đầu ra bình thường và bổ sung, không có thời gian chết.

Đây là cách tôi định cấu hình PWM trong CubeMX:

  1. Trong chế độ xem sơ đồ chân, tôi đã chọn hai chân làm chân TIM1_CH & TIM1_CHN. Trên khung bên trái, đặt kênh TIM1 1 là "Thế hệ PWM CH1 CH1N".
  2. Trong tab cấu hình, tôi đặt cài đặt sau (TIM1 clk là 64 MHz) Cài đặt cấu hình CubeMX TIM1
  3. Sau khi mã được tạo, chúng ta vẫn cần khởi động PWM. Điều này được thực hiện bằng cách gọi các hàm sau trong vùng mã người dùng trước while (1), trong hàm main ():

    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //starts PWM on CH1 pin HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1); //starts PWM on CH1N pin

  4. Để thay đổi cài đặt cấu hình, hãy sử dụng các macro sau được cung cấp trong stm32f3xx_hal_tim.h. HAL_TIM_PWM_ConfigChannel()không phải là cách duy nhất để cập nhật cài đặt PWM theo cách thủ công như đã nói bởi @akohlsmith.

    __HAL_TIM_GET_AUTORELOAD(&htim1); //gets the Period set for PWm __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, dutyCycle); //sets the PWM duty cycle (Capture Compare Value)

Không cần phải gọi lại HAL_TIM_PWM_Start(). Các macro này thay đổi cài đặt trong thời gian chạy.


6

Khi sử dụng Cube Mx, mã được tạo sẽ khởi tạo thiết bị ngoại vi hẹn giờ nhưng không khởi động nó chạy. Giải pháp theo đề xuất của người khác: thêm các chức năng Bắt đầu.

HAL_TIM_Base_Start(&htim3); 
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_ALL); 

Đặt mã này vào phần "MÃ NGƯỜI DÙNG" sau khi mã được tạo MX_TIM3_Init().


2
Tôi đã thử điều này cho Nucleo-32 (vi điều khiển STM32F042K6), cũng cho bộ đếm thời gian 3. Nó không hoạt động bằng cách sử dụng TIM_CHANNEL_ALLtrong cuộc gọi thứ hai, nhưng sử dụng TIM_CHANNEL1 thay vì hoạt động (nó bắt đầu đầu ra PWM thực tế trên chân đầu ra). Tương tự như vậy cho 3 kênh khác, sử dụng TIM_CHANNEL2, TIM_CHANNEL3TIM_CHANNEL14, tương ứng, trong cuộc gọi đến HAL_TIM_PWM_Start()(vì vậy 4 cuộc gọi trong tất cả để HAL_TIM_PWM_Start()).
Peter Mortensen

Cuộc gọi đến HAL_TIM_Base_Start(&htim3);không cần thiết (xác định theo kinh nghiệm và cả trong câu trả lời của akohlsmith ).
Peter Mortensen

@PeterMortensen thật tuyệt vời. Thật ngạc nhiên khi rất ít thông tin có thể có ý nghĩa rất nhiều. Cảm ơn bạn đã chia sẻ, điều này cũng rất quan trọng trên bảng tùy chỉnh STM32F412.
Heath Raftery

2

Bạn cần bắt đầu hẹn giờ trước. Thêm dòng tiếp theo vào main()để bắt đầu timer3 trên CH1:

HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);

0
        void PWM_Output(void)
        {


          TimerPeriod = 1000;



          /* TIM1 clock enable */
          RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 , ENABLE);

          /* Time Base configuration */
          TIM_TimeBaseStructure.TIM_Prescaler = 48;
          TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
          TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
          TIM_TimeBaseStructure.TIM_ClockDivision = 1;
          TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

          TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

          /* Channel 1, 2, 3 and 4 Configuration in PWM mode */
          TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
          TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
          TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;



          TIM_OCInitStructure.TIM_Pulse = 899;
          TIM_OC1Init(TIM1, &TIM_OCInitStructure);

          TIM_OCInitStructure.TIM_Pulse = 899;
          TIM_OC2Init(TIM1, &TIM_OCInitStructure);

          TIM_OCInitStructure.TIM_Pulse = 899;
          TIM_OC3Init(TIM1, &TIM_OCInitStructure);

          TIM_OCInitStructure.TIM_Pulse = 899;
          TIM_OC4Init(TIM1, &TIM_OCInitStructure);

          /* TIM1 counter enable */
          TIM_Cmd(TIM1, ENABLE);

          /* TIM1 Main Output Enable */
          TIM_CtrlPWMOutputs(TIM1, DISABLE);

        }

    void GPIO_init(){
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);


              GPIO_PWMEnPins.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
              GPIO_PWMEnPins.GPIO_Mode = GPIO_Mode_AF;
              GPIO_PWMEnPins.GPIO_Speed = GPIO_Speed_Level_1;
              GPIO_PWMEnPins.GPIO_OType = GPIO_OType_PP;
              GPIO_PWMEnPins.GPIO_PuPd = GPIO_PuPd_NOPULL;
              GPIO_Init(GPIOA, &GPIO_PWMEnPins);

 /*SMT32F0 has different config for Alternate Function assignment; below is the example. STM32F4 might have less code footprint to configure alternate func.*/
              GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_2);
              GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_2);
              GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_2);
              GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_2);

    }

Mã này hoạt động trong CooCox với các thư viện STM32f0xx_yyy tiêu chuẩn. Bạn cũng cần bật đồng hồ của GPIOC trong GPIO init.


Điều đó có thể hoạt động, nhưng câu hỏi là về việc sử dụng các thư viện ST HAL.
Peter Mortensen

0

Tôi nghĩ bạn cần khởi tạo đồng hồ GPIO bằng cách gọi __GPIOC_CLK_ENABLE();

Tôi có mã tương tự làm việc - nhưng tôi đã bỏ qua công cụ cấu hình chính.

Có một ví dụ trong thư mục stm32g-eval có thể được điều chỉnh phù hợp với bảng khám phá (nếu đó là bảng bạn đang sử dụng).


0

Bạn cần điều này:

HAL_TIM_Base_Start_IT(&htim3);
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_ALL);
HAL_TIMEx_PWMN_Start(&htim3,TIM_CHANNEL_ALL);

3
Hãy giải thích ở đâu và tại sao.
JRE

"_IT" đề cập đến một cái gì đó liên quan đến ngắt. Tại sao điều đó chỉ cần thiết để có được đầu ra PWM?
Peter Mortensen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.