目录
Introduction
在英飞凌MCU中,UART通信可以通过三种主要模式进行:Interrupt(中断)、Direct(直接)和DMA(直接存储器访问)。下面是这三种通讯模式的区别:
-
Interrupt(中断)模式:
- 在中断模式下,UART通过中断请求(IRQ)与CPU通信。当UART接收到数据或者发送数据时,它会生成一个中断信号给CPU,CPU响应中断并执行相应的中断服务程序(ISR)来处理数据。
- 这种模式下,CPU需要在每次数据传输时响应中断,这可能会导致CPU资源的频繁占用,尤其是在数据传输频繁时。
- 适用于数据传输速率不高,对实时性要求不是非常高的应用场景。
-
Direct(直接)模式:
- 直接模式下,UART的数据传输不通过中断或DMA,而是直接通过CPU编程控制数据的发送和接收。
- 这种方式下,CPU需要轮询UART的状态寄存器,检查是否可以发送或接收数据,然后进行相应的读写操作。
- 直接模式通常用于简单的串口通信,或者在系统资源允许的情况下,对实时性要求较高的场合。
-
DMA(直接存储器访问)模式:
- DMA模式允许UART通过DMA控制器直接将数据从外设传输到内存,或者从内存传输到外设,而不需要CPU的直接参与。
- 在这种模式下,DMA控制器负责管理数据的移动,减少了CPU的负担,使得CPU可以处理其他任务。
- DMA模式适用于高速数据传输,可以显著提高数据传输效率,尤其在数据量大且频繁传输的场景中。
总结来说,中断模式适合于数据传输速率较低的应用,直接模式适用于简单的串口通信,而DMA模式适合于高速且数据量大的传输场景,可以有效地减轻CPU负担。每种模式都有其适用的场景和优缺点,开发者可以根据具体的应用需求选择合适的通信模式。
实践
英飞凌的IDE DAVE(Digital Application Virtual Engineer)是一款专为XMC系列微控制器(MCU)设计的集成开发环境(IDE)。以下是DAVE的主要特点和功能:
-
基于Eclipse的IDE:DAVE基于Eclipse平台,提供了一个熟悉的开发环境,支持代码提示和快捷键自定义等功能。
-
DAVE APPs:DAVE提供了可配置的应用库(DAVE APPs),这些是预定义的模块,可以通过图形化界面进行配置,然后自动生成源代码库供开发者进行上层逻辑的开发。
-
图形化配置界面:DAVE提供了一个图形化的外设配置界面,用户可以通过拖放组件来配置外设(如GPIO、UART、SPI、PWM等),并自动生成相应的初始化代码。
-
代码生成工具:配置完外设后,用户可以点击“Project” -> “Generate Code”,DAVE会自动根据配置生成相应的初始化代码,包含了每个外设的初始化函数,自动配置了所有外设寄存器。
-
实时调试功能:DAVE支持实时调试功能,包括设置断点、单步调试、查看变量和调用栈等,以及实时查看外设状态的功能。
-
支持多种编译工具:DAVE支持多种编译工具,如GCC ARM,以及与硬件的无缝集成,使得开发者可以专注于应用逻辑的实现,而无需过多关注底层硬件的配置和管理。
-
性能分析工具:DAVE IDE支持性能分析工具,可以对代码的执行时间进行剖析,查找性能瓶颈,并提供了针对不同外设的低功耗配置,帮助实现节能优化。
-
固件包:DAVE IDE提供了固件包(如XMC-Device-FW),里面包含了XMC系列MCU的所有驱动程序和外设配置函数,便于快速开始开发。
-
免费使用:DAVE是一个免费提供给用户的开发工具,可以帮助用户减少开发时间和成本。
-
支持多种MCU系列:DAVE支持英飞凌的多种MCU系列,包括XMC系列、XC800、C166、XC166、XE166、XC2000和TriCore AUDO系列产品。
DAVE通过提供图形化的配置界面、强大的代码生成工具、实时调试功能以及对XMC MCU系列的全面支持,使得开发者能够高效地开发、调试和部署嵌入式应用。
New Project in DAVE
关于一个简单的串口程序,我原来写过一篇blog, 可以参考:【基于DAVE的英飞凌XMC4200的RS485通讯】
Interrupt mode
在UART APP configuration 界面的advanced settings页面中可以看到,默认模式是Interrupt模式。
generate code 之后我们可以去uart.c里面看具体怎么收发数据。
/*
* @brief Common function to transmit data.
*
* @param[in] handle UART APP handle pointer of type UART_t*
* @param[in] data_ptr Pointer to data of type uint8_t
* @param[in] count Number of uint8_t type bytes to be transmitted
*
* @return UART_STATUS_t
* UART_SUCCESS: If the data is put to transmit.<BR>
* UART_STATUS_BUSY : If the channel is busy.<BR>
* UART_STATUS_BUFFER_INVALID: Either if buffer is NULL or count is 0.<BR>
* UART_STATUS_MODE_MISMATCH: If the configured mode is invalid.<BR>
*
*/
UART_STATUS_t UART_Transmit(const UART_t *const handle, uint8_t* data_ptr, uint32_t count)
{
UART_STATUS_t ret_stat = UART_STATUS_MODE_MISMATCH;
switch(handle->config->transmit_mode)
{
#ifdef UART_TX_INTERRUPT_USED
case UART_TRANSFER_MODE_INTERRUPT:
ret_stat = UART_StartTransmitIRQ(handle, data_ptr, count);
break;
#endif
#ifdef UART_TX_DMA_USED
case UART_TRANSFER_MODE_DMA:
ret_stat = UART_StartTransmitDMA(handle, data_ptr, count);
break;
#endif
#ifdef UART_TX_DIRECT_USED
case UART_TRANSFER_MODE_DIRECT:
ret_stat = UART_lStartTransmitPolling(handle, data_ptr, count);
break;
#endif
default:
break;
}
return ret_stat;
}
/*
* @brief Common function to receive data.
*
* @param[in] handle UART APP handle pointer of type UART_t*
* @param[in] data_ptr Pointer to data of type uint8_t
* @param[in] count Number of uint8_t type bytes to be received
*
* @return UART_STATUS_t
* UART_SUCCESS: If the data is put to transmit.<BR>
* UART_STATUS_BUSY : If the channel is busy.<BR>
* UART_STATUS_BUFFER_INVALID: Either if buffer is NULL or count is 0.<BR>
* UART_STATUS_MODE_MISMATCH: If the configured mode is invalid.<BR>
*
*/
UART_STATUS_t UART_Receive(const UART_t *const handle, uint8_t* data_ptr, uint32_t count)
{
UART_STATUS_t ret_stat = UART_STATUS_MODE_MISMATCH;
switch(handle->config->receive_mode)
{
#ifdef UART_RX_INTERRUPT_USED
case UART_TRANSFER_MODE_INTERRUPT:
ret_stat = UART_StartReceiveIRQ(handle, data_ptr, count);
break;
#endif
#ifdef UART_RX_DMA_USED
case UART_TRANSFER_MODE_DMA:
ret_stat = UART_StartReceiveDMA(handle, data_ptr, count);
break;
#endif
#ifdef UART_RX_DIRECT_USED
case UART_TRANSFER_MODE_DIRECT:
ret_stat = UART_lStartReceivePolling(handle, data_ptr, count);
break;
#endif
default:
break;
}
return ret_stat;
}
/*
* @brief Registers a request for transmitting data over UART channel.
*
* @param[in] UART_t* UART APP handle pointer of type UART_t
* @param[in] uint8_t* Pointer to data
* @param[in] uint32_t Total no of words to be transmitted.
*
* @return UART_STATUS_t UART_STATUS_SUCCESS if the request is accepted.
* UART_STATUS_BUSY if a transmission is in progress.
* Details of function:
* The data transmission is accomplished using transmit interrupt. User can configure
* a callback function in the APP UI. When the data is fully transmitted, the callback
* function will be executed. If transmit FIFO is enabled, the trigger limit is set to 0.
* So the transmit interrupt will be generated when all the data in FIFO is moved from FIFO.
*
* <i>Imp Note:</i> Return value should be validated by user to ensure that the
* request is registered.
*
*
*/
UART_STATUS_t UART_StartTransmitIRQ(const UART_t *const handle, uint8_t* data_ptr, uint32_t count)
{
UART_STATUS_t ret_stat = UART_STATUS_MODE_MISMATCH;
UART_RUNTIME_t * ptr_runtime = handle->runtime;
XMC_ASSERT("UART_StartTransmitIRQ: UART APP handle invalid", ((handle != NULL)&&
(handle->runtime != NULL)));
if (handle->config->transmit_mode == UART_TRANSFER_MODE_INTERRUPT)
{
ret_stat = UART_STATUS_BUSY;
if (ptr_runtime->tx_busy == false)
{
/*If there is no transmission in progress*/
if ((data_ptr != NULL) && (count > 0U))
{
/*Obtain the address of data, size of data*/
ptr_runtime->tx_data = data_ptr;
ptr_runtime->tx_data_count = count;
/*Initialize to first index and set the busy flag*/
ptr_runtime->tx_data_index = 0U;
ptr_runtime->tx_busy = true;
/*Enable the transmit buffer event*/
if (handle->config->tx_fifo_size != XMC_USIC_CH_FIFO_DISABLED)
{
/*Clear the transmit FIFO*/
XMC_USIC_CH_TXFIFO_Flush(handle->channel);
/*Enable transmit buffer interrupt*/
XMC_USIC_CH_TXFIFO_EnableEvent(handle->channel,(uint32_t)XMC_USIC_CH_TXFIFO_EVENT_CONF_STANDARD);
}
else
{
XMC_USIC_CH_EnableEvent(handle->channel, (uint32_t)XMC_USIC_CH_EVENT_TRANSMIT_BUFFER);
}
ret_stat = UART_STATUS_SUCCESS;