一个mm:ss计时器C

时间:2018-08-29 14:15:56

标签: c timer clock teensy

尝试在C中制作一个以mm:ss格式计数的计时器,我不一定需要打印该值,只要有它存在以供参考即可。

这个想法是一个青少年设备上的“已用时间”时钟,计时器每经过一秒钟便会增加1秒,即60秒,分钟计时器会增加1,秒计时器会重置为0。计时器在后台运行,每秒更新一次,作为一种连续的秒表。

类似于下图,但是计时器不会随意启动或停止,它在程序初始化时启动,只需每秒增加一次计数器,不需要转换分钟即可达到99,因为这个时候程序应该已经结束了。

enter image description here

一个例子是一个时钟,显示从开始游戏关卡以来所经过的时间,向用户显示他们花了多长时间来完成游戏关卡。

我在下面进行了介绍,但是由于我不熟悉基于C和C的语言的工作方式,因此不确定自己是否朝着正确的方向前进。

int minutes = 0;
int seconds = 0, trigger = 1000;
clock_t start = clock();
do {
  if(seconds == 60) {
    seconds = 0;
    minutes += 1;
  }
  clock_t difference = clock() - start;
  seconds = difference * 1000 / CLOCKS_PER_SEC;
  i++;
} while ( seconds < trigger );

例如,说x秒过去了;

  • 89秒(1分9秒)

    Time: 01:19
    
  • 360秒(6分钟0秒)

    Time: 06:00
    
  • 27秒(0分钟27秒)

    Time: 00:27
    
  • 4893秒(81分33秒)

    Time: 81:33
    

计时器应返回与上述类似的结果。

Windows系统。

有人可以帮忙吗?您可以组成所需的任何变量或任何变量,因为据我所知,我所做的甚至都无法做到。预先感谢。

2 个答案:

答案 0 :(得分:1)

可以使用Teensy系统通过其溢出和中断来启动计时器。下面的代码将设置并启动一个将递增计数的计时器。一个结构用于初始化一个布尔值(程序中可能有其他事情),该布尔值可用于控制计时器的溢出是否计数,有效地暂停计时器。

绘制字符串的功能

 // Render a string of printable ASCII characters into the screen buffer.
 // Parameters:
 // x - The horizontal position of the top-left corner of the displayed text.
 // y - The vertical position of the top-left corner of the displayed text.
 // character - The ASCII code of the character to render. Valid values range from 
 0x20 == 32 to 0x7f == 127.
 // colour - The colour, FG_COLOUR or BG_COLOUR. If colour is BG_COLOUR,
 the text is rendered as an inverse video block.

void draw_string(int top_left_x, int top_left_y, char *text, colour_t colour) {
    // Draw each character until the null terminator is reached
    for ( uint8_t x = top_left_x, i = 0; text[i] != 0; x += CHAR_WIDTH, i++ ) {
        draw_char(x, top_left_y, text[i], colour);
        // Add a column of spaces here if you want to space out the lettering.
        // (see lcd.c for a hint on how to do this)
    }
}

下面是格式化函数,使用上述函数绘制字符串,该格式化函数用于获取mm:ss布局

// a formatting function to assist with printing to the screen
void draw_formatted(int x, int y, const char * format, ...) {
    va_list args;
    va_start(args, format);
    char buffer[1000];
    vsprintf(buffer, format, args);
    draw_string(x, y, buffer, FG_COLOUR);
}

排序格式后,应创建一个结构以初始化操作计时器所需的值,并启动计时器

// initiates a struct for the timer, which includes a minute, second and 
// validator accessed using tim
struct val_store {
    bool timer_validator;
    uint8_t time_passed
    uint8_t min;
    uint8_t sec;
} tim;

// initiates timer parameters, essentially setting up the timer to be able to function, 
// sets timer to begin, this should be included in the initial setup of a program
TCCR1A = 0;
TCCR1B = 2; 
TIMSK1 = 1;
sei();
tim.timer_validator = true;

下面是计时器的隐藏部分,这是心脏,它创建了作为整个问题基础的值,这非常重要,除非TCCR1A,TCCR1B,TIMSK1和sei(),否则它将不起作用预先初始化,其值可以分别为0、2、1,但是,下面的计时器中使用的值必须使用位图进行相应调整

// Create a volatile global variable called over_flow_count
volatile unsigned int over_flow_count = 0;
//  interrupt service routine to process timer overflow
//  interrupts for Timer 1.
ISR(TIMER1_OVF_vect) {
    // checks if timer is active or not
    if (tim.timer_validator) {
    over_flow_count++;
    }
}
// elapsed time since program start
// use float instead of double to save memory
float elapsed_time(void) {
    float current_time = (float)
        ( ( over_flow_count * 65536.0 + TCNT1 ) * 8.0  / 8000000 );
    return current_time;
}

最后,与上述计时器配合使用以生成mm:ss格式的输出的代码很简单,这是因为上面的计时器完成了所有工作,剩下的只是格式化。传递的时间调用了先前创建的函数,即传递的总时间范围,然后使用除法和取模来找到min和sec,并使用先前制作的格式化函数对其进行格式化

tim.time_passed = elapsed_time();
tim.min = time_passed / 60;
tim.sec = time_passed % 60;
draw_formatted(x, y, "Time: %02d:%02d", tim.min, tim.sec);

可以使用类似的方法创建暂停

if (BIT_VALUE(PINB, 0)) {
    // buffer before and after to prevent a single press activating
    // multiple instances of a joystick press, cheap interrupt
    _delay_ms(250);

    // pauses timer by setting the boolean to false, preventing the if statement passing
    tim.timer_validator = false;

    while(true) {
        clear_screen();
        #Put processes to occur while paused here

        // checks to see if the pause should resume
        if (BIT_VALUE(PINB, 0)) {
            break;
        }

    // continue timer
    tim.timer_validator = true;

    // once again a buffer for good measure
    _delay_ms(250);
    }

如果正确创建了程序,则计时器应追溯更新! 希望对您有帮助!

相关包含,并非所有包含都可以使用。

// includes
#include <assert.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include <cpu_speed.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <util/delay.h>

答案 1 :(得分:0)

不确定此处的用途,只是数秒,直到到达触发器,然后转换为mm:ss?您可以计算到达触发条件之前的秒数,并将触发条件表示为mm:ss,基本上是同一回事。

仅凭猜测,您正在寻找类似的东西吗?

unsigned int minutes = 0;
unsigned int seconds = 0;

unsigned int trigger = 360;
unsigned int elapsed_seconds = 0;

/* Count the seconds until #trigger seconds are reached (?)*/
clock_t start = clock();

do {

  clock_t difference = clock() - start;
  elapsed_seconds = difference * 1000 / CLOCKS_PER_SEC;

  /* Stop at trigger (?)*/
} while ( elapsed_seconds < trigger );

/* Express in minutes and seconds */
minutes = elapsed_seconds / 60;
seconds = elapsed_seconds % 60;

printf("Time: %02d:%02d\n", minutes, seconds);