stm32 七段数码管计时

img

img

img


使用stm32和keil5,使五个数码管从00000向99999计时,到99999的时候重置。我这个代码能编译,但是灯只亮一个,还不变。求指出哪里出了问题。

该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
根据您提供的代码和电路图,我认为问题可能出在以下几个方面:

  1. 您在Seven_Segment()函数中使用了switch语句,但是没有为所有的数字提供对应的段选信号,这会导致一些数字无法正确显示。因此,您需要在switch语句中为所有数字提供对应的段选信号。

  2. main()函数中,您使用了while(1)循环来控制数码管的计时,但是并没有提供任何延时函数,导致程序执行速度非常快,数码管无法正确显示计时结果。因此,您需要在while(1)循环中添加适当的延时函数,例如HAL_Delay()函数。

  3. 在电路图中,您将五个数码管的共阴极接地,但是在程序中,您使用了GPIO_PIN_SET来设置数码管的段选信号,这会导致数码管无法正确显示。因此,您需要使用GPIO_PIN_RESET来设置数码管的段选信号。

基于上述问题,我对您的代码和电路图进行了一些修改,具体修改内容如下:

代码修改:

#include "main.h"
#include "stdio.h"

#define SEGMENT_GPIO_PORT GPIOC
#define SEGMENT_GPIO_PIN_1 GPIO_PIN_0
#define SEGMENT_GPIO_PIN_2 GPIO_PIN_1
#define SEGMENT_GPIO_PIN_3 GPIO_PIN_2
#define SEGMENT_GPIO_PIN_4 GPIO_PIN_3
#define SEGMENT_GPIO_PIN_5 GPIO_PIN_4

void Seven_Segment(int num)
{
    switch(num) {
        case 0:
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_1, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_2, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_3, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_4, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_5, GPIO_PIN_RESET);
            break;
        case 1:
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_2, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_3, GPIO_PIN_RESET);
            break;
        case 2:
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_1, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_2, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_4, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_5, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_3, GPIO_PIN_RESET);
            break;
        case 3:
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_1, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_2, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_3, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_4, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_5, GPIO_PIN_RESET);
            break;
        case 4:
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_2, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_3, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_5, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_4, GPIO_PIN_RESET);
            break;
        case 5:
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_1, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_3, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_4, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_5, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_2, GPIO_PIN_RESET);
            break;
        case 6:
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_1, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_3, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_4, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_5, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_2, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_1, GPIO_PIN_RESET);
            break;
        case 7:
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_1, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_2, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_3, GPIO_PIN_RESET);
            break;
        case 8:
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_1, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_2, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_3, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_4, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_5, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_1, GPIO_PIN_RESET);
            break;
        case 9:
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_1, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_2, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_3, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_4, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_5, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(SEGMENT_GPIO_PORT, SEGMENT_GPIO_PIN_5, GPIO_PIN_RESET);
            break;
    }
}

int main(void)
{
    int i = 0;
    int j = 0;
    int k = 0;
    int l = 0;
    int m = 0;

    HAL_Init();
    SystemClock_Config();
    GPIO_Init();
    MX_TIM2_Init();

    while (1)
    {
        Seven_Segment(i);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_SET);
        HAL_Delay(5);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_RESET);

        Seven_Segment(j);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET);
        HAL_Delay(5);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET);

        Seven_Segment(k);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
        HAL_Delay(5);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);

        Seven_Segment(l);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_SET);
        HAL_Delay(5);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, GPIO_PIN_RESET);

        Seven_Segment(m);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_SET);
        HAL_Delay(5);
        HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_RESET);

        m++;
        if (m == 10)
        {
            l++;
            m = 0;
        }
        if (l == 10)
        {
            k++;
            l = 0;
        }
        if (k == 10)
        {
            j++;
            k = 0;
        }
        if (j == 10)
        {
            i++;
            j = 0;
        }
        if (i == 10)
        {
            i = 0;
            j = 0;
            k = 0;
            l = 0;
            m = 0;
        }
    }
}

电路图修改:

将五个数码管的共阴极改为共阳极,并将数码管的引脚连接到正确的控制端口和引脚上。


如果以上回答对您有所帮助,点击一下采纳该答案~谢谢

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
首先,可以通过以下步骤实现七段数码管的计时功能:

  1. 配置定时器,使用定时器中断来实现每秒更新数码管的显示。

  2. 配置GPIO,控制七段数码管的显示。

  3. 编写计时器中断服务函数,实现秒数的累加和更新数码管的显示。

以下是一个基本的代码示例,你可以根据自己的需求进行修改,注释也非常详细。

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include <stdio.h>

int sec = 0;         // 定义一个变量 sec 表示秒数

/* 数码管共阳极接法,因此亮起的位置为低电平,定义显示字符(共阳极) */
static const uint8_t LCD_ShowChar[] = {
    ~0x3f,        // 0
    ~0x06,        // 1
    ~0x5b,        // 2
    ~0x4f,        // 3
    ~0x66,        // 4
    ~0x6d,        // 5
    ~0x7d,        // 6
    ~0x07,        // 7
    ~0x7f,        // 8
    ~0x6f         // 9
};

/* GPIO端口配置 */
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);    // 使能 GPIO 时钟

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         // 推挽输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        // GPIO输出最大速度是50MHz
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5;    // 数码管的位选和段选IO口
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;         // 推挽输出模式
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        // GPIO输出最大速度是50MHz
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;   // DP和LED指示IO口
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

/* 定时器3配置,定时1s */
void TIM3_Configuration(void)
{
    TIM_TimeBaseInitTypeDef TIM_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);     // 使能TIM3时钟

    TIM_InitStructure.TIM_Period = 1000;            // 定时器周期为 1s
    TIM_InitStructure.TIM_Prescaler = 7199;         // 定时器分频,得到 1MHz 的计数频率
    TIM_InitStructure.TIM_ClockDivision =  TIM_CKD_DIV1;
    TIM_InitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_InitStructure);
    TIM_ClearFlag(TIM3, TIM_FLAG_Update);
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);      // 使能定时器 TIM3 的更新中断

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;          // 中断通道是 TIM3
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 抢占优先级 0
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;        // 子优先级 0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/* 定时器3中断服务函数 */
void TIM3_IRQHandler(void)
{
    /* 检查 TIM3 更新中断是否发生 */
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
    {
        /* 更新数码管显示 */
        GPIO_Write(GPIOC, (uint16_t) (0x003f));          // 关闭所有数码管
        GPIO_Write(GPIOC, (uint16_t) (LCD_ShowChar[sec % 10]));    // 个位
        GPIO_Write(GPIOC, (uint16_t) (0x0040));          // 选择十位,即 BCDEF
        GPIO_Write(GPIOC, (uint16_t) (LCD_ShowChar[sec % 100 / 10])); // 十位
        GPIO_Write(GPIOC, (uint16_t) (0x0050));          // 选择千位,即 CDEFG
        GPIO_Write(GPIOC, (uint16_t) (LCD_ShowChar[sec % 1000 / 100])); // 百位
        GPIO_Write(GPIOC, (uint16_t) (0x0060));          // 选择万位,即 ABFEG
        GPIO_Write(GPIOC, (uint16_t) (LCD_ShowChar[sec % 10000 / 1000])); // 千位
        GPIO_Write(GPIOC, (uint16_t) (0x0070));          // 选择 LED 灯
        if (sec == 0) {
            /* 熄灭 DP 点 */
            GPIO_Write(GPIOB, (uint16_t) (0x00c0));      // DP点
        } else {
            /* 在数码管的第二位上显示 DP 点 */
            GPIO_Write(GPIOB, (uint16_t) (0x0040));      // DP点
        }

        /* 计时器加1 */
        sec++;
        if (sec >= 100000) {         // 值素大于等于99999时,复位计时器
            sec = 0;
        }

        TIM_ClearITPendingBit(TIM3, TIM_IT_Update);    // 清除 TIM3 更新中断标志位
    }
}

int main(void)
{
    GPIO_Configuration();       // 配置GPIO
    TIM3_Configuration();       // 配置定时器3

    /* Enable the TIM3 */
    TIM_Cmd(TIM3, ENABLE);

    while (1);
}

上述代码可以在Keil5下进行编译调试,如果需要更改数字长度或单位时间,可以在相应的位置进行修改。
如果我的回答解决了您的问题,请采纳!

这个代码使用了TIM2定时器和PA0-PA4 GPIO口来控制5个数码管。

#include "stm32f1xx.h"
#define MAX_COUNT 99999
uint32_t counter = 0;
void TIM2_IRQHandler(void)
{
    if(TIM2->SR & TIM_SR_UIF)
    {
        TIM2->SR &= ~TIM_SR_UIF;
        counter++;
        if(counter > MAX_COUNT)
        {
            counter = 0;
        }
        update_display();
    }
}
void update_display(void)
{
    uint32_t temp = counter;
    uint8_t digit[5] = {0};
    for(int i = 0; i < 5; i++)
    {
        digit[i] = temp % 10;
        temp /= 10;
    }
    // Output BCD code to GPIO pins
    GPIOA->ODR &= ~(GPIO_ODR_ODR0 | GPIO_ODR_ODR1 | GPIO_ODR_ODR2 | GPIO_ODR_ODR3 | GPIO_ODR_ODR4);
    GPIOA->ODR |= (digit[0] << 0) | (digit[1] << 1) | (digit[2] << 2) | (digit[3] << 3) | (digit[4] << 4);
}
int main(void)
{
    // Enable GPIOA clock
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
    // Configure PA0-PA4 as output
    GPIOA->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_CNF1 | GPIO_CRL_CNF2 | GPIO_CRL_CNF3 | GPIO_CRL_CNF4);
    GPIOA->CRL |= GPIO_CRL_MODE0_0 | GPIO_CRL_MODE1_0 | GPIO_CRL_MODE2_0 | GPIO_CRL_MODE3_0 | GPIO_CRL_MODE4_0;
    // Enable TIM2 clock
    RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
    // Configure TIM2 to generate 1 second interrupt
    TIM2->PSC = 7199;
    TIM2->ARR = 999;
    TIM2->DIER |= TIM_DIER_UIE;
    // Enable TIM2 interrupt
    NVIC_EnableIRQ(TIM2_IRQn);
    // Start TIM2
    TIM2->CR1 |= TIM_CR1_CEN;
    while(1)
    {
        // Do nothing
    }
}