stm32f103rct6使用io口直接操控数码管动态显示,使用定时器不用delay延时函数

之前使用数码管做一些东西,由于外设比较少就直接用单片机的IO口控制数码管了。我用的3641BS四位共阳数码管,一共12个引脚,全部使用单片机IO。数码管引脚图如下:

写程序的思路是位选置1,段选为0的地方点亮显示。一般动态显示需要用到延时用于视觉暂留,以前用delay函数空等待,这样只能放在main函数的while循环里面,如果while函数中有程序占用时间过长会产生闪烁的感觉。放在定时器中断里面也会出问题。于是就取消delay函数,把动态扫描程序放在定时器中断中,利用定时器来切换数码管显示位置,方便很多。

main.c

#include "led.h"
#include "delay.h"
#include "sys.h"
//ALIENTEK miniSTM32开发板实验1
//跑马灯实验  
//技术支持:www.openedv.com
//广州市星翼电子科技有限公司

//数码管显示位数
#define  DIS_NUM  3   //修改此数值可设置显示位数  只可减小此值
//共阳数码管段码表
//              0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F    全灭
u8 smg_code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff};
//数码管位选表,最后一位表示全部不选择
uint8_t numb[]={0x08,0x04,0x02,0x01,0x00};
u8 dis_pos=0;   //数码管显示位置
u16 time=0;     //秒表时间
/*******************************************************************************
* Function Name  : Write_data
* Description    : 数码管写段选
* Input          : data :要发送的段选数据
* Output         : None
* Return         : None
*******************************************************************************/
void  Write_data(u8 data)
{
		if((data & 0x80) >> 7)    H=1;
		else  H=0;	 
			if((data & 0x40) >> 6)  G=1;
		else  G=0;	 
			if((data & 0x20) >> 5)  F=1;
		else  F=0;	 
			if((data & 0x10) >> 4)  E=1;
		else  E=0;	 
			if((data & 0x08) >> 3)  D=1;
		else  D=0;	 
			if((data & 0x04) >> 2)  C=1;
		else  C=0;	 
			if((data & 0x02) >> 1)  B=1;
		else  B=0;	 
			if((data & 0x01) )      A=1;
		else  A=0;	 
}
/*******************************************************************************
* Function Name  : dis_bit
* Description    : 数码管显示位置,用于选择某个要显示的数码管
* Input          : pos : 数码管位置
* Output         : None
* Return         : None
*******************************************************************************/
void  dis_bit(u8 pos)
{
	//以下屏蔽的代码也可用
/*	if((pos&0x01)) {		
		DIG1=1;
		DIG2=0;
		DIG3=0;
		DIG4=0;	
	}
	else 	if((pos&0x02)) {		
		DIG1=0;
		DIG2=1;
		DIG3=0;
		DIG4=0;	
	}
	else 	if((pos&0x04)) {		
		DIG1=0;
		DIG2=0;
		DIG3=1;
		DIG4=0;	
	}
	else 	if((pos&0x08)) {		
		DIG1=0;
		DIG2=0;
		DIG3=0;
		DIG4=1;	
	}
	else if(pos==0x00)
	{
		DIG1=0;
		DIG2=0;
		DIG3=0;
		DIG4=1;	
}*/
	switch(pos)
	{
		case 0x01:
			DIG1=1;
			DIG2=0;
			DIG3=0;
			DIG4=0;	
		break;
		case 0x02:
			DIG1=0;
			DIG2=1;
			DIG3=0;
			DIG4=0;	
		break;
		case 0x04:
			DIG1=0;
			DIG2=0;
			DIG3=1;
			DIG4=0;	
		break;
		case 0x08:
			DIG1=0;
			DIG2=0;
			DIG3=0;
			DIG4=1;	
		break;
		case 0x00:
			DIG1=0;
			DIG2=0;
			DIG3=0;
			DIG4=0;	
		break;								
	}
}
/*******************************************************************************
* Function Name  : dis_num
* Description    : 数码管显示数据
* Input          : num:要显示的数据
* Output         : None
* Return         : None
*******************************************************************************/
void  dis_num(u16 num)
{
	u8 tab[4];    //定义一个数组,用于存放各个数码管显示的数据
	tab[3]=smg_code[num%10000/1000];
	tab[2]=smg_code[num%1000/100];
	tab[1]=smg_code[num%100/10];
	tab[0]=smg_code[num%10];       //分离数据

	Write_data(smg_code[16]);   //段选全不亮,消影
  Write_data(tab[dis_pos]);   //送段选
	dis_bit(numb[dis_pos]);     //送位选
}
 /*******************************************************************************
* Function Name  : TIM3_Int_Init
* Description    : 定时器3初始化函数
* Input          : arr:自动重装值。 psc:时钟预分频数
* Output         : None
* Return         : None
* 定时时间=(arr+1)*(psc+1)/72MHz(单位us)
*******************************************************************************/
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_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					 
}

 int main(void)
 {	
	delay_init();	    	 //延时函数初始化	  
	LED_Init();		  		//初始化与LED连接的硬件接口
	TIM3_Int_Init(49,7199);  //定时5ms 时间太长数码管会闪烁
	while(1)
	{ 
		LED1=!LED1;     //LED闪烁
		delay_ms(1000);
	}
 }
 /*******************************************************************************
* Function Name  : TIM3_IRQHandler
* Description    : 定时器3中断处理函数
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void TIM3_IRQHandler(void)
{
  static 	u8 cnt=0;    //定义一个变量用于秒表计数  要定义成static类型,否则 ++cnt>200条件进不去
	if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) 
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update); 
		if(++cnt>200)    //计时1秒时间到
		{	
			cnt=0;
			time++;        //秒钟加1
			if(time>9999)time=0;
		}
		dis_num(time);    //显示数据
		dis_pos++;        //数码管位置变化1位
		if(dis_pos>DIS_NUM)    dis_pos=0;  //限定数码管显示位数,可改小DIS_NUM得到想要的位数	
	}
}
 

 



 数码管控制io口配置文件led.h

#ifndef __LED_H
#define __LED_H	 
#include "sys.h"
//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK战舰STM32开发板
//LED驱动代码	   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/9/2
//版本:V1.0
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved									  
// 
#define LED0 PAout(8)	// PA8
#define LED1 PDout(2)	// PD2	

//1E 2D 3H 4C 5G 6DIG4 7B 8DIG3 9DIG2 10F 11A 12DIG1
//B7 B9 C0 C2 A0 A2    A3 A1    A3    C1  C13    B8

#define A PAout(0)	// 段选a	
#define B PAout(1)	// 段选b	
#define C PAout(2)	// 段选c	
#define D PAout(3)	// 段选d
#define E PAout(4)	// 段选e	
#define F PAout(5)	// 段选f	
#define G PAout(6)	// 段选g	
#define H PAout(7)	// 段选h

#define DIG1 PCout(3)	// 位选1
#define DIG2 PCout(2)	// 位选2	
#define DIG3 PCout(1)	// 位选3	
#define DIG4 PCout(0)	// 位选4

void LED_Init(void);//初始化

		 				    
#endif

实物效果,前面两位数码管显示不完整是因为手机拍照的原因。

 数码管未点亮时工作电流

 数码管正常工作时最大电流

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值