[STM32学习]定时器实现码表(数码管显示)

实验:要求完成码表,具体要求如下:

要求:显示格式XX.YY。
    按键1 可控制计数暂停还是启动
    按键2 清零(必需在暂停后才可以操作
    按键3 存储当前码表的时间,存储成功后显示y(必需在暂停后才可以操作
    按键4 显示存储的码表时间(必需在暂停后才可以操作
    按键5 记录的码表时间向下翻页(必需在暂停后才可以操作

简单分析:

      码表,其实就是显示秒的下一个单位,电子手表上一般都有码表的功能,秒到分钟一般是59秒进行,而码表的下一个单位,则要计到99上才能进位到1秒,所以需要修改定时器,将定时器修改成10ms溢出中断一次,这样记录100次后就达到了1秒。

Tim4Init(719, 999);		//	定时10ms 720*1000/72000000 = 1/100

我们在完成实验之前一定要搞清楚它的硬件电路,分析好引脚所对应的IO口,下图为数码管硬件设计图,完全可以按照电路图设计。

由上图可以知道,该数码管为四位八段数码管,引脚分析如下

数码管电路STM32的IO口
A1PB2
A2PB3
A3PB4
A4PB5
aPE0
bPE1
cPE2
dPE3
ePE4
fPE5
gPE6
dpPC13

通过上述电路图可知,数码管为共阳极数码管,PB2-PB5低电平选中数码管,其中,注意:PB3和PB3引脚默认状态下不是普通的IO口,所以需要用到其复用功能:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);		//	开启服用引脚时钟,保证引脚第二功能正常使用
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //关闭JTAG,使能SWD

数码管为共阳极数码管,其编码为:

//	共阳极编码 0-9 a- f
unsigned char seg[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

接下来是按键的截下图,如下:

 引脚对应关系:

按键STM32 的IO引脚
KEY1PC0
KEY2PC1
KEY3PC2
KEY4PC3
KEY5PC4

接下来依据任务要求完成代码:

按键初始化:

/********************************************
函数名称:void KeyInit(void)
函数参数:无参,返回值为空
函数功能:实现按键功能初始化
作者:***
时间:2022.3.8
修改作者:
修改实现:
修改说明:
*********************************************/
void KeyInit(void)
{
	// KEY接在PC0-PC4上,一共5个按键
	//初始化步骤
	/**
		1.开启所对应的时钟
		2.选择所需要的IO口
		3.设置IO口的工作模式
		4.初始化上述配置
	**/
	GPIO_InitTypeDef GPIO_InitStruct;											//	结构体变量申明
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);	//	开启时钟
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3
								|GPIO_Pin_4;	//  选择PC0-PC4口
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;			//	浮空输入模式
	
	GPIO_Init(GPIOC,&GPIO_InitStruct);													//	配置初始化
	
}

数码管初始化:

/********************************************
函数名称:void SegInit(void)
函数参数:无参,返回值为空
函数功能:实现数码管初始化
作者:***
时间:2022.3.17
修改作者:
修改实现:
修改说明:
*********************************************/
void SegInit(void)
{
	//初始化步骤
	/**
		1.开启所对应的时钟
		2.选择所需要的IO口
		3.设置IO口的工作模式
		4.设置IO的输出速率(当IO口设置成输出模式才需要)
		5.初始化上述配置
		6.初始化IO的初值
	**/
	GPIO_InitTypeDef GPIO_InitStruct;											//	结构体变量申明
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);	//	开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);	//	开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);	//	开启时钟
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);		//	开启服用引脚时钟,保证引脚第二功能正常使用

	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); //关闭JTAG,使能SWD

	//	设置片选引脚
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5;	//  选择PB2-PB5口
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;								//	推挽输出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;							//	设置输出速率50MHz
	GPIO_Init(GPIOB,&GPIO_InitStruct);													//	配置初始化
	
	//	设置七段引脚
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3
								|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6;	//  选择PE0-PE6口
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;								//	推挽输出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;							//	设置输出速率50MHz
	GPIO_Init(GPIOE,&GPIO_InitStruct);													//	配置初始化
	
	//	设置DP(小数点)引脚
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;	//  选择PE0-PE6口
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;								//	推挽输出
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;							//	设置输出速率50MHz
	GPIO_Init(GPIOC,&GPIO_InitStruct);													//	配置初始化
	
	GPIO_Write(GPIOE, 0X007F);		//	设置七段引脚为高电平   0111 1111
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);		//	小数点
	GPIO_WriteBit(GPIOB,GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5,Bit_SET);		//	设置片选引脚为高电平
	
}

定时器中断服务函数:

/********************************************
函数名称:TIM4_IRQHandler(void)
函数参数:
				无参,无返回参数
函数功能:定时器定时10ms
作者:***
时间:2022.5.19
修改作者:
修改时间:
修改说明:
修改作者:
修改时间:
修改说明:
*********************************************/
void TIM4_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM4, TIM_IT_Update) == 1)		//	标志计数溢出中断产生
	{
		tim4Cnt++;			//	秒统计
		if(tim4Cnt>9999)		//	99:99			99*100+99
		{
			tim4Cnt = 0;
		}
	}
	TIM_ClearITPendingBit(TIM4, TIM_IT_Update);	
}

按键功能实现:

/********************************************
函数名称:int KeyScan6(void)
函数参数:无
函数功能:要求:显示格式XX.YY。
				按键1可控制计数暂停还是启动
				按键2 清零(必需在暂停后才可以操作)
				按键3 存储当前码表的时间,存储成功后显示y
				按键4 显示存储的码表时间
				按键5 记录的码表时间向下翻页
作者:***
时间:2022.5.19
修改作者:
修改实现:
修改说明:
*********************************************/
void KeyScan6(void)
{
	if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0	)			//	判断按键是否按下
	{
		delay_ms(10);	//	消抖
		if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0	)
		{
			flag = -1*flag;	//	-1和1跳转
		}
		while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0);
	}
	if(1 == flag)	//	计数
	{
		TIM_Cmd(TIM4,ENABLE);
	}
	if(-1 == flag) //	暂停
	{
		TIM_Cmd(TIM4,DISABLE);		//	关闭定时器
		
		if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0	)			//	判断按键是否按下
		{
			delay_ms(10);	//	消抖
			if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0	)
			{
				tim4Cnt = 0;		//	在暂停的条件下实现码表清0 
			}
			while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0);
		}
		if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0	)			//	判断按键是否按下
		{
			delay_ms(10);	//	消抖
			if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0	)
			{
				saveTime[key3Cnt] = tim4Cnt;
				key3Cnt++;			//	按键按下次数统计
				if(key3Cnt>9)
				{
					key3Cnt = 0;			//	计数归0
				}
				//SegDis10();			//	显示y
			}
			while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0)		//	按键松开检查
			{
				SegDis10();			//	显示y
			}
		}
		
		if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0	)			//	判断按键是否按下
		{
			delay_ms(10);	//	消抖
			if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0	)
			{		
				tim4Cnt = saveTime[0];
			}
			while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0);		//	按键松开检查
		}
		
		if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0	)			//	判断按键是否按下
		{
			delay_ms(10);	//	消抖
			if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0	)
			{
				key5Cnt++;    					//	按键按下计数 
				if(key5Cnt>9)
				{
					key5Cnt = 0;		//	归0
				}
				tim4Cnt = saveTime[key5Cnt];
			}
			while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_4) == 0);		//	按键松开检查
		}		
	}
	
	SegDis9();
}

数码管功能实现:


/********************************************
函数名称:void SegDis9(int value)
函数参数:无参,返回值为空
函数功能:
					要求:显示格式XX.YY。
作者:***
时间:2022.5.17
修改作者:
修改实现:
修改说明:
*********************************************/
void SegDis9(void)
{
		
	//	数码管a
	GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_RESET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);	//	
	GPIO_Write(GPIOE, seg[tim4Cnt/1000]);								//	可以实现多位写入
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);	//	小数点不需要显示
	delay_ms(5);
	//	数码管b
	GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_RESET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);	//	
	GPIO_Write(GPIOE, seg[tim4Cnt/100%10]);								//	可以实现多位写入
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);	//	小数点不需要显示
	delay_ms(5);
	//	数码管c
	GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_RESET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);	//	
	GPIO_Write(GPIOE, seg[tim4Cnt/10%10]);								//	可以实现多位写入
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);	//	小数点不需要显示
	delay_ms(5);
	//	数码管d
	GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_RESET);	//	
	GPIO_Write(GPIOE, seg[tim4Cnt%10]);								//	可以实现多位写入
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);	//	小数点不需要显示
	delay_ms(5);
}

/********************************************
函数名称:void SegDis10(int value)
函数参数:无参,返回值为空
函数功能:
					要求:y。
					共阳极编码y的值:0X91
作者:***
时间:2022.5.17
修改作者:
修改实现:
修改说明:
*********************************************/
void SegDis10(void)
{
	//	数码管a
	GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_RESET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);	//	
	GPIO_Write(GPIOE, 0X91);								//	可以实现多位写入
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);	//	小数点不需要显示
	delay_ms(5);
	//	数码管b
	GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_RESET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);	//	
	GPIO_Write(GPIOE, 0X91);								//	可以实现多位写入
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);	//	小数点不需要显示
	delay_ms(5);
	//	数码管c
	GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_RESET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);	//	
	GPIO_Write(GPIOE, 0X91);								//	可以实现多位写入
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);	//	小数点不需要显示
	delay_ms(5);
	//	数码管d
	GPIO_WriteBit(GPIOB,GPIO_Pin_2,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_3,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_4,Bit_SET);		//	
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_RESET);	//	
	GPIO_Write(GPIOE, 0X91);								//	可以实现多位写入
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);	//	小数点不需要显示
	delay_ms(5);
}

实现效果:

源码下载地址:定时器实现码表(数码管显示)-C文档类资源-CSDN文库

  • 11
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
实现这个功能,你可以通过以下步骤来进行: 1. 配置定时器 首先,你需要配置一个定时器,并使其产生中断。在定时器的中断服务函数中,你可以更新显示的数字并输出到数码管。 2. 配置数码管 你需要将数码管连接到 MCU 的 GPIO 引脚上,并设置这些引脚为输出模式。然后,你需要根据你的硬件连接方式和数码管类型来编写驱动代码,以便将数字显示到数码管上。 3. 编写中断服务程序 在定时器中断服务函数中,你需要实现以下功能: a. 记录当前要显示的数字 b. 更新数字以显示下一个数字 c. 将数字输出到数码管上 4. 调试代码 在编写完代码后,你需要调试它,确保它能够正确地将数字显示在数码管上。 下面是一个示例代码,用于 STM32F103C8T6 开发板,使用定时器 TIM2 和共阳数码管来显示数字: ``` #include "stm32f10x.h" #include "stm32f10x_gpio.h" #include "stm32f10x_tim.h" // 数码管引脚定义 #define LED_A GPIO_Pin_0 #define LED_B GPIO_Pin_1 #define LED_C GPIO_Pin_2 #define LED_D GPIO_Pin_3 #define LED_E GPIO_Pin_4 #define LED_F GPIO_Pin_5 #define LED_G GPIO_Pin_6 #define LED_DP GPIO_Pin_7 // 数码管数字表 const uint8_t LED_NUMS[] = { 0x3F, // 0 0x06, // 1 0x5B, // 2 0x4F, // 3 0x66, // 4 0x6D, // 5 0x7D, // 6 0x07, // 7 0x7F, // 8 0x6F, // 9 }; uint8_t led_index = 0; // 当前要显示的数字 // 数码管显示函数 void LED_Display(uint8_t num) { GPIO_Write(GPIOB, LED_NUMS[num]); } // 定时器中断服务函数 void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) == RESET) { return; } TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 更新数码管显示 LED_Display(led_index++ % 10); } // 主函数 int main(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; // 使能 GPIOB 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 配置 PB0 - PB7 为推挽输出模式 GPIO_InitStructure.GPIO_Pin = LED_A | LED_B | LED_C | LED_D | LED_E | LED_F | LED_G | LED_DP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); // 使能 TIM2 时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); // 配置 TIM2 TIM_TimeBaseStructure.TIM_Period = 1999; // 定时器重装值,控制定时周期 TIM_TimeBaseStructure.TIM_Prescaler = 7199; // 定时器预分频值,控制定时器时钟频率 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); // 使能定时器中断 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); // 配置定时器中断优先级 NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 启动定时器 TIM_Cmd(TIM2, ENABLE); while (1) { // 主循环空闲 } } ``` 这段代码使用 TIM2 定时器,每隔 100ms 切换数码管显示的数字,将 0-9 循环显示在数码管上。你需要根据你的硬件和需求来进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小材大用

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值