华大单片机(F460),使用串口+DMA重复接收数据

继上一篇文章,由于串口中断接收数据包有问题,还没找到,所以在此使用DMA搬运数据。

DMA配置如下:因为我使用DMA搬运数据,只是为了对数据包进行校验(每次传输数据都可以覆盖之前数组中的数据),在这里RxData的数据包大小只有4个字节,自己定义即可。

注:为了实现,数据可重复传输(串口接收到数据DMA就干活),这里的传输次数设置为0(TransferCnt=0),不然传输完后又要初始化DMA。

void DmaBtcIrqCallback(){
	flag=1;
 DMA_ClearIrqFlag(DMA_UNIT, DMA_CH, BlkTrnCpltIrq);
}

void DmaInit()
{
    stc_dma_config_t stcDmaInit;
    stc_irq_regi_conf_t stcIrqRegiCfg;

    /* Enable peripheral clock */
    PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_DMA1,Enable);

    /* Enable DMA. */
    DMA_Cmd(DMA_UNIT,Enable);

    /* Initialize DMA. */
    MEM_ZERO_STRUCT(stcDmaInit);
    stcDmaInit.u16BlockSize = 1u; /* 1 block */
		stcDmaInit.u16TransferCnt = 0u;
    stcDmaInit.u32SrcAddr = ((uint32_t)(&M4_USART1->DR)+2ul); /* Set source address. *///设置源头地址
    stcDmaInit.u32DesAddr = (uint32_t)(&RxData[0]);     /* Set destination address. *///目标地址
		stcDmaInit.u16SrcRptSize = 4;
    stcDmaInit.u16DesRptSize = 4;
    stcDmaInit.stcDmaChCfg.enSrcInc = AddressFix;  /* Set source address mode. *///传输源地址模式(递增还是递减或不变)
   	stcDmaInit.stcDmaChCfg.enDesInc = AddressIncrease;  /* Set destination address mode. *///传输目标地址模式(递增还是递减或不变)
		stcDmaInit.stcDmaChCfg.enDesRptEn=Enable;
		stcDmaInit.stcDmaChCfg.enSrcRptEn=Enable;
//		stcDmaInit.stcDmaChCfg.enLlpEn = Enable;
		stcDmaInit.stcDmaChCfg.enIntEn = Enable;       /* Enable interrupt. *///中断
    stcDmaInit.stcDmaChCfg.enTrnWidth = Dma8Bit;   /* Set data width 8bit. *///设置数据宽度
    DMA_InitChannel(DMA_UNIT, DMA_CH, &stcDmaInit);

    /* Enable the specified DMA channel. */
    DMA_ChannelCmd(DMA_UNIT, DMA_CH, Enable);

    /* Clear DMA flag. */
    DMA_ClearIrqFlag(DMA_UNIT, DMA_CH, TrnCpltIrq);

    /* Enable peripheral circuit trigger function. *///开启DMA外设上的时钟
    PWC_Fcg0PeriphClockCmd(PWC_FCG0_PERIPH_PTDIS,Enable);

    /* Set DMA trigger source. */
    DMA_SetTriggerSrc(DMA_UNIT, DMA_CH, DMA_TRG_SEL);//设置DMA触发源

    /* Set DMA block transfer complete IRQ */
    stcIrqRegiCfg.enIRQn = Int007_IRQn;
		stcIrqRegiCfg.enIntSrc = INT_DMA1_BTC0;
    stcIrqRegiCfg.pfnCallback = &DmaBtcIrqCallback;
    enIrqRegistration(&stcIrqRegiCfg);
    NVIC_SetPriority(stcIrqRegiCfg.enIRQn, DDL_IRQ_PRIORITY_08);
    NVIC_ClearPendingIRQ(stcIrqRegiCfg.enIRQn);
    NVIC_EnableIRQ(stcIrqRegiCfg.enIRQn);
}

然后写了个和校验:校验成功就就发送数据

// 计算校验值(和校验)
uint8_t calculateChecksum(uint8_t data) {
    return (0x55 + data) & 0xFF;
}

// 验证数据包
bool verifyPacket(uint8_t* packet) {
    // 检查帧头和帧尾
    if (packet[0] != 0x55 || packet[3] != 0xEE) {
        return false;
    }
    
    // 计算校验值并比较
    uint8_t calculatedChecksum = calculateChecksum(packet[1]);
    return (calculatedChecksum == packet[2]);
}

// 构建数据包
void buildPacket(uint8_t data, uint8_t* packet) {
    packet[0] = 0x55;       // 帧头
    packet[1] = data;       // 数据
    packet[2] = calculateChecksum(data); // 校验
    packet[3] = 0xEE;       // 帧尾
}
//速度校验回调函数
void SpeedCallBack(){
		
	if(flag ==1 ){
	
		 if(RxData[1] == 0x12 &&	verifyPacket(RxData) ){
		   RS485_SendFloat(g_fSpeedRpm,1);
				}		
	}
		
		flag = 0;
}

在实现这个功能的时候,出现的问题是DMA配置不太会,以及手欠在DMA传输源地址中DR+2,这地方的+2加进括号里去了,导致数据一致是0C。

实验结果:第一次发送 55 12 67 EE

        第二次发送:66 77 88 99

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值