简体   繁体   English

AVR32 UC3A0如何利用USART中断示例并接收字符串然后执行某些操作

[英]AVR32 UC3A0 how to utilize USART interrupt example and receive string then do something

I am having some trouble, and I cannot tell if it's my understanding of the Atmel syntax, the Atmel Studio 6.0 or, the program itself. 我遇到了一些麻烦,我不能说这是我对Atmel语法,Atmel Studio 6.0还是程序本身的理解。 I cannot seem to get the interrupt handler to receive a simple string then do something. 我似乎无法让中断处理程序接收一个简单的字符串然后执行某些操作。 I have success with just implimenting a single character turning an LED when USART receives one character it turns the LED on, then if it receives a different character it turns the LED off. 我成功地暗示了,当USART接收到一个字符时,它会暗示一个字符会点亮LED,然后打开LED,而如果接收到一个字符时,它会熄灭LED。 By the way I have a design board that the program is having some trouble getting to the receive sub routine because the send code within the main is so large, so it was suggested to me to utilize interrupts to fix this. 顺便说一句,我有一个设计委员会,由于主程序中的发送代码太大,程序无法进入接收子例程,因此建议我利用中断来解决此问题。 By the way, I am trialing this program on an EVK1100 AVR32 board MCU:AT32UC3A0512-U, not sure if any of you have played with these before, but they're pretty great. 顺便说一下,我正在EVK1100 AVR32板上的MCU:AT32UC3A0512-U上试用此程序,不确定是否有人曾经玩过这些程序,但是它们的确很棒。 Not sure I like Atmel syntax though. 不确定我是否喜欢Atmel语法。 Anyway, you can see I'm doing nothing in the main at the moment until I get the receive portion working. 无论如何,您可以看到我目前基本上什么也没做,直到我使接收部分工作为止。

I'm fairly new to interrupts in the Atmel world. 我对Atmel世界中的打扰还很陌生。

Any help would be much appreciated. 任何帮助将非常感激。 I made just a few modifications to the built in ASF USART interrup "INTC" project example. 我仅对内置ASF USART interrup“ INTC”项目示例进行了一些修改。

Thanks, 谢谢,

#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.
         */
    }
}  

Try to keep your interrupt handlers short. 尽量使您的中断处理程序简短。 Interrupt handlers or ISRs are executed usually with interrupts disabled. 中断处理程序或ISR通常在禁用中断的情况下执行。 Their goal is to get in, do something, and get out quickly. 他们的目标是进入,做某事并迅速离开。 If you have other interrupts running (like a real-time clock for example), they are blocked out while you're in the ISR and that can cause problems such as lost interrupts. 如果您正在运行其他中断(例如实时时钟),则在您进入ISR时它们会被阻止,这可能会导致诸如中断丢失之类的问题。

The best thing to do here would be to declare the input buffer as a global static. 最好的做法是将输入缓冲区声明为全局静态。 Also define a static uchar_t have_line or similar, and in the ISR, save each character until either the buffer is full (an important check!), or you receive a CR (\\r). 还要定义一个static uchar_t have_line或类似的字符,并在ISR中保存每个字符,直到缓冲区已满(一个重要检查!),或者您收到一个CR(\\ r)。 Also check for newline (\\n). 还要检查换行符(\\ n)。 Save a zero to null-terminate the buffer, and then set have_line = 1 . 保存一个零以使缓冲区为空终止,然后设置have_line = 1

In your main loop, wait for have_line to be non-zero, and then process what's in the input buffer. 在您的主循环中,等待have_line为非零,然后处理输入缓冲区中的内容。 Finally, set have_line back to zero. 最后,将have_line设置回零。

That way, your ISR is brief and fairly robust. 这样,您的ISR便简短而强大。

In your sample code, does the function usart_write_line require interrupts to be enabled? 在您的示例代码中,功能usart_write_line需要启用中断?

Oops! 哎呀! Sorry, I just noticed that your index isn't a static variable. 抱歉,我只是注意到您的索引不是静态变量。 That means it'll be initialized to zero each time the routine is called. 这意味着它将在每次调用例程时初始化为零。 Add a static declarator in front of int index and that should sort it out. int索引前面添加一个静态声明器,应该将其整理出来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM