打印
[技术问答]

HC32F460 UART+DMA 接收丢包问题

[复制链接]
3244|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
huiscii|  楼主 | 2021-5-13 16:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在使用460 做串口Modbus通信时,发送几包数据就会有一包接收的数据不对,各位给看看我的串口配置有问题么?

void UART_Init(devCom_t *com, uint32_t baudRate, char parity)
{
        uint64_t tmpreg = 0x00;
        float DIV = 0.0;
        uint32_t DIV_Integer, DIV_Fraction = 0x00;
        USART_TypeDef *USARTx = com->comPort;
        M4_SYSREG->PWR_FPRC_f.FPRCB1 = 1;
        ENABLE_FCG0_REG_WRITE();
        M4_MSTP->FCG0_f.AOS = 0;
        DISABLE_FCG0_REG_WRITE();
        {
                // PORT RX3 PB5,TX3 PB7 RTS3 PB6
                PORT_Unlock();
                M4_PORT->PFSRB5 = 33;
                M4_PORT->PFSRB7 = 32;
                M4_PORT->PCRB5_f.DDIS = 0;
                M4_PORT->PCRB5_f.PUU = 1;
                M4_PORT->PCRB7_f.DDIS = 0;
                M4_PORT->PCRB7_f.PUU = 1;
                M4_PORT->PCRB6_f.DDIS = 0;
                M4_PORT->PCRB6_f.PUU = 0;         // 上拉无效
                M4_PORT->PCRB6_f.DRV = 0b10; // 高驱动模式
                M4_PORT->PCRB6_f.POUTE = 1;
                PORT_Lock();
                M4_MSTP->FCG1_f.USART3 = 0;
        }
       
        M4_SYSREG->PWR_FPRC_f.FPRCB1 = 0;
        /* Set default value */
        USARTx->CR1 = (uint32_t)0x801B0000ul;
        USARTx->CR2 = (uint32_t)0x00000000ul;
        USARTx->CR3 = (uint32_t)0x00000000ul;
        USARTx->BRR = (uint32_t)0x0000FFFFul;
        USARTx->PR = (uint32_t)0x00000000ul;
        stc_usart_cr1_field_t CR1 = USARTx->CR1_f;
        /* Set USART mode */
        USARTx->CR3_f.SCEN = (uint32_t)0ul; // disable sc mode
        CR1.MS = (uint32_t)0ul;                                // uart mode

        USARTx->PR_f.PSC = 0b10;
        CR1.M = 0u;
        CR1.ML = 0u;
        USARTx->CR2_f.STOP = 0u; // 1 stop bit
        USARTx->CR2_f.CLKC = 0u; //  pclk1

        switch (parity)
        {
        case 'n':
                CR1.PCE = (uint32_t)0ul;
                break;
        case 'e':
                CR1.PS = (uint32_t)0ul;
                CR1.PCE = (uint32_t)1ul;
                break;
        case 'o':
                CR1.PS = (uint32_t)1ul;
                CR1.PCE = (uint32_t)1ul;
                break;
        default:
                break;
        }

        USARTx->CR3_f.CTSE = 0u; // rts enable
        CR1.SBS = 0u;
        CR1.OVER8 = 0u; // 16bit

        uint32_t C = 100000000 / 16; //6.250M

        DIV = ((float)C / ((float)baudRate * 16)) - 1.0f;
        DIV_Integer = (uint32_t)DIV;

        if (!((DIV < 0.0f) || (DIV_Integer > 0xFFul)))
        {
                if ((DIV - (float)DIV_Integer) > 0.00001f)
                {
                        tmpreg = (uint64_t)(((uint64_t)DIV_Integer + 1ul) * (uint64_t)baudRate) * 2;
                        DIV_Fraction = (uint32_t)(2048ul * tmpreg / C - 128ul);
                }
                CR1.FBME = (DIV_Fraction > 0x7Ful) ? 0ul : 1ul;
                USARTx->BRR_f.DIV_FRACTION = DIV_Fraction;
                USARTx->BRR_f.DIV_INTEGER = DIV_Integer;
        }


if (USARTx == M4_USART3)
        {
                USART3_DMA_Init();

                M4_MSTP->FCG2_f.TIMER0_2 = 0;
                M4_TMR02->CNTAR_f.CNTA = 0;          // 计数值清零
                M4_TMR02->CMPAR_f.CMPA = 150; // 比较器
                M4_TMR02->BCONR_f.CKDIVA = 0; // 计数器分频器

                M4_TMR02->BCONR_f.HCLEA = 1;        //硬件触发清除
                M4_TMR02->BCONR_f.HSTAA = 1;        // 硬件触发启动
                M4_TMR02->BCONR_f.ASYNCLKA = 0; //异步技术时钟选择:XTAL32
                M4_TMR02->BCONR_f.SYNCLKA = 0;        // 同步计数时钟源选择 内部硬件触发事件
                M4_TMR02->BCONR_f.SYNSA = 1;

                M4_INTC->SEL6_f.INTSEL = INT_USART3_TCI;
                M4_INTC->SEL7_f.INTSEL = INT_USART3_EI;
                M4_INTC->SEL8_f.INTSEL = INT_USART3_RTO;
                NVIC_EnableIRQ(Int006_IRQn);
                NVIC_EnableIRQ(Int007_IRQn);
                NVIC_EnableIRQ(Int008_IRQn);
        }
       
        CR1.RIE = 1;
        CR1.RTOE = 1;
        CR1.RTOIE = 1;
        CR1.TE = 1;
        CR1.RE = 1;
        USARTx->CR1_f.CRTOF = 1ul;
        USARTx->CR1 = *(__IO uint32_t *)(&CR1);
}

static void USART3_DMA_Init(void)
{
        /* Enable peripheral clock */
        ENABLE_FCG0_REG_WRITE();
        M4_MSTP->FCG0_f.DMA2 = 0;
        DISABLE_FCG0_REG_WRITE();

        /* Enable DMA. */
        M4_DMA2->EN_f.EN = 1;

        /* Initialize DMA. */
        M4_DMA2->DTCTL0_f.BLKSIZE = 1;                                  // 1  block
        M4_DMA2->DTCTL0_f.CNT = 10;                                          // 传输字节数
        M4_DMA2->SAR0 = ((uint32_t)(COM3_TX_BUFF + 1));  // 源地址
        M4_DMA2->DAR0 = ((uint32_t)(&M4_USART3->DR)); // 目标地址
        M4_DMA2->CH0CTL_f.SINC = 1;                                          // 源地址递增
        M4_DMA2->CH0CTL_f.DINC = 0;                                          // 目标地址固定
        M4_DMA2->CH0CTL_f.HSIZE = 0;                                  // 传输数据宽度 8bit
        M4_DMA2->CH0CTL_f.SRPTEN = 1;                                  // 源地址重置
        M4_DMA2->CH0CTL_f.IE = 0;                                          // 禁止中断

        M4_DMA2->DTCTL1_f.BLKSIZE = 1;                                                // 1  block
        M4_DMA2->DTCTL1_f.CNT = UART_BUFF_SIZE;                                // 传输字节数
        M4_DMA2->SAR1 = ((uint32_t)(&M4_USART3->DR) + 2ul); // 源地址
        M4_DMA2->DAR1 = ((uint32_t)(COM3_RX_BUFF));                        // 目标地址
        M4_DMA2->CH1CTL_f.SINC = 0;                                                        // 源地址固定
        M4_DMA2->CH1CTL_f.DINC = 1;                                                        // 目标地址递增
        M4_DMA2->CH1CTL_f.HSIZE = 0;                                                // 传输数据宽度 8bit
        M4_DMA2->CH1CTL_f.DRPTEN = 1;                                                // 目标址重置
        M4_DMA2->CH1CTL_f.IE = 0;                                                        // 禁止中断
        M4_DMA2->CHEN |= 2;
        M4_DMA2->INTCLR1 |= 3; // 清空 0,1 通道IT
        M4_AOS->DMA2_TRGSEL0 = EVT_USART3_TI;
        M4_AOS->DMA2_TRGSEL1 = EVT_USART3_RI;
}




void UART3_Send(uint16_t length)
{
        com3.lock = true;
        com3.buff.txOK = false;
        USART3_RTS_HIGHT;
        vTaskDelay(1);
        length -= 1;
        M4_DMA2->DTCTL0_f.CNT = length;
        M4_DMA2->RPT0_f.SRPT = length;
        M4_DMA2->CHEN |= 1;
        M4_USART3->DR_f.TDR = COM3_TX_BUFF[0];
        M4_USART3->CR1_f.TCIE = 1;
}



void IRQ006_Handler(void) // USART1 DMA 1 CH0
{
        portDISABLE_INTERRUPTS();
        M4_USART3->CR1_f.TCIE = 0;
        M4_DMA2->INTCLR1 |= 0x10001; // reset DMA 中断
        com3.buff.txOK = true;
        com3.lock = false;
        USART3_RTS_LOW;
        portENABLE_INTERRUPTS();
}
void IRQ007_Handler(void) // USART DMA 1 CH1
{
        M4_USART3->CR1_f.CFE = 1u;
        M4_USART3->CR1_f.CPE = 1u;
}

void IRQ008_Handler(void) // USART3 RXOT
{
        BaseType_t xHigherPriorityTaskWoken = pdFALSE;
        portDISABLE_INTERRUPTS();
        M4_TMR02->BCONR_f.CSTA = 0;
        M4_TMR02->STFLR_f.CMAF = 0;
        M4_USART3->CR1_f.CRTOF = 1ul;
        M4_DMA2->CHEN &= 0x0D;
        com3.lock = false;
        com3.buff.rxOK = true;
        com3.buff.rxLength = UART_BUFF_SIZE - M4_DMA2->MONDTCTL1_f.CNT;
        M4_DMA2->DTCTL1_f.CNT = UART_BUFF_SIZE;
        M4_DMA2->DAR1 = ((uint32_t)(COM3_RX_BUFF));
        M4_DMA2->CHEN |= 2;
        portENABLE_INTERRUPTS();
        vTaskNotifyGiveFromISR(mbMasterReviceHandle, &xHigherPriorityTaskWoken);
       
}

使用特权

评论回复
沙发
huquanz711| | 2021-5-17 07:15 | 只看该作者
逻辑处理有问题

使用特权

评论回复
板凳
sgrtf661| | 2021-6-16 11:35 | 只看该作者
华大代理可以技术支持  qq:409946461

使用特权

评论回复
地板
merry_zsp| | 2021-6-16 11:54 | 只看该作者
如果移植的是标准的modbus的话,不应该出现丢帧那么严重的情况。你是走着标准的协议吗

使用特权

评论回复
5
huiscii|  楼主 | 2021-6-23 09:36 | 只看该作者
谢谢各位,问题已经解决,配置问题

使用特权

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

本版积分规则

2

主题

6

帖子

0

粉丝