c - 如何开发这个算法?

标签 c assembly fpga intel-fpga nios

pollkey() 应该每毫秒调用一次,tick(&timeloc) 应该每秒调用一次,我没有线程库。显而易见的方法是使用线程来完成,但现在看来我需要有关如何执行这两个更新的建议。我正在尝试的代码是

int main() {
    while (TRUE) {
        pollkey();
        puttime(&timeloc);
        delay(1);
        IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_REDLED18_BASE, timeloc);
        if (RUN == 1) {
            tick(&timeloc);
            puthex(timeloc);
        }

    }
    return 0;
}

但我不认为以上是 100% 正确的。整个程序是

#include <stdio.h>
#include "system.h"
#include "altera_avalon_pio_regs.h"
extern void puttime(int* timeloc);
extern void puthex(int time);
extern void tick(int* timeloc);
extern void delay(int millisec);
extern int hexasc(int invalue);

#define TRUE 1
#define KEYS4 ( (unsigned int *) 0x840 )

int timeloc = 0x5957; /* startvalue given in hexadecimal/BCD-code */
int RUN = 0;

void pollkey() {

    int action = IORD_ALTERA_AVALON_PIO_DATA(DE2_PIO_KEYS4_BASE);
    putchar(action);
    if (action == 7) {
        timeloc = 0x0;
    } else if (action == 13) {
        RUN = 0;
    } else if (action == 14) {
        RUN = 1;
    } else if (action == 11) {
        tick(&timeloc);
    }
}

int main() {
    while (TRUE) {
        pollkey();
        puttime(&timeloc);
        delay(1);
        IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_REDLED18_BASE, timeloc);
        if (RUN == 1) {
            tick(&timeloc);
            puthex(timeloc);
        }

    }
    return 0;
}

int hex7seg(int digit) {
    int trantab[] = { 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00,
            0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0e };
    register int tmp = digit & 0xf;
    return (trantab[tmp]);
}

void puthex(int inval) {
    unsigned int hexresult;
    hexresult = hex7seg(inval);
    hexresult = hexresult | (hex7seg(inval >> 4) << 7);
    hexresult = hexresult | (hex7seg(inval >> 8) << 14);
    hexresult = hexresult | (hex7seg(inval >> 12) << 21);
    IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_HEX_LOW28_BASE, hexresult);
}

int hex7seg2(int digit) {
    int trantab[] = { 0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00,
            0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0e };
    register int tmp = digit & 0xf0;
    return (trantab[tmp]);
}

我为延迟创建了子程序,我想我可能不会改变这个:

        .equ    delaycount,     16911 #set right delay value here!
        .text                   # Instructions follow
        .global delay           # Makes "main" globally known

delay:  beq     r4,r0,fin       # exit outer loop

        movi    r8,delaycount   # delay estimation for 1ms

inner:  beq     r8,r0,outer     # exit from inner loop

        subi    r8,r8,1         # decrement inner counter

        br      inner

outer:  subi    r4,r4,1         # decrement outer counter
        br      delay


fin:    ret

打勾文件是

extern void delay(int millisec);

/*
 * tick - update the time by adding one second
 * 
 * Parameter (only one): the address of the time variable.
 */
void tick( int * timeloc )
{
  /* Read time variable. */
  int tmp = * timeloc;

  tmp = tmp + 1; /* try a tick */

  /* if we ticked from 9 seconds to 10, adjust time properly */
  if( (tmp & 0x000f) == 0x000a ) tmp = tmp - 0x000a + 0x0010;

  /* if we ticked from 59 seconds to 60, adjust time properly */
  if( (tmp & 0x00f0) == 0x0060 ) tmp = tmp - 0x0060 + 0x0100;

  /* if we ticked from 9 minutes to 10, adjust time properly */
  if( (tmp & 0x0f00) == 0x0a00 ) tmp = tmp - 0x0a00 + 0x1000;

  /* if we ticked from 59 minutes to 60, adjust time properly */
  if( (tmp & 0xf000) == 0x6000 ) tmp = 0x0000;

  *timeloc = tmp;      /* update memory with new time value */
  delay(1000);
}

它在 1 秒延迟所在的 tick 文件中。你能想出更正确的方法来实现这个结果吗?

最佳答案

对此的标准方法是跟踪最后一次调用函数的时间,并在经过足够长的时间后重新运行它。

#include <unistd.h>
#include <sys/time.h>

#define SLEEP_INTERVAL 200

struct timeval last_pollkey_call, last_tick_call, now, diff;
memset(&last_pollkey_call, 0, sizeof(last_pollkey_call));
memset(&last_tick_call, 0, sizeof(last_pollkey_call));

while(1) {
    gettimeofday(&now, NULL);

    timersub(&now, &last_pollkey_call, &diff);
    if (diff.tv_sec >= 1 || diff.tv_usec >= 1000) {
        pollkey();
        last_pollkey_call = now;
    }

    timersub(&now, &last_tick_call, &diff);
    if (diff.tv_sec >= 1) {
        tick();
        last_tick_call = now;
    }

    usleep(SLEEP_INTERVAL);
}

您可以根据需要设置任意多的不同间隔的事件。

关于c - 如何开发这个算法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18657912/

相关文章:

c - 如何创建静态链接共享库

c - 将字符串解析为空终止数组的最佳方法是什么?

组合常量后缀和可移植数据类型

vhdl - HDL 中的默认分配可靠吗?

c# - 在 C 系列中,在一个循环中,为什​​么 "less than or equal to"比 "less than"符号更受欢迎?

c - ARMv7 汇编语言 : How to add two uint32_t and return a uint64_t result

c++ - 如何定义导出符号的地址

assembly - 增加指针比执行 "mov [pointer+1],eax"更快吗?

hardware - 如何估计某个功能是否会占用 FPGA 上的过多资源?

math - FPGA:使用查找表将范围除以固定数字