欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 520|回復: 3
打印 上一主題 下一主題
收起左側

stm32求助:PWM功能實現流水燈,怎樣合適修改參數以實現較好的流水燈頻率?

[復制鏈接]
跳轉到指定樓層
樓主
ID:1162684 發表于 2025-11-7 21:57 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
各位帖友大家好,本人是一枚剛學stm32的萌新。一直修改PWM的有關參數,就是無法達到想要的呼吸燈效果。
想要的呼吸燈效果:LED6和LED7交接閃爍。LED6從暗到亮時,LED7從亮到暗;緊接著LED6從亮到暗,LED7從暗到亮。
目前存在的問題:1、兩盞燈之間交接得太慢:LED6從暗到亮,要過很久LED7才會從亮到暗。2、單個燈的呼吸效果不明顯,一下子就從暗到亮。

以下是代碼,不勝感激!
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"    // 包含led.h,使用LED_ON_OFF函數
#include "rtc.h"
#include "smg.h"
#include "timer.h"
#include "beep.h"
#include "exti.h"   // 包含exti.h,使用其中定義的類型
#include "key.h"
#include "test.h"
#include "adc.h"
#include "string.h"

/************************************************
STM32F103RC Fall Detection System
Functions: 1.Normal state: digital tube displays RTC time, LED6 and LED7 breathing light
            2.Fall detected (KEY2 pressed): buzzer sounds, LED0-LED7 flowing light
            3.KEY0 confirms safety, sends "Safe", stops buzzer;
              KEY1 confirms unsafe, sends "Unsafe", buzzer beeps every 3 seconds
            4.After receiving "SOS received" via serial port, LED0-LED7 all light up and buzzer sounds
************************************************/

// 全局變量定義 - 現在使用exti.h中定義的SystemState類型
SystemState system_state = STATE_NORMAL;  // System state
u8 LED_Shift = 0xFF;      // LED display control
u8 smg_wei = 0;           // Digital tube bit selection
u8 num = 0;               // Digital tube display value
u16 breath_count = 0;     // Breathing light counter
u8 breath_dir = 0;        // Breathing light direction (0-brighten, 1-dim)
u16 flow_count = 0;       // Flowing light counter
u8 flow_index = 0;        // Flowing light index
u16 beep_count = 0;       // Buzzer counter
u8 all_led_on = 0;        // All LEDs on flag
u8 all_led_timer = 0;     // All LEDs on timer
u8 sos_beep_flag = 0;     // SOS buzzer flag
u8 sos_beep_timer = 0;    // SOS buzzer timer
u16 unsafe_timeout = 0;   // Unsafe state timeout counter
u16 safe_timeout = 0;     // Safe state timeout counter
u16 fall_timeout = 0;     // Fall detected state timeout counter
u16 brightness = 0;    // 亮度值 0-1000

        
// Digital tube segment codes
// 0,1,2,3,4,5,6,7,8,9,dot,all off
u8 smg_num[] = {0xfc, 0x60, 0xda, 0xf2, 0x66, 0xb6, 0xbe, 0xe0, 0xfe, 0xf6, 0x01, 0x00};

// 超時時間定義 (單位: 50ms)
#define FALL_STATE_TIMEOUT   60   // 摔倒狀態30秒超時 (50ms * 60 = 3s)
#define SAFE_STATE_TIMEOUT   40  // 安全狀態20秒超時 (50ms * 40 = 2s)
#define UNSAFE_STATE_TIMEOUT 120 // 不安全狀態60秒超時 (50ms * 120 = 6s)
#define LED6_PWM_VAL  TIM3->CCR1  // PC6
#define LED7_PWM_VAL  TIM3->CCR2  // PC7

// Function declarations
void Display_Time(void);
void Breath_LED(void);
void Flow_LED(void);
void USART_ProcessCommand(u8* buf, u16 len);
void Set_RTC_To_Beijing_Time(void);
void Reset_To_Normal_State(void);
void TIM3_PWM_Init(u16 arr, u16 psc);

// 主函數
int main(void) {
    // 系統初始化
    Stm32_Clock_Init(9);    // 系統時鐘設置
    delay_init(72);         // 延時初始化
    uart_init(72, 115200);  // 串口初始化
    LED_Init();             // LED初始化
    BEEP_Init();            // 蜂鳴器初始化
    LED_SMG_Init();         // 數碼管初始化
    EXTIX_Init();           // 外部中斷初始化(在exti.c中定義)
    TIM3_PWM_Init(999, 71);
        
    // RTC初始化
    while(RTC_Init()) {
        printf("RTC Init Failed!\r\n");
        delay_ms(800);
        printf("RTC Retry Init...\r\n");
    }

    // 設置RTC為北京時間
    Set_RTC_To_Beijing_Time();

    // 初始化定時器
    TIM3_Init(19, 7199);    // 定時器3初始化,2ms中斷一次
    TIM2_Init(499, 7199);   // 定時器2初始化,50ms中斷一次

    printf("Fall Detection System Init Complete!\r\n");
    printf("Normal: Digital tube shows time, LED6/LED7 breathing\r\n");
    printf("Press KEY2 to simulate fall, KEY0 for safe, KEY1 for unsafe\r\n");
    printf("Current RTC Time: %d-%d-%d %02d:%02d:%02d\r\n",
           calendar.w_year, calendar.w_month, calendar.w_date,
           calendar.hour, calendar.min, calendar.sec);
    printf("Timeout settings: Fall(30s), Safe(20s), Unsafe(60s)\r\n");

    // 初始狀態:所有LED滅
    LED_ON_OFF(0xFF);

    // 主循環
    while(1) {
        // 處理串口接收
        if(USART_RX_STA & 0x8000) {
            u16 len = USART_RX_STA & 0x3FFF;
            USART_RX_BUF[len] = '\0';

            USART_ProcessCommand(USART_RX_BUF, len);

            USART_RX_STA = 0;
        }

        // 處理LED全亮狀態(5秒后自動恢復)
        if(all_led_on) {
            all_led_timer++;
            if(all_led_timer > 2500) { // 5秒后恢復
                all_led_on = 0;
                all_led_timer = 0;
                sos_beep_flag = 0; // 停止SOS蜂鳴器
                if(system_state == STATE_NORMAL) {
                    LED_ON_OFF(0xFF); // 恢復為全滅
                }
            }
        }

                //處理呼吸燈
                if(system_state == STATE_NORMAL || system_state == STATE_CONFIRMED_SAFE){
                if(breath_dir == 0) {            
            brightness += 3;
            if(brightness >= 999) {                 
                breath_dir = 1;            // 改變方向
                printf("Switch to direction 1\r\n");
            }
                }
                else {
            brightness -= 3;
            if(brightness <= 0) {               
                breath_dir = 0;            // 改變方向
                printf("Switch to direction 0\r\n");
            }
        }

        LED6_PWM_VAL = brightness;        
        LED7_PWM_VAL = 999 - brightness;
               
        delay_ms(10);
    }
}
}

// 重置到正常狀態
void Reset_To_Normal_State(void) {
    system_state = STATE_NORMAL;
    BEEP = 1;  // 停止蜂鳴器
    LED_ON_OFF(0xFF); // 恢復LED狀態
    fall_timeout = 0;
    safe_timeout = 0;
    unsafe_timeout = 0;
        beep_count = 0;
        sos_beep_flag = 0;
        sos_beep_timer = 0;
        brightness = 0;
        breath_dir = 0;
        LED6_PWM_VAL = 0;
        LED7_PWM_VAL = 0;
    printf("Timeout: Returning to normal state\r\n");
}

// 設置RTC為北京時間
void Set_RTC_To_Beijing_Time(void) {
    // 這里需要根據實際時間設置,示例設置為2024年1月1日 12:00:00
    // 在實際使用中,可以通過串口命令來設置準確的時間
    RTC_Set(2024, 1, 1, 12, 0, 0);
    printf("RTC set to Beijing time: 2024-01-01 12:00:00\r\n");
    printf("Use serial command 'SETTIME:YYYY-MM-DD HH:MM:SS' to set exact time\r\n");
}

// TIM2中斷處理函數 - 用于處理蜂鳴器周期性響鈴和超時恢復
void TIM2_IRQHandler(void) {
    if(TIM2->SR & 0X0001) {  // 溢出中斷
        // 狀態超時處理
        switch(system_state) {
            case STATE_FALL_DETECTED:
                // 摔倒狀態30秒后自動恢復
                fall_timeout++;
                if(fall_timeout >= FALL_STATE_TIMEOUT) {
                    Reset_To_Normal_State();
                    printf("Fall state timeout (30s), auto recovery\r\n");
                }
                break;

            case STATE_CONFIRMED_SAFE:
                // 安全狀態20秒后自動恢復
                safe_timeout++;
                if(safe_timeout >= SAFE_STATE_TIMEOUT) {
                    Reset_To_Normal_State();
                    printf("Safe state timeout (20s), auto recovery\r\n");
                }
                break;

            case STATE_CONFIRMED_UNSAFE:
                //不安全狀態60秒后自動恢復
                unsafe_timeout++;
                if(unsafe_timeout >= UNSAFE_STATE_TIMEOUT) {
                    Reset_To_Normal_State();
                    printf("Unsafe state timeout (60s), auto recovery\r\n");
                                        break;
                }
                                
                // 不安全狀態下,蜂鳴器每1秒響200ms
                                
                                        beep_count++;
                                        BEEP = (beep_count % 20 >= 4);  // 前4次中斷響(200ms),后16次中斷靜音(800ms)
                                        break;               
            default:
                // 正常狀態,不做超時處理
                break;
        }

        // SOS蜂鳴器處理 (快速響鳴)
        if(sos_beep_flag) {
            sos_beep_timer++;
            if(sos_beep_timer % 2 == 0) { // 每1秒切換一次
                BEEP = !BEEP; // 蜂鳴器快速切換
            }
        }

        // 更新RTC時間
        RTC_Get();
    }
    TIM2->SR &= ~(1 << 0);  // 清除中斷標志位
}

// TIM3中斷處理函數 - 用于處理LED顯示、數碼管刷新等
void TIM3_IRQHandler(void) {
    if(TIM3->SR & 0X0001) {  // 溢出中斷
        // 數碼管顯示(所有狀態都顯示時間)
        Display_Time();

        // 根據系統狀態執行不同的LED操作
        switch(system_state) {
            case STATE_NORMAL:
                // 正常狀態:LED6和LED7呼吸燈交替亮暗
                //Breath_LED();
                break;

            case STATE_FALL_DETECTED:
                // 檢測到摔倒:LED0-LED7流水燈閃爍,蜂鳴器持續響
                Flow_LED();
                BEEP = 0;  // 蜂鳴器持續響
                break;

            case STATE_CONFIRMED_SAFE:
                // 確認安全:LED6和LED7呼吸燈交替亮暗
                //Breath_LED();
                BEEP = 1;  // 停止蜂鳴器
                break;

            case STATE_CONFIRMED_UNSAFE:
                // 確認不安全:LED0-LED7流水燈閃爍
                Flow_LED();
                // 蜂鳴器由TIM2控制每3秒響一次
                break;
        }

        // 所有LED全亮標志處理
        if(all_led_on) {
            LED_ON_OFF(0x00);  // 所有LED全亮
        }
    }
    TIM3->SR &= ~(1 << 0);  // 清除中斷標志位
}

// 數碼管顯示時間
void Display_Time(void) {
    switch(smg_wei) {
        case 0: num = smg_num[calendar.hour / 10]; break;  // Hour tens
        case 1: num = smg_num[calendar.hour % 10]; break;  // Hour units
        case 2: num = 0x01; break;  // Colon (using dot from segment codes)
        case 3: num = smg_num[calendar.min / 10]; break;   // Minute tens
        case 4: num = smg_num[calendar.min % 10]; break;   // Minute units
        case 5: num = 0x01; break;  // Colon
        case 6: num = smg_num[calendar.sec / 10]; break;   // Second tens
        case 7: num = smg_num[calendar.sec % 10]; break;   // Second units
    }

    LED_Write_Data(num, smg_wei);  // Write data
    LED_Refresh();  // Refresh display
    smg_wei = (smg_wei + 1) % 8;  // Cycle through bit selection
}


// 流水燈效果(LED0-LED7依次閃爍)
void Flow_LED(void) {
    flow_count++;
    if(flow_count >= 20) {  // Adjust flowing speed
        flow_count = 0;

        // Use bit operation to light current LED
        LED_Shift = ~(1 << flow_index);  // Light current LED
        LED_ON_OFF(LED_Shift);

        flow_index = (flow_index + 1) % 8;  // Cycle through LEDs
    }
}

// 串口命令處理函數
void USART_ProcessCommand(u8* buf, u16 len) {
    // Compare received command with "SOS received"
    const char* cmd = "SOS received";

    if(len == strlen(cmd)) {
        if(strncmp((char*)buf, cmd, len) == 0) {
            // LED0 to LED7 all on and buzzer sounds
            all_led_on = 1;
            all_led_timer = 0;
            sos_beep_flag = 1; // 啟動SOS蜂鳴器
            sos_beep_timer = 0;
            // Output confirmation message to serial
            printf("All LEDs ON and Buzzer activated\r\n");
        }
    }

    // 處理設置時間命令
    if(len >= 7 && strncmp((char*)buf, "SETTIME:", 8) == 0) {
        // 命令格式: SETTIME:2024-01-01 12:00:00
        int year, month, day, hour, min, sec;
        if(sscanf((char*)buf + 8, "%d-%d-%d %d:%d:%d",
                  &year, &month, &day, &hour, &min, &sec) == 6) {
            RTC_Set(year, month, day, hour, min, sec);
            printf("RTC time set to: %d-%02d-%02d %02d:%02d:%02d\r\n",
                   year, month, day, hour, min, sec);
        } else {
            printf("Invalid time format. Use: SETTIME:YYYY-MM-DD HH:MM:SS\r\n");
        }
    }

    // 處理重置命令
    if(len == 6 && strncmp((char*)buf, "RESET", 5) == 0) {
        Reset_To_Normal_State();
        printf("System manually reset to normal state\r\n");
    }
}

void TIM3_PWM_Init(u16 arr, u16 psc)
{  
    // 1. 開啟時鐘
    RCC->APB1ENR |= 1 << 1;    // TIM3時鐘使能
    RCC->APB2ENR |= 1 << 4;    // GPIOC時鐘使能
    RCC->APB2ENR |= 1 << 0;    // AFIO時鐘使能

    // 2. 配置GPIO為復用推挽輸出
    // PC6 - TIM3_CH1 (完全重映射)
    GPIOC->CRL &= 0xF0FFFFFF;  // 清除PC6配置位
    GPIOC->CRL |= 0x0B000000;  // 50MHz, 復用推挽輸出

    // PC7 - TIM3_CH2 (完全重映射)
    GPIOC->CRL &= 0x0FFFFFFF;  // 清除PC7配置位
    GPIOC->CRL |= 0xB0000000;  // 50MHz, 復用推挽輸出

    // 3. 完全重映射:TIM3_CH1->PC6, TIM3_CH2->PC7
    AFIO->MAPR &= 0xFFFFF3FF;  // 清除MAPR的[11:10]
    AFIO->MAPR |= 3 << 10;     // 完全重映射 (11)

    // 4. 配置TIM3時基
    TIM3->ARR = arr;           // 自動重裝載值
    TIM3->PSC = psc;           // 預分頻器

    // 5. 配置通道1 (PC6)
    TIM3->CCMR1 |= 6 << 4;     // OC1M=110, PWM模式1
    TIM3->CCMR1 |= 1 << 3;     // OC1PE=1, 預裝載使能
    TIM3->CCER |= 1 << 0;      // CC1E=1, 輸出使能
    TIM3->CCR1 = 500;          // 初始占空比50%

    // 6. 配置通道2 (PC7)
    TIM3->CCMR1 |= 6 << 12;    // OC2M=110, PWM模式1  
    TIM3->CCMR1 |= 1 << 11;    // OC2PE=1, 預裝載使能
    TIM3->CCER |= 1 << 4;      // CC2E=1, 輸出使能
    TIM3->CCR2 = 500;          // 初始占空比50%

    // 7. 使能定時器
    TIM3->CR1 |= 1 << 7;       // ARPE=1, 自動重裝載預裝載使能
    TIM3->CR1 |= 1 << 0;       // CEN=1, 使能計數器

    printf("TIM3 PWM Initialized: PC6(TIM3_CH1), PC7(TIM3_CH2)\r\n");
}


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:685462 發表于 2025-11-7 23:05 | 只看該作者
感覺思路可以使用定時器實現呼吸,從暗到亮,從亮到暗。比如呼吸時間從暗-亮-暗總時間4s,明暗級別50級,亮度每一級時間us為4x1000/(50+50)=40us。至于哪個燈運行,按你的邏輯編輯程序就好了
回復

使用道具 舉報

板凳
ID:1155037 發表于 2025-11-8 11:22 | 只看該作者
    TIM3_PWM_Init(999, 71);             // RTC初始化     while(RTC_Init()) {         printf("RTC Init Failed!\r\n");         delay_ms(800);         printf("RTC Retry Init...\r\n");     }      // 設置RTC為北京時間     Set_RTC_To_Beijing_Time();      // 初始化定時器     TIM3_Init(19, 7199);    // 定時器3初始化,2ms中斷一次     TIM2_Init(499, 7199);   // 定時器2初始化,50ms中斷一次
回復

使用道具 舉報

地板
ID:1162684 發表于 2025-11-11 16:36 | 只看該作者
lose2836 發表于 2025-11-7 23:05
感覺思路可以使用定時器實現呼吸,從暗到亮,從亮到暗。比如呼吸時間從暗-亮-暗總時間4s,明暗級別50級,亮 ...

感謝!
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表