找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 179|回复: 2
打印 上一主题 下一主题
收起左侧

求一个STM32的8个流水灯

[复制链接]
跳转到指定楼层
楼主
ID:1151234 发表于 2025-5-22 00:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
通过按键能够实现对灯光的启动、关闭、效果花样切换功能 3.设计要求至少控制8盏LED灯,能够完成至少四种花样的切换加分项:能够实现灯光能与蜂鸣器的配合
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1155444 发表于 2025-6-27 09:31 | 只看该作者
#include "stm32f10x.h"

// 硬件定义
#define LED_PORT GPIOA
#define LED_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | \
                 GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7)

#define KEY_PORT GPIOB
#define KEY_PIN GPIO_Pin_0

#define BEEP_PORT GPIOB
#define BEEP_PIN GPIO_Pin_1

// 系统状态
typedef enum {
    SYSTEM_OFF,
    SYSTEM_RUNNING
} SystemState;

// 灯光模式
typedef enum {
    MODE_1_RIGHT_LEFT,
    MODE_2_LEFT_RIGHT,
    MODE_3_INSIDE_OUT,
    MODE_4_BLINK_ALL,
    MODE_COUNT
} LightMode;

// 全局变量
volatile SystemState sysState = SYSTEM_OFF;
volatile LightMode currentMode = MODE_1_RIGHT_LEFT;
uint8_t ledPosition = 0;
uint16_t delayCounter = 0;
uint8_t blinkState = 0;

// 函数原型
void RCC_Configure(void);
void GPIO_Configure(void);
void TIM_Configure(void);
void SysTick_Handler(void);
void UpdateLEDs(void);
void Beep(uint16_t duration, uint8_t times);
void ProcessKey(void);

int main(void) {
    // 初始化
    RCC_Configure();
    GPIO_Configure();
    TIM_Configure();
   
    // 系统启动提示
    Beep(100, 2);
   
    while(1) {
        ProcessKey();
        __WFI();  // 进入低功耗模式等待中断
    }
}

// 时钟配置
void RCC_Configure(void) {
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
                           RCC_APB2Periph_AFIO, ENABLE);
   
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
}

// GPIO配置
void GPIO_Configure(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
   
    // LED配置 - PA0~PA7
    GPIO_InitStructure.GPIO_Pin = LED_PINS;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(LED_PORT, &GPIO_InitStructure);
    LED_PORT->ODR = 0x00;  // 初始关闭所有LED
   
    // 按键配置 - PB0 (外部上拉)
    GPIO_InitStructure.GPIO_Pin = KEY_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(KEY_PORT, &GPIO_InitStructure);
   
    // 蜂鸣器配置 - PB1
    GPIO_InitStructure.GPIO_Pin = BEEP_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(BEEP_PORT, &GPIO_InitStructure);
    GPIO_ResetBits(BEEP_PORT, BEEP_PIN);
}

// 定时器配置 - 10ms中断一次
void TIM_Configure(void) {
    TIM_TimeBaseInitTypeDef TIM_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
   
    TIM_InitStructure.TIM_Period = 1000 - 1;      // 自动重装载值
    TIM_InitStructure.TIM_Prescaler = 720 - 1;     // 72MHz/720 = 100kHz
    TIM_InitStructure.TIM_ClockDivision = 0;
    TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_InitStructure);
   
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    TIM_Cmd(TIM2, ENABLE);
   
    // 配置中断
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

// 蜂鸣器控制
void Beep(uint16_t duration, uint8_t times) {
    for(uint8_t i = 0; i < times; i++) {
        GPIO_SetBits(BEEP_PORT, BEEP_PIN);
        for(volatile uint32_t j = 0; j < duration * 1000; j++);
        GPIO_ResetBits(BEEP_PORT, BEEP_PIN);
        for(volatile uint32_t j = 0; j < 10000; j++); // 短暂间隔
    }
}

// 处理按键
void ProcessKey(void) {
    static uint8_t keyLastState = 1;  // 假设初始高电平
    static uint32_t pressTime = 0;
   
    uint8_t currentState = GPIO_ReadInputDataBit(KEY_PORT, KEY_PIN);
   
    // 检测按键按下 (下降沿)
    if((keyLastState == 1) && (currentState == 0)) {
        pressTime = 0;
    }
   
    // 检测按键释放 (上升沿)
    if((keyLastState == 0) && (currentState == 1)) {
        if(pressTime < 50) {  // 短按 (<0.5s)
            if(sysState == SYSTEM_OFF) {
                sysState = SYSTEM_RUNNING;  // 启动系统
                Beep(100, 1);
            } else {
                // 切换灯光模式
                currentMode = (currentMode + 1) % MODE_COUNT;
                Beep(150, currentMode + 1);
                ledPosition = 0;  // 重置灯光位置
            }
        } else {  // 长按 (>0.5s)
            sysState = (sysState == SYSTEM_OFF) ? SYSTEM_RUNNING : SYSTEM_OFF;
            Beep(100, (sysState == SYSTEM_ON) ? 1 : 2);
            LED_PORT->ODR = 0x00;  // 关闭所有LED
        }
    }
   
    keyLastState = currentState;
    pressTime++;
}

// 更新LED显示
void UpdateLEDs(void) {
    if(sysState != SYSTEM_RUNNING) return;
   
    if(delayCounter++ < 10) return;  // 100ms延迟
    delayCounter = 0;
   
    switch(currentMode) {
        case MODE_1_RIGHT_LEFT:  // 从左向右流水灯
            LED_PORT->ODR = (1 << ledPosition);
            ledPosition = (ledPosition + 1) % 8;
            break;
            
        case MODE_2_LEFT_RIGHT:  // 从右向左流水灯
            LED_PORT->ODR = (0x80 >> ledPosition);
            ledPosition = (ledPosition + 1) % 8;
            break;
            
        case MODE_3_INSIDE_OUT:  // 从中间向两边扩展
            if(ledPosition < 4) {
                LED_PORT->ODR = (1 << (3 - ledPosition)) | (1 << (4 + ledPosition));
            } else {
                LED_PORT->ODR = 0;
            }
            ledPosition = (ledPosition + 1) % 5;
            break;
            
        case MODE_4_BLINK_ALL:  // 所有LED同步闪烁
            LED_PORT->ODR = blinkState ? 0xFF : 0x00;
            blinkState = !blinkState;
            break;
    }
}

// 定时器中断 (10ms)
void TIM2_IRQHandler(void) {
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        UpdateLEDs();
        ProcessKey();
    }
}
回复

使用道具 举报

板凳
ID:1152291 发表于 2025-6-27 14:47 | 只看该作者
这种的程序网上开源的很多,你需要去网上找找,在这个网站学习STM32完全不够用的哦,你要去别的网站再去搜寻点STM32的资料哦
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表