【STM32学习】(10)STM32F1通用定时器实现脉冲计数器

STM32F1通用定时器实现脉冲计数器

通过TIM3实现定时,我设计的一秒计数一次,然后在数码管(光阳极)上显示。数码不仅记录脉冲,还可以通过按键来调节:

按键1 清零

按键2加一

按键3减一

按键4选择暂停/开始启动 两个功能

需要注意的是:按键1-按键3 的功能必须在按键4选择暂停功能时才能完成,其他情况失效。

接线:

1.PE0接LED灯,放置在中断函数中,起到中断执行提示

2.四个数码管的数据口分别接在PD8- PD15    片选口分别接在PA0-PA3口

3.四个按键分别接在PC0-PC4

 

代码如下:

main.c

/*
创建时间:2019.9.17
创建人:王艇
功能:四个数码管循环显示0000 - 9999

接线:
	每个数码管分别接在PD8-PD15
	四个数码管的驱动口(com)分别接在 PA0-PA3

实现步骤:
	
	
数码管共阳与共阴的区别
*/
#include "stm32f10x.h"                  // Device header
#include "led.h"
#include "key.h"
#include "delay.h"
#include "time.h"

int main(void)
{
	
	GPIOD_init_wt();
	GPIOA_init_wt();
	GPIOC_Init_key();
	
	GPIOE_init_led();
	TIM3_Init(999,35999);	//	0.5s    T = (999+1)*(35999+1)/72MHz = 0.5s

	while(1)
	{
		key_scan();
		display();
	}
}

time.h

#include "stdint.h"

void TIM3_Init(uint16_t per,uint16_t psc);

time.c


#include "stm32f10x_tim.h"

int temp = 1;
extern int cnt;
void TIM3_Init(uint16_t per,uint16_t psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStruct;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	
	TIM_TimeBaseInitStructure.TIM_Period=per; //自动装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
	
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); 
	
	NVIC_InitStruct.NVIC_IRQChannel=TIM3_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=3;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStruct);
	
	TIM_Cmd(TIM3,ENABLE);
}	

void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update) == SET)
	{
		TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
		temp = (-1)*temp;
		if(temp == -1)
		{
			GPIO_WriteBit(GPIOE, GPIO_Pin_0, Bit_SET);
			cnt++;
			if(cnt>9999)
			{
				cnt = 0;
			}
		}
		else
		{
			GPIO_WriteBit(GPIOE, GPIO_Pin_0, Bit_RESET);
			
		}
			
	}
	
}

led.h

void GPIOD_init_wt(void);
void GPIOA_init_wt(void);
void GPIOE_init_led(void);
void display(void);

led.c



/*

函数名:void GPIOA_init_wt(void)
又无参数:	无参
功能:开启GPIOA口
	 低8位推挽输出,50MHz
创建人:王艇
创建时间:2019.9.12

函数名:void GPIOA_init_wt(int x)
又无参数:有参
功能:开启GPIOA口
	 低8位推挽输出,50MHz
修改人:王艇
工号:0111001
创建时间:2019.9.13

*/
#include "stm32f10x_gpio.h"
#include "delay.h"


unsigned short int table1[]={
0xc000,0xf900,0xa400,0xb000,
0x9900,0x9200,0x8200,0xf800,
0x8000,0x9000,0x8800,0x8300,
0xc600,0xa100,0x8600,0x8e00};		//	共阳

unsigned short int table2[]={		//	0-F
0x3f00,0x0600,0x5b00,0x4f00,
0x6600,0x6d00,0x7d00,0x0700,
0x7f00,0x6f00,0x7700,0x7c00,
0x3900,0x5e00,0x7900,0x7100};		//	共阴


int cnt;	//	全局变量,计数
//extern int flag;	//	全局变量,标记位

void GPIOD_init_wt(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;	//	GPIO初始化结构体	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11
								|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOD,&GPIO_InitStruct);
}

void GPIOA_init_wt(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;	//	GPIO初始化结构体	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3; //0000 0000
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
}

void GPIOE_init_led(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;	//	GPIO初始化结构体	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; //0000 0000
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOE,&GPIO_InitStruct);
}


/* 显示1234 */
/*void display(void)
{
	GPIO_Write(GPIOA,0X000E);	// 片选第一个数码管0000 0000 0000 1110
	GPIO_Write(GPIOD,table1[1]);	//	显示1
	delay();
	
	GPIO_Write(GPIOA,0X000D);	// 片选第一个数码管0000 0000 0000 1101
	GPIO_Write(GPIOD,table1[2]);	//	显示1
	delay();
	
	GPIO_Write(GPIOA,0X000B);	// 片选第一个数码管0000 0000 0000 1011
	GPIO_Write(GPIOD,table1[3]);	//	显示1
	delay();
	
	GPIO_Write(GPIOA,0X0007);	// 片选第一个数码管0000 0000 0000 0111
	GPIO_Write(GPIOD,table1[4]);	//	显示1
	delay();
}*/
/* 

数码管动态显示 - 0000 - 9999
创建人:王艇

方法一
*/
//void display(void)
//{
//	int i,j,k,m,n;	//	分别控制个十百千为
//	
//	for(m=0;m<10;m++)
//	{		
//		for(k=0;k<10;k++)
//		{			
//			for(j=0;j<10;j++)
//			{				
//				for(i=0;i<10;i++)
//				{
//					for(n=0;n<10;n++)	//	起延时作用
//					{
//						GPIO_Write(GPIOA,0X000E);	// 片选第一个数码管0000 0000 0000 1110
//						GPIO_Write(GPIOD,table1[m]);	//	显示
//						delay();
//						
//						GPIO_Write(GPIOA,0X000D);	// 片选第一个数码管0000 0000 0000 1110
//						GPIO_Write(GPIOD,table1[k]);	//	显示
//						delay();
//						
//						GPIO_Write(GPIOA,0X000B);	// 片选第一个数码管0000 0000 0000 1110
//						GPIO_Write(GPIOD,table1[j]);	//	显示
//						delay();
//						
//						GPIO_Write(GPIOA,0X0007);	// 片选第一个数码管0000 0000 0000 1110
//						GPIO_Write(GPIOD,table1[i]);	//	显示
//						delay();
//					}
//					
//				}
//			}
//		}
//	}
//	
//}
/* 

数码管动态显示 - 0000 - 9999
创建人:王艇

方法二
*/
//void display(void)
//{
//	int cnt;	//	计数
//	int i;	//	循环变量
//	int g,s,b,q;
//	for(cnt=0;cnt<10000;cnt++)
//	{
//		g = cnt%10;
//		s = cnt%100/10;
//		b = cnt/100%10;
//		q = cnt/1000;
//		for(i=0;i<10;i++)
//		{
//			GPIO_Write(GPIOA,0X000E);	// 片选第一个数码管0000 0000 0000 1110
//			GPIO_Write(GPIOD,table1[q]);	//	显示
//			delay();
//			
//			GPIO_Write(GPIOA,0X000D);	// 片选第一个数码管0000 0000 0000 1110
//			GPIO_Write(GPIOD,table1[b]);	//	显示
//			delay();
//			
//			GPIO_Write(GPIOA,0X000B);	// 片选第一个数码管0000 0000 0000 1110
//			GPIO_Write(GPIOD,table1[s]);	//	显示
//			delay();
//			
//			GPIO_Write(GPIOA,0X0007);	// 片选第一个数码管0000 0000 0000 1110
//			GPIO_Write(GPIOD,table1[g]);	//	显示
//			delay();
//		}
//	}		
//}

/*
数码管动态显示 - 0000 - 9999
创建人:王艇

方法三
*/
void display(void )
{
	int g,s,b,q;
//	if(-1 == flag)
//	{
//		
//	}
//	else if(1 == flag)
//	{
//		cnt++;
//	}
	g = cnt%10;
	s = cnt%100/10;
	b = cnt/100%10;
	q = cnt/1000;
	GPIO_Write(GPIOA,0X000E);	// 片选第一个数码管0000 0000 0000 1110
	GPIO_Write(GPIOD,table1[q]);	//	显示
	delay();
	
	GPIO_Write(GPIOA,0X000D);	// 片选第一个数码管0000 0000 0000 1101
	GPIO_Write(GPIOD,table1[b]);	//	显示
	delay();
	
	GPIO_Write(GPIOA,0X000B);	// 片选第一个数码管0000 0000 0000 1011
	GPIO_Write(GPIOD,table1[s]);	//	显示
	delay();
	
	GPIO_Write(GPIOA,0X0007);	// 片选第一个数码管0000 0000 0000 0111
	GPIO_Write(GPIOD,table1[g]);	//	显示
	delay();		
}

key.h

void GPIOC_Init_key(void);
void key_scan(void);

key.c

/*
创建时间:2019.9.20
创建人:王艇
修改时间:2019.9.23
接线:key1-key4 分别接在PC0-PC3
步骤:
	1.开启时钟
	2.设置工作模式
	3.数据的输入
*/
#include "stm32f10x_rcc.h"
#include "delay.h"

int	flag=1;	//	标记位
extern int cnt;
void GPIOC_Init_key(void)	//	PC0-PC2
{
	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_InitStruct.GPIO_Mode = GPIO_Mode_IPU ;
	GPIO_Init(GPIOC,&GPIO_InitStruct);	
}


void key_scan(void)
{
	//	key1
	if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0 &&(-1 == flag))
	{
		delay_wt();	//	消除抖动
		if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0 &&(-1 == flag))
		{
			cnt=0;
		}
		while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0) == 0);	//	判断按键是否松开
	}
	// key2	加1操作
	if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0 &&(-1 == flag))
	{
		delay_wt();	//	消除抖动
		if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0 &&(-1 == flag))
		{
			cnt++;
			if(cnt>=10000)
			{
				cnt=0;
			}
		}
		while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1) == 0);	//	判断按键是否松开
	}
	
	// key3	减1操作
	if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0 &&(-1 == flag))
	{
		delay_wt();	//	消除抖动
		if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0 &&(-1 == flag))
		{
			cnt--;
			if(cnt<0)
			{
				cnt=9999;
			}
		}
		while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2) == 0);	//	判断按键是否松开
	}

	if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0)
	{
		delay_wt();	//	消除抖动
		if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0)
		{
			flag = (-1)*flag;
			if(flag == 1)
			{
				TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
				//TIM_Cmd(TIM3, ENABLE);
			}
			else
			{
				TIM_ITConfig(TIM3,TIM_IT_Update,DISABLE);
				//TIM_Cmd(TIM3, DISABLE);
			}
		}
		while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3) == 0);	//	判断按键是否松开
	}
}

delay.h

void delay(void);	//	函数声明
void delay_wt(void);

delay.c


void delay(void)
{
	int i,j;
	for(i=0;i<100;i++)
	{
		for(j=0;j<400;j++);
	} 
}

void delay_wt(void)
{
	int i,j;
	for(i=0;i<100;i++)
	{
		for(j=0;j<400;j++);
	} 
}

效果如下:

 

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
首先需要连接一个数码管到STM32开发板上,并且需要了解数码管的工作原理和接线方式。 假设我们使用的是共阴极数码管,接线方式如下: - 数码管的8个引脚分别连接到STM32的8个IO口(例如PA0~PA7)。 - 数码管的共阴极引脚连接到GND。 接线完成后,可以按照以下步骤实现数码管计数: 1. 配置IO口为输出模式。 ```c GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pins : PA0-PA7 */ GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); ``` 2. 定义一个计数器变量,初始值为0。 ```c int count = 0; ``` 3. 在一个循环中,将计数器的值依次显示在数码管上,并且每隔一段时间更新一次计数器的值。可以使用delay函数来实现延时。 ```c while (1) { // 显示计数器的值 display_hex(count); // 延时一段时间 HAL_Delay(100); // 更新计数器的值 count++; if (count > 0xf) { count = 0; } } ``` 4. 编写一个函数display_hex,用于将一个16进制数显示在数码管上。该函数需要将16进制数转换为对应的数码管显示形式,并且输出到IO口。 ```c void display_hex(int hex) { int seg_map[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; int seg_data = seg_map[hex]; for (int i = 0; i < 8; i++) { int bit = (seg_data >> i) & 0x01; HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0+i, bit); } } ``` 在这个函数中,我们定义了一个seg_map数组,用于将16进制数转换为对应的数码管显示形式。例如,当hex=0时,seg_data=0x3f,表示数码管显示0。 然后,我们依次将seg_data的每一位输出到IO口,从而实现数码管的显示。 以上就是一个简单的数码管计数程序的实现方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小材大用

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

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

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

打赏作者

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

抵扣说明:

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

余额充值