0

pollkey 関数を 1 ミリ秒に 1 回呼び出し、時間変数 (timeloc) を 1 秒に 1 回インクリメントしたいと考えています。遅延サブルーチンに a を追加すればうまくいくと思いますが、call pollkeyなぜうまくいかないのですか?

        .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
        call    pollkey
        br      delay


fin:    ret

上記はCで実行しました

#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 = 1;

void pollkey() {
    int action = IORD_ALTERA_AVALON_PIO_DATA(DE2_PIO_KEYS4_BASE);
    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) {
        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]);
}

毎秒ポーリングする場合、ポーリングは機能しますが、ミリ秒ごとにポーリングしたいのですが、それができると思う唯一の方法は、dely サブルーチンから pollkey を呼び出すことですが、それを行っても何も起こらないようです。手伝って頂けますか?前にどうしたらいいのか聞いてみたところ、アセンブリを変更すればいいのかと思っていたところ、Cでしか答えがありませんでした。

このアルゴリズムを開発するにはどうすればよいですか?

アップデート

brの代わりに使用した方がはるかに良い結果が得られているcallので、違いを確認する必要があります。これは私が使用しているもので、よりうまく機能します:

        .equ    delaycount,     16911 #set right delay value here!
        .text                   # Instructions follow
        .global delay           # Makes "delay" 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      pollkey
        br      delay


fin:    ret

唯一の問題は、時計が速すぎることです。

アップデート

モジュロ1000を数秒間破るカウンターを導入することで解決したと思います:

#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);
    if (action == 7) {
        timeloc = 0x0;
        puttime(&timeloc);
        puthex(timeloc);
    } else if (action == 13) {
        RUN = 0;
    } else if (action == 14) {
        RUN = 1;
    } else if (action == 11) {
        tick(&timeloc);
        puttime(&timeloc);
        puthex(timeloc);
        delay(1000);
    }
}

int main() {
    int counter = 0;
    while (TRUE) {
        pollkey();
        delay(1);
        ++counter;
        if (counter % 1000 == 0) {
            IOWR_ALTERA_AVALON_PIO_DATA(DE2_PIO_REDLED18_BASE, timeloc);
            if (RUN == 1) {
                tick(&timeloc);
                puttime(&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 "delay" 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
4

1 に答える 1

1

特定のタイムスケールで組み込みシステムでルーチンを実行する正しい方法は、ハードウェア タイマーを使用し、アクション (比較的小さいと仮定して) をそのタイマーの割り込みサービス ルーチンに入れるか、その関数を使用してより長いルーチンを実行するように指示することです。バックグラウンドループで。

delay()関数をボッジすると、

  • 可変遅延 - 遅延関数はすでに命令サイクルを使用した近似値であり、途中で別の関数を呼び出すために実行すると、悪化するだけです
  • inaccurate 1ms polling - 不正確さのレベルは目的に十分である場合とそうでない場合があります。

1 ミリ秒のタイマーを取得したら、pollkeyそこから関数を実行し、より長いイベントを正確にスケジュールすることもできます。

もちろん、その時点で RTOS の構築を開始しているので、いずれにしても RTOS を使用することをお勧めします :)

于 2013-09-07T18:38:51.237 に答える