4

私のプラットフォームは c8051F120 マイクロコントローラーです。割り込みを使用して UART0 経由で (=tx) バイトを送信したいと考えています。これまでの私のデザインは次のとおりです。

#define UART0_TX_SIZE 16    
char UART0_tx[UART0_TX_SIZE];
short UART0_tx_uart = 0;
short UART0_tx_main = 0;
short UART0_tx_available = 0;

void UART0_putChar(char value) {
  char SAVE_SFRPAGE;
  bit EA_SAVE = EA;
  // potentially blocking code
  while (UART0_tx_available == UART0_TX_SIZE)
    ;
  // disable interrupts
  EA = 0;
  EA = 0;
  if (UART0_tx_available) {
    UART0_tx[UART0_tx_main] = value;
    ++UART0_tx_main;
    if (UART0_tx_main == UART0_TX_SIZE)
      UART0_tx_main = 0;
    ++UART0_tx_available;
  } else {
    SAVE_SFRPAGE = SFRPAGE;
    SFRPAGE = UART0_PAGE;
    SBUF0 = value;
    SFRPAGE = SAVE_SFRPAGE;
  }
  // reenable if necessary
  EA = EA_SAVE;
}

// (return void works for other interrupts)
void UART0_Interrupt() interrupt (4) {
  if (RI0 == 1) {
    RI0 = 0;
  }
  if (TI0 == 1) { // cause of interrupt: previous tx is finished
    TI0 = 0; // Q: Should this clear tx interrupt flag be further down?
    if (SSTA0 & 0x20) { // Errors tx collision
      SSTA0 &= 0xDF;
    }
    if (UART0_tx_available) { // If buffer not empty
      --UART0_tx_available; // Decrease array size
      SBUF0 = UART0_tx[UART0_tx_uart]; //Transmit
      ++UART0_tx_uart; //Update counter
      if (UART0_tx_uart == UART0_TX_SIZE)
        UART0_tx_uart = 0;
    }    
  }
}

ブロッキング関数を使用できるため、UART0 レジスタと Timer2 を介したタイミング (上記のコードの一部ではない) に関する初期化が正しいと確信しています。

char putchar_Blocking(char value) {
  char SFRPAGE_SAVE = SFRPAGE;
  SFRPAGE = UART0_PAGE;
  while (!TI0) // while TI0 == 1 wait for transmit complete
    ;
  TI0 = 0;
  SBUF0 = value;
  SFRPAGE = SFRPAGE_SAVE;
  return value;
}

もちろん、割り込み設計に切り替えたいときも設定します

ES0 = 1;

割り込みを使用しようとする私の設計の欠陥を誰かが見つけますか? または、このためのサンプルコードを持っている人はいますか? ありがとうございました!そして、TCNT レジスターの読み取りに関する私の質問に答えてくれた jzakmeister に大声で叫びました。

4

2 に答える 2

0

私の同僚の Guo Xiong が間違いを発見しました。以下は、修正およびテスト済みのバージョンです。

#define UART0_TX_SIZE 16    
char UART0_tx[UART0_TX_SIZE];
short UART0_tx_uart = 0;
short UART0_tx_main = 0;
short UART0_tx_available = 0;

void UART0_putChar(char value) {
  char SAVE_SFRPAGE;
  bit EA_SAVE = EA;
  // potentially blocking code
  while (UART0_tx_available == UART0_TX_SIZE)
    ;
  // disable interrupts
  EA = 0;
  EA = 0;
  if (UART0_tx_available) {
    UART0_tx[UART0_tx_main] = value;
    ++UART0_tx_main;
    if (UART0_tx_main == UART0_TX_SIZE)
      UART0_tx_main = 0;
  } else {
    SAVE_SFRPAGE = SFRPAGE;
    SFRPAGE = UART0_PAGE;
    SBUF0 = value;
    SFRPAGE = SAVE_SFRPAGE;
  }
  ++UART0_tx_available;
  // reenable if necessary
  EA = EA_SAVE;
}

// (return void works for other interrupts)
void UART0_Interrupt() interrupt (4) {
  if (RI0 == 1) {
    RI0 = 0;
  }
  if (TI0 == 1) { // cause of interrupt: previous tx is finished
    TI0 = 0; // Q: Should this clear tx interrupt flag be further down?
    if (SSTA0 & 0x20) { // Errors tx collision
      SSTA0 &= 0xDF;
    }
    --UART0_tx_available; // Decrease array size
    if (UART0_tx_available) { // If buffer not empty
      SBUF0 = UART0_tx[UART0_tx_uart]; //Transmit
      ++UART0_tx_uart; //Update counter
      if (UART0_tx_uart == UART0_TX_SIZE)
        UART0_tx_uart = 0;
    }    
  }
}
于 2012-09-20T09:12:32.547 に答える