1

Atmel の構文、Atmel Studio 6.0、またはプログラム自体を理解しているのかわかりません。割り込みハンドラに単純な文字列を受け取ってから何かをさせるようには見えません。USARTが1つの文字を受け取ったときにLEDをオンにし、別の文字を受け取った場合はLEDをオフにする1つの文字を実装するだけで成功しました。ところで、メイン内の送信コードが非常に大きいため、プログラムが受信サブルーチンに到達するのに問題がある設計ボードを持っているので、割り込みを利用してこれを修正するよう提案されました。ところで、私は EVK1100 AVR32 ボード MCU:AT32UC3A0512-U でこのプログラムを試しています。以前にこれらで遊んだことがあるかどうかはわかりませんが、かなり素晴らしいものです。ただし、Atmel 構文が好きかどうかはわかりません。ともかく、

私は、Atmel の世界で割り込みを行うのはかなり新しいものです。

どんな助けでも大歓迎です。組み込みの ASF USART 割り込み "INTC" プロジェクト例にいくつかの変更を加えました。

ありがとう、

#include <string.h>
#include <avr32/io.h>
#include "compiler.h"
#include "board.h"
#include "print_funcs.h"
#include "intc.h"
#if defined (__GNUC__)
#  if   defined (__AVR32_AP7000__)
#    include "pm_at32ap7000.h"
#  else
#    include "power_clocks_lib.h"
#  endif
#elif defined (__ICCAVR32__) || defined (__AAVR32__)
#  if  defined (__AT32AP7000__)
#    include "pm_at32ap7000.h"
#  else
#    include "power_clocks_lib.h"
#  endif
#endif
#include "gpio.h"
#include "usart.h"
//#include "conf_example.h"    
#  define EXAMPLE_TARGET_PBACLK_FREQ_HZ FOSC0  // PBA clock target frequency, in Hz

#if BOARD == EVK1100
#  define EXAMPLE_USART                 (&AVR32_USART1)
#  define EXAMPLE_USART_RX_PIN          AVR32_USART1_RXD_0_0_PIN
#  define EXAMPLE_USART_RX_FUNCTION     AVR32_USART1_RXD_0_0_FUNCTION
#  define EXAMPLE_USART_TX_PIN          AVR32_USART1_TXD_0_0_PIN
#  define EXAMPLE_USART_TX_FUNCTION     AVR32_USART1_TXD_0_0_FUNCTION
#  define EXAMPLE_USART_CLOCK_MASK      AVR32_USART1_CLK_PBA
#  define EXAMPLE_PDCA_CLOCK_HSB        AVR32_PDCA_CLK_HSB
#  define EXAMPLE_PDCA_CLOCK_PB         AVR32_PDCA_CLK_PBA
#  define EXAMPLE_USART_IRQ             AVR32_USART1_IRQ
#  define EXAMPLE_USART_BAUDRATE        57600
#endif
    /**
     * \brief The USART interrupt handler.
     *
     * \note The `__attribute__((__interrupt__))' (under GNU GCC for AVR32) and
     *       `__interrupt' (under IAR Embedded Workbench for Atmel AVR32) C function
 *       attributes are used to manage the `rete' instruction.
 */
#if defined (__GNUC__)
__attribute__((__interrupt__))
#elif defined(__ICCAVR32__)
__interrupt
#endif

static void usart_int_handler(void)
{   
    static char Cmnd[30];
    int index = 0;
    int c;

    usart_read_char(EXAMPLE_USART, &c);
    Cmnd[index++] = c;

if (c = '\r')
{
    Cmnd[index] = '\0';
    usart_write_line(EXAMPLE_USART, Cmnd);
}

}   


/**
 * \brief The main function.
 *
 * It sets up the USART module on EXAMPLE_USART. The terminal settings are 57600
 * 8N1.
 * Then it sets up the interrupt handler and waits for a USART interrupt to
 * trigger.
 */
int main(void)
{
    static const gpio_map_t USART_GPIO_MAP =
    {
        {EXAMPLE_USART_RX_PIN, EXAMPLE_USART_RX_FUNCTION},
        {EXAMPLE_USART_TX_PIN, EXAMPLE_USART_TX_FUNCTION}
    };

    // USART options.
    static const usart_options_t USART_OPTIONS =
    {
        .baudrate     = 57600,
        .charlength   = 8,
        .paritytype   = USART_NO_PARITY,
        .stopbits     = USART_1_STOPBIT,
        .channelmode  = USART_NORMAL_CHMODE
    };

#if BOARD == EVK1100 || BOARD == EVK1101 || BOARD == UC3C_EK \
    || BOARD == EVK1104 || BOARD == EVK1105 || BOARD == STK600_RCUC3L0 \
    || BOARD == STK600_RCUC3D
    /*
     * Configure Osc0 in crystal mode (i.e. use of an external crystal
     * source, with frequency FOSC0) with an appropriate startup time then
     * switch the main clock source to Osc0.
     */
    pcl_switch_to_osc(PCL_OSC0, FOSC0, OSC0_STARTUP);

#elif BOARD == STK1000
    pm_reset();
#elif BOARD == UC3L_EK
    /*
     * Note: on the AT32UC3L-EK board, there is no crystal/external clock
     * connected to the OSC0 pinout XIN0/XOUT0. We shall then program the
     * DFLL and switch the main clock source to the DFLL.
     */
    pcl_configure_clocks(&pcl_dfll_freq_param);
    /*
     * Note: since it is dynamically computing the appropriate field values
     * of the configuration registers from the parameters structure, this
     * function is not optimal in terms of code size. For a code size
     * optimal solution, it is better to create a new function from
     * pcl_configure_clocks_dfll0() and modify it to use preprocessor
     * computation from pre-defined target frequencies.
     */
#end if

    // Assign GPIO to USART.
    gpio_enable_module(USART_GPIO_MAP,
        sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));

    // Initialize USART in RS232 mode.
    usart_init_rs232(EXAMPLE_USART, &USART_OPTIONS,
        EXAMPLE_TARGET_PBACLK_FREQ_HZ);
    print(EXAMPLE_USART, ".: Using interrupts with the USART :.\r\n\r\n");

    // Disable all interrupts.
    Disable_global_interrupt();

    // Initialize interrupt vectors.
    INTC_init_interrupts();

    /*
     * Register the USART interrupt handler to the interrupt controller.
     * usart_int_handler is the interrupt handler to register.
     * EXAMPLE_USART_IRQ is the IRQ of the interrupt handler to register.
     * AVR32_INTC_INT0 is the interrupt priority level to assign to the
     * group of this IRQ.
     */
    INTC_register_interrupt(&usart_int_handler, EXAMPLE_USART_IRQ, AVR32_INTC_INT0);

    // Enable USART Rx interrupt.
    EXAMPLE_USART->ier = AVR32_USART_IER_RXRDY_MASK;
    print(EXAMPLE_USART, "Type a character to use the interrupt handler."
        "\r\nIt will show up on your screen.\r\n\r\n");

    // Enable all interrupts.
    Enable_global_interrupt();

    /**
     * We have nothing left to do in the main, so we may switch to a device
     * sleep mode: we just need to be sure that the USART module will be
     * still be active in the chosen sleep mode. The sleep mode to use is
     * the FROZEN sleep mode: in this mode the PB clocks are still active
     * (so the USART module which is on the Peripheral Bus will still be
     * active while the CPU and HSB will be stopped).
     * --
     * Modules communicating with external circuits should normally be
     * disabled before entering a sleep mode that will stop the module
     * operation: this is not the case for the FROZEN sleep mode.
     * --
     * When the USART interrupt occurs, this will wake the CPU up which will
     * then execute the interrupt handler code then come back to the
     * while(1) loop below to execute the sleep instruction again.
     */

    while(1)
    {
        /*
         * If there is a chance that any PB write operations are
         * incomplete, the CPU should perform a read operation from any
         * register on the PB bus before executing the sleep
         * instruction.
         */
        AVR32_INTC.ipr[0];  // Dummy read


        /*
         * When the device wakes up due to an interrupt, once the
         * interrupt has been serviced, go back into FROZEN sleep mode.
         */
    }
}  
4

1 に答える 1

1

割り込みハンドラを短くするようにしてください。割り込みハンドラまたは ISR は、通常、割り込みを無効にして実行されます。彼らの目標は、入って何かをして、すぐに出ることです。他の割り込み (リアルタイム クロックなど) を実行している場合、それらは ISR にいる間はブロックされ、割り込みが失われるなどの問題が発生する可能性があります。

ここで行う最善の方法は、入力バッファーをグローバルな静的として宣言することです。static uchar_t have_lineaまたは類似のものも定義し、バッファがいっぱいになるまで (重要なチェックです!)、CR (\r) を受け取るまで、各文字を ISR に保存します。改行 (\n) も確認してください。ゼロを保存してバッファをヌルで終了させて​​から、 を設定しhave_line = 1ます。

メイン ループでは、have_lineゼロ以外になるのを待ってから、入力バッファーの内容を処理します。最後に、have_line をゼロに戻します。

そうすれば、ISR は簡潔でかなり堅牢になります。

サンプル コードでは、関数usart_write_lineは割り込みを有効にする必要がありますか?

おっとっと!申し訳ありませんが、インデックスが静的変数ではないことに気付きました。つまり、ルーチンが呼び出されるたびにゼロに初期化されます。int インデックスの前に静的宣言子を追加すると、それが整理されます。

于 2013-09-10T16:29:58.473 に答える