基于STM32的时钟设计及Proteus仿真实现在六位数码管上显示

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、项目介绍
  • 二、代码展示
  • 1.SMG.C
  • 2.SWG.H
  • 3.timer.c
  • 4.timer.h
  • 5.main.c
  • 三、Proteus仿真
  • 四、总结

  • 前言

    提示:这里可以添加本文要记录的大概内容:

    例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


    提示:以下是本篇文章正文内容,下面案例可供参考

    一、项目介绍

    本项目包含KEIL代码编写和Proteus代码仿真两部分,主要通过基础定时器实现时钟功能,难点在于在六位数码管上显示,本项目采用定时器3的中断,以一秒为一单位,重点对时间的处理,让小时,分钟,秒显示在数码管上,项目扩展部分,可以加入按键来进行一个时间的设置与校准。
    Proteus仿真方面,配置好I/O后,在驱动数码管时,需要添加74LS245模块来增强I/O的驱动能力,数码管采用的是共阳极连接,对于段选和位选这里就不多赘述,值得注意的是,段选和位选的I/O分配最好不要都在一个I/O上,这样避免GPIO写入时发生冲突。

    二、代码展示

    1.SMG.C

    代码如下(示例):

    #include "stm32f10x.h"
    #include "smg.h"
    void SMG_Init(void)
    {
    	GPIO_InitTypeDef  GPIO_InitStructure;
    //使能GPIOC时钟
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOC, ENABLE); 
    	GPIO_InitStructure.GPIO_Pin = 0x00ff;					//PC0-PC7引脚配置
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //配置为推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //GPIOC速度为50MHz
     	GPIO_Init(GPIOC, &GPIO_InitStructure);				//初始化PC0-PC7
    	GPIO_InitStructure.GPIO_Pin = 0x003f;					//PB0-PC5引脚配置
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //配置为推挽输出
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;   //GPIOB速度为50MHz
     	GPIO_Init(GPIOB, &GPIO_InitStructure);				//初始化PB0-PB5
    }
    

    2.SWG.H

    代码如下(示例):

    #ifndef __SMG_H
    #define __SMG_H
    void SMG_Init(void);  
    #endif
    

    3.timer.c

    #include "timer.h"
    #include "stm32f10x_tim.h"
    
    int count=0;
    // 通用定时器3中断初始化
    // 这里时钟选择为APB1的2倍,而APB1为36M
    // arr:自动重装值。
    // psc:时钟预分频数
    // 这里使用的是定时器3!
    void TIM3_Int_Init(u16 arr, u16 psc)
    {
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 						// 时钟使能
    	
    	// 定时器TIM3初始化
    	TIM_TimeBaseStructure.TIM_Period = arr; 												// 设置在下一个更新事件装入活动的自动重装载寄存器周期的值	
    	TIM_TimeBaseStructure.TIM_Prescaler = psc; 											// 设置用来作为TIMx时钟频率除数的预分频值
    	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 				// 设置时钟分割:TDTS = Tck_tim
    	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  		// TIM向上计数模式
    	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 								// 根据指定的参数初始化TIMx的时间基数单位
     
    	TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); 											// 使能指定的TIM3中断,允许更新中断
    
    	// 中断优先级NVIC设置
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//设定中断优先级分组0
    	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  								// TIM3中断
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  			// 先占优先级0级
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  						// 从优先级3级
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 								// IRQ通道被使能
    	NVIC_Init(&NVIC_InitStructure);  																// 初始化NVIC寄存器
    
    	TIM_Cmd(TIM3, ENABLE);  																				// 使能TIMx					 
    }
    
    
    // 定时器3中断服务程序
    void TIM3_IRQHandler (void)  																		  // TIM3中断
    {
    	if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  						// 检查TIM3更新中断发生与否
    	{
    		count++;
    		
    		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);  									// 清除TIMx更新中断标志 
    	}
    }
    
    

    4.timer.h

    #ifndef __TIMER_H
    #define __TIMER_H
    
    #include "sys.h" 
    
    extern int count;
    void TIM3_Int_Init(u16 arr,u16 psc);
     
    #endif
    
    

    5.main.c

    #include "stm32f10x.h"
    #include "Delay.h"
    #include "smg.h"
    #include "timer.h"
    //定义0~9十个数字的字型码表
    uint16_t table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};   
    uint16_t wei[]={0x0fe,0x0fd,0x0fb,0x0f7,0x0ef,0x0df,0xff,0xff}; //位码;
    int main(void)
    {
    	SMG_Init();
    	TIM3_Int_Init(719,9999);
    	while(1)
    	{
    		
    		if(count<60)
    		{
    			GPIO_Write(GPIOB,wei[0]);
    			GPIO_Write(GPIOC,table[count%10]);
    			Delay(10);
    			GPIO_Write(GPIOB,wei[1]);
    			GPIO_Write(GPIOC,table[count/10%10]);
    			Delay(10);
    			for(uint8_t i=2;i<=5;i++)
    			{
    				GPIO_Write(GPIOB,wei[i]);
    				GPIO_Write(GPIOC,table[0]);
    				Delay(10);
    			}
    		}
    		if(count>=60||count<3600)
    		{
    			int m,n,t=0;
    			n=count/60%10;
    			m=count/60/10;
    			t=count%60;
    			
    			GPIO_Write(GPIOB,wei[0]);
    			GPIO_Write(GPIOC,table[t%10]);
    			Delay(10);
    			
    
    			GPIO_Write(GPIOB,wei[1]);
    			GPIO_Write(GPIOC,table[t/10%10]);
    			Delay(10);
    			
    			GPIO_Write(GPIOB,wei[2]);
    			GPIO_Write(GPIOC,table[n]);
    			Delay(10);
    			
    			GPIO_Write(GPIOB,wei[3]);
    			GPIO_Write(GPIOC,table[m]);
    			Delay(10);
    			
    			GPIO_Write(GPIOB,wei[4]);
    			GPIO_Write(GPIOC,table[0]);
    			Delay(10);
    						
    			GPIO_Write(GPIOB,wei[5]);
    			GPIO_Write(GPIOC,table[0]);
    			Delay(10);
    		}
    		if(count>=3600||count<86400)
    		{
    			int m,n,t,x,y,q=0;
    			x=count/3600/10;
    			y=count/3600%10;
    			q=count%3600;
    			m=q/60/10;
    			n=q/60%10;
    			t=q%60;
    			
    			GPIO_Write(GPIOB,wei[0]);
    			GPIO_Write(GPIOC,table[t%10]);
    			Delay(10);
    			
    			GPIO_Write(GPIOB,wei[1]);
    			GPIO_Write(GPIOC,table[t/10%10]);
    			Delay(10);
    			
    			GPIO_Write(GPIOB,wei[2]);
    			GPIO_Write(GPIOC,table[n]);
    			Delay(10);
    			
    			GPIO_Write(GPIOB,wei[3]);
    			GPIO_Write(GPIOC,table[m]);
    			Delay(10);
    			
    			GPIO_Write(GPIOB,wei[4]);
    			GPIO_Write(GPIOC,table[y]);
    			Delay(10);
    			
    			GPIO_Write(GPIOB,wei[5]);
    			GPIO_Write(GPIOC,table[x]);
    			Delay(10);	
    		}
    		
    	}
    }
    
    

    三、Proteus仿真

    四、总结

    在项目开发时候,需要理解数码管的工作原理,理解段选和位选的区别,对于数码管动态显示来说,认识到同一时间数码管只能显示一位,重点在于定时器中断后时间的处理,需要对数据进行分解。Proteus仿真方面,芯片调频72MHz。

    物联沃分享整理
    物联沃-IOTWORD物联网 » 基于STM32的时钟设计及Proteus仿真实现在六位数码管上显示

    发表评论