OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 131|回复: 7

外部与我50微秒通讯一次,串口时间来不急怎么办

[复制链接]

16

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
116
金钱
116
注册时间
2021-9-8
在线时间
56 小时
发表于 7 天前 | 显示全部楼层 |阅读模式
200金钱
要求外部与我50微秒通讯一次,串口2.5M,
使用485,需要切换方向角
我接收用串口空闲中断+DMA接收不定长数据包,
发送直接在中断中轮询发送数据,能够正常通讯,但是进行其他操作时间就不充足了,必须要用DMA去发送,
但是我用DMA启动时需要时间,然后我发送完数据后就来不及接收数据了,有没有大佬帮忙看看我设置有什么问题吗
发送是轮询代码
void USARTy_IRQHandler(void)
{
   uint16_t clear;
   if(USART_GetIntStatus(USARTy, USART_INT_IDLEF)!= RESET )
   {
       /* 切换到发送模式 */
        GPIO_SetBits(CHALF_PORT, CHALF_PIN);

        uint16_t length = RxBufferSize - USARTy_Rx_DMA_Channel->TXNUM;
        TxCounter1 =0;
               
                /*
                *        数据处理
                */
               
        while (TxCounter1 < length)
        {
            /* Send one byte from USARTy to USARTz */
            USART_SendData(USARTy, TxBuffer[TxCounter1++]);
            /* Loop until USARTy DAT register is empty */
            while (USART_GetFlagStatus(USARTy, USART_FLAG_TXDE) == RESET)
            {
            }
        }

        DMA_EnableChannel(USARTy_Rx_DMA_Channel, DISABLE);
        clear = USARTy->STS;
        clear = USARTy->DAT;
        USART_ConfigInt(USARTy, USART_INT_IDLEF, DISABLE);
        GPIO_ResetBits(CHALF_PORT, CHALF_PIN);

        DMA_SetCurrDataCounter(USARTy_Rx_DMA_Channel, 6);
        DMA_EnableChannel(USARTy_Rx_DMA_Channel, ENABLE);
        USART_ConfigInt(USARTy, USART_INT_IDLEF, ENABLE);
   }     
}

发送是DMA代码
void USARTy_IRQHandler(void)
{
   uint16_t clear;
   if(USART_GetIntStatus(USARTy, USART_INT_IDLEF)!= RESET )
   {
       /* 切换到发送模式 */
        GPIO_SetBits(CHALF_PORT, CHALF_PIN);
        USARTy_Rx_Done = 1;

        uint16_t length = RxBufferSize - USARTy_Rx_DMA_Channel->TXNUM;
        /*
                *        数据处理
                */

        clear = USARTy->STS;
        clear = USARTy->DAT;
        DMA_EnableChannel(USARTy_Tx_DMA_Channel, DISABLE);
        DMA_SetCurrDataCounter(USARTy_Tx_DMA_Channel, length);
        DMA_EnableChannel(USARTy_Tx_DMA_Channel, ENABLE);
   }     
}

void DMA_Channel3_4_IRQHandler(void)
{
    if(DMA_GetIntStatus(USARTy_Tx_DMA_INT, DMA) != RESET)
    {
        USARTy_Tx_Done = 1;
        GPIO_ResetBits(CHALF_PORT, CHALF_PIN);
        DMA_ClrIntPendingBit(USARTy_Tx_DMA_INT, DMA);

        DMA_EnableChannel(USARTy_Rx_DMA_Channel, DISABLE);
        DMA_SetCurrDataCounter(USARTy_Rx_DMA_Channel, 6);
        DMA_EnableChannel(USARTy_Rx_DMA_Channel, ENABLE);
    }   
}

其他配置
void RS485_Init(void)
{
    RCC_Configuration();
    NVIC_Configuration();
    GPIO_Configuration();
    DMA_Configuration();

    USART_InitStructure.BaudRate            = 2500000;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

    /* Configure USARTy and USARTz */
    USART_Init(USARTy, &USART_InitStructure);


    USART_ConfigInt(USARTy, USART_INT_IDLEF, ENABLE);
    /* Enable USARTy DMA Rx and TX request */
    USART_EnableDMA(USARTy, USART_DMAREQ_RX | USART_DMAREQ_TX, ENABLE);
    /* Enable USARTy RX DMA1 Channel */
    DMA_EnableChannel(USARTy_Rx_DMA_Channel, ENABLE);


    /* Enable the USARTy and USARTz */
    USART_Enable(USARTy, ENABLE);
}

void RCC_Configuration(void)
{
    /* DMA clock enable */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);
    /* Enable GPIO clock */
    RCC_EnableAPB2PeriphClk(USARTy_GPIO_CLK, ENABLE);
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
    /* Enable USARTy Clock */
    USARTy_APBxClkCmd(USARTy_CLK, ENABLE);
}

void GPIO_Configuration(void)
{
    GPIO_InitType GPIO_InitStructure;

    /* Initialize GPIO_InitStructure */
    GPIO_InitStruct(&GPIO_InitStructure);


    //dir
    GPIO_InitStructure.Pin            = CHALF_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_HIGH;
    GPIO_InitPeripheral(CHALF_PORT, &GPIO_InitStructure);
    GPIO_ResetBits(CHALF_PORT, CHALF_PIN);

    /* Configure USARTy Tx as alternate function push-pull */
    GPIO_InitStructure.Pin            = USARTy_TxPin;   
    GPIO_InitStructure.GPIO_Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = USARTy_Tx_GPIO_AF;
    GPIO_InitPeripheral(USARTy_GPIO, &GPIO_InitStructure);

    /* Configure USARTx Rx as alternate function push-pull */
    GPIO_InitStructure.Pin            = USARTy_RxPin;
    GPIO_InitStructure.GPIO_Alternate = USARTy_Rx_GPIO_AF;
    GPIO_InitPeripheral(USARTy_GPIO, &GPIO_InitStructure);


}

void NVIC_Configuration(void)
{
    NVIC_InitType NVIC_InitStructure;

    /* Enable the USARTy_Rx Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel            = USARTy_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority    = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    /* Enable the USARTy_Tx DMA Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel            = USARTy_Tx_DMA_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority    = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd         = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

}

void DMA_Configuration(void)
{
    DMA_InitType DMA_InitStructure;

    /* USARTy_Tx_DMA_Channel (triggered by USARTy Tx event) Config */
    DMA_DeInit(USARTy_Tx_DMA_Channel);
    DMA_InitStructure.PeriphAddr     = USARTy_DAT_Base;
    DMA_InitStructure.MemAddr        = (uint32_t)TxBuffer;
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_DST;
    DMA_InitStructure.BufSize        = TxBufferSize;
    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE;
    DMA_InitStructure.MemDataSize    = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.CircularMode   = DMA_MODE_NORMAL;
    DMA_InitStructure.Priority       = DMA_PRIORITY_VERY_HIGH;
    DMA_InitStructure.Mem2Mem        = DMA_M2M_DISABLE;
    DMA_Init(USARTy_Tx_DMA_Channel, &DMA_InitStructure);
    DMA_RequestRemap(USARTy_Tx_DMA_REMAP, DMA, USARTy_Tx_DMA_Channel, ENABLE);


    /* USARTy RX DMA Channel (triggered by USARTy Rx event) Config */
    DMA_DeInit(USARTy_Rx_DMA_Channel);
    DMA_InitStructure.PeriphAddr = USARTy_DAT_Base;
    DMA_InitStructure.MemAddr    = (uint32_t)RxBuffer;
    DMA_InitStructure.Direction  = DMA_DIR_PERIPH_SRC;
    DMA_InitStructure.BufSize    = RxBufferSize;
    DMA_Init(USARTy_Rx_DMA_Channel, &DMA_InitStructure);
    DMA_RequestRemap(USARTy_Rx_DMA_REMAP, DMA, USARTy_Rx_DMA_Channel, ENABLE);

}


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

16

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
116
金钱
116
注册时间
2021-9-8
在线时间
56 小时
 楼主| 发表于 7 天前 | 显示全部楼层
我用示波器抓了一下波形,接收数据4微秒,如果我用轮询发送数据,那我接收数据完到发送数据开始时间是14微秒,发送数据24微秒,接收数据就来的及,如果我用DMA,那么接收完数据到发送数据是20微秒,发送数据24微秒,然后就来不及接收数据了
回复

使用道具 举报

12

主题

3364

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8570
金钱
8570
注册时间
2020-5-11
在线时间
3984 小时
发表于 7 天前 | 显示全部楼层
啥型号?
没看太明白,接收DMA可以立即打开啊,干嘛要等发完再开?
收完到发送开始的耗时14微秒或20微秒是因为数据处理比较耗时吗?
专治疑难杂症
回复

使用道具 举报

16

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
116
金钱
116
注册时间
2021-9-8
在线时间
56 小时
 楼主| 发表于 7 天前 | 显示全部楼层
LcwSwust 发表于 2025-3-24 18:42
啥型号?
没看太明白,接收DMA可以立即打开啊,干嘛要等发完再开?
收完到发送开始的耗时14微秒或20微秒 ...

国名技术的N32G031,因为用的芯片需要切换方向角来确定是接收还是发送,有部分原因处理数据需要时间,但是没有办法,我需要通过接收的数据来刷新发送的数据
回复

使用道具 举报

12

主题

3364

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8570
金钱
8570
注册时间
2020-5-11
在线时间
3984 小时
发表于 7 天前 | 显示全部楼层
本帖最后由 LcwSwust 于 2025-3-24 19:35 编辑
pyq1518186024 发表于 2025-3-24 18:50
国名技术的N32G031,因为用的芯片需要切换方向角来确定是接收还是发送,有部分原因处理数据需要时间,但 ...

这个,我也不怎么了解。
如果时间只差一点点的话,建议IRQHandler里不要用库函数,
而是直接操作寄存器,其实就是把库函数里的代码摘出来,可以省一点点时间。


专治疑难杂症
回复

使用道具 举报

16

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
116
金钱
116
注册时间
2021-9-8
在线时间
56 小时
 楼主| 发表于 7 天前 | 显示全部楼层
LcwSwust 发表于 2025-3-24 19:33
这个,我也不怎么了解。
如果时间只差一点点的话,建议IRQHandler里不要用库函数,
而是直接操作寄存器 ...

好,我试一下看能不能行,感谢
回复

使用道具 举报

4

主题

901

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4368
金钱
4368
注册时间
2019-9-4
在线时间
903 小时
发表于 5 天前 | 显示全部楼层
接收到数据,切换成发送模式,启动发送DMA。发送DMA发送完成中断,切换回接收模式。
回复

使用道具 举报

16

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
116
金钱
116
注册时间
2021-9-8
在线时间
56 小时
 楼主| 发表于 4 天前 | 显示全部楼层
出现这个问题的原因,1是触发DMA发送完成中断后,实际上并没有发送完成,需要while (USART_GetFlagStatus(USARTy, USART_FLAG_TXC) == RESET){}等待串口发送完成。2抓取波形切换方向脚时产生了毛刺。加上等待串口发送完成后,就能够正常通讯了,将所有的库函数都直接操作寄存器就能够缩短时间
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-3-31 07:18

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表