gpt4 book ai didi

c - AVR32 UC3A0 如何利用 USART 中断示例并接收字符串然后做一些事情

转载 作者:太空宇宙 更新时间:2023-11-04 03:56:51 25 4
gpt4 key购买 nike

我遇到了一些麻烦,我不知道这是我对 Atmel 语法、Atmel Studio 6.0 还是程序本身的理解。我似乎无法让中断处理程序接收一个简单的字符串然后做一些事情。当 USART 接收到一个字符时,它会打开 LED,然后如果它接收到不同的字符,它会关闭 LED,我成功地实现了一个单个字符打开 LED。顺便说一句,我有一个设计板,该程序在进入接收子例程时遇到了一些麻烦,因为主程序中的发送代码太大了,所以有人建议我利用中断来解决这个问题。顺便说一下,我正在 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.
*/
}
}

最佳答案

尽量让您的中断处理程序简短。中断处理程序或 ISR 通常在禁用中断的情况下执行。他们的目标是进入,做点什么,然后迅速离开。如果您有其他中断正在运行(例如实时时钟),当您在 ISR 中时它们会被阻止,这可能会导致中断丢失等问题。

这里最好的做法是将输入缓冲区声明为全局静态。还定义一个 static uchar_t have_line 或类似的,并在 ISR 中保存每个字符,直到缓冲区已满(一项重要的检查!),或者您收到一个 CR (\r)。还要检查换行符 (\n)。保存零以空终止缓冲区,然后设置 have_line = 1

在您的主循环中,等待have_line 为非零,然后处理输入缓冲区中的内容。最后,将 have_line 设置回零。

这样,您的 ISR 就会简短且相当可靠。

在您的示例代码中,usart_write_line 函数是否需要启用中断?

糟糕!抱歉,我刚刚注意到您的索引不是静态变量。这意味着每次调用例程时它都会被初始化为零。在 int index 前面添加一个静态声明符,应该可以解决问题。

关于c - AVR32 UC3A0 如何利用 USART 中断示例并接收字符串然后做一些事情,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15691293/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com