野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 226|回复: 1

Proteus8.17仿真STM32,按键点灯异常

[复制链接]
发表于 2025-7-3 15:37:04 | 显示全部楼层 |阅读模式
本帖最后由 lyf123 于 2025-7-3 15:39 编辑

使用Proteus仿真,用STM32和74HC595级联控制64个LED,形成特定图案。while循环中,(1)如果使用自动切换模式,则6幅图案可正常切换;(2)如果使用按键切换时,前3幅图案正常切换,第4至第6幅图案则异常。相关代码,原理图及按键切换的6幅图案如下:
1、按键代码Key.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

/**
  * 函    数:按键初始化
  * 参    数:无
  * 返 回 值:无
  */
void Key_Init(void)
{
        /*开启时钟*/
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);       
       
        /*GPIO初始化*/
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //上拉输入
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);                                               
}

/*获取键码函数*/
uint8_t Key_GetNum(void)
{
        uint8_t KeyNum = 0;                //定义变量,默认键码值为0
       
        if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)                       
        {
                Delay_ms(20);                                                                                        //延时消抖
                while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);       
                Delay_ms(20);                                                                                        //延时消抖
                KeyNum = 1;                                                                                                //置键码为1
        }
        return KeyNum;                        //返回键码值
}



2、主函数代码main.c
#include "stm32f10x.h"                 
#include "Delay.h"
#include "Key.h"

#define HC595_Num 8
uint8_t Data1[HC595_Num] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
uint8_t Data2[HC595_Num] = {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55};
uint8_t Data3[HC595_Num] = {0xFC,0x3F,0xF8,0x1F,0xE0,0x0F,0x80,0x01};
uint8_t Data4[HC595_Num] = {0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00};
uint8_t Data5[HC595_Num] = {0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF};
uint8_t Data6[HC595_Num] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

// 定义74HC595控制引脚
#define HC595_LATCH_PIN    GPIO_Pin_7  // ST_CP /RCK
#define HC595_CLK_PIN      GPIO_Pin_6  // SH_CP /SCK
#define HC595_DATA_PIN     GPIO_Pin_5  // SER /DS
#define HC595_PORT         GPIOA     

/*GPIO初始化*/
void HC595_GPIO_Init(void) {
    GPIO_InitTypeDef GPIO_InitStruct;
   
    // 使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
   
    // 配置引脚为推挽输出
    GPIO_InitStruct.GPIO_Pin = HC595_LATCH_PIN | HC595_CLK_PIN | HC595_DATA_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(HC595_PORT, &GPIO_InitStruct);
   
    // 初始状态:拉低所有引脚
    GPIO_ResetBits(HC595_PORT, HC595_LATCH_PIN | HC595_CLK_PIN | HC595_DATA_PIN);
}



/*74HC595发送数据,多个字节,低位先发*/
void HC595_SendMultipleBytes(uint8_t *data, uint16_t length) {
    // 锁存引脚拉低,准备接收数据
    GPIO_ResetBits(HC595_PORT, HC595_LATCH_PIN);
   
    // 从最后一个字节开始发送(低位优先LSB)
    for (int16_t byte = length - 1; byte >= 0; byte--) {
        for (int8_t bit = 0; bit <= 7; bit++) {
            GPIO_ResetBits(HC595_PORT, HC595_CLK_PIN);  // 时钟拉低
            
            // 发送当前位
            if (data[byte] & (1 << bit)) {
                GPIO_SetBits(HC595_PORT, HC595_DATA_PIN);
            } else {
                GPIO_ResetBits(HC595_PORT, HC595_DATA_PIN);
            }
            
            GPIO_SetBits(HC595_PORT, HC595_CLK_PIN);    // 时钟上升沿
        }
    }
   
    // 所有数据发送完毕后,触发锁存
    GPIO_SetBits(HC595_PORT, HC595_LATCH_PIN);
}




/*主函数*/
int main(void) {
    HC595_GPIO_Init();  // 初始化GPIO
       
        Key_Init();     
        uint8_t *mydata[] = {Data1,Data2,Data3,Data4,Data5,Data6};
       
               
    while (1) {
               
               
                /****1.图案自动切换****/
//                HC595_SendMultipleBytes(Data1,HC595_Num);
//                Delay_ms(500);
//                HC595_SendMultipleBytes(Data2,HC595_Num);
//                Delay_ms(500);
//                HC595_SendMultipleBytes(Data3,HC595_Num);
//                Delay_ms(500);
//                HC595_SendMultipleBytes(Data4,HC595_Num);
//                Delay_ms(500);
//                HC595_SendMultipleBytes(Data5,HC595_Num);
//                Delay_ms(500);
//                HC595_SendMultipleBytes(Data6,HC595_Num);
//                Delay_ms(500);
               
                /****2.按键切换图案****/
                uint8_t KeyNum = Key_GetNum();
                if(KeyNum == 1){
                        static uint8_t pattern = 0;  
                        HC595_SendMultipleBytes(mydata[pattern], HC595_Num);
                        pattern = (pattern + 1 ) % 6;                       
                        Delay_ms(100);  
                }                               
    }
}


原理图,第1次按键

原理图,第1次按键

第2次按键

第2次按键

第3次按键

第3次按键

第4次按键

第4次按键

第5次按键

第5次按键

第6次按键

第6次按键
回复

使用道具 举报

发表于 前天 15:43 | 显示全部楼层
把你的工程发出来,proteus图和程序
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2025-7-19 09:49 , Processed in 0.146977 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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