/******************************************************************************************* * File Name: Serial.c * Function Describe:device for serial * Relate Module: * Explain: 接收采用中断方式 UART1: 连接尾插,用于与PC相连 另外,printf映射到UART1 UART2: 连接GPS UART3: 连接Modem 全局变量g_ucUARTSel 调试选择控制,决定了3个串口的转发关系,其值通过以下3个宏控分别代表: COM_SEL_MCU 正常使用不转发,尾插用于MCU打印LOG或 MCU软件升级 COM_SEL_GPS UART1<-->UART2,尾插用于GPS LOG打印 COM_SEL_MODEM UART1<-->UART3,尾插用于MODEM AT momand 或模块软件升级 * Writer: ShiLiangWen * Date: 2015.1.20 ********************************************************************************************/ #define THIS_FILE_ID 4 /* Includes ------------------------------------------------------------------*/ #include "includes.h" #define USART1_DR_Base 0x40013804 #define USART2_DR_Base 0x40004404 #define USART3_DR_Base (u32)&USART3->DR unsigned char g_ucUARTSel=COM_SEL_MCU;//0--MCU 1--Modem 2--GPS unsigned short g_usUSART_WordLength = 0x0000;//用于串口初始化,无校验位时为0x0000,有校验位时为0x1000 unsigned char g_ucDebugLog=0;//0--不打印DEBUG信息 1--打印DEBUG信息 //UART1 对外接口 unsigned char RxBuffer1[UART1_RX_BUFFER_SIZE]; unsigned char TxBuffer1[UART1_TX_BUFFER_SIZE]; unsigned char ModbusBuf[UART1_RX_BUFFER_SIZE]; static unsigned short rx1_ct; static unsigned char rx1_ct_max=0; unsigned char g_ucUart1Sending; unsigned char g_usUart1RecvLen=0; //UART3 用于与MODEM通讯 unsigned char RxBuffer3[UART3_RX_BUFFER_SIZE]; unsigned char TxBuffer3[UART3_TX_BUFFER_SIZE]; static unsigned short susRx3In=0; static unsigned short susRx3Len=0; static unsigned short susRx3Out=0; //UART2 用于与GPS通讯 unsigned char RxBuffer2[UART2_RX_BUFFER_SIZE]; static unsigned short rx2_ct; unsigned short g_usRx2Len; /******************************************************************** *Uart1DMAInit *串口1 DMA设置 *串口1 发送必须用通道4,接收必须用通道5 *********************************************************************/ void Uart1DMAInit(void) { NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure; //启动DMA时钟 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); #if UART1_TX_USE_DMA!=0 //DMA 通道4用于UART1 TX DMA_DeInit(DMA1_Channel4); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);//外设地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer1;//内存地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//DMA传输方向单向 DMA_InitStructure.DMA_BufferSize = UART1_TX_BUFFER_SIZE; //设置DMA在传输时缓冲区的长度 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置DMA的外设递增模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //设置DMA的内存递增模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据字长 DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;//内存数据字长 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //设置DMA的传输模式 DMA_InitStructure.DMA_Priority = DMA_Priority_Low; //设置DMA的优先级别 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//设置DMA的2个memory中的变量互相访问 DMA_Init(DMA1_Channel4,&DMA_InitStructure); // //DMA中断设置 // NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn; // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&NVIC_InitStructure); DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);//中断设置 DMA_Cmd(DMA1_Channel4, DISABLE); //等到需要发送的时候再使能 #endif //DMA 通道5用于UART1 RX DMA_DeInit(DMA1_Channel5); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);//外设地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer1;//内存地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//DMA传输方向单向 DMA_InitStructure.DMA_BufferSize = UART1_RX_BUFFER_SIZE; //设置DMA在传输时缓冲区的长度 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置DMA的外设递增模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //设置DMA的内存递增模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据字长 DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;//内存数据字长 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //设置DMA的传输模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设置DMA的优先级别 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//设置DMA的2个memory中的变量互相访问 DMA_Init(DMA1_Channel5,&DMA_InitStructure); DMA_Cmd(DMA1_Channel5, ENABLE); //使能通道 } /******************************************************************** *Uart3DMAInit *串口3 DMA设置 *串口3 发送必须用通道2,接收必须用通道3 *********************************************************************/ /* void Uart3DMAInit(void) { NVIC_InitTypeDef NVIC_InitStructure; DMA_InitTypeDef DMA_InitStructure; //启动DMA时钟 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //DMA 通道2用于UART3 TX DMA_DeInit(DMA1_Channel2); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART3->DR);//外设地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer3;//内存地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//DMA传输方向单向 DMA_InitStructure.DMA_BufferSize = UART3_TX_BUFFER_SIZE; //设置DMA在传输时缓冲区的长度 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置DMA的外设递增模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //设置DMA的内存递增模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据字长 DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;//内存数据字长 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //设置DMA的传输模式 DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设置DMA的优先级别 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//设置DMA的2个memory中的变量互相访问 DMA_Init(DMA1_Channel2,&DMA_InitStructure); //DMA中断设置 // NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn; // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // NVIC_Init(&NVIC_InitStructure); DMA_ITConfig(DMA1_Channel2,DMA_IT_TC,ENABLE);//中断设置 DMA_Cmd(DMA1_Channel2, DISABLE); //等到需要发送的时候再使能 //DMA 通道3用于UART3 RX DMA_DeInit(DMA1_Channel3); DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART3->DR);//外设地址 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer3;//内存地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//DMA传输方向单向 DMA_InitStructure.DMA_BufferSize = UART3_RX_BUFFER_SIZE; //设置DMA在传输时缓冲区的长度 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置DMA的外设递增模式 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //设置DMA的内存递增模式 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据字长 DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;//内存数据字长 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //设置DMA的传输模式 DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; //设置DMA的优先级别 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//设置DMA的2个memory中的变量互相访问 DMA_Init(DMA1_Channel3,&DMA_InitStructure); DMA_Cmd(DMA1_Channel3, DISABLE); //使能通道 } */ extern unsigned short atous(char *pMsg); static unsigned char uart_data_last=0; /* Use for Modem */ void UART3RxTxISRHandler(void) { __IO unsigned char uart_data; unsigned short len; static unsigned char GSAFlag=0; if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) { uart_data = USART_ReceiveData(USART3); // Read one byte from the receive data register if(g_ucUARTSel==COM_SEL_MODEM){ USART_SendData(USART1,uart_data); }else{ if(susRx3Len=UART3_RX_BUFFER_SIZE)susRx3In=0; susRx3Len++; } isr_sem_send(&ModemUartSem); } USART_ClearITPendingBit(USART3, USART_IT_RXNE); } //--- if(USART_GetFlagStatus(USART3,USART_FLAG_ORE)==SET) { USART_ReceiveData(USART3); // USART_ClearFlag(USART3,USART_FLAG_ORE); // } } static unsigned short susTcpRecvDataLen=0;//如果是$MYNETREAD: 0,8的AT响应,则应该记录其长度并存放在susTcpRecvDataLen中,然后其后的与长度相匹配数据也一起打包成应用层的消息 /********************************************************************** Uart3RecvProcess 从UART3接收缓冲区RxBuffer3中提取消息,放入环形消息队列Uart3MsgQueue中 RxBuffer3也是环形缓冲区。 需要处理以下几种消息: (1)长度为1的'>' 消息。 (2)非+QIURC: "recv"开头,以\r\n结尾的消息 (3)以+QIURC: "recv"开头,以\r\n结尾的消息,这种消息需要处理中间接收数据中可能存在\r\n,避免分包需要一并处理 +QIURC: "recv",0,20 ************************************************************************/ void Uart3RecvProcess(void) { char data; unsigned short RxLen,out; char preData[10]; char lastData1,lastData2; unsigned short i,j; static const char RECVHEAD[]={'+','Q','I','U','R','C',':',' ','\"','r','e','c','v','\"',','};//+QIURC: "recv", RunMake(THIS_FILE_ID); //处理只有'>'的消息 if(susRx3Len==1){ USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); //关闭串口接收中断 i=susRx3In; RxLen=susRx3Len; USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //打开串口接收中断 if(i>0)i--; else i=UART3_RX_BUFFER_SIZE-1; lastData1=RxBuffer3[i]; if(lastData1=='>'){ MsgQueuePostLoopBuf(&ModemMsgQueue,(char *)RxBuffer3,UART3_RX_BUFFER_SIZE,susRx3Out,RxLen); susRx3Out=(susRx3Out+RxLen)%UART3_RX_BUFFER_SIZE; USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); //关闭串口接收中断 susRx3Len=susRx3Len-RxLen; USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //打开串口接收中断 return; } } //处理其他消息,其他消息必须以\r\n作为结束符,因此至少2字节长度, if(susRx3Len<2){ return; } //如果长度溢出,清空并重置缓冲区。 if(susRx3Len>(UART3_RX_BUFFER_SIZE-2)){ USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); //关闭串口接收中断 susRx3In=0; susRx3Out=0; susRx3Len=0; USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //打开串口接收中断 SlwTrace(DEBUG,"[Rx3Buf Over]\r\n"); RunMake(THIS_FILE_ID); return; } //获取当前缓冲区中最后的两个字节并存放在lastData1和lastData2中,并记录下当前长度放在RxLen中 USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); //关闭串口接收中断 i=susRx3In; RxLen=susRx3Len; USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //打开串口接收中断 if(i>0)i--; else i=UART3_RX_BUFFER_SIZE-1; lastData1=RxBuffer3[i]; if(i>0)i--; else i=UART3_RX_BUFFER_SIZE-1; lastData2=RxBuffer3[i]; if(lastData2!='\r' || lastData1!='\n')return; if(RxLen==2){//只有\r\n的消息抛弃掉 //更新环形缓冲区读指针和数据长度 susRx3Out=(susRx3Out+RxLen)%UART3_RX_BUFFER_SIZE; USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); //关闭串口接收中断 susRx3Len=susRx3Len-RxLen; USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //打开串口接收中断 return; } //+QIURC: "recv",x,y\r\n if(susTcpRecvDataLen==0){ if(RxLen>19){//如果缓冲区里的数据大于19字节,则先需要判断是否为+QIURC: "recv",x,y\r\n 如果是则需要和后续的数据合并 //预读15个字节,然后判断是否等于+QIURC: "recv", out=susRx3Out; for(i=0;iUART3_RX_BUFFER_SIZE)out=0; if(data!=RECVHEAD[i])break; } if(i==sizeof(RECVHEAD)){//等于RECVHEAD 则需要和后续的数据进行合并 //因此继续读后面的数据,取RECVHEAD,x,y中的y 并转为整数存在susTcpRecvDataLen中 if(++out>UART3_RX_BUFFER_SIZE)out=0;//, if(++out>UART3_RX_BUFFER_SIZE)out=0;//y for(i=0;i<4;i++){//1234 preData[i]=RxBuffer3[out]; if(++out>UART3_RX_BUFFER_SIZE)out=0; } preData[i]=0; susTcpRecvDataLen=atoi(preData); //printf("L=%d\r\n",susTcpRecvDataLen); //在此要判断一下susTcpRecvDataLen的值,如果是0,则将此包立刻输出应用层消息,否则会进入死循环 if(susTcpRecvDataLen == 0){ MsgQueuePostLoopBuf(&ModemMsgQueue,(char *)RxBuffer3,UART3_RX_BUFFER_SIZE,susRx3Out,RxLen); //更新环形缓冲区读指针和数据长度 susRx3Out=(susRx3Out+RxLen)%UART3_RX_BUFFER_SIZE; USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); //关闭串口接收中断 susRx3Len=susRx3Len-RxLen; USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //打开串口接收中断 } }else{//非RECVHEAD 开头的,则认为已是完整的消息,直接产生应用层消息。 MsgQueuePostLoopBuf(&ModemMsgQueue,(char *)RxBuffer3,UART3_RX_BUFFER_SIZE,susRx3Out,RxLen); //更新环形缓冲区读指针和数据长度 susRx3Out=(susRx3Out+RxLen)%UART3_RX_BUFFER_SIZE; USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); //关闭串口接收中断 susRx3Len=susRx3Len-RxLen; USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //打开串口接收中断 } }else{//长度小于19字节,当然是非RECVHEAD消息了,那就认为已是完整的消息,直接产生应用层消息。 MsgQueuePostLoopBuf(&ModemMsgQueue,(char *)RxBuffer3,UART3_RX_BUFFER_SIZE,susRx3Out,RxLen); //更新环形缓冲区读指针和数据长度 susRx3Out=(susRx3Out+RxLen)%UART3_RX_BUFFER_SIZE; USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); //关闭串口接收中断 susRx3Len=susRx3Len-RxLen; USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //打开串口接收中断 } }else{ //比如:+QIURC: "recv",0,20\r\n..... //则sTcpRecvDataLen=20, 总长度=19+2+20 //如果susTcpRecvDataLen是1位数,那么RxLen=susTcpRecvDataLen+20 //如果susTcpRecvDataLen是2位数,那么RxLen=susTcpRecvDataLen+21 //如果susTcpRecvDataLen是3位数,那么RxLen=susTcpRecvDataLen+22 //如果susTcpRecvDataLen是4位数,那么RxLen=susTcpRecvDataLen+23 if(susTcpRecvDataLen<10)i=susTcpRecvDataLen+20; else if(susTcpRecvDataLen<100)i=susTcpRecvDataLen+21; else if(susTcpRecvDataLen<1000)i=susTcpRecvDataLen+22; else i=susTcpRecvDataLen+23; if(RxLen>=i){//长度够了,完整的数据包,产生应用层消息 MsgQueuePostLoopBuf(&ModemMsgQueue,(char *)RxBuffer3,UART3_RX_BUFFER_SIZE,susRx3Out,RxLen); //更新环形缓冲区读指针和数据长度 susRx3Out=(susRx3Out+RxLen)%UART3_RX_BUFFER_SIZE; USART_ITConfig(USART3, USART_IT_RXNE, DISABLE); //关闭串口接收中断 susRx3Len=susRx3Len-RxLen; USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //打开串口接收中断 susTcpRecvDataLen=0; } } } /******************************************************************************** *Uart1Send *串口1启动发送 *********************************************************************************/ /* void Uart1Send(char *txbuf,int len) { int i; unsigned char data; unsigned char last_data=~UART_TRANSFORM; //Send Head USART_SendData(USART1, UART_HEAD); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); for(i=0;i(UART1_TX_BUFFER_SIZE-12))len=UART1_TX_BUFFER_SIZE-12; else len=size; len+=12; pData=(char *)&TxBuffer1[12]; #else if(size>UART1_TX_BUFFER_SIZE)len=UART1_TX_BUFFER_SIZE; else len=size; pData=(char *)&TxBuffer1[0]; #endif for(i=0;iCMAR = (u32)TxBuffer1; DMA1_Channel4->CNDTR = len; g_ucUart1Sending=1; DMA_Cmd (DMA1_Channel4,ENABLE); //使能DMA,开始发送 #else Uart1Send(pbuffer,size); #endif } void USART1_SendWaitCompleted(void) { #if UART1_TX_USE_DMA==1 while(g_ucUart1Sending!=0){ os_dly_wait(1); } #endif } //void USART2_SendWaitCompleted(void) //{ //#if UART2_TX_USE_DMA==1 // while(g_ucUart2Sending!=0){ // os_dly_wait(1); // } //#endif //} void USART3_SendWaitCompleted(void) { #if UART3_TX_USE_DMA==1 while(g_ucUart3Sending!=0){ os_dly_wait(1); } #endif } /************************************************************************************* * 函数名:USART2_Send * 描述 :串口2发送数据函数 * 输入 :要发送数据的首地址,发送数据的个数。发送数据的地址任意,并不用固定为Txd1Buffer * 输出 : 无 * 举例 :Usart2_Send("Hello word!",11); Usart1_Send(Txd1Buffer,11); **************************************************************************************/ //void USART2_Send(char *pbuffer, unsigned short size) //{ //#if UART2_TX_USE_DMA==1 // unsigned short i; // unsigned short len; // if(size==0)return; // //等待上一次发送完成 // while(g_ucUart2Sending!=0){} // // if(size>UART2_TX_BUFFER_SIZE)len=UART2_TX_BUFFER_SIZE; // else len=size; // for(i=0;iCMAR = (u32)DMATxBuffer2; // DMA1_Channel7->CNDTR = len; // g_ucUart2Sending=1; // DMA_Cmd (DMA1_Channel7,ENABLE); //使能DMA,开始发送 //数据发送中 //灯亮 // RunMake(THIS_FILE_ID); //#else // Uart2Send(pbuffer,size); //#endif //} /************************************************************************************* * 函数名:USART3_Send * 描述 :串口1发送数据函数 通过DMA实现 * 输入 :要发送数据的首地址,发送数据的个数。发送数据的地址任意,并不用固定为Txd1Buffer * 输出 : 无 * 举例 :Usart3_Send("Hello word!",11); Usart3_Send(Txd3Buffer,11); **************************************************************************************/ void USART3_Send(char *pbuffer, unsigned short size) { #if UART3_TX_USE_DMA==1 unsigned short i; if(size==0 || size>UART3_TX_BUFFER_SIZE)return; //等待上一次发送完成 while(g_ucUart3Sending!=0){ os_dly_wait(1); } for(i=0;iCMAR = (u32)TxBuffer3; DMA1_Channel2->CNDTR = size; g_ucUart3Sending=1; DMA_Cmd (DMA1_Channel2,ENABLE); //使能DMA,开始发送 //数据发送中 //灯亮 #else Uart3Send(pbuffer,size); #endif } /********************************************************************************************* *UART1RxTxISRHandler *串口1中断处理函数 通讯协议 RxBuffer1接收缓冲区 sutMsg.Uart1Recv为1表明接受到一包数据,需要应用层处理数据后将其清零以便接受新的数据包 每包数据均以UART_HEAD开头,UART_END结尾。如解决数据包内容刚好有与UART_HEAD或UART_END相等的值,则需要转义 转义字符为UART_TRANSFORM,当收到UART_TRANSFORM开头时将根据紧挨其后的字符决定转义 如UART_HEAD=0x7a UART_END=0x7b UART_TRANSFORM=0x7c 如拟发送数据为: 01 02 7a 03 04 7b 05 06 7c 08 09 经过转换后的数据包为: 01 02 7c 02 03 04 7c 03 05 06 7c 01 08 09 加上包头包尾后: 7a 01 02 7c 02 03 04 7c 03 05 06 7c 01 08 09 7b ********************************************************************************************** void UART1RxTxISRHandler(void) { __IO unsigned char uart_data; __IO static unsigned char last_data; //----接收中断-------- if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { uart_data = USART_ReceiveData(USART1); if(sutMsg.Uart1Recv){//上一批没处理,不接受新数据 USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除中断标志 rx1_ct=0; return; } if(uart_data==UART_HEAD){//包头 RxBuffer1[0]=UART_HEAD; rx1_ct=1; }else if(rx1_ct>=(UART1_RX_BUFFER_SIZE-1)){//超出接受缓冲区,丢掉此包数据,复位重新接收 rx1_ct=0; }else if(rx1_ct>0){ if(uart_data==UART_END){//包尾 RxBuffer1[rx1_ct++]=uart_data; rx1_len=rx1_ct; rx1_ct=0; sutMsg.Uart1Recv=1; }else if(uart_data==UART_TRANSFORM){//转义字符,忽略 }else{ if(last_data==UART_TRANSFORM){ if(0x01==uart_data)RxBuffer1[rx1_ct++]=UART_TRANSFORM; else if(0x02==uart_data)RxBuffer1[rx1_ct++]=UART_HEAD; else if(0x03==uart_data)RxBuffer1[rx1_ct++]=UART_END; }else{ RxBuffer1[rx1_ct++]=uart_data; } } } last_data=uart_data; USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除中断标志 } } */ unsigned char max_len=0; /********************************************************************************************* *UART1RxTxISRHandler *串口1中断处理函数 **********************************************************************************************/ void UART1RxTxISRHandler(void) { __IO unsigned char uart_data; __IO static unsigned char uart_last_data; static unsigned short len,cnt=0; //----接收中断-------- if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) { len = USART1->SR;//先读SR,再读DR len = USART1->DR;//方可清USART_IT_IDLE标志 // len = UART1_RX_BUFFER_SIZE - DMA1_Channel5->CNDTR; // DMA_Cmd(DMA1_Channel5,DISABLE); //// if(g_usUart1RecvLen==0){ //// memcpy(ModbusBuf,RxBuffer1,len); //// g_usUart1RecvLen=len; //// } // DMA1_Channel5->CNDTR = UART1_RX_BUFFER_SIZE; // DMA_Cmd(DMA1_Channel5,ENABLE); } if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { uart_data = USART_ReceiveData(USART1); USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除中断标志 if(g_ucUARTSel==COM_SEL_MODEM){ USART_SendData(USART3,uart_data); }else{ if(g_usUart1RecvLen!=0){//上一包数据未处理完,不处理新来的数据,直接扔掉! cnt=0; return; } RxBuffer1[cnt++]=uart_data; #if 1 if(RxBuffer1[0] == 'R'){//检测RT+TM指令 if((cnt >= 2 && RxBuffer1[1] != 'T') || (cnt >= 3 && RxBuffer1[2] != '+')){ cnt=0; }else if(uart_last_data=='\r' && uart_data=='\n'){ g_usUart1RecvLen=cnt; cnt=0; } }else if(RxBuffer1[0] == PRO_HEADER){ if(cnt >= 3){ len=RxBuffer1[2]+3;//总接收长度 if(cnt>=len){//收够一包长度了 g_usUart1RecvLen=cnt; cnt=0; } } }else{//命令不认可 cnt=0; RxBuffer1[0]=0; } #else if(rx1_ct>2){ if( RxBuffer1[0]==0xAA && RxBuffer1[1]==0xBB){ if(rx1_ct==3)max_len=uart_data; else if(rx1_ct>max_len){ rx1_ct=0; max_len=0; RxBuffer1[0]=0; return; } if(uart_last_data==0xDD && uart_data==0x55){ g_usUart1RecvLen=rx1_ct; RxBuffer1[rx1_ct]=0;//末尾补0,方便应用层调试直接打印消息内容。 rx1_ct=0; } }else if((RxBuffer1[0]=='R'|| RxBuffer1[0]=='A') && RxBuffer1[1]=='T'){ if(uart_last_data=='\r' && uart_data=='\n'){ g_usUart1RecvLen=rx1_ct; RxBuffer1[rx1_ct]=0;//末尾补0,方便应用层调试直接打印消息内容。 rx1_ct=0; max_len=0; } }else{ rx1_ct=0; max_len=0; RxBuffer1[0]=0; } }else if(rx1_ct==1 && uart_data!=0xAA && uart_data!='R' && uart_data!='A'){ rx1_ct=0; max_len=0; RxBuffer1[0]=0; }else if(rx1_ct==2 && uart_data!=0xBB && uart_data!='T'){ rx1_ct=0; max_len=0; RxBuffer1[0]=0; } #endif if(rx1_ct>=(UART1_RX_BUFFER_SIZE-1)){//数据超过缓冲区的数据,过滤不处理 rx1_ct=0; max_len=0; g_usUart1RecvLen=0; } uart_last_data=uart_data; } } //---异常中断--- if(USART_GetFlagStatus(USART1,USART_FLAG_ORE)==SET) { USART_ReceiveData(USART1); // USART_ClearFlag(USART1,USART_FLAG_ORE); // } } /******************************************************************************* Uart1Init 对外接口 mode=0 正常模式 采用Idel中断 波特率 9600 mode=1 GPS透传模式 采用RXEN中断 波特率 9600 mode=2 Modem透传模式 采用RXEN中断 波特率 115200 *******************************************************************************/ void Uart1Init(int mode) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1,ENABLE); /* * USART1_TX -> PA9 , USART1_RX -> PA10 , RS485_DIR -> PA8 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU;// GPIO_Mode_IPU;//GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); if(mode<2){ USART_InitStructure.USART_BaudRate =115200;//9600; }else{ USART_InitStructure.USART_BaudRate = 115200; } USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); USART_ClearFlag(USART1,USART_FLAG_TC); USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //ENABLE DISABLE if(mode==0){ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //ENABLE DISABLE USART_ITConfig(USART1, USART_IT_IDLE, DISABLE); //USART_IT_IDLE USART_IT_RXNE //USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE); //使能USART1的接收DMA请求ENABLE //USART_DMACmd(USART1,USART_DMAReq_Tx,DISABLE); //使能USART1的发送DMA请求 Uart1DMAInit(); }else{ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //ENABLE DISABLE USART_ITConfig(USART1, USART_IT_IDLE, DISABLE); //USART_IT_IDLE USART_IT_RXNE USART_DMACmd(USART1,USART_DMAReq_Rx,DISABLE); //使能USART1的接收DMA请求ENABLE USART_DMACmd(USART1,USART_DMAReq_Tx,DISABLE); //使能USART1的发送DMA请求 DMA_Cmd(DMA1_Channel5, DISABLE); //使能通道 } rx1_ct=0; g_usUart1RecvLen=0; g_ucUart1Sending=0; RS485_DIR_LOW; } /******************************************************************** *Uart2DMAInit *串口2 DMA设置 *串口2 发送必须用通道7,接收必须用通道6 *********************************************************************/ //void Uart2DMAInit(void) //{ // NVIC_InitTypeDef NVIC_InitStructure; // DMA_InitTypeDef DMA_InitStructure; // //启动DMA时钟 // RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // //DMA 通道7用于UART2 TX // DMA_DeInit(DMA1_Channel7); // DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART2->DR);//外设地址 // DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer2;//内存地址 // DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//DMA传输方向单向 // DMA_InitStructure.DMA_BufferSize = UART2_TX_BUFFER_SIZE; //设置DMA在传输时缓冲区的长度 // DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置DMA的外设递增模式 // DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //设置DMA的内存递增模式 // DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据字长 // DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;//内存数据字长 // DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //设置DMA的传输模式 // DMA_InitStructure.DMA_Priority = DMA_Priority_Low; //设置DMA的优先级别 // DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//设置DMA的2个memory中的变量互相访问 // DMA_Init(DMA1_Channel7,&DMA_InitStructure); // DMA_ITConfig(DMA1_Channel7,DMA_IT_TC,ENABLE);//中断设置 // DMA_Cmd(DMA1_Channel7, DISABLE); //等到需要发送的时候再使能 ///* // //DMA 通道6用于UART2 RX // DMA_DeInit(DMA1_Channel6); // DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART2->DR);//外设地址 // DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer2;//内存地址 // DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//DMA传输方向单向 // DMA_InitStructure.DMA_BufferSize = UART2_RX_BUFFER_SIZE; //设置DMA在传输时缓冲区的长度 // DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //设置DMA的外设递增模式 // DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //设置DMA的内存递增模式 // DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据字长 // DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;//内存数据字长 // DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //设置DMA的传输模式 // DMA_InitStructure.DMA_Priority = DMA_Priority_High; //设置DMA的优先级别 // DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//设置DMA的2个memory中的变量互相访问 // DMA_Init(DMA1_Channel6,&DMA_InitStructure); // // DMA_ITConfig(DMA1_Channel6,DMA_IT_TC,DISABLE);//中断设置 RX DMA不需要中断 // DMA_Cmd(DMA1_Channel6, ENABLE); //*/ //} /*************************************************************************** Uart2Init Use for GPS ****************************************************************************/ void Uart2Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; memset(RxBuffer2,0,sizeof(RxBuffer2)); /*使能串口2使用的GPIO时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /*使能串口2时钟*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); /*串口2 RX管脚配置*/ /* Configure USART2 Rx as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /*串口2 TX管脚配置*/ /* Configure USART2 Tx as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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(USART2, &USART_InitStructure); USART_ClearFlag(USART2,USART_FLAG_TC); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //ENABLE DISABLE USART_ITConfig(USART2, USART_IT_IDLE, DISABLE); //USART_IT_IDLE USART_IT_RXNE USART_DMACmd(USART2,USART_DMAReq_Tx,DISABLE); USART_DMACmd(USART2,USART_DMAReq_Rx,DISABLE); USART_Cmd(USART2, ENABLE); g_usRx2Len=0; rx2_ct=0; //USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE); //使能USART1的接收DMA请求 //Uart2DMAInit(); } /* Use for GPS */ void UART2RxTxISRHandler(void) { __IO unsigned char uart_data; __IO static unsigned char last_uart_data=0; if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET){ uart_data = USART_ReceiveData(USART2); if(g_ucUARTSel==COM_SEL_GPS){ USART_ClearITPendingBit(USART2,USART_IT_RXNE); USART_SendData(USART1,uart_data); return; } if(g_usRx2Len==0){ RxBuffer2[rx2_ct]=uart_data; if(rx2_ct<(UART2_RX_BUFFER_SIZE-1))rx2_ct++; //$GNRMC, //$BDGSV, //$GNRMC,062056.000,A,2237.2459,N,11402.1144,E,0.00,147.89,110319,,,A*77 if(last_uart_data=='\r' && uart_data=='\n'){ if(RxBuffer2[0]=='$' && RxBuffer2[3]=='R' && RxBuffer2[4]=='M' && RxBuffer2[5]=='C'){ g_usRx2Len=rx2_ct; sutGpsInfo.isGpsWork=1; sutGpsInfo.GpsCheckWorkCt=0; sutGpsInfo.BDCheckWorkCt=0; RxBuffer2[rx2_ct]=0; } rx2_ct=0; } }else{ rx2_ct=0; } last_uart_data=uart_data; USART_ClearITPendingBit(USART2, USART_IT_RXNE); } if(USART_GetFlagStatus(USART2,USART_FLAG_ORE)==SET) { USART_ReceiveData(USART2); // USART_ClearFlag(USART2,USART_FLAG_ORE); // } } /*************************************************************************** Uart3Init ****************************************************************************/ void Uart3Init(void) { NVIC_InitTypeDef NVIC_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; susRx3In=0; susRx3Len=0; susRx3Out=0; //初始化接收消息队列 MsgQueueInit(&ModemMsgQueue,ModemMsgQueueDataBuffer,MODEM_MSG_DATA_BUF_LEN); //使能串口3使用的GPIO时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能串口3时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //串口3 RX管脚配置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//GPIO_Mode_IPU;//GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //串口3 TX管脚配置 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//GPIO_Mode_AF_PP; GPIO_Init(GPIOB, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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); USART_ClearFlag(USART3,USART_FLAG_TC); USART_ITConfig(USART3, USART_IT_TXE, DISABLE); USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); USART_ITConfig(USART3, USART_IT_IDLE, DISABLE); USART_Cmd(USART3, ENABLE); } /* void IapTrace(char* format, ...) { static char TraceBuffer[512]; va_list argptr; int cnt; va_start(argptr, format); cnt = vsprintf(TraceBuffer, format, argptr); va_end(argptr); if(cnt>152){ printf("TraceBuffer Error!\r\n"); return; } DelayTick(10); printf("[IAP]"); printf(TraceBuffer); DelayTick(10); } */ /*********************************************************************************** * ************************************************************************************/ void SlwTrace(TRACE_TYPE type,char *buf) { int len; #ifndef SLW_DEBUG if(type==DEBUG)return; #endif if(sutDeviceConfig.DebugPrintEn == 0) if(type==DEBUG)return; if(g_ucUARTSel!=COM_SEL_MCU)return; RS485_DIR_HIGH; #if UART1_TX_USE_DMA==0 len=strlen(buf); if(len>256)len=256; Uart1Send(buf,len); #else len=strlen(buf); if(len>512)len=512; if(len>UART1_TX_BUFFER_SIZE)len=UART1_TX_BUFFER_SIZE; USART1_Send(buf,len); #endif } /******************************************************************************* ComSelect 调试口选择 #define COM_SEL_MCU 0 #define COM_SEL_GPS 1 #define COM_SEL_MODEM 2 *******************************************************************************/ void ComSelect(unsigned char sel) { switch(sel) { case COM_SEL_GPS: SlwTrace(INF,"Debug COM selcet to GPS!\r\n"); g_ucUARTSel=sel; os_tsk_delete(idModemTask); Uart1Init(1); RS485_DIR_HIGH; break; case COM_SEL_MODEM: SlwTrace(INF,"Debug COM selcet to Modem!\r\n"); g_ucUARTSel=sel; os_tsk_delete(idModemTask); Uart1Init(2); break; } } /************************************************************************** * USART1_SendOK_IQ * 串口1发送数据完毕后,会调用的中断函数,将发送标志置0 * 此函数需在stm32f10x_it.c 的 DMA1_Channel4_IRQHandler()中被调用 ***************************************************************************/ void USART1_SendOK_IQ(void) { //判断是否为DMA发送完成中断 if(DMA_GetFlagStatus(DMA1_FLAG_TC4)==SET) { DMA_ClearITPendingBit(DMA1_IT_GL4); DMA_ClearFlag(DMA1_FLAG_TC4); DMA_Cmd (DMA1_Channel4,DISABLE); g_ucUart1Sending = 0; //数据发送完毕 } //printf("USART1_SendOK_IQ\r\n"); } /************************************************************************** * USART1_SendOK_IQ * 串口1发送数据完毕后,会调用的中断函数,将发送标志置0 * 此函数需在stm32f10x_it.c 的 DMA1_Channel2_IRQHandler()中被调用 ***************************************************************************/ //void USART2_SendOK_IQ(void) //{ // // //判断是否为DMA发送完成中断 // if(DMA_GetFlagStatus(DMA1_FLAG_TC7)==SET) // { // DMA_ClearITPendingBit(DMA1_IT_GL7); // DMA_ClearFlag(DMA1_FLAG_TC7); // DMA_Cmd (DMA1_Channel7,DISABLE); // g_ucUart2Sending = 0; //数据发送完毕 // } //} /************************************************************************** * USART3_SendOK_IQ * 串口3发送数据完毕后,会调用的中断函数,将发送标志置0 * 此函数需在stm32f10x_it.c 的 DMA1_Channel2_IRQHandler()中被调用 ***************************************************************************/ //void USART3_SendOK_IQ(void) //{ // //判断是否为DMA发送完成中断 // if(DMA_GetFlagStatus(DMA1_FLAG_TC2)==SET) // { // DMA_ClearITPendingBit(DMA1_IT_GL2); // DMA_ClearFlag(DMA1_FLAG_TC2); // DMA_Cmd (DMA1_Channel2,DISABLE); // g_ucUart3Sending = 0; //数据发送完毕 // } // //printf("USART3_SendOK_IQ\r\n"); //} #ifdef __GNUC__ /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif /* __GNUC__ */ /** * @brief Retargets the C library printf function to the USART. * @param None * @retval None */ PUTCHAR_PROTOTYPE { RS485_DIR_HIGH; /* Place your implementation of fputc here */ /* e.g. write a character to the USART */ USART_SendData(USART1, (uint8_t) ch); /* Loop until the end of transmission */ while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {} RS485_DIR_LOW; return ch; }