2013-03-28 21 views
1

,我不能告訴我們,如果這是我的愛特梅爾語法的理解,愛特梅爾Studio 6.0中,或者程序本身。 我似乎無法得到中斷處理程序接收一個簡單的字符串,然後做一些事情。當USART接收到一個字符來打開LED時,我只能使用一個字符來轉換LED,然後如果它接收到不同的字符,就會關閉LED。順便說一下,我有一個設計板,程序在接收子程序時遇到了一些麻煩,因爲主程序中的發送代碼非常大,所以建議我使用中斷來解決這個問題。 順便說一下,我正在EVK1100 AVR32板上的MCU上試用這個程序:AT32UC3A0512-U,不知道你之前是否曾經玩過這些程序,但它們非常棒。不知道我喜歡Atmel語法。 無論如何,你可以看到我目前在主體中什麼都沒做,直到我得到接收部分的工作。AVR32 UC3A0如何利用USART中斷例子,接收字符串,然後做我有一些麻煩事

我對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. 
     */ 
    } 
} 
+0

這是多年來我做了這樣的事情,但我沒有看到你在ISR中清除任何中斷標誌。你也應該檢查中斷源(如果它是TX或RX),所以如果緩衝區滿/空,你不會掛起ISR等待。 – Spektre

回答

1

儘量保持你的中斷處理程序短。中斷處理程序或ISR通常在禁止中斷的情況下執行。他們的目標是進入,做一些事情,並迅速離開。如果您有其他中斷正在運行(例如實時時鐘),那麼當您處於ISR中時,它們會被阻塞,並可能導致中斷丟失等問題。

這裏要做的最好的事情就是將輸入緩衝區聲明爲全局靜態。還要定義一個static uchar_t have_line或類似的,並且在ISR中,保存每個字符,直到緩衝區滿(一個重要的檢查!),或者您收到一個CR(\ r)。同時檢查換行符(\ n)。保存零以空終止緩衝區,然後設置have_line = 1

在你的主循環,等待have_line是非零,然後再處理什麼是輸入緩衝區。最後,將has_line設置回零。

這樣,你的ISR是簡短而且相當健壯的。

在你的示例代碼,並啓用usart_write_line需要中斷的功能?

糟糕!對不起,我只注意到你的索引不是一個靜態變量。這意味着每次調用例程時它都會被初始化爲零。在int index前面添加一個靜態聲明器,並且應該對它進行整理。

+0

是的,我相信它確實需要啓用中斷。他們是。 – cheapkid1

相關問題