打印
[AIROC™ 蓝牙]

【英飞凌CYW20829测评】第2篇 呼吸灯实验

[复制链接]
314|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 小宏121 于 2024-7-17 23:52 编辑

先简单说下MTB和官方例程的用法

新建一个自己的文件夹myproject用于放置自己工程



复制一个官方的empty_app例程到myproject路径下


如果MTB有提示要输入 make getlibs,则在MTB终端里输入即可


复制后,这里添加新的工程


等待MTB将新的工程加载完成

这里可以对该工程的配置



比如配置GPIO


配置后的代码可以在右边看到预览


这里可以打开配置后的文件路径


这个文件夹里有配置的代码


这是刚刚配置的代码文件

这是刚刚配置的GPIO代码

熟悉了MTB的简单应用后,下面我复制官方例程的TCPWM例程 "HAL_PWM_Square_Wave",在这基础上实现彩虹呼吸灯的效果
注意的是开发板的LED是低电平点亮灯,高电平灭灯,所以占空比越大灯越暗。

/*******************************************************************************
* File Name:   main.c
*
* Description: This is the source code for the PWM square wave code example
*              for ModusToolbox.
*
* Related Document: See README.md
*
********************************************************************************
* Copyright 2019-2024, Cypress Semiconductor Corporation (an Infineon company) or
* an affiliate of Cypress Semiconductor Corporation.  All rights reserved.
*
* This software, including source code, documentation and related
* materials ("Software") is owned by Cypress Semiconductor Corporation
* or one of its affiliates ("Cypress") and is protected by and subject to
* worldwide patent protection (United States and foreign),
* United States copyright laws and international treaty provisions.
* Therefore, you may use this Software only as provided in the license
* agreement accompanying the software package from which you
* obtained this Software ("EULA").
* If no EULA applies, Cypress hereby grants you a personal, non-exclusive,
* non-transferable license to copy, modify, and compile the Software
* source code solely for use in connection with Cypress's
* integrated circuit products.  Any reproduction, modification, translation,
* compilation, or representation of this Software except as specified
* above is prohibited without the express written permission of Cypress.
*
* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress
* reserves the right to make changes to the Software without notice. Cypress
* does not assume any liability arising out of the application or use of the
* Software or any product or circuit described in the Software. Cypress does
* not authorize its products for use in any products where a malfunction or
* failure of the Cypress product may reasonably be expected to result in
* significant property damage, injury or death ("High Risk Product"). By
* including Cypress's product in a High Risk Product, the manufacturer
* of such system or application assumes all risk of such use and in doing
* so agrees to indemnify Cypress against all liability.
*******************************************************************************/

/*******************************************************************************
* Header Files
*******************************************************************************/
#include "cybsp.h"
#include "cyhal.h"
#include "cy_retarget_io.h"
#include <inttypes.h>


/*******************************************************************************
* Macros
*******************************************************************************/
/* PWM Frequency = 2Hz */
#define PWM_FREQUENCY (20000u)
/* PWM Duty-cycle = 50% */
#define PWM_DUTY_CYCLE (50.0f)

#define RGB_LED_R_CHANNEL 1
#define RGB_LED_G_CHANNEL 2
#define RGB_LED_B_CHANNEL 3
#define PWM_PERIOD 1000 // PWM周期
#define MAX_DUTY_CYCLE 1000 // 最大占空比
#define MIN_DUTY_CYCLE 100 // 最小占空比
#define BREATHING_PERIOD_MS 6000 // 呼吸周期
#define RAINBOW_STEPS 500 // 彩虹渐变细腻程度

#define CYBSP_USER_LED_R (P0_2)
#define CYBSP_USER_LED_G (P0_3)
#define CYBSP_USER_LED_B (P0_4)

// 呼吸模式枚举
typedef enum {
    CHASE_BREATHING,       // 追逐呼吸模式
    SYNC_BREATHING,        // 同步呼吸模式
    HEARTBEAT_DIALOGUE     // 心跳对话模式
} breathing_pattern_t;

// 当前模式
breathing_pattern_t current_pattern = HEARTBEAT_DIALOGUE;

/*******************************************************************************
* Function Prototypes
*******************************************************************************/


/*******************************************************************************
* Function Definitions
*******************************************************************************/

/*******************************************************************************
* Function Name: handle_error
********************************************************************************
* Summary:
*  User defined error handling function.
*
* Parameters:
*  status - status for evaluation.
*
* Return:
*  void
*
*******************************************************************************/
void handle_error(cy_rslt_t status)
{
    if (CY_RSLT_SUCCESS != status)
    {
        /* Halt the CPU while debugging */
        CY_ASSERT(0);
    }
}


/*******************************************************************************
* Function Name: check_status
********************************************************************************
* Summary:
*  Prints the message and waits forever when an error occurs.
*
* Parameters:
*  message - message to print if status is non-zero.
*  status - status for evaluation.
*
* Return:
*  void
*
*******************************************************************************/
void check_status(char *message, cy_rslt_t status)
{
    if (CY_RSLT_SUCCESS != status)
    {
        printf("\r\n=====================================================\r\n");
        printf("\nFAIL: %s\r\n", message);
        printf("Error Code: 0x%08" PRIX32 "\n", status);
        printf("\r\n=====================================================\r\n");

        while(true);
    }
}


void SetPWM(cyhal_pwm_t *timer_obj, uint16_t channel, uint16_t duty_cycle)
{
    float f_duty_cycle = 0.0f;
//    printf("duty_cycle=%d\n", duty_cycle);
    if (channel == RGB_LED_R_CHANNEL || channel == RGB_LED_G_CHANNEL || channel == RGB_LED_B_CHANNEL)
    {
        if (duty_cycle > 1000) duty_cycle = 1000; // 限制占空比最大值

        duty_cycle = 1000 - duty_cycle;
        f_duty_cycle = (float)duty_cycle/10;
        cyhal_pwm_set_duty_cycle(timer_obj, (float)duty_cycle/10, PWM_FREQUENCY);
    }
}

// 当前色彩阶段
static uint16_t rainbowStep = 0;
cyhal_pwm_t pwm_led_r_control;
cyhal_pwm_t pwm_led_g_control;
cyhal_pwm_t pwm_led_b_control;

void SetRGBDutyCycle(float rFraction, float gFraction, float bFraction) {
    // 将颜色分量映射到占空比
    int redDuty = (int)(MAX_DUTY_CYCLE * rFraction);
    int greenDuty = (int)(MAX_DUTY_CYCLE * gFraction);
    int blueDuty = (int)(MAX_DUTY_CYCLE * bFraction);

    // 设置RGB LED的占空比
    SetPWM(&pwm_led_r_control, RGB_LED_R_CHANNEL, redDuty);
    SetPWM(&pwm_led_g_control, RGB_LED_G_CHANNEL, greenDuty);
    SetPWM(&pwm_led_b_control, RGB_LED_B_CHANNEL, blueDuty);
}

void RainbowBreathing(void) {
    static uint16_t breathingCounter = 0;
    static bool directionUp = true; // 控制呼吸方向

    // 计算呼吸效果的当前位置
    uint16_t dutyCycle = MIN_DUTY_CYCLE + (MAX_DUTY_CYCLE - MIN_DUTY_CYCLE) * (breathingCounter % (BREATHING_PERIOD_MS / 10)) / (BREATHING_PERIOD_MS / 10);

    // 计算当前的彩虹颜色
    float hueFraction = rainbowStep / (float)RAINBOW_STEPS;
    while (hueFraction > 1.0f) hueFraction -= 1.0f; // 确保在0到1之间

    // 根据当前色彩阶段设置RGB LED的色彩
    float r, g, b;
    if (hueFraction < 1.0f / 3.0f) {
        r = 1.0f;
        g = hueFraction / (1.0f / 3.0f);
        b = 0;
    } else if (hueFraction < 2.0f / 3.0f) {
        r = 1.0f - (hueFraction - 1.0f / 3.0f) * 3.0f;
        g = 1.0f;
        b = 0;
    } else {
        r = 0;
        g = 1.0f - (hueFraction - 2.0f / 3.0f) * 3.0f;
        b = 1.0f;
    }

    // 应用呼吸效果
    r *= dutyCycle / (float)MAX_DUTY_CYCLE;
    g *= dutyCycle / (float)MAX_DUTY_CYCLE;
    b *= dutyCycle / (float)MAX_DUTY_CYCLE;

    // 防止生成过于明亮的白色光
    float maxBrightness = 0.5f * dutyCycle / (float)MAX_DUTY_CYCLE; // 设定最大亮度系数,避免达到最亮
    if (r + g + b > maxBrightness) { // 如果总亮度超过限制
        float scale = maxBrightness / (r + g + b); // 计算缩放因子
        r *= scale;
        g *= scale;
        b *= scale; // 缩放各颜色通道的亮度
    }

    SetRGBDutyCycle(r, g, b);

    // 更新rainbowStep以实现颜色移动
    rainbowStep = (rainbowStep + 1) % RAINBOW_STEPS;

    // 呼吸效果递增或递减计数器
    if (directionUp) {
        if (breathingCounter >= BREATHING_PERIOD_MS / 10 - 1) {
            directionUp = false;
        } else {
            breathingCounter++;
        }
    } else {
        if (breathingCounter <= 0) {
            directionUp = true;
        } else {
            breathingCounter--;
        }
    }
}

int main(void)
{
    /* PWM object */
    cyhal_pwm_t pwm_led_1_control;
    cyhal_pwm_t pwm_led_2_control;

    /* API return code */
    cy_rslt_t result;

#if defined(CY_DEVICE_SECURE)
    cyhal_wdt_t wdt_obj;
    /* Clear watchdog timer so that it doesn't trigger a reset */
    result = cyhal_wdt_init(&wdt_obj, cyhal_wdt_get_max_timeout_ms());
    CY_ASSERT(CY_RSLT_SUCCESS == result);
    cyhal_wdt_free(&wdt_obj);
#endif

    /* Initialize the device and board peripherals */
    result = cybsp_init();
    handle_error(result);

    /* Enable global interrupts */
    __enable_irq();

    /* Initialize the retarget-io to use the debug UART port */
    result = cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX,
                                 CY_RETARGET_IO_BAUDRATE);
    handle_error(result);


    /* Initialize the PWM */
    result = cyhal_pwm_init(&pwm_led_r_control, CYBSP_USER_LED_R, NULL);
    check_status("API cyhal_pwm_init failed with error code", result);

    result = cyhal_pwm_init(&pwm_led_g_control, CYBSP_USER_LED_G, NULL);
    check_status("API cyhal_pwm_init failed with error code", result);

    result = cyhal_pwm_init(&pwm_led_b_control, CYBSP_USER_LED_B, NULL);
    check_status("API cyhal_pwm_init failed with error code", result);

    /* Set the PWM output frequency and duty cycle */
    result = cyhal_pwm_set_duty_cycle(&pwm_led_r_control, 100.0f,
                                      PWM_FREQUENCY);
    check_status("API cyhal_pwm_set_duty_cycle failed with error code", result);

    result = cyhal_pwm_set_duty_cycle(&pwm_led_g_control, 100.0f,
                                      PWM_FREQUENCY);
    check_status("API cyhal_pwm_set_duty_cycle failed with error code", result);

    result = cyhal_pwm_set_duty_cycle(&pwm_led_b_control, 100.0f,
                                      PWM_FREQUENCY);
    check_status("API cyhal_pwm_set_duty_cycle failed with error code", result);

    /* Start the PWM */
    result = cyhal_pwm_start(&pwm_led_r_control);
    check_status("API cyhal_pwm_start failed with error code", result);

    result = cyhal_pwm_start(&pwm_led_g_control);
    check_status("API cyhal_pwm_start failed with error code", result);

    result = cyhal_pwm_start(&pwm_led_b_control);
    check_status("API cyhal_pwm_start failed with error code", result);
    printf("PWM started successfully. Entering the sleep mode...\r\n");

    while (1) {
        RainbowBreathing();
        Cy_SysLib_Delay(10); // 基于10ms的延时,调整以匹配系统时钟
    }
}


/* [] END OF FILE */


这里放置GIF图效果

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

15

帖子

0

粉丝