基于stm32的多功能时钟1——时钟显示

kuaidi.ping-jia.net  作者:佚名   更新日期:2024-08-26
        读者们,大家好!

        接着上一章多功能时钟(绪论)的内容,在这一章中,我将介绍多功能时钟的时钟显示部分。话不多说,我们正式开始吧~

        多功能时钟,时钟显示功能是必不可少的。所以,我们利用stm32的定时器来计时。本来打算采用stm32的RTC实时时钟,但后来想,刚开始弄得时候,尽量简单一些,别一开始就给自己出难题,毕竟RTC实时时钟要配置的东西还挺多的。如果此次做得不错的话,后面可以再加RTC实时时钟。

        stm32不同于51,共有11个定时器,其中2个高级控制定时器(TIM1和TIM8),4个普通定时器(TIM2~TIM5)和2个基本定时器(TIM6和TIM7),以及2个看门狗定时器和1个系统滴答定时器。这里,我们采用普通定时器TIM2,并且开启定时器的中断,中断时间为1s,并且在中断函数里,模拟时钟的计时功能。

(1)配置嵌套中断控制器NVIC

void tim2_nvic_config(void)

{

    NVIC_InitTypeDef NVIC_InitStruct;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;

    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;//抢占优先级为2

    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;//子优先级为0

    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStruct);

}

        这里,我们只需对NVIC_InitStruct结构体的每个元素赋值,其中TIM2_IRQn为定时器TIM2中断线,设置优先级组为2,即抢占优先级组为4组,这里抢占优先级为2,子优先级为0,然后使能NVIC(优先级不能理解上网查询)。

(2)定时器初始化配置

void tim2_config(void)

{

    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

    tim2_nvic_config();                                //配置NVIC

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启时钟

    TIM_DeInit(TIM2);                                      //定时器2复位

    TIM_TimeBaseInitStruct.TIM_Period = 2000-1;                  //自动重装载寄存器值

    TIM_TimeBaseInitStruct.TIM_Prescaler = 36000-1;              //时钟预分频数

    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;    //采样分频

    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; //计数模式

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);            //初始化TIM2

    TIM_ClearFlag(TIM2, TIM_FLAG_Update);                        //清除溢出中断标志

    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

    TIM_Cmd(TIM2, ENABLE);                                      //使能时钟

}

        TIM2初始化,首先配置NVIC,打开TIM2时钟,复位TIM2。然后对TIM_TimeBaseInitStruct结构体的每个元素赋值。这里,主要阐述如何计算定时中断时间。定时器的溢出中断时间由TIM_Period和TIM_Prescaler来决定的。这里,我直接给出公式:发生中断时间=(TIM_Period+1)*(TIM_Prescaler+1)/FCLK,而FCLK为72M,所以定时1s,可以这样:TIM_Period=2000-1,TIM_Prescaler=36000-1;最后清除溢出中断标志,使能时钟即可计时。

(3)编写中断计时函数

void TIM2_IRQHandler(void)

{

    if(TIM_GetITStatus(TIM2 ,TIM_IT_Update)!=RESET)

    {

        sec++;

        if(sec>=60)

        {

            sec = 0;

            min++;

            if(min>=60)

            {

                min = 0;

                hour++;

                if(hour>=24)

                {

                    hour = 0;

                }

            }

        }

    }

    TIM_ClearITPendingBit(TIM2 ,TIM_FLAG_Update);

}

这里,先定义时、分、秒三个变量,然后在中断函数里,对时间变量的关系进行换算即可。

(4)编写时钟显示函数

        这里,我们采用LCD12864实时显示。LCD12864的相关内容,我后面在LCD库函数章节中,会专门介绍的。这里,只将时间显示即可。

    lcd_display_num_m(2, 16, hour/10);

    lcd_display_num_m(2, 24, hour%10);

    lcd_display_string(2,32,"时");

    lcd_display_num_m(2, 48, min/10);

    lcd_display_num_m(2, 56, min%10);

    lcd_display_string(2,64,"分");

    lcd_display_num_m(2, 80, sec/10);

    lcd_display_num_m(2, 88, sec%10);

    lcd_display_string(2,96,"秒");

        LCD12864的驱动函数,我跟着黄老师的视频后面写的,在老师的基础上,增加了汉字字符串显示函数。这里,看成库函数即可,只需简单的调用,显示时间就行。

(5)按键调整时间

        成功显示时间后,我们需要按键来调整时间。 我们需要设置时钟启/停键(K1),时间位选择键(K2),数值增加键(K3),数值减小键(K4)。

1.我们先对按键的GPIO进行配置,开启相应的时钟,选择相关引脚,设置浮空输入模式等。

void key_gpio_init(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    /*使能GPIO的RCC时钟*/

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

    /*配置PB11~PB14引脚*/

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_Init(GPIOB,&GPIO_InitStructure);

}

2.配置好按键的GPIO口后,编写按键扫描函数,从而达到调整时间的功能。

u8 flag,mark;//flag为定时器启停标志位,mark为位选择标志位

//mark为0表示未选中,mark为1表示选择时位,mark为2表示选择分位,mark为3表示选择秒位

void keyscan(void)

{

    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET)

    {

        delay_ms(10);

        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET)

        {

            flag = ~flag;

            if(!flag)

            {

                TIM_Cmd(TIM2, ENABLE);

            }

            else

            {

                TIM_Cmd(TIM2, DISABLE);

                mark = 0;

            }

        }while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11)==RESET);

    }

    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET)

    {

        delay_ms(10);

        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET)

        {

            mark = mark>=3?0:mark+1;

        }while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12)==RESET);

    }

    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET)

    {

        delay_ms(10);

        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET)

        {

            if(flag)

            {

                switch(mark)

                {

                    case 1:hour = hour<23?hour+1:0;break;

                    case 2:min = min<59?min+1:0;break;

                    case 3:sec = sec<59?sec+1:0;break;

                    default:break;

                }

            }

        }while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==RESET);

    }

    if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET)

    {

        delay_ms(10);

        if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET)

        {

            if(flag)

            {

                switch(mark)

                {

                    case 1:hour = hour>0?hour-1:23;break;

                    case 2:min = min>0?min-1:59;break;

                    case 3:sec = sec>0?sec-1:59;break;

                    default:break;

                }

            }

        }while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==RESET);

    }

}

        至此,我们完成了时钟显示的功能,当然,后期如果可以的话,我们可以使用stm32的RTC实时时钟资源,还可以设置闹钟、整点报时的功能。

         本章,我主要介绍了如何利用stm32的TIM定时器和GPIO资源,实现时钟显示和按键调整的功能。下一章中,我将介绍如何利用DHT11模块来测量温度和湿度,从而实现系统对环境参量的获取。

  • STM32单片机最小系统详解
    答:复位引脚NRST负责单片机的重启,它是一个低电平复位系统,用于初始化单片机到预设状态。上电复位则是通过外接电容和电阻来实现的,确保在适当的时间内达到复位条件。晶振电路则提供了两种时钟源,主时钟和RTC时钟,分别使用8MHz和32.768KHz的晶振,确保精准的时间同步。STM32的时钟模式有内外两种,可以根据...
  • 毕业论文设计 基于STM32的四键输入多模式时钟显示在TFT 我买的是ALIN...
    答:有开发板应该很容易做吧,我也有他们公司的开发板,mini版的
  • stm32的1自增到27000多少毫秒
    答:通常情况下,stm32的时钟频率是72MHz或者更高。假设stm32的时钟频率是72MHz(即每秒钟能进行72000000次操作),那么就可以计算出1自增到27000需要的时间。时间(秒) = 增量 / 时钟频率其中,增量为27000,时钟频率为72000000。所以,时间(秒)= 27000 / 72000000 ≈ 0.000375 秒将秒转换为毫秒,...
  • stm32 RTC时钟加个倒计时
    答:在RTC中断里面设置一个变量,每次减1就可以了啊!当然你可以把显示的函数也放在RTC中断里,这样每秒的变化都能显示在液晶上。
  • 单片机STM32中,在使能用到的时钟是,为什么多个外设可以通过|运算符写 ...
    答:STM32的外设在使用之前必须先对其使能!只要在同一条总线上外设,可以利用“|”对多个外设时钟进行同时使能!“|”是个位运算符,如0000 1111 | 1111 0000 = 1111 1111 比如:使能APB2总线上的GPIOD和GPIOE。APB2ENR的复位值为0x0000 0000 如果使能了ENABLE RCC->APB2ENR |= RCC_APB2Periph; ...
  • 想用stm32的定时器,定时一分钟,该怎样做呀?尽量描述细点,谢谢了_百度...
    答:首先,你做一个100ms的时钟中断,然后设一个int counter = 0;变量,每进入一次中断,对他加1(counter++),直到他等于 60s/0.1s = 600时,就是一分钟了,然后counter清零继续累加。
  • 2018-04-26 STM32中使用内部RC振荡器做系统时钟
    答:STM32使用内部RC振荡器时,OSC32_IN,OSC32_OUT接法:    1)对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。    2)对于少于100脚的产品,有2种接法:          ...
  • stm32的rtc实时时钟实验设计要求目的
    答:stm32的rtc实时时钟实验设计要求目的是测试功能。STM32的RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
  • 请问stm32的引脚时钟设置或者其他的时钟设置有什么意义吗?程序的执行...
    答:51单片机的引脚也需要时钟吗?---需要,不过也不是必须的,有些有片内时钟,看你自己应用情况 这到底是什么意思啊,时钟不就是来推动程序执行的,怎么引脚等外设会需要时钟?引脚不是什么外设,引脚是输入输入的一个接口,可以是电源,地,时钟,中断,总线等等,时钟你就可以理解为是个输入引脚就可以...
  • STM32的系统默认时钟是多少
    答:如果你没有做配置,系统默认时钟频率是72MHz的。system_stm32f10x.c文件中有定义。define SYSCLK_FREQ_72MHz 72000000