秒表的设计与开发 (1) 要求在MSP-LAB上实现秒表(跑步计时表)功能 ① 要求仅实现时分秒毫秒、十进制以1ms为单位的纯累加计时显示,两种显示方式切换; (2) 秒表记录功能 ① 支持正计时功能,此时可以同时记录两人以上的同时起步,不同到达用时;两个或者多个记录完毕之后,可以翻阅查看不同的计时值; ② 正计时,可以暂停、停止、继续、清零重新开始等操作逻辑; ③ 可以支持倒计时功能,倒计时时间到,则数码管闪烁、LED闪烁/蜂鸣器响提醒。编写代码
时间: 2024-02-09 22:10:12 浏览: 66
好的,以下是一个基本的MSP-LAB秒表代码,实现了时分秒毫秒的纯累加计时显示、正计时记录、倒计时功能:
```
#include "msp430g2553.h"
#define MAX_TIMERS 8 //最多同时记录8个计时器
volatile unsigned long int millis = 0; //毫秒计时器
volatile unsigned int seconds = 0; //秒计时器
volatile unsigned int minutes = 0; //分钟计时器
volatile unsigned int hours = 0; //小时计时器
volatile unsigned int timers[MAX_TIMERS] = {0}; //计时器数组
volatile unsigned int num_timers = 0; //当前记录的计时器数量
volatile unsigned int countdown = 0; //倒计时时间
volatile unsigned int countdown_running = 0; //倒计时是否正在运行
void init_timer(void)
{
TA0CTL = TASSEL_2 + ID_0 + MC_1; //SMCLK时钟源,不分频,Up模式
TA0CCR0 = 1000 - 1; //1ms产生一次中断
TA0CCTL0 = CCIE; //开启比较模块0中断
}
void update_display(void)
{
//将毫秒计时器转换为时分秒毫秒并显示
unsigned long int total_millis = millis + seconds * 1000 + minutes * 60000 + hours * 3600000;
unsigned int ms = total_millis % 1000;
unsigned int s = (total_millis / 1000) % 60;
unsigned int m = (total_millis / 60000) % 60;
unsigned int h = total_millis / 3600000;
//根据显示模式选择不同的显示方式
if(P1IN & BIT3) //P1.3口高电平为纯累加计时
{
P1OUT = (ms / 100) << 4 | (ms % 100 / 10) << 1 | 1; //以毫秒为单位显示
}
else //P1.3口低电平为时分秒毫秒显示
{
P1OUT = (h / 10) << 5 | (h % 10) << 1 | 1; //以时分秒毫秒为单位显示
__delay_cycles(1000);
P1OUT = (m / 10) << 5 | (m % 10) << 1 | 1; //以时分秒毫秒为单位显示
__delay_cycles(1000);
P1OUT = (s / 10) << 5 | (s % 10) << 1 | 1; //以时分秒毫秒为单位显示
__delay_cycles(1000);
P1OUT = (ms / 100) << 5 | (ms % 100 / 10) << 1 | 1; //以时分秒毫秒为单位显示
__delay_cycles(1000);
}
}
void start_timer(void)
{
if(num_timers < MAX_TIMERS) //如果还有空闲计时器
{
timers[num_timers++] = millis; //记录当前毫秒计时器的值
}
}
void stop_timer(unsigned int index)
{
if(index < num_timers) //如果该计时器存在
{
unsigned int elapsed = millis - timers[index]; //计算消耗的毫秒数
unsigned int ms = elapsed % 1000;
unsigned int s = (elapsed / 1000) % 60;
unsigned int m = (elapsed / 60000) % 60;
unsigned int h = elapsed / 3600000;
//以时分秒毫秒的格式输出
printf("Timer %d: %d:%02d:%02d.%03d\n", index + 1, h, m, s, ms);
//将该计时器从数组中删除
for(unsigned int i = index + 1; i < num_timers; i++)
{
timers[i - 1] = timers[i];
}
num_timers--;
}
}
void clear_timers(void)
{
num_timers = 0; //清空所有计时器
}
void start_countdown(unsigned int seconds)
{
countdown = seconds * 1000; //转换为毫秒
countdown_running = 1; //开始倒计时
}
void stop_countdown(void)
{
countdown_running = 0; //停止倒计时
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; //停止看门狗定时器
P1SEL &= ~BIT3; //P1.3口设为普通I/O口
P1DIR &= ~BIT3; //P1.3口设为输入口
P1REN |= BIT3; //P1.3口开启上拉电阻
P1OUT |= BIT3; //P1.3口上拉
P1SEL &= ~BIT0; //P1.0口设为普通I/O口
P1DIR |= BIT0; //P1.0口设为输出口
init_timer(); //初始化定时器
__enable_interrupt(); //开启全局中断
while(1)
{
if((P1IN & BIT3) == 0) //如果P1.3口被按下
{
//切换显示方式
P1OUT ^= BIT0;
__delay_cycles(500000); //延时,防止按键抖动
}
if((P1IN & BIT4) == 0) //如果P1.4口被按下
{
//开始记录计时器
start_timer();
__delay_cycles(500000); //延时,防止按键抖动
}
if((P1IN & BIT5) == 0) //如果P1.5口被按下
{
//停止记录计时器,并输出计时结果
stop_timer(num_timers - 1);
__delay_cycles(500000); //延时,防止按键抖动
}
if((P1IN & BIT6) == 0) //如果P1.6口被按下
{
//清空所有计时器
clear_timers();
__delay_cycles(500000); //延时,防止按键抖动
}
if((P1IN & BIT7) == 0) //如果P1.7口被按下
{
//开始倒计时
start_countdown(10); //设定倒计时时间为10秒
__delay_cycles(500000); //延时,防止按键抖动
}
}
}
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer0_A0_ISR(void)
{
millis++; //毫秒计时器加1
if(millis >= 1000) //如果毫秒计时器达到1秒
{
millis = 0; //重置毫秒计时器
seconds++; //秒计时器加1
if(seconds >= 60) //如果秒计时器达到60秒
{
seconds = 0; //重置秒计时器
minutes++; //分钟计时器加1
if(minutes >= 60) //如果分钟计时器达到60分钟
{
minutes = 0; //重置分钟计时器
hours++; //小时计时器加1
}
}
}
if(countdown_running) //如果倒计时正在运行
{
if(countdown == 0) //如果倒计时时间到了
{
P1OUT |= BIT0; //数码管闪烁
P1OUT |= BIT6; //LED闪烁
P2OUT |= BIT0; //蜂鸣器响
}
else //否则继续倒计时
{
countdown--; //倒计时器减1
}
}
update_display(); //更新显示
}
```
注意:以上代码只是一个基本的示例,可能存在一些错误或者不足之处,需要根据具体的硬件和需求进行修改和完善。另外,由于我无法在您的MSP-LAB环境中进行测试,因此无法保证代码的完全正确性,需要您自行进行测试和调试。
阅读全文