OpenEdv-开源电子网

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

DMA发送时不发CRC校验。。。。。很奇怪啊

[复制链接]

145

主题

445

帖子

0

精华

高级会员

Rank: 4

积分
823
金钱
823
注册时间
2014-1-15
在线时间
350 小时
发表于 2014-11-12 11:03:55 | 显示全部楼层 |阅读模式
5金钱
[mw_shl_code=c,true]void MYDMA_Config( DMA_Channel_TypeDef *DMA_CHx,u32 paddr) { RCC->AHBENR |= 1<<0; //开启DMA1时钟 delay_ms(5); //等待DMA时钟稳定 DMA_CHx->CCR = 0X00000000; //复位 DMA_CHx->CCR |= 1<<1; //传输完成中断 DMA_CHx->CCR |= 1<<4; //从存储器读 DMA_CHx->CCR |= 0<<5; //普通模式 DMA_CHx->CCR |= 0<<6; //外设地址非增量模式 DMA_CHx->CCR |= 1<<7; //存储器增量模式 DMA_CHx->CCR |= 0<<8; //外设数据宽度为8位 DMA_CHx->CCR |= 0<<10; //存储器数据宽度8位 DMA_CHx->CCR |= 1<<12; //中等优先级 DMA_CHx->CCR |= 0<<14; //非存储器到存储器模式 DMA_CHx->CPAR = paddr; //DMA1 外设地址 DMA_CHx->CCR |= 1<<1; //USART DMA传输完成中断 //DMA } void USART2_Init(u32 bound) { float temp; u16 mantissa; u16 fraction; temp = ( (float)(36*1000000) ) / (bound*16);//得到USARTDIV mantissa = temp; //得到整数部分 fraction = (temp-mantissa)*16; //得到小数部分 mantissa <<= 4; mantissa += fraction; RCC->APB2ENR |= 1<<2; //使能PORTA口时钟 GPIOA->CRL &= 0XFFFF000F; //IO状态设置 GPIOA->CRL |= 0X00008B30; //IO状态设置 RCC->APB1ENR |= 1<<17; //使能串口时钟 RCC->APB1RSTR |= 1<<17; //复位串口3 RCC->APB1RSTR &= ~(1<<17);//停止复位 USART2->BRR = mantissa; // 波特率设置 USART2->CR1 |= 0X340C; //1位停止 USART2->CR1 |= 1<<8; //PE中断使能 USART2->CR1 |= 1<<5; //接收缓冲区非空中断使能 USART2->CR3 |= 1<<7; // DMA MY_NVIC_Init(2,3,USART2_IRQChannel,2);//组2,最低优先级 USART2_TX_EN = 0;//默认为接收模式 } void USART2_DMATransmit(u8 *mbdata,u8 mblen) { USART2_TX_EN = 1; //设置为发送模式 DMA1_Channel7->CCR &= ~(1<<0); // DMA1_Channel7->CMAR = (u32)mbdata; // DMA1_Channel7->CNDTR = mblen; DMA1_Channel7->CCR |= 1<<0; } void DMA1_Channel7_IRQHandler(void) { if(DMA1->ISR&0X02000000) { USART2_TX_EN = 0; USARTPARA.USART_RX_CNT[2] = 0; } DMA1->IFCR|=1<<25;//清发送完成中断标志位 }[/mw_shl_code] [mw_shl_code=c,true][/mw_shl_code] [mw_shl_code=c,true]以上是配置,下面是发送函数。当我使用DMA时串口监视发现并没有加上CRC,如果测试ex[2]的数据则不能接收到任何数据。发送函数如果使用原子的串口发送函数(非DMA)则有CRC。因此感觉是DMA原因,请大家帮帮忙 void Modbus_SendFrame(u8*data,u8 datalen,void(*Trans)(u8*data,u8 datalen)) { u16 crc16 = 0xFFFF; u8 ex[2]={0,0}; crc16 = CRC16Calculation(data,datalen); data[datalen] = (u8)(crc16 & 0x00ff); ex[0]=data[datalen]; datalen++; data[datalen] = (u8)(crc16>>8); datalen++; ex[1]=data[datalen]; Trans(data,datalen); }[/mw_shl_code]
以上是配置,下面是发送函数。当我使用DMA时串口监视发现并没有加上CRC,如果测试ex[2]的数据则不能接收到任何数据。发送函数如果使用原子的串口发送函数(非DMA)则有CRC。因此感觉是DMA原因,请大家帮帮忙

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

使用道具 举报

145

主题

445

帖子

0

精华

高级会员

Rank: 4

积分
823
金钱
823
注册时间
2014-1-15
在线时间
350 小时
 楼主| 发表于 2014-11-12 12:52:18 | 显示全部楼层
经测试发现不能发送少于2个字节的数据
对于数组ex[5]={1,2,3,4,5};只能发出去1,2,3,而4,5是发不出去的
回复

使用道具 举报

145

主题

445

帖子

0

精华

高级会员

Rank: 4

积分
823
金钱
823
注册时间
2014-1-15
在线时间
350 小时
 楼主| 发表于 2014-11-12 14:08:13 | 显示全部楼层
如果改写程序,让程序一直发ex[5]={1,2,3,4,5};并且不使能DMA传输完成中断,则可以接收到全部数据。可知是中断“过早”,看配置,我明明是传输完成中断啊??????????????????????
回复

使用道具 举报

145

主题

445

帖子

0

精华

高级会员

Rank: 4

积分
823
金钱
823
注册时间
2014-1-15
在线时间
350 小时
 楼主| 发表于 2014-11-12 15:40:25 | 显示全部楼层
网上答案
配置USART 和DMA :DMA的中断不用开

准备发送的时候  开485发  配置好DMA  开启USART的传输完成TC中断  使能DMA  =======等串口TC中断就行  失能TC  开485收
实测  无误
发这个  是因为 刚开始直接在DMA的发送完成中断里面去切换485的收发  会导致最后的2个字节发布出去  
  DMA的“发送完成中断”出现在 刚发送倒数第二个字节的起始位的地方  这时候切换485 若接收端不是奇校验的话 将会误收到0xFF 最后第一肯定也出不去

网上大部分的解决办法的:①在DMA的TC中断里面  加大于两个字节的延时 这是OK的 ②在DMA的TC中断里面  开启USART的“发送完成中断”   去USART的中断里面去处理  这是OK的

我试了上面的第二个办法 OK的

认真看手册  感觉完全可以利用TC的特点  开启USART的DMA  开启DMA通道  开启USART的TC中断   就试了一下  是可以的


开始传输
//-----尝试不开启DMA TC中断  直接直观传输  
void USART2_SendMsg(INT8U *msg,INT8U len)
{
        SET_RS485_SEND;                //高发送
        DMA_ClearFlag(DMA1_FLAG_TC7);      //清DMA发送完成标志
        USART_ClearITPendingBit(USART2,USART_IT_TC);
        DMA_Cmd(DMA1_Channel7, DISABLE);   //停止DMA
        DMA1_Channel7->CMAR = (INT32U) msg;                        //源地址
        DMA1_Channel7->CNDTR = len;//重设传输长度
        USART_ITConfig(USART2,USART_IT_TC,ENABLE);
        DMA_Cmd(DMA1_Channel7, ENABLE);    //启动DMA
}
复制代码
传完后

void USART2_IRQHandler(void)
{
        /*
        ...................
        */
        if(0x00000040 & (USART2->SR))//(USART_GetITStatus(USART2,USART_IT_TC))
        {
                USART2->SR &= ~0x00000040;//USART_ClearITPendingBit(USART2,USART_IT_TC);
                OSSemPost(Sem_Usart2Send);                
                SET_RS485_RECV;                        //发送完毕 改成接收状态
                USART2->CR1 &= ~0x00000040;//USART_ITConfig(USART2,USART_IT_TC,DISABLE);
                //OSIntExit();
                return;
        }
        /*
        ...................
        */
}        
复制代码
回复

使用道具 举报

145

主题

445

帖子

0

精华

高级会员

Rank: 4

积分
823
金钱
823
注册时间
2014-1-15
在线时间
350 小时
 楼主| 发表于 2014-11-12 16:52:07 | 显示全部楼层
不论使用TC中断还是在DMA的TC中断里设置延时发现最后两个字节《《《《《严重》》》》》误码!!!不知是什么原因。
回复

使用道具 举报

145

主题

445

帖子

0

精华

高级会员

Rank: 4

积分
823
金钱
823
注册时间
2014-1-15
在线时间
350 小时
 楼主| 发表于 2014-11-12 17:04:34 | 显示全部楼层


由上图可以看出在DMA TCIF里开启USART TC中断来判断传输是否完成是可以的,但是实际操作中发现最后两个字节超大误码率
PS:如果一直开USART TC中断是不是在DMA发送时一直占用串口CPU???
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2014-11-12 22:38:23 | 显示全部楼层
帮顶....
回复

使用道具 举报

145

主题

445

帖子

0

精华

高级会员

Rank: 4

积分
823
金钱
823
注册时间
2014-1-15
在线时间
350 小时
 楼主| 发表于 2014-11-13 12:44:09 | 显示全部楼层
我擦,竟然没人回!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

回复

使用道具 举报

145

主题

445

帖子

0

精华

高级会员

Rank: 4

积分
823
金钱
823
注册时间
2014-1-15
在线时间
350 小时
 楼主| 发表于 2014-11-13 13:47:37 | 显示全部楼层
他妈的,不搞了!!!!
回复

使用道具 举报

17

主题

55

帖子

0

精华

初级会员

Rank: 2

积分
99
金钱
99
注册时间
2015-1-2
在线时间
18 小时
发表于 2015-8-21 11:39:53 | 显示全部楼层
看的我笑起来了。。。
回复

使用道具 举报

145

主题

445

帖子

0

精华

高级会员

Rank: 4

积分
823
金钱
823
注册时间
2014-1-15
在线时间
350 小时
 楼主| 发表于 2015-8-22 09:07:27 | 显示全部楼层
回复【10楼】小杰:
---------------------------------
才学单口,笑果不好,请担待
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-16 07:24

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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