Picoblaze从中断错误返回

时间:2018-05-18 18:53:51

标签: assembly verilog fpga

我们有蓝牙模块,当接收器数据被更改时,它会发送中断信号到picoblaze并通过中断确认降低该信号。 中断子程序工作成功但系统无法返回主程序。当我们运行系统主循环按要求流动但在中断信号之后它停留在中断子程序中。我们能够一遍又一遍地调用中断子程序但是不能回到主循环。

我们的汇编代码是:

CONSTANT SONAR, 81
CONSTANT REMOTE, 82
CONSTANT MOTOR_R, 83
CONSTANT MOTOR_L, 84

CONSTANT ILERI, 00
CONSTANT SAG, 01
CONSTANT SOL, 02
CONSTANT SAGX, 03
CONSTANT SOLX, 04
CONSTANT ILERI2, 08
CONSTANT SAG2, 09
CONSTANT SOL2, 0A
CONSTANT SAGX2, 0B
CONSTANT SOLX2, 0C
CONSTANT HIZLAN, 05
CONSTANT YAVASLA, 06

NAMEREG sD, SPEED
NAMEREG sC, ENGELLER

LOAD sE, 00
LOAD SPEED, 3F  ; hiz degeri 0 ile 128 arasi degissin, main icinde degeri 
degisebilsin

ENABLE INTERRUPT

LOOP:

INPUT ENGELLER, 81

COMPARE ENGELLER, 1
JUMP NZ SOLSERBEST
CALL RIGHT
CALL DELAY_QS
JUMP LOOP

SOLSERBEST:

COMPARE ENGELLER, 2
JUMP NZ SAGSERBEST
CALL LEFT
CALL DELAY_QS
JUMP LOOP

SAGSERBEST:

CALL FORWARD
CALL DELAY_QS
JUMP LOOP

;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ileri ve geri fonksiyonlari birlestirilebilir 
ilk bitin degeri main icinde verilirse

    FORWARD:                    ; her hamleden once pwm 0 ediliyor
    LOAD sE, 00         
    OUTPUT sE, MOTOR_R      ; MOTOR_R gelen port id'e gore degisecek
    OUTPUT sE, MOTOR_L      ; ikinci pwm modulune
    TEST sE, 00         ; delay

    ADD sE, SPEED
    ADD sE, 80          ; simdiki sisteme gore ilk biti 1 yapilip ileri yon 
veriliyor

    OUTPUT sE, MOTOR_R      
    OUTPUT sE, MOTOR_L

    LOAD sE, 00
    RETURN


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RIGHT:
    LOAD sE, 00
    OUTPUT sE, MOTOR_R
    OUTPUT sE, MOTOR_L
    TEST sE, 00

    ADD sE, SPEED
    ADD sE, 80          ; bu herhalde ileri olacak :D

    OUTPUT sE, MOTOR_R      ; sag motor MOTOR_R deymis gibi

    LOAD sE, 00
    RETURN

LEFT:
    LOAD sE, 00
    OUTPUT sE, MOTOR_R
    OUTPUT sE, MOTOR_L
    TEST sE, 00

    ADD sE, SPEED
    ADD sE, 80          ; bu herhalde ileri olacak :D

    OUTPUT sE, MOTOR_L      ; sol motor MOTOR_L deymis gibi

    LOAD sE, 00
    RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;      
FORW_R:
    LOAD sE, 00
    OUTPUT sE, MOTOR_R
    OUTPUT sE, MOTOR_L
    TEST sE, 00

    ADD sE, SPEED
    SR0 sE              ; sol motora hizin yarisi gitsin
    ADD sE, 80          ; ikisi de ileri

    OUTPUT sE, MOTOR_L
    TEST sE, 00         ; delay

    ADD sE, SPEED           ; sag motora hizin bir bucuk kati gitsin

    OUTPUT sE, MOTOR_R

    LOAD sE,00
    RETURN


FORW_L:
    LOAD sE, 00
    OUTPUT sE, MOTOR_R
    OUTPUT sE, MOTOR_L
    TEST sE, 00

    ADD sE, SPEED
    SR0 sE              ; sag motora hizin yarisi gitsin
    ADD sE, 80

    OUTPUT sE, MOTOR_R
    TEST sE, 00         ; delay

    ADD sE, SPEED           ; sol motora hizin bir bucuk kati gitsin

    OUTPUT sE, MOTOR_L

    LOAD sE,00
    RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DELAY_1S:
    LOAD s0, 80
    LOAD s1, F0
    LOAD s2, FA
    LOAD s3, 02

DONGU1:
    SUB s0, 01
    JUMP NZ, DONGU1
DONGU2:
    SUB s1, 01
    JUMP Z, DONGU3
    LOAD s0, FF
    JUMP DONGU1
DONGU3:
    SUB s2, 01
    JUMP Z, DONGU4
    LOAD s1, FF
    JUMP DONGU2
DONGU4:
    SUB s3, 01
    RETURN Z
    LOAD s2, FF
    JUMP DONGU3

    RETURN          ; bu komut calisirsa fonksiyon yanlistir :D



ISR:
INPUT sC, REMOTE    ; bluetoothtan veri okunsun

COMPARE sC, ILERI       ; komutlari tek tek deniyo, ilerde TEST kullanan 
 guzel bu hale getirebilirim
JUMP NZ, SECIM2
CALL FORWARD        ; bu 1 saniyelik ileri komutu
CALL DELAY_1S
RETURNI ENABLE

SECIM2:
COMPARE sC, SAG
JUMP NZ, SECIM3
CALL RIGHT          ; 1 saniyelik sag
CALL DELAY_1S
RETURNI ENABLE

SECIM3:
COMPARE sC, SOL
JUMP NZ, SECIM4
CALL LEFT           ; 1 saniyelik sol
CALL DELAY_1S
RETURNI ENABLE

SECIM4:
COMPARE sC, SAGX
JUMP NZ, SECIM5
CALL FORW_R         ; 1 saniyelik ileri sag
CALL DELAY_1S
RETURNI ENABLE

SECIM5:
COMPARE sC, SOLX
JUMP NZ, SECIM6
CALL FORW_L         ; 1 saniyelik ileri sol
CALL DELAY_1S
RETURNI ENABLE

SECIM6:
COMPARE sC, ILERI2
JUMP NZ, SECIM7
CALL FORWARD        ; 3 saniyelik ileri
CALL DELAY_1S
CALL DELAY_1S
CALL DELAY_1S
RETURNI ENABLE

SECIM7:
COMPARE sC, SAG2
JUMP NZ, SECIM8
CALL RIGHT          ; 3 saniyelik sag
CALL DELAY_1S
CALL DELAY_1S
CALL DELAY_1S
RETURNI ENABLE

SECIM8:
COMPARE sC, SOL2
JUMP NZ, SECIM9
CALL LEFT           ; 3 saniyelik sol
CALL DELAY_1S
CALL DELAY_1S
CALL DELAY_1S
RETURNI ENABLE  

SECIM9:
COMPARE sC, SAGX2
JUMP NZ, SECIM10
CALL FORW_R         ; 3 saniyelik ileri sag
CALL DELAY_1S
CALL DELAY_1S
CALL DELAY_1S
RETURNI ENABLE

SECIM10:
COMPARE sC, SOLX2
JUMP NZ, SECIM11
CALL FORW_L         ; 3 saniyelik ileri SOL
CALL DELAY_1S
CALL DELAY_1S
CALL DELAY_1S
RETURNI ENABLE

SECIM11:
COMPARE sC, HIZLAN
JUMP NZ, SECIM12

COMPARE SPEED, 78       ; hiz zaten max ise atla
JUMP C, GECERSIZ
ADD SPEED, 20       ; degilse 20 eklesin (hexa)
RETURNI ENABLE

SECIM12:
COMPARE sC, YAVASLA
JUMP NZ, GECERSIZ

COMPARE SPEED, 20       ; hiz zaten min ise atla
JUMP C, GECERSIZ
SUB SPEED, 20       ; degilse 20 azalt
RETURNI ENABLE

GECERSIZ:
RETURNI ENABLE      ; komut bos ise direk cik


ADDRESS 3FF
JUMP ISR

子模块取自github。 我们的蓝牙verilog代码是:

module uart(
     input wire [7:0] din,
    input wire wr_en,
    input wire clk_50m,
    output wire tx,
    output wire tx_busy,
    input wire rx,
    output wire rdy,
    input wire rdy_clr,
    output reg [7:0] dout,
     output tx_, 

   // input wire select,
     output reg interrupt,
     input interrupt_ack
     );


wire [7:0] rx_dout;
//reg [7:0] dout;

baud_rate_gen uart_baud(
        .clk_50m(clk_50m),
        .rxclk_en(rxclk_en),
        .txclk_en(txclk_en)
        );

 transmitter uart_tx(
        .din(din),
       .wr_en(wr_en),
       .clk_50m(clk_50m),
       .clken(txclk_en),
        .tx(tx),
       .tx_busy(tx_busy)
        );

  receiver uart_rx(
        .rx(rx),
        .rdy(rdy),
        .rdy_clr(rdy_clr),
        .clk_50m(clk_50m),
        .clken(rxclk_en),
        .data(rx_dout)
        );

     assign tx_ = 1;

initial
begin
interrupt = 1'b0;
end

always @ (posedge clk_50m)
begin
if(dout != rx_dout)
begin
dout <= rx_dout;

case(dout)
8'b00000000 : interrupt = 1;
8'b00000001 : interrupt = 1;
8'b00000010 : interrupt = 1;
8'b00000011 : interrupt = 1;
8'b00000100 : interrupt = 1;
8'b00000101 : interrupt = 1;
8'b00000110 : interrupt = 1;
//8'b000000111 :
8'b00001000 : interrupt = 1;
8'b00001001 : interrupt = 1;
8'b00001010 : interrupt = 1;
8'b00001011 : interrupt = 1;
8'b00001100 : interrupt = 1;
default: interrupt = 0;

endcase
end

if(interrupt_ack)
    interrupt = 0;


end





 endmodule

0 个答案:

没有答案