RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);,第1张

        读者们,大家好!

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

        多功能时钟,时钟显示功能是必不可少的。所以,我们利用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_InitStructNVIC_IRQChannel = TIM2_IRQn;

    NVIC_InitStructNVIC_IRQChannelPreemptionPriority = 2;//抢占优先级为2

    NVIC_InitStructNVIC_IRQChannelSubPriority = 0;//子优先级为0

    NVIC_InitStructNVIC_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_TimeBaseInitStructTIM_Period = 2000-1;                  //自动重装载寄存器值

    TIM_TimeBaseInitStructTIM_Prescaler = 36000-1;              //时钟预分频数

    TIM_TimeBaseInitStructTIM_ClockDivision = TIM_CKD_DIV1;    //采样分频

    TIM_TimeBaseInitStructTIM_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_InitStructureGPIO_Pin = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14;

    GPIO_InitStructureGPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructureGPIO_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>=30: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<23hour+1:0;break;

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

                    case 3:sec = sec<59sec+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>0hour-1:23;break;

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

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

                    default:break;

                }

            }

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

    }

}

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

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

Stm32共有11个定时器:

1两个高级定时器:TIM1、TIM8-------------------------APB2

2四个通用定时器:TIM2~TIM5-------------------------APB1

3两个基本定时器:TIM6、TIM7-------------------------APB1

4两个看门狗

5一个系统嘀嗒定时器(SysTick)

主程序mainc

说明: 

PA0:KEY1;PA1:KEY2; 

PA2:LED1;PA3:LED2; 

PA9:USART1_TX;PA10:USART1_RX 

/  

#include "stm32f10xh"  

#include "stm32f10x_rcch"  

#include "stm32f10x_gpioh"  

#include "stm32f10x_timh"  

#include "stm32f10x_extih"  

#include "system_stm32f10xh"  

#include "misch"  

  

void RCC_Configuration(void);  

void GPIO_Configuration(void);   

void TIM3_Configuration(void);  

void NVIC_Configuration(void);  

  

int main()  

{  

    SystemInit();  

      

    RCC_Configuration();  

    GPIO_Configuration();   

    TIM3_Configuration();  

    NVIC_Configuration();  

                                                              

    while(1);  

}  

  

void RCC_Configuration(void)    

{     

  ////USART2和USART3都在在APB1上而USART1是在APB2上的  

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);     

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);     

}   

  

void GPIO_Configuration(void)    

{    

  GPIO_InitTypeDef GPIO_InitStructure;    

    

  GPIO_InitStructureGPIO_Pin = GPIO_Pin_2|GPIO_Pin_3;    

  GPIO_InitStructureGPIO_Speed = GPIO_Speed_50MHz;  

  GPIO_InitStructureGPIO_Mode = GPIO_Mode_Out_PP;  

  GPIO_Init(GPIOA, &GPIO_InitStructure);   

}  

  

void TIM3_Configuration(void)    

{  

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  

    

  TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  

    

  TIM_TimeBaseStructureTIM_Period = 2000;//频率:72MHz  72000000/36000=2000  

  TIM_TimeBaseStructureTIM_Prescaler = 35999;//36000-1=35999  

  TIM_TimeBaseStructureTIM_ClockDivision = 0x0;  

  TIM_TimeBaseStructureTIM_CounterMode = TIM_CounterMode_Up;  

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  

    

  TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE );  

  TIM_Cmd(TIM3,ENABLE);  

}  

  

void NVIC_Configuration(void)//配置中断优先级    

{    

  NVIC_InitTypeDef NVIC_InitStructure;    

      

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);    

      

  NVIC_InitStructureNVIC_IRQChannel = TIM3_IRQn;    

  NVIC_InitStructureNVIC_IRQChannelPreemptionPriority = 0;    

  NVIC_InitStructureNVIC_IRQChannelSubPriority = 1;    

  NVIC_InitStructureNVIC_IRQChannelCmd = ENABLE;    

  NVIC_Init(&NVIC_InitStructure);    

}

中断函数stm32f10x_itc

#include "\include\stm32f10xh"   

#include "\include\stm32f10x_ith"  

#include "\include\stm32f10x_gpioh"  

#include "\include\stm32f10x_timh"  

  

void TIM3_IRQHandler(void)  

{  

  TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  

    

  if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)==Bit_RESET)  

  {  

    GPIO_SetBits(GPIOA,GPIO_Pin_2);  

  }else{  

    GPIO_ResetBits(GPIOA,GPIO_Pin_2);  

  }  

}

中断函数声明头文件stm32f10x_ith

#ifndef __STM32F10x_IT_H  

#define __STM32F10x_IT_H  

  

/ Includes ------------------------------------------------------------------/  

/ Exported types ------------------------------------------------------------/  

/ Exported constants --------------------------------------------------------/  

/ Exported macro ------------------------------------------------------------/  

/ Exported functions ------------------------------------------------------- /    

void NMIException(void);  

void HardFaultException(void);  

void MemManageException(void);  

void BusFaultException(void);  

void UsageFaultException(void);  

void DebugMonitor(void);  

void SVCHandler(void);  

void PendSVC(void);  

void SysTickHandler(void);  

void WWDG_IRQHandler(void);  

void PVD_IRQHandler(void);  

void TAMPER_IRQHandler(void);  

void RTC_IRQHandler(void);  

void FLASH_IRQHandler(void);  

void RCC_IRQHandler(void);  

void EXTI0_IRQHandler(void);  

void EXTI1_IRQHandler(void);  

void EXTI2_IRQHandler(void);  

void EXTI3_IRQHandler(void);  

void EXTI4_IRQHandler(void);  

void DMA1_Channel1_IRQHandler(void);  

void DMA1_Channel2_IRQHandler(void);  

void DMA1_Channel3_IRQHandler(void);  

void DMA1_Channel4_IRQHandler(void);  

void DMA1_Channel5_IRQHandler(void);  

void DMA1_Channel6_IRQHandler(void);  

void DMA1_Channel7_IRQHandler(void);  

void ADC1_2_IRQHandler(void);  

void USB_HP_CAN_TX_IRQHandler(void);  

void USB_LP_CAN_RX0_IRQHandler(void);  

void CAN_RX1_IRQHandler(void);  

void CAN_SCE_IRQHandler(void);  

void EXTI9_5_IRQHandler(void);  

void TIM1_BRK_IRQHandler(void);  

void TIM1_UP_IRQHandler(void);  

void TIM1_TRG_COM_IRQHandler(void);  

void TIM1_CC_IRQHandler(void);  

void TIM2_IRQHandler(void);  

void TIM3_IRQHandler(void);  

void TIM4_IRQHandler(void);  

void I2C1_EV_IRQHandler(void);  

void I2C1_ER_IRQHandler(void);  

void I2C2_EV_IRQHandler(void);  

void I2C2_ER_IRQHandler(void);  

void SPI1_IRQHandler(void);  

void SPI2_IRQHandler(void);  

void USART1_IRQHandler(void);  

void USART2_IRQHandler(void);  

void USART3_IRQHandler(void);  

void EXTI15_10_IRQHandler(void);  

void RTCAlarm_IRQHandler(void);  

void USBWakeUp_IRQHandler(void);  

void TIM8_BRK_IRQHandler(void);  

void TIM8_UP_IRQHandler(void);  

void TIM8_TRG_COM_IRQHandler(void);  

void TIM8_CC_IRQHandler(void);  

void ADC3_IRQHandler(void);  

void FSMC_IRQHandler(void);  

void SDIO_IRQHandler(void);  

void TIM5_IRQHandler(void);  

void SPI3_IRQHandler(void);  

void UART4_IRQHandler(void);  

void UART5_IRQHandler(void);  

void TIM6_IRQHandler(void);  

void TIM7_IRQHandler(void);  

void DMA2_Channel1_IRQHandler(void);  

void DMA2_Channel2_IRQHandler(void);  

void DMA2_Channel3_IRQHandler(void);  

void DMA2_Channel4_5_IRQHandler(void);  

                       

#endif / __STM32F10x_IT_H /  

  

/ (C) COPYRIGHT 2008 STMicroelectronics END OF FILE/

void TIM2_Int_Init(u16 arr,u16 psc)

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

TIM_TimeBaseStructureTIM_Period = arr;

TIM_TimeBaseStructureTIM_Prescaler =psc;

TIM_TimeBaseStructureTIM_ClockDivision = TIM_CKD_DIV1;

TIM_TimeBaseStructureTIM_CounterMode = TIM_CounterMode_Up; //up

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE ); //中断

TIM_Cmd(TIM2, ENABLE); //使能

}

32定时器tim2-7 的频率等于APB1倍频数 倍频数:1 或2

tim2-7的倍频数取决于APB1的预分频数

预分频数为1时 倍频数也为1

预分频数不为1 倍频数为2

由于apb1最大36mhz,所以当AHB为72MHZ时,分频数需大于1,倍频数就为2

取分频数为2

则TIM时钟=72MHZ(ahb)/2分频2倍频=72;

改为

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

{

TIM_ClearITPendingBit(TIM3, TIM_IT_Update );

LED1 = 0 ;//LED亮

}

vu16型最大是32767,timercounter超出32767后从-32768开始计数,从32700到-32700,共计数是682=136,超出100了,也许是这个问题,你可以试试在if(timercounter%100==0)里面把timercounter清零

以上就是关于基于stm32的多功能时钟1——时钟显示全部的内容,包括:基于stm32的多功能时钟1——时钟显示、新人求助 刚接触STM32 做一个开关控制LED灯闪烁 调试一直没反应、RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/8811964.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-21
下一篇2023-04-21

发表评论

登录后才能评论

评论列表(0条)

    保存