完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本人在使用STM32F0和STM32F4做远程可插拔IO产品,遇到一些问题,请求帮忙。
一、性能要求 (1)一主多从,轮询问答方式; (2)能跑6Mbps,主机收到从机应答后间隔50us左右发送下一次轮询,单次轮询字节12Byte,应答12Byte,判定超时时间为200us (3)具备容错处理功能 (4)从机根据轮询报文中的地址字节是否为自己的来确定是否应答 二、硬件配置 主机主要使用的MCU:STM32F051C8T6和STM32F407VGT6 从机主要使用的MCU:STM32F051C8T6 高速485芯片:SP3078EE,TXD没有外部上拉,RXD用10K上拉,DE和RE用10K下拉 051系列利用DE功能驱动485的发送使能,407系列用IO驱动 三、软件配置 使用DMA发送并使能发送完成中断;使用DMA接收但不用DMA接收完成中断,而是用IDLE中断 四、目前状况 (1)目前只能跑到2Mbps,而且不是非常稳定,错误包太多,导致有效更新速度很低 (2)用外部接一个高速USB转485发现,发送出来的报文都没有错,只是有些报文从机没有回复 (3)两个MCU全部用Jlink仿真全速跑,出错以后,发现一部分是因为接收中断里面count和UART_DMA_POS_record相等,因此算出来的实际接收长度为0;另一部分原因是其中的某个字节传输错误导致最后CRC计算出错,但是我认真比对了MCU实际发送的和USB转485抓取的完全相同,但是另一个MCU接收的错误一个字节。 (4)上电一开始可以正常无差错运行1-3分钟,之后出错概率一直在增加,差不多10分钟就基本都是错的,主机LED指示灯显示大多数处于超时阶段,USB转485抓的报文也证明从机没有回复 五、串口软件配置(STM32F051为例) void USART_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; DMA_InitTypeDef DMA_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1); GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1); GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_1); // USART1_TX -> PA9, USART1_RX -> PA10, USART1_RTS -> PA12 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // USART_DeInit(USART1); USART_InitStructure.USART_BaudRate = 2000000;//921600; USART_InitStructure.USART_WordLength = USART_WordLength_9b;//USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_Even;//USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_OverSampling8Cmd(USART1, ENABLE); USART_Init(USART1, USART_InitStructure); /// Modbus RTO settings USART_MSBFirstCmd(USART1, DISABLE); // USART_SetReceiverTimeOut(USART1, 100); // USART_ReceiverTimeOutCmd(USART1, ENABLE); // USART_ITConfig(USART1, USART_IT_RTO, ENABLE); // USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // Test for circular 20180801 USART_ClearITPendingBit(USART1, USART_IT_IDLE); USART_ClearITPendingBit(USART1, USART_IT_TC); USART_ClearITPendingBit(USART1, USART_IT_RXNE); USART_ClearITPendingBit(USART1, USART_IT_TXE); USART_ITConfig(USART1, USART_IT_TC, DISABLE); USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); USART_ITConfig(USART1, USART_IT_TXE, DISABLE); USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); USART_ClearITPendingBit(USART1, USART_IT_IDLE); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init( NVIC_InitStructure); USART_DECmd(USART1, ENABLE); USART_DEPolarityConfig(USART1, USART_DEPolarity_High); USART_SetDEAssertionTime(USART1, 10); USART_SetDEDeassertionTime(USART1, 0); DMA_DeInit(DMA1_Channel2); DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)( MODBUS_SYS_PTR->ADU_BUFF_SND[0]); DMA_InitStructure.DMA_BufferSize = 12; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) USART1->TDR; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel2, DMA_InitStructure); DMA_ClearFlag(DMA1_FLAG_TC2); USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); DMA_DeInit(DMA1_Channel3); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) USART1->RDR; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)( UART1_RCV[0]); DMA_InitStructure.DMA_BufferSize = UART_DMA_SIZE; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_Init(DMA1_Channel3, DMA_InitStructure); DMA_ClearFlag(DMA1_FLAG_TC2); USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE); DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE); // DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE); DMA_Cmd(DMA1_Channel2, DISABLE); DMA_Cmd(DMA1_Channel3, ENABLE); USART_Cmd(USART1, ENABLE); } void USART1_IRQHandler(void) { uint8_t temp = 0; uint16_t u16temp = 0; uint32_t length = 0; uint32_t count =0 ; int index =0 ; // Test for circular 20180801 if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) { // for 051 series USART_ClearITPendingBit(USART1, USART_IT_IDLE); // for 407 series // u16temp = USART1->SR; // u16temp = USART1->DR; index = DMA_GetCurrDataCounter(DMA1_Channel3); count = UART_DMA_SIZE - index; if( count >= UART_DMA_POS_record ) { MODBUS_SYS_PTR->ADU_RCV_LEN =count - UART_DMA_POS_record; } else { MODBUS_SYS_PTR->ADU_RCV_LEN =count - UART_DMA_POS_record + UART_DMA_SIZE; } // Hurry20180810 // Just copy the data stream with length 0x0C if(MODBUS_SYS_PTR->ADU_RCV_LEN == 0x0C) { for(index =0;index < MODBUS_SYS_PTR->ADU_RCV_LEN; index++) { MODBUS_SYS_PTR->ADU_BUFF_RCV[index] = UART1_RCV[UART_DMA_POS_record+index]; } // To inform the data stream received MODBUS_SYS_PTR->MODBUS_ADU_RCV = 0xFF; } // Update the UART_DMA_POS_record UART_DMA_POS_record += MODBUS_SYS_PTR->ADU_RCV_LEN; if(UART_DMA_POS_record >= UART_DMA_SIZE) { UART_DMA_POS_record -= UART_DMA_SIZE; } } } void DMA1_Channel2_3_IRQHandler(void) { if(DMA_GetFlagStatus(DMA1_FLAG_TC2) != RESET) //??DMA1TC1?? { DMA_ClearFlag(DMA1_FLAG_TC2); DMA_Cmd(DMA1_Channel2, DISABLE); } } void ModulbusMain( void ) { UBYTE CRCTemp = 0; if( MODBUS_SYS_PTR->MODBUS_ADU_RCV ) // One complete Modulbus ADU has been accepted { MODBUS_SYS_PTR->MODBUS_ADU_RCV = 0x00; MODBUS_SYS_PTR->ADU_RCV_LEN = 0x00; if( (MODBUS_SYS_PTR->ADU_BUFF_RCV[0] == 0x68) (MODBUS_SYS_PTR->ADU_BUFF_RCV[1] == MODBUS_SYS_PTR->MODBUS_ADD) ) { // Check CRC CRCTemp = MODBUSCRC( ( MODBUS_SYS_PTR->ADU_BUFF_RCV[0]), 11 ); if( CRCTemp == MODBUS_SYS_PTR->ADU_BUFF_RCV[11] ) // Check the ADU data validity { // if( (MODBUS_SYS_PTR->ADU_BUFF_RCV[1] == MODBUS_SYS_PTR->MODBUS_ADD) ) { // DO1~8 if( MODBUS_SYS_PTR->ADU_BUFF_RCV[3] != MODBUS_SYS_PTR->DataRecord) { MODBUS_SYS_PTR->DataRecord = MODBUS_SYS_PTR->ADU_BUFF_RCV[3]; if(MODBUS_SYS_PTR->DataRecord 0x01) { GPIO_SetBits(GPIOA, GPIO_Pin_7); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_7); } if(MODBUS_SYS_PTR->DataRecord 0x02) { GPIO_SetBits(GPIOA, GPIO_Pin_6); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_6); } if(MODBUS_SYS_PTR->DataRecord 0x04) { GPIO_SetBits(GPIOA, GPIO_Pin_5); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_5); } if(MODBUS_SYS_PTR->DataRecord 0x08) { GPIO_SetBits(GPIOA, GPIO_Pin_4); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_4); } if(MODBUS_SYS_PTR->DataRecord 0x10) { GPIO_SetBits(GPIOA, GPIO_Pin_3); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_3); } if(MODBUS_SYS_PTR->DataRecord 0x20) { GPIO_SetBits(GPIOA, GPIO_Pin_2); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_2); } if(MODBUS_SYS_PTR->DataRecord 0x40) { GPIO_SetBits(GPIOA, GPIO_Pin_1); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_1); } if(MODBUS_SYS_PTR->DataRecord 0x80) { GPIO_SetBits(GPIOA, GPIO_Pin_0); } else { GPIO_ResetBits(GPIOA, GPIO_Pin_0); } MODBUS_SYS_PTR->ADU_BUFF_SND[1] = MODBUS_SYS_PTR->MODBUS_ADD; MODBUS_SYS_PTR->ADU_BUFF_SND[3] = MODBUS_SYS_PTR->ADU_BUFF_RCV[3]; MODBUS_SYS_PTR->ADU_BUFF_SND[0] = 0x68; CRCTemp = MODBUSCRC( ( MODBUS_SYS_PTR->ADU_BUFF_SND[0]), 11 ); MODBUS_SYS_PTR->ADU_BUFF_SND[11] = CRCTemp; MODBUS_SYS_PTR->ADU_SND_LEN = 0x0C; MODBUS_SYS_PTR->ADU_SND_MAX = MODBUS_SYS_PTR->ADU_SND_LEN; MODBUS_SYS_PTR->ADU_SND_DONE = 0x01; // Transmitting DMA_SetCurrDataCounter(DMA1_Channel2, 12); DMA_Cmd(DMA1_Channel2, ENABLE); } } } else // Reject { MODBUS_SYS_PTR->MODBUS_TIMER1_ON = 0x01; // Add 20171017 MODBUS_SYS_PTR->BACKBUS_Poll1ms = 0; } } else // Reject { MODBUS_SYS_PTR->MODBUS_TIMER1_ON = 0x01; // Add 20171017 MODBUS_SYS_PTR->BACKBUS_Poll1ms = 0; } } } 请有用过STM32F051和STM32F407高速UART的大神及专家予以帮助,万分感谢! 上海鹤锐电子科技有限公司 李仁涛18601228404(微信同号),QQ 157454269[/td] 以下内容为评论 [td]今天又做了几个试验,发现进入UART中断后,经常会发生ORE和NE事件 void USART1_IRQHandler(void) { uint8_t temp = 0; uint16_t u16temp = 0; uint32_t length = 0; uint32_t count =0 ; int index =0 ; // Test for circular 20180801 if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) { USART_ClearITPendingBit(USART1, USART_IT_IDLE); index = DMA_GetCurrDataCounter(DMA1_Channel3); count = UART_DMA_SIZE - index; if( count >= UART_DMA_POS_record ) { BACKBUS_SYS_PTR->ADU_RCV_LEN =count - UART_DMA_POS_record; } else { BACKBUS_SYS_PTR->ADU_RCV_LEN =count - UART_DMA_POS_record + UART_DMA_SIZE; } // Hurry20180810 // Just copy the data stream with length 0x0C if(BACKBUS_SYS_PTR->ADU_RCV_LEN == 0x0C) { for(index =0;index < BACKBUS_SYS_PTR->ADU_RCV_LEN; index++) { BACKBUS_SYS_PTR->ADU_BUFF_RCV[index] = UART1_RCV[UART_DMA_POS_record+index]; } // To inform the data stream received BACKBUS_SYS_PTR->BACKBUS_ADU_RCV = 0xFF; } // Update the UART_DMA_POS_record UART_DMA_POS_record += BACKBUS_SYS_PTR->ADU_RCV_LEN; if(UART_DMA_POS_record >= UART_DMA_SIZE) { UART_DMA_POS_record -= UART_DMA_SIZE; } } // deal with error instance if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET) { USART_ClearFlag(USART1,USART_FLAG_ORE); temp = USART1->RDR; UART1_ERROR_COUNT |= 0x0001; } if(USART_GetFlagStatus(USART1,USART_FLAG_NE)==SET) { USART_ClearFlag(USART1,USART_FLAG_NE); temp = USART1->RDR; UART1_ERROR_COUNT |= 0x0010; } if(USART_GetFlagStatus(USART1, USART_FLAG_FE) != RESET) /// Timeout event { USART_ClearITPendingBit(USART1, USART_FLAG_FE); temp = USART1->RDR; UART1_ERROR_COUNT |= 0x0100; } if(USART_GetFlagStatus(USART1, USART_FLAG_PE) != RESET) /// Timeout event { USART_ClearITPendingBit(USART1, USART_FLAG_PE); temp = USART1->RDR; UART1_ERROR_COUNT |= 0x1000; } } 分支if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET)和 if(USART_GetFlagStatus(USART1,USART_FLAG_NE)==SET)经常进去,我在主程序里面加了判断,如果有错误发生,就重新初始化串口,但是结果就是经常出错,所以经常初始化... 我在运行的时候量了SP3078的电源3.3V,非常稳定,就算出错的时候也没有任何波动,而且纹波峰峰值才20mV左右 不知道哪位大神有什么办法给指点指点 |
|
相关推荐
1个回答
|
|
个人见解
硬件: 1、查询官方资料,可以确定407和051的UART都能达到6Mbps的通讯速率,但这已经是051的最大极限值。建议LZ使用一组407互相通讯测试一下; 2、485的通讯速率与通讯距离以及使用的通讯材质相关,通讯速率与通讯距离成反比,6M的速率,通讯距离不能太长,否则要加中继。不知LZ测试的通讯距离以及线材是什么情况,但是测试时可以尽量缩短距离,使用符合标准的线材。 软件: 6Mbps的通讯速率,则一个字节的传输时间为4/3us,2Mbps则为4us。LZ需要分析一下接收中断里的程序执行时间,如果大于或等于(甚至略小于)1个字节的传输时间,那么就会出现当前接收的数据还未处理完成,下一个字节已经到达,导致数据丢失。这也是系统开始时还能正常工作,一段时间以后就不能正常通讯的一个原因。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1645 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1564 浏览 1 评论
992 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
691 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1610 浏览 2 评论
1870浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
655浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
525浏览 3评论
541浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
514浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-26 18:51 , Processed in 1.072697 second(s), Total 78, Slave 61 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号