2012-02-10 36 views
2

私はAVRチップ上でCプログラムを実行しています。シリアル信号が聞こえると、シリアル割り込みISR(USART_RX_vect)が実行されます。この方法では、変更を= 1;にする必要があります。その後、私のメインのwhileループでは、LCDをクリアして表示してから、change = 0を再度設定する必要があります。C言語のグローバル変数を変更する

これは、それが継続的にcalulationsをやって、そしてLCD万回分で結果の表示を停止する..です

ただし、割り込み方法が1に変更変数を変更した場合、それはしていないようですそれを "グローバルに"変更してください。メインメソッドでは常に0になります。

ここにはデバッグのためのものが少しあります。

あなたはvolatileキーワードを使用して変更を宣言する必要が
/* LCD DEFINES */ 
#define LED PB5 
#define output_low(port,pin) port &= ~(1<<pin) 
#define output_high(port,pin) port |= (1<<pin) 
#define set_input(portdir,pin) portdir &= ~(1<<pin) 
#define set_output(portdir,pin) portdir |= (1<<pin) 

/* UART SERIAL DEFINES */ 
#define F_CPU 16000000UL 
#define BAUD 9600 
#define MYUBRR F_CPU/16/BAUD-1 

#define STARTCHAR 'R' 
#define ENDCHAR 'E' 

char reading; 
char inputBuffer[12]; 
char readStatus; 
uint8_t position; 
int change; 

char output; 
int result; 

struct Axis 
{ 
    uint8_t axisNumber; 
    uint16_t position; 
    uint16_t oldPosition; 

} axis1, axis2, axis3; 


/* SETUP UART */ 

void USART_Init(unsigned int ubrr) 
{ 
    /*Set baud rate */ 
    UBRR0H = (unsigned char)(ubrr>>8); 
    UBRR0L = (unsigned char)ubrr; 

    /*Enable receiver and transmitter */ 
    UCSR0B = (1<<RXEN0)|(1<<TXEN0); 

    /* Set frame format: 8data, 2stop bit */ 
    UCSR0C = (1<<USBS0)|(3<<UCSZ00); 
} 

void USART_Transmit(unsigned char data) 
{ 
    UDR0 = data; 
} 

unsigned char USART_Receive(void) 
{ 
    return UDR0; 
} 

/*****************************************************************/ 

int main(void) 
{ 
    /* INITALISE SERIAL */ 
    USART_Init(MYUBRR); 

    /* Turn on Receive Complete Interrupt */ 
    UCSR0B |= (1 << RXCIE0); 

    /* Turn On GLobal Interrupts */ 
    sei(); 

    position = 0; 
    change = 0; 

    /* Initialise LCD */ 
    lcd_init(LCD_DISP_ON); /* Initialize display, cursor off. */ 
    lcd_clrscr(); 
    lcd_puts("READY"); 

    //Turn on LED 13 
    set_output(PORTB,LED); 
    output_low(PORTB,LED); 

    while (1)    /* Loop forever */ 
    { 
     if (change == 1) 
     { 
      //If not reading, display the result on the LCD display. 
      axis1.position = (inputBuffer[0]<< 8) | inputBuffer[1]; 
      axis2.position = (inputBuffer[2]<< 8) | inputBuffer[3]; 
      axis3.position = (inputBuffer[4]<< 8) | inputBuffer[5]; 

      char axis1Printout[12]; 
      char axis2Printout[12]; 
      char axis3Printout[12]; 

      sprintf(axis1Printout,"%u ", axis1.position); 
      sprintf(axis2Printout,"%u ", axis2.position); 
      sprintf(axis3Printout,"%u ", axis3.position); 

      char output[40] = ""; 
      strcat(output, axis1Printout); 
      strcat(output, axis2Printout); 
      //strcat(output, axis3Printout); 

      lcd_clrscr(); /* Clear the screen*/ 
      lcd_puts(output); 
      _delay_ms(300); 
      change = 0; 
     } 
    } 
} 

/* INTERRUPTS */ 

ISR (USART_RX_vect) 
{ 
    change = 1; 
    unsigned char input = USART_Receive(); 

    if (input == 'R') 
    { 
     readStatus = 0; //Reading 
     position = 0; 
    } 
    else if ((input != 'E') && (position < 12) && (position > -1)) 
    { 
     inputBuffer[position] = input; 
     position++; 
    } 
    else if (input == 'E') 
    { 
     readStatus = 1; //Stop Reading 
     position = -1; 
     output_high(PORTB,LED); 
    } 
} 
+1

本当にISRが実際に呼び出されていますか? – NPE

答えて

7

volatile int change; 

これは、レジスタの値が「キャッシュ」ではないに2つの「スレッド」(メイン実行ループとあなたのISRコード)を伝えます常にメモリから取得します。

編集:コードには別の問題があります。メインループでは、0に変更したときにもう一度割り込みが発生し、ループを再度実行する必要があります。簡単には保証されていない修正は、チェックした直後に直ちに0に変更されます。適切な方法は、ロックを使用することですが、状況に応じて、最初のオプションが行う可能性があります。

+1

私は最後に変更を残し、変更が0になるまで割り込みが値を更新しないことを確認します。これにより、メインルーチンが値を破損するのを防ぐことができます。 – Jeff

+0

別のオプションは、割り込みフラグを割り込み自体にクリアしたままにし、メインルーチンのままにして割り込みを再び有効にすることです。私はAVR自身に精通していませんが、プロセッサは通常割り込みで割り込みフラグをクリアしませんし、割り込みルーチンの最後にsei()を呼び出す必要がありますか? 処理を済ませた後はメインルーチンのままにしておくことができます。使用したほとんどのプロセッサで割り込みをキューに入れます。グローバル割り込みが無効なので、処理中にデータが到着すると割り込みが発生しますそれらを再度有効にします。バッファの長さが問題になる可能性があります。 – Rophuine

3

変数宣言volatileを作成して、変更された値がメモリ内の変数に確実に書き込まれるようにします。

0

割り込みハンドラによって共有されるオブジェクトとアプリケーションコードは、宣言でvolatileと修飾されている必要があります。

修飾子がないと、実装はアプリケーションコード内でオブジェクトが予期せず変更されることはないと想定し、アプリケーションコードの実行中に最適化のために(レジスタなどに)変数をキャッシュできます。

関連する問題