【单片机】数码管前三位品示一个跑 表,从000到999之间以1%秒速度 运行,当按下一个独立键盘时跑表停 止,松开手后跑表继续运行
时间: 2024-03-09 13:48:01 浏览: 130
好的,这是一个使用单片机控制数码管实现跑表功能的例子。以下是步骤:
1. 确定使用的单片机和数码管类型,并连接电路。这里以STM32F103C8T6单片机和共阳极4位数码管为例,数码管的接口为PA0-PA3。
2. 编写初始化程序,设置GPIO端口为输出模式,并将数码管的所有段熄灭。
3. 编写计数器程序,使用定时器中断计算时间,每隔1%秒更新计数器的值,同时将计数器的值转换为数码管的输出,显示在数码管上。
4. 编写中断程序,处理按键事件。当按下按键时,停止计数器的计数,同时将计数器的值保存下来。当松开按键时,恢复计数器的计数,并将计数器的值更新为保存的值,使得数码管从停止的地方继续运行。
以下是示例代码:
```
#include "stm32f10x.h"
#define SEG_A GPIO_Pin_0
#define SEG_B GPIO_Pin_1
#define SEG_C GPIO_Pin_2
#define SEG_D GPIO_Pin_3
#define SEG_E GPIO_Pin_4
#define SEG_F GPIO_Pin_5
#define SEG_G GPIO_Pin_6
#define SEG_DP GPIO_Pin_7
#define DIGIT_0 GPIO_Pin_8
#define DIGIT_1 GPIO_Pin_9
#define DIGIT_2 GPIO_Pin_10
#define DIGIT_3 GPIO_Pin_11
#define KEY GPIO_Pin_12
int digitToSeg[] = {SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F, // 0
SEG_B|SEG_C, // 1
SEG_A|SEG_B|SEG_G|SEG_E|SEG_D, // 2
SEG_A|SEG_B|SEG_C|SEG_D|SEG_G, // 3
SEG_F|SEG_G|SEG_B|SEG_C, // 4
SEG_A|SEG_F|SEG_G|SEG_C|SEG_D, // 5
SEG_A|SEG_F|SEG_E|SEG_D|SEG_C|SEG_G, // 6
SEG_A|SEG_B|SEG_C, // 7
SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G,// 8
SEG_A|SEG_B|SEG_C|SEG_D|SEG_F|SEG_G}; // 9
volatile uint32_t counter = 0;
volatile uint32_t savedCounter = 0;
volatile int stopFlag = 0;
void initGpio(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_DP |
DIGIT_0 | DIGIT_1 | DIGIT_2 | DIGIT_3 | KEY;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
void initTimer(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 9999;
TIM_TimeBaseStructure.TIM_Prescaler = 7199;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
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);
}
void displayDigit(int digit, int dp, int digitIndex)
{
uint16_t seg = digitToSeg[digit];
if (dp) {
seg |= SEG_DP;
}
switch (digitIndex) {
case 0:
GPIO_SetBits(GPIOA, DIGIT_0);
GPIO_ResetBits(GPIOA, DIGIT_1 | DIGIT_2 | DIGIT_3);
break;
case 1:
GPIO_SetBits(GPIOA, DIGIT_1);
GPIO_ResetBits(GPIOA, DIGIT_0 | DIGIT_2 | DIGIT_3);
break;
case 2:
GPIO_SetBits(GPIOA, DIGIT_2);
GPIO_ResetBits(GPIOA, DIGIT_0 | DIGIT_1 | DIGIT_3);
break;
case 3:
GPIO_SetBits(GPIOA, DIGIT_3);
GPIO_ResetBits(GPIOA, DIGIT_0 | DIGIT_1 | DIGIT_2);
break;
}
GPIO_Write(GPIOA, seg);
}
void displayCounter(uint32_t counter)
{
if (counter > 999) {
counter = 999;
}
int d1 = counter / 100;
int d2 = counter / 10 % 10;
int d3 = counter % 10;
displayDigit(d1, 0, 0);
displayDigit(d2, 1, 1);
displayDigit(d3, 0, 2);
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
if (!stopFlag) {
counter++;
displayCounter(counter);
}
}
}
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line12) != RESET) {
EXTI_ClearITPendingBit(EXTI_Line12);
if (stopFlag) {
stopFlag = 0;
counter = savedCounter;
} else {
stopFlag = 1;
savedCounter = counter;
}
}
}
int main(void)
{
initGpio();
initTimer();
GPIO_SetBits(GPIOA, KEY);
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource12);
EXTI_InitStructure.EXTI_Line = EXTI_Line12;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
while (1) {
}
return 0;
}
```
在该示例代码中,按下KEY键时,跑表会暂停,再次按下KEY键可以恢复跑表。
阅读全文