打印
[新品上市]

【APM32F107VCT6 MINI开发板测评】之串口空闲帧中断DMA接收

[复制链接]
727|16
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 woai32lala 于 2023-3-19 21:36 编辑


    【APM32F107VCT6 MINI开发板测评】之串口空闲帧中断DMA接收

准备
发送XCOM2串口助手
波特率115200   RX   PA10
DMA1  通道channel5
/**
* [url=home.php?mod=space&uid=247401]@brief[/url] Definition for COM port1, connected to USART1
*/
#define MINI_COM1                        USART1
#define MINI_COM1_CLK                    RCM_APB2_PERIPH_USART1
#define MINI_COM1_TX_PIN                 GPIO_PIN_9
#define MINI_COM1_TX_GPIO_PORT           GPIOA
#define MINI_COM1_TX_GPIO_CLK            RCM_APB2_PERIPH_GPIOA
#define MINI_COM1_RX_PIN                 GPIO_PIN_10
#define MINI_COM1_RX_GPIO_PORT           GPIOA
#define MINI_COM1_RX_GPIO_CLK            RCM_APB2_PERIPH_GPIOA
#define MINI_COM1_IRQn                   USART1_IRQn

/**
* [url=home.php?mod=space&uid=247401]@brief[/url] Definition for COM port2, connected to USART2
*/
#define MINI_COM2                        USART2
#define MINI_COM2_CLK                    RCM_APB1_PERIPH_USART2
#define MINI_COM2_TX_PIN                 GPIO_PIN_2
#define MINI_COM2_TX_GPIO_PORT           GPIOA
#define MINI_COM2_TX_GPIO_CLK            RCM_APB2_PERIPH_GPIOA
                                                                     
#define MINI_COM2_RX_PIN                 GPIO_PIN_3
#define MINI_COM2_RX_GPIO_PORT           GPIOA
#define MINI_COM2_RX_GPIO_CLK            RCM_APB2_PERIPH_GPIOA
#define MINI_COM2_IRQn                   USART2_IRQn

  我们平时接收固定长度的一般用普通串口中断或者DMA传送完成中断,但串口普通中断是接收到1个字节就会中断一次,这样严重拖慢了CPU的效率。DMA传送完成中断一般是用于固定字节的传输, 但是如果我们发送的数据长度是不固定的怎么办呢?STM32有串口空闲中断,HC32有串口超时钟中断,那么极海AMP32有什么呢?
  我们查阅用户手册发现,极海AMP32有串口空闲帧中断。
那么空闲帧是什么呢?

其实可以说和Stm32的空闲IDLE一样,就是超过1个字节连续高电平,还有断开帧等,如下图所示。

普通的一帧数据有起始位、1个字节数据和停止位。空闲帧没有起始位,是一帧连续高电平。断开是发送一个0x00,其实我有点疑问,那么0x00万一是有效数据视为断开帧咋那么解决,等官方解释一下,我们继续往下说。

像我们下面发送的两帧数据,就可以用空闲帧中断来获取,两帧数据之间有超过一个字节的高电平时间。
要使能空闲帧中断生效,需要我们使能空闲帧中断,也就是这个函数。

串口配置
 * [url=home.php?mod=space&uid=247401]@brief[/url]       Configures COM port.
*
* @param       COM: Specifies the COM port to be configured.
*              This parameter can be one of following parameters:
*              [url=home.php?mod=space&uid=2817080]@ARG[/url] COM1
*              [url=home.php?mod=space&uid=2817080]@ARG[/url] COM2
*
* @retval      None
*/
void APM_MINI_COMInit(COM_TypeDef COM, USART_Config_T* configStruct)
{
    GPIO_Config_T GPIO_configStruct;

    /* Enable GPIO clock */
    RCM_EnableAPB2PeriphClock(COM_TX_PORT_CLK[COM] | COM_RX_PORT_CLK[COM]);

    if (COM == COM1)
    {
        RCM_EnableAPB2PeriphClock(COM_USART_CLK[COM]);
    }
    else
    {
        RCM_EnableAPB1PeriphClock(COM_USART_CLK[COM]);
    }

    /* Configure USART Tx as alternate function push-pull */
    GPIO_configStruct.mode = GPIO_MODE_AF_PP;
    GPIO_configStruct.pin = COM_TX_PIN[COM];
    GPIO_configStruct.speed = GPIO_SPEED_50MHz;
    GPIO_Config(COM_TX_PORT[COM], &GPIO_configStruct);

    /* Configure USART Rx as input floating */
    GPIO_configStruct.mode = GPIO_MODE_IN_FLOATING;
    GPIO_configStruct.pin = COM_RX_PIN[COM];
    GPIO_Config(COM_RX_PORT[COM], &GPIO_configStruct);

    /* USART configuration */
    USART_Config(COM_USART[COM], configStruct);

    /* Enable USART */
    USART_Enable(COM_USART[COM]);

}
以上是串口相关函数,下面是DMA部分。

DMA配置
直接存储器访问 (DMA) 用于在外设与存储器之间以及存储器与存储器之间提供高速数据传输。可以在无需任何 CPU 操作的情况下通过 DMA 快速移动数据。这样节省的 CPU 资源可供其它操作使用。说白了DMA就是一个搬运工,将数据从一个地方搬到另一个地方而不需要CPU处理。作为一个搬运工,要他正常工作必须要确定几个重要的参数:
传输模式:数据从哪里搬到哪里。三种可能的传输方向:存储器到外设、外设到存储器或存储器到存储器,我们我次选择的方向是从外设到内存DMA_DIR_PERIPHERAL_SRC
通道选择:就是数据传输的是走那条道路,这里是DMA1channel5
仲裁器:多个DMA传输是优先级高的优先传输。
传输字节量:我们这里设置200,最大为65535,根据需求设置。
数据长度:每次传输的数据长度,可以一个字节,两个字节(半字),四个字节()
指针递增:如果使能了递增模式,则下一次传输的地址将是前一次传输的地址递增 1(字节)2(半字)4(),我们这里用1个字节。
循环模式:循环模式可用于处理循环缓冲区和连续数据流(例如 ADC 扫描模式)。可以使用 DMA_SxCR寄存器中的 CIRC 位使能,我们用正常模式
其他:关于DMA还有双缓冲区模式、突发传输等等其他设置,一般用不到,具体查询用户手册。
我们这里DMA只需要作为通道,不需要进行中断,DMA中断我们不使能。

中断接收函数
void USART1_Isr(void)
{
    if(USART_ReadIntFlag(USART1, USART_INT_IDLE))
    {

        USART_ClearIntFlag(USART1, USART_INT_IDLE);         //清除中断标志
        USART_RxData(USART1);
        DMA_Disable(DMA1_Channel5);
        /* Data number */
        data_num = BufSize -  DMA_ReadDataNumber(DMA1_Channel5);
        DMA_ConfigDataNumber(DMA1_Channel5,BufSize);
        DMA_Enable(DMA1_Channel5);
        APM_MINI_LEDToggle(LED2);

    }
}

测试
接线


XCOM2发送数据

MCU接收到数据

我们可以看到右侧Watch中有35个数据,且数据跟我们发送一致,数量也一致,并用过LED灯反转来表示接收数据次数,因此增加Demo测试成功。


  

DMA_UsartToMemory_IDLE.zip

3.66 MB

使用特权

评论回复
沙发
tpgf| | 2023-4-11 16:14 | 只看该作者
一般来说 一帧数据的最大长度是多少呢

使用特权

评论回复
板凳
观海| | 2023-4-11 16:48 | 只看该作者
如何识别空闲帧是否已经传输完成了呢

使用特权

评论回复
地板
woai32lala|  楼主 | 2023-4-11 17:41 | 只看该作者
观海 发表于 2023-4-11 16:48
如何识别空闲帧是否已经传输完成了呢

IDLE标志位

使用特权

评论回复
5
woai32lala|  楼主 | 2023-4-11 17:41 | 只看该作者
tpgf 发表于 2023-4-11 16:14
一般来说 一帧数据的最大长度是多少呢

不超过SIZE数据类型

使用特权

评论回复
6
guanjiaer| | 2023-4-12 11:11 | 只看该作者
使用DMA会节省的CPU 资源,那么这个节省的占比一般能达到多少呢

使用特权

评论回复
7
heimaojingzhang| | 2023-4-12 11:36 | 只看该作者
请问什么是空闲帧啊 它的具体格式是什么呢

使用特权

评论回复
8
keaibukelian| | 2023-4-12 11:53 | 只看该作者
heimaojingzhang 发表于 2023-4-12 11:36
请问什么是空闲帧啊 它的具体格式是什么呢

空闲帧的长度可配置。在 Profibus 协议中,空闲帧长度为 33 位

使用特权

评论回复
9
paotangsan| | 2023-4-12 12:04 | 只看该作者
完全由1组成的帧称为空闲帧

使用特权

评论回复
10
cemaj| | 2023-5-5 19:42 | 只看该作者
一直想要测试一下APM32F107VCT6 芯片的性能  

使用特权

评论回复
11
mollylawrence| | 2023-5-5 20:08 | 只看该作者
当DMA传输完成后,可以使用回调函数或者其他方式进行数据处理。

使用特权

评论回复
12
pl202| | 2023-5-5 21:23 | 只看该作者
在使用DMA接收串口数据时,可以开启串口空闲帧中断,并配置DMA通道为循环模式。当串口接收到完整的数据帧后,触发空闲帧中断,此时DMA通道自动打开并开始传输数据。

使用特权

评论回复
13
zerorobert| | 2023-5-5 22:08 | 只看该作者
需要注意的是,在使用DMA接收串口数据时,需要设置DMA传输数据的长度,以确保传输正确的数据量。

使用特权

评论回复
14
bartonalfred| | 2023-5-5 22:39 | 只看该作者
空闲中断接收,当一帧数据接收完成之后,串口会进入到空闲中断中去,然后在空闲中断中处理收到的数据。

使用特权

评论回复
15
pentruman| | 2023-5-5 22:49 | 只看该作者
DMA(直接内存访问)技术可以减轻CPU的负担,实现高效、快速的数据传输。

使用特权

评论回复
16
mikewalpole| | 2023-5-6 00:10 | 只看该作者
需要考虑数据的粘包和分包问题,以及对于异常情况的处理,例如溢出等。

使用特权

评论回复
17
abotomson| | 2023-5-7 13:55 | 只看该作者
串口空闲帧中断是指当串口接收到完整的数据帧后,在接收下一个数据帧之前会出现一段时间的空闲期,可以利用这段时间来进行一些处理。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

107

主题

535

帖子

5

粉丝