在使用DMA做RS485通信的时候,需要在发送的时候将芯片设置为发送,在发送完毕设置为接收模式。但是用下面的代码,程序一直在发送的函数里面死循环,无法理解,下面是我的代码,请做过的朋友帮我分析一下谢谢!
时钟使能了的 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 , ENABLE); 中断向量也是打开了的 /* Enable DMA1 channel2 IRQ Channel RS485发送完成中断 */ NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQChannel; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);
GPIO也是设置好的
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_13 | GPIO_Pin_15; //CAN TX(PB9),RS485 TX(PA9),SPI SCK(PB13),SPI MOSI(PB15)设置为复用功能推挽输出 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //RS485 RX(PB11) 设置为输入浮空 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOB, &GPIO_InitStructure);
/******************************************************************************** *函数原型: void RS232_Init(u32 baud) *参数说明: baud: 波特率 *返回值: 无 *说明: USART 通讯口初始化程序 设置帧格式: 8 个数据位,无奇偶效验位,1个停止位 8N1 * 0:2400 bps 4.2MS 每字节 1:9600bps 1MS 每字节 2:19200bps 0.5MS 每字节 3:38400bps 0.25 每字节 4:115200bps 0.087MS 每字节 * 对于通信接收数据打包的判断,一个就是接收数据超过64字节,另外就是超时的计算,超时 * 设定为各个通信波特率的,两字节传输时间没有收到数据就打包发出。 ********************************************************************************/ void RS485Bus_Init(u8 BaudNum) //USART 通讯口初始化程序 { USART_InitTypeDef USART_InitStructure; DMA_InitTypeDef DMA_InitStructure; u32 baud = 19200; switch(BaudNum) { case 0: baud = 2400; break; case 1: baud = 9600; break; case 2: baud = 19200; break; case 3: baud = 38400; break; case 4: baud = 115200; break; default : baud = 19200; break; }
USART_InitStructure.USART_BaudRate = baud; //波特率设置 USART_InitStructure.USART_WordLength = USART_WordLength_8b; //通讯格式 8N1,无硬件流控 USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART3, &USART_InitStructure); ///////////////////////////////////首先开启一次DMA传送使DMA1_FLAG_TC2 置位///////////////////// DMA_DeInit(DMA1_Channel2); DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)RS485BusTxData; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = 1; 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_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel2, &DMA_InitStructure); DMA_ClearFlag(DMA1_FLAG_TC2); DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE); //使能发送完成中断
/* DMA1 Channel3 (triggered by USART3_RX event) Config */ DMA_DeInit(DMA1_Channel3); DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)RS485BusRxData; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = RS485_BUF_NUM; DMA_Init(DMA1_Channel3, &DMA_InitStructure);
USART_DMACmd(USART3, USART_DMAReq_Rx | USART_DMAReq_Tx, ENABLE); USART_ITConfig(USART3, USART_IT_IDLE, ENABLE); //接收空闲中断使能
DMA_Cmd(DMA1_Channel2, ENABLE); DMA_Cmd(DMA1_Channel3, ENABLE);
USART_Cmd(USART3, ENABLE); }
/******************************************************************************** *函数原型: void RS232_SendData(void) *参数说明: Len : 帧数据长度 * *data : 指向发送数据寄存器组 *返回值: 无 *说明: 将待发送的数据发送出去 ********************************************************************************/ void RS485Bus_SendData(void) //将待发送的数据发送出去 { DMA_InitTypeDef DMA_InitStructure;
RS485_TXEN; //发送使能
while (DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET); //等待上一个数据帧发送完毕
DMA_DeInit(DMA1_Channel2); DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)RS485BusTxData; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = RS485BusTxNum; 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_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel2, &DMA_InitStructure);
DMA_ClearFlag(DMA1_FLAG_TC2); DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE); //使能发送完成中断
DMA_Cmd(DMA1_Channel2, ENABLE); } 发送完成中断函数,清标记,设置RS485为接收状态 void DMA1_Channel2_IRQHandler(void) { //DMA1 Channel2 发送完成中断 */ if(DMA_GetITStatus(DMA1_IT_TC2) != RESET) { DMA_ClearITPendingBit(DMA1_IT_TC2); //清中断标志 RS485_RXEN; //接收使能 } }
|