继上一篇文章,由于串口中断接收数据包有问题,还没找到,所以在此使用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