低压电量采集平台DW710C与PC的通信
2014-04-22 16:13
162 查看
采集器的一个485接口与RS-485与RS-232转换模块的485端相连,RS-485与RS-232转换模块的232端通过串口线与PC的232串口相连,我们通过编写上位机串口通信软件和运行在采集器中的程序实现二者的通信。
1)上位机软件:
采用MFC,主要利用串口函数SetCommState、WriteFile和ReadFile进行串口设置、发送和接收。具体程序如下:
2)采集器端程序:
在采集器端25ms进行一次串口数据读取,通过判断接收到的数据是否为0x99,决定是否进行应答。通过UART_ByteSend函数进行发送应答信息。
1)上位机软件:
采用MFC,主要利用串口函数SetCommState、WriteFile和ReadFile进行串口设置、发送和接收。具体程序如下:
void CComplDlg::OnReseved() { DWORD length=0; unsigned char Com_Recv_Buf[256]; ReadFile(hCom,Com_Recv_Buf,20,&length,NULL); //读取串口内容 m_sReseved = 150; //电量 //电表地址,十六进制 m_sAddr1.Format("0x%02x", Com_Recv_Buf[4]); m_sAddr2.Format("0x%02x", Com_Recv_Buf[5]); m_sAddr3.Format("0x%02x", Com_Recv_Buf[6]); m_sAddr4.Format("0x%02x", Com_Recv_Buf[7]); m_sAddr5.Format("0x%02x", Com_Recv_Buf[8]); m_sAddr6.Format("0x%02x", Com_Recv_Buf[9]); UpdateData(false); SetCommMask(hCom,EV_TXEMPTY); UpdateData(false); } void CComplDlg::OnSend() { UpdateData(true); DWORD length=0; unsigned char Com_Send_Buf[10]; Com_Send_Buf[0]=m_sSend; if(WriteFile(hCom,Com_Send_Buf,1,&length,NULL)) { m_cReseved.EnableWindow(true); } else { MessageBox(TEXT("数据发送失败!请重试!"),TEXT("提示"),MB_OK); } } void CComplDlg::OnSetupcom() { UpdateData(true); SetupComm(hCom,1024,1024); COMMTIMEOUTS Timeouts; //DCB dcb GetCommState(hCom,&dcb); dcb.BaudRate=38400;//m_nSetupbt; dcb.ByteSize=8; dcb.StopBits=ONESTOPBIT; dcb.Parity=NOPARITY; SetCommState(hCom,&dcb); UpdateData(false); m_cSend.EnableWindow(true); m_cSend.SetFocus(); m_cSetupcomm.EnableWindow(false); m_cEditsend.SetFocus(); }
2)采集器端程序:
void main(void) { Str711_Init(); //对主芯片STR711进行初始化 /*设置初始的与PC通信的波特率*/ Base_ParaMeter.Baud_to_Pc = BAUD_UART_PC_ORDER_38400; /*因为更改了初始的与PC通信的波特率所以再将数据重新写回到SPI_Flash中去*/ SPI_Write_161d(BASE_ADDR_BASE_PARA,(u8*)&Base_ParaMeter,sizeof(Base_ParaMeter)); /*配置与PC通信的UART*/ UART_Config(UART_PC, BAUD_UART_PC_38400, UART_EVEN_PARITY, UART_1_StopBits, UARTM_8D_P); //主循环 while(1) { WDG_CntRefresh(); //刷新看门狗的计数器值 //*****************************************************************************/ /*发送一个数据包过去,请求读电量*/ /* if(Global_Task_Flag &TASK_FLAG_BEGIN_LUNXUN) { Global_Task_Flag &=(~TASK_FLAG_BEGIN_LUNXUN); if((Global_Task_Flag&TASK_FLAG_LUNXUN_ING)==0) { WDG_CntRefresh();//刷新看门狗的计数器值 LunXun_Start(); //开始轮询 } }*/ //*****************************************************************************/ if(Global_Task_Flag&TASK_FLAG_RX_PC_BIT_OK) {//串口PC的有效数据帧被收到, 执行上位机的相关命令 Global_Task_Flag &= (~TASK_FLAG_RX_PC_BIT_OK); WDG_CntRefresh(); //刷新看门狗的计数器值 Send_Ack_Or_Data_To_Host_Uart_PC(); } if(Global_Task_Flag&TASK_FLAG_25MS_TASK) {//25MS执行一次的任务 Global_Task_Flag &=(~TASK_FLAG_25MS_TASK); WDG_CntRefresh(); //刷新看门狗的计数器值 Task_2(); } WDG_CntRefresh(); //刷新看门狗的计数器值 Task_3(); } } /********************************************************************************************* *任务函数: Task2() *功能: 25ms 执行一次的任务 *********************************************************************************************/ void Task_2() { WDG_CntRefresh(); //刷新看门狗的计数器值 Parse_Com_Data(3); //串口PC } /********************************************************************************************* *任务函数: Task3() *功能: 判断串口数据的发送是否完成,如果完成将状态转换为接收状态 *********************************************************************************************/ void Task_3() { //判断串口PC的发送是否完成,如果完成,则将状态转换为接收状态 if(Com_Task_Flag& TASK_FLAG_COM_PC_SEND_COMPLETE) { Com_Task_Flag &= (~TASK_FLAG_COM_PC_SEND_COMPLETE); Com_PC_Send_Total_Len =0; Com_PC_Send_Pos =0; } } /********************************************************************************************* *函数名称: Send_Ack_Or_Data_To_Host_Uart_PC() *功能描述: 对收到串口PC 的上位机命令进行应答 *********************************************************************************************/ void Send_Ack_Or_Data_To_Host_Uart_PC() { u32 i; u8 ch; /*自定义返回格式与内容,参照DLT 645-1997多功能电能表通信规约的通信协议*/ for(int index=0; index<10; index++) Com_PC_Send_Buf[index] = index; //向上位机发送应答数据帧 Com_PC_Send_Data_Len = 3; Com_PC_Send_Check_Sum = 0; //对数据域加 0x33 for(i=0;i<Com_PC_Send_Data_Len;i++) { Com_PC_Send_Buf[10+i] +=0X33; } for(i=0;i<10+Com_PC_Send_Data_Len;i++) { Com_PC_Send_Check_Sum += Com_PC_Send_Buf[i]; } Com_PC_Send_Buf[i]= Com_PC_Send_Check_Sum; Com_PC_Send_Buf[i+1] = 0x16; Com_PC_Send_Buf[i+2] = 0x16; Com_PC_Send_Buf[i+3] = 0x16; Com_PC_FE_Number =0; //关闭接收中断,取得发送的总长度 Com_PC_Send_Total_Len = Com_PC_Send_Data_Len +14; //包括校验和以及0X16 Com_PC_Send_Pos =0; ch = 0XFE; PC_TX_ENABLE; //PC发送使能 UART_ByteSend(UART_PC,&ch ); UART_ByteSend(UART_PC,&ch ); UART_ByteSend(UART_PC,&ch ); UART_ByteSend(UART_PC,&ch ); do { if(Com_PC_Send_Pos<Com_PC_Send_Total_Len) { UART_ByteSend(UART_PC,&Com_PC_Send_Buf[Com_PC_Send_Pos]); Com_PC_Send_Pos++; } else { break; } }while (!(UART_FlagStatus(UART_PC) & UART_TxFull)); Com_Task_Flag |= TASK_FLAG_COM_PC_SEND_TIME; UART_ItConfig(UART_PC,UART_TxEmpty|UART_TxHalfEmpty,ENABLE); //发送中断使能 UART_ItConfig(UART_PC,UART_RxHalfFull|UART_TimeOutNotEmpty,DISABLE); //接收中断禁止 } /*************************************************************************************************** * FunctionName : Parse_Com_Data * Description : 解析COM口是否有一个完整的数据帧收到 * Parameter(s) : * Com_Number : 是哪一个COM口 2为下行的485口有;3为上行的PC口 * * Return : void ***************************************************************************************************/ void Parse_Com_Data(u8 Com_Number) { u8* Com_Recv_Buf; /*指向串口接收缓冲区的指针*/ u8 Com_Data_Len; /*记录数据帧的数据域长度*/ u8* Com_Recv_Buf_Ptr_W; /*串口接收缓冲区的写指针*/ u8* Com_Recv_Buf_Ptr_R; /*串口接收缓冲区的读指针*/ u16 COM_RECV_BUF_SIZE; /*接收缓冲区的大小*/ u32 TASK_FLAG_COM_RX_OK; /*接收到一个完整的帧的标志位*/ u8* Com_Process_Buf; /*如果接收的帧完整则将这一帧数据转存到这个处理缓冲区中为后面处理做准备*/ u16 i=0; switch(Com_Number) { case 3: Com_Recv_Buf = Com_PC_Recv_Buf; Com_Recv_Buf_Ptr_W = &Com_PC_Recv_Buf_Ptr_W; Com_Recv_Buf_Ptr_R = &Com_PC_Recv_Buf_Ptr_R; Com_Process_Buf = Com_PC_Process_Buf; COM_RECV_BUF_SIZE = COM_RECV_BUF_SIZE_HW_PC; TASK_FLAG_COM_RX_OK = TASK_FLAG_RX_PC_BIT_OK; break; default: return; } /*若发过来的数据是0x99,则视为可以通信,进行应答*/ if(Com_Recv_Buf[0] == 0x99) { Com_Process_Buf[0]=Com_Recv_Buf[0]; //清除缓冲区中所有的数据. memset(Com_Recv_Buf,0,COM_RECV_BUF_SIZE); //读写指针清零也可以. 暂时先不清零吧 *Com_Recv_Buf_Ptr_R = 0; *Com_Recv_Buf_Ptr_W = 0; Global_Task_Flag |= TASK_FLAG_COM_RX_OK; } //设置收到串口1有效数据帧标志 return; }
在采集器端25ms进行一次串口数据读取,通过判断接收到的数据是否为0x99,决定是否进行应答。通过UART_ByteSend函数进行发送应答信息。
相关文章推荐
- 基于低压电量采集平台DW710C的基础开发
- 低压电力采集平台DW710C与PC沟通
- 基于低压电力采集平台DW710C的基础开发
- 一个Window/Linux(Fedora测试平台)的CPU,磁盘,内存,PC,进程相关信息采集功能
- Qt开发:Qt+OpenCV在(Linux平台)PC上采集摄像头视频(源码奉送)
- ”WinForm上位机+OV7670摄像头+STM32+蓝牙“图像采集系统(二)PC-MCU蓝牙通信及WinForm上位机开发
- 统一通信平台的市场或将爆发
- 使用boch仿真器在x86 PC平台上搭建Linux0.11系统环境(windows下)
- windows平台下 c/c++进行http通信的教训
- android中利用Socket实现手机客户端与PC端进行通信
- android socket编程——两个模拟器间的通信(一台PC)
- Linux驱动基础:MSM平台AP/CP通信机制
- pc 机和android 手机之间的通信
- EverNote 极致的免费笔记资料管理软件 (数据网络同步、支持PC、Mac与手机多平台) 转自:http://www.iplaysoft.com/evernote.html
- PC软件与PLC串口通信 奇偶检验问题
- 20145221《网络对抗》PC平台逆向破解
- android虚拟机实现于本地PC相互通信
- Java程序员,你一定需要了解的六款大数据采集平台
- Android与PC客户端进行Socket通信的一些问题
- 节点-PC串口通信实验问题