[AT32F423] 【AT-START-F423测评】基于freeRTOS的流水呼吸灯

[复制链接]
1817|0
 楼主| lulugl 发表于 2023-10-28 17:03 | 显示全部楼层 |阅读模式
AT32F23呼吸流水灯
【工程简介】
传统都是用GPIO的高低电平来实现流水灯。这次用PWM来实现呼吸的流水灯。
【实现步骤】
新建freertos工程,复一份官方的freertos的工程,重命名,并打开工程,并确保编译通过。
打开雅特力的图形配置工具,配置板载的三个LED为PWM输出。
17e51a32e8fe4fbe91cf59b2ad1b8873
d179806c0d630ded7d80a244ae7f84ff
复制配置工具生成的代码到工程中。
60bdb2a902d484f80b0c49883c6b8700
代码为:
  1. void wk_tmr4_init(void)
  2. {
  3.   /* add user code begin tmr4_init 0 */

  4.   /* add user code end tmr4_init 0 */

  5.   gpio_init_type gpio_init_struct;
  6.   tmr_output_config_type tmr_output_struct;

  7.   gpio_default_para_init(&gpio_init_struct);

  8.   /* add user code begin tmr4_init 1 */
  9.          /* enable gpiod periph clock */
  10.   crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);

  11.   /* enable tmr4 periph clock */
  12.   crm_periph_clock_enable(CRM_TMR4_PERIPH_CLOCK, TRUE);
  13.   /* add user code end tmr4_init 1 */

  14.   /* configure the tmr4 CH2 pin */
  15.   gpio_init_struct.gpio_pins = GPIO_PINS_13;
  16.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  17.   gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  18.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  19.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  20.   gpio_init(GPIOD, &gpio_init_struct);

  21.   gpio_pin_mux_config(GPIOD, GPIO_PINS_SOURCE13, GPIO_MUX_2);

  22.   /* configure the tmr4 CH3 pin */
  23.   gpio_init_struct.gpio_pins = GPIO_PINS_14;
  24.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  25.   gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  26.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  27.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  28.   gpio_init(GPIOD, &gpio_init_struct);

  29.   gpio_pin_mux_config(GPIOD, GPIO_PINS_SOURCE14, GPIO_MUX_2);

  30.   /* configure the tmr4 CH4 pin */
  31.   gpio_init_struct.gpio_pins = GPIO_PINS_15;
  32.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  33.   gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  34.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  35.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
  36.   gpio_init(GPIOD, &gpio_init_struct);

  37.   gpio_pin_mux_config(GPIOD, GPIO_PINS_SOURCE15, GPIO_MUX_2);

  38.   /* configure counter settings */
  39.   tmr_base_init(TMR4, 14999, 0);
  40.   tmr_cnt_dir_set(TMR4, TMR_COUNT_UP);
  41.   tmr_clock_source_div_set(TMR4, TMR_CLOCK_DIV1);
  42.   tmr_period_buffer_enable(TMR4, FALSE);

  43.   /* configure primary mode settings */
  44.   tmr_sub_sync_mode_set(TMR4, FALSE);
  45.   tmr_primary_mode_select(TMR4, TMR_PRIMARY_SEL_RESET);

  46.   /* configure channel 2 output settings */
  47.   tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
  48.   tmr_output_struct.oc_output_state = TRUE;
  49.   tmr_output_struct.occ_output_state = FALSE;
  50.   tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_LOW;
  51.   tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_LOW;
  52.   tmr_output_struct.oc_idle_state = FALSE;
  53.   tmr_output_struct.occ_idle_state = FALSE;
  54.   tmr_output_channel_config(TMR4, TMR_SELECT_CHANNEL_2, &tmr_output_struct);
  55.   tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_2, 0);
  56.   tmr_output_channel_buffer_enable(TMR4, TMR_SELECT_CHANNEL_2, FALSE);

  57.   tmr_output_channel_immediately_set(TMR4, TMR_SELECT_CHANNEL_2, FALSE);

  58.   /* configure channel 3 output settings */
  59.   tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
  60.   tmr_output_struct.oc_output_state = TRUE;
  61.   tmr_output_struct.occ_output_state = FALSE;
  62.   tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_LOW;
  63.   tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_LOW;
  64.   tmr_output_struct.oc_idle_state = FALSE;
  65.   tmr_output_struct.occ_idle_state = FALSE;
  66.   tmr_output_channel_config(TMR4, TMR_SELECT_CHANNEL_3, &tmr_output_struct);
  67.   tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_3, 0);
  68.   tmr_output_channel_buffer_enable(TMR4, TMR_SELECT_CHANNEL_3, FALSE);

  69.   tmr_output_channel_immediately_set(TMR4, TMR_SELECT_CHANNEL_3, FALSE);

  70.   /* configure channel 4 output settings */
  71.   tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
  72.   tmr_output_struct.oc_output_state = TRUE;
  73.   tmr_output_struct.occ_output_state = FALSE;
  74.   tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_LOW;
  75.   tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_LOW;
  76.   tmr_output_struct.oc_idle_state = FALSE;
  77.   tmr_output_struct.occ_idle_state = FALSE;
  78.   tmr_output_channel_config(TMR4, TMR_SELECT_CHANNEL_4, &tmr_output_struct);
  79.   tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_4, 0);
  80.   tmr_output_channel_buffer_enable(TMR4, TMR_SELECT_CHANNEL_4, FALSE);

  81.   tmr_output_channel_immediately_set(TMR4, TMR_SELECT_CHANNEL_4, FALSE);


  82.   tmr_counter_enable(TMR4, TRUE);

  83.   /* add user code begin tmr4_init 2 */

  84.   /* add user code end tmr4_init 2 */
  85. }

创建三个任务,实现三个灯的交替呼吸。创建三个信量,实现三个PWM呼着灯的交替工作。
  1. /* led2 task function */
  2. void led2_task_function(void *pvParameters)
  3. {
  4.         uint32_t tmr_channel_value;
  5.         uint8_t f;
  6.         BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
  7.         xSemaphoreGive( xBinarySemaphorePWM1 );//给出二值信号量
  8.   while(1)
  9.   {
  10.                 //获取二值信号量 xSemaphore,没获取到则一直等待
  11.     xReturn = xSemaphoreTake(xBinarySemaphorePWM1,/* 二值信号量句柄 */
  12.                                 portMAX_DELAY); /* 等待时间 */
  13.     for(f=0; f<180; f++)
  14.                 {
  15.                         tmr_channel_value = (uint32_t)(14999*cos(f*3.14/180));
  16.                         tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_2, tmr_channel_value);
  17.                         vTaskDelay(10);
  18.                 }
  19.                 tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_2, tmr_channel_value);
  20.                 xSemaphoreGive( xBinarySemaphorePWM2 );//给出二值信号量
  21.   }
  22. }

  23. /* led3 task function */
  24. void led3_task_function(void *pvParameters)
  25. {
  26.         BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
  27.         uint32_t tmr_channel_value;
  28.         uint8_t f;
  29.   while(1)
  30.   {
  31.                 //获取二值信号量 xSemaphore,没获取到则一直等待
  32.                         
  33.     xReturn = xSemaphoreTake(xBinarySemaphorePWM2,/* 二值信号量句柄 */
  34.                                 portMAX_DELAY); /* 等待时间 */
  35.     for(f=0; f<180; f++)
  36.                 {
  37.                         tmr_channel_value = (uint32_t)(14999*sin(f*3.14/180));
  38.                         tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_3, tmr_channel_value);
  39.                         vTaskDelay(10);
  40.                 }
  41.                 tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_3, 0);
  42.                 xSemaphoreGive( xBinarySemaphorePWM3 );//给出二值信号量
  43.   }
  44. }

  45. /* led3 task function */
  46. void led4_task_function(void *pvParameters)
  47. {
  48.         BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
  49.         uint32_t tmr_channel_value;
  50.         uint8_t f;
  51.   while(1)
  52.   {
  53.                 //获取二值信号量 xSemaphore,没获取到则一直等待
  54.                         
  55.     xReturn = xSemaphoreTake(xBinarySemaphorePWM3,/* 二值信号量句柄 */
  56.                                 portMAX_DELAY); /* 等待时间 */
  57.     for(f=0; f<180; f++)
  58.                 {
  59.                         tmr_channel_value = (uint32_t)(14999*sin(f*3.14/180));
  60.                         tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_4, tmr_channel_value);
  61.                         vTaskDelay(10);
  62.                 }
  63.                 tmr_channel_value_set(TMR4, TMR_SELECT_CHANNEL_4, 0);
  64.                 xSemaphoreGive( xBinarySemaphorePWM1 );//给出二值信号量
  65.   }
  66. }

在主程序中开始三个任务,任务中等待其的任务发出信号量,来实现工作。
/**
  * @brief  main function.
  * @param  none
  * @retval none
  */
int main(void)
{
  system_clock_config();

  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);

        wk_tmr4_init();
  /* init usart1 */
  uart_print_init(115200);
        xBinarySemaphorePWM1 = xSemaphoreCreateBinary();//创建信号量
        if (NULL != xBinarySemaphorePWM1)
    {
        printf("BinarySem_Handle 二值信号量1创建成功!\r\n");
    }
        xBinarySemaphorePWM2 = xSemaphoreCreateBinary();//创建信号量
        if (NULL != xBinarySemaphorePWM2)
    {
        printf("BinarySem_Handle 二值信号量2创建成功!\r\n");
    }
        xBinarySemaphorePWM3 = xSemaphoreCreateBinary();//创建信号量
        if (NULL != xBinarySemaphorePWM3)
    {
        printf("BinarySem_Handle 二值信号量3创建成功!\r\n");
    }
  /* enter critical */
  taskENTER_CRITICAL();

  /* create led2 task */
  if(xTaskCreate((TaskFunction_t )led2_task_function,
                 (const char*    )"LED2_task",
                 (uint16_t       )512,
                 (void*          )NULL,
                 (UBaseType_t    )2,
                 (TaskHandle_t*  )&led2_handler) != pdPASS)
  {
    printf("LED2 task could not be created as there was insufficient heap memory remaining.\r\n");
  }
  else
  {
    printf("LED2 task was created successfully.\r\n");
  }
  /* create led3 task */
  if(xTaskCreate((TaskFunction_t )led3_task_function,
                 (const char*    )"LED3_task",
                 (uint16_t       )512,
                 (void*          )NULL,
                 (UBaseType_t    )2,
                 (TaskHandle_t*  )&led3_handler) != pdPASS)
  {
    printf("LED3 task could not be created as there was insufficient heap memory remaining.\r\n");
  }
  else
  {
    printf("LED3 task was created successfully.\r\n");
  }
  /* create led3 task */
  if(xTaskCreate((TaskFunction_t )led4_task_function,
                 (const char*    )"LED4_task",
                 (uint16_t       )512,
                 (void*          )NULL,
                 (UBaseType_t    )2,
                 (TaskHandle_t*  )&led4_handler) != pdPASS)
  {
    printf("LED4 task could not be created as there was insufficient heap memory remaining.\r\n");
  }
  else
  {
    printf("LED4 task was created successfully.\r\n");
  }
  /* exit critical */
  taskEXIT_CRITICAL();

  /* start scheduler */
  vTaskStartScheduler();
}
实现交替的呼吸流水灯:

【小结】
此工程实现了定时器的驱动,同时应用信号量来实现三个任务的交替运行呼吸灯。开程提供了FreeRTOS的移植、信号量的创建,任务之间的信号传递,实现了不一样的流水灯效果。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

188

主题

843

帖子

12

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