#include "one2onecomm.h" #include "delay.h" #include "crc16.h" #include "trigger.h" //----------------------------------------------------------------- // 控制数据结构 typedef struct { u16 modBusWait; // 通讯延时, 单位us // 通讯函数指针 UsartSendData One2OneCommSend; // 发送数据 UsartGetData One2OneCommReceive; // 接收数据 IsUsartSendOver IsOne2OneCommSendOver; // 判断发送缓冲区是否为空 }One2OneCommCtrl; // 控制结构 One2OneCommCtrl g_one2onecommCtrl; #define MAX_ONE2ONE_CMD 10 // 最大支持的命令个数 typedef struct { One2OneCmd cmdbuf[MAX_ONE2ONE_CMD]; u8 sending; // =1,发送中 u8 bufCmdNum; // 命令个数 != 0, 有新命令 u8 bufHead; u8 bufTail; u8 steps; ResvOne2OneExProc resvexproc; // 收到数据处理函数 u16 rsvTimout; // 读取超时时间, 单位为 100us }One2OneCtrl; One2OneCtrl g_one2oneCtrl; //----------------------------------------------------------------- // 功能:初始化一对一通讯 void InitOne2OneComm(int usart, BAUD_TypeDef baud, char dat, char parity, char stop); int One2OneCommTx(u16 addr, u16 * pData, u8 len, int steps); // 功能:发送 int One2OneCommRx(u8 rDat); // 功能:接收 //----------------------------------------------------------------- // 注册通讯函数 void RegisterOne2OneCommFunc(One2OneCommCtrl* pCtrl, UsartSendData send, UsartGetData get, IsUsartSendOver sdover) { pCtrl->One2OneCommSend = send; pCtrl->One2OneCommReceive = get; pCtrl->IsOne2OneCommSendOver = sdover; } /*----------------------------------------------------------------- 功能:初始化设备串口 usart; 串口通道 baud : 波特率 dat: 数据长度 parity: 校验位 stop: 停止位 */ void InitOne2OneComm(int usart, BAUD_TypeDef baud, char dat, char parity, char stop) { memset(&g_one2onecommCtrl, 0, sizeof(One2OneCommCtrl)); // 延时 switch(baud) { // 根据波特率来计算 通讯延时, 单位us = 10000000 / baud case B4800: { g_one2onecommCtrl.modBusWait = 2200; break; } case B9600: { g_one2onecommCtrl.modBusWait = 1100; break; } case B14400: { g_one2onecommCtrl.modBusWait = 750; break; } case B19200: { g_one2onecommCtrl.modBusWait = 600; break; } case B38400: { g_one2onecommCtrl.modBusWait = 300; break; } case B57600: { g_one2onecommCtrl.modBusWait = 200; break; } case B115200: { g_one2onecommCtrl.modBusWait = 100; break; } case B230400: { g_one2onecommCtrl.modBusWait = 50; break; } case B460800: { g_one2onecommCtrl.modBusWait = 25; break; } case B921600: { g_one2onecommCtrl.modBusWait = 13; break; } default: { break; } } // 初始化串口 switch(usart) { #ifdef COMM_USART1 case COMM_USART1: { InitUsart1(baud, dat, parity, stop); // 串口1 RegisterOne2OneCommFunc(&g_one2onecommCtrl, Usart1SendData, Usart1GetData, IsUsart1SendOver); break; } #endif #ifdef COMM_USART2 case COMM_USART2: { InitUsart2(baud, dat, parity, stop); // 串口2 RegisterOne2OneCommFunc(&g_one2onecommCtrl, Usart2SendData, Usart2GetData, IsUsart2SendOver); break; } #endif #ifdef COMM_USART3 case COMM_USART3: { InitUsart3(baud, dat, parity, stop); // 串口3 RegisterOne2OneCommFunc(&g_one2onecommCtrl, Usart3SendData, Usart3GetData, IsUsart3SendOver); break; } #endif #ifdef COMM_USART4 case COMM_USART4: { InitUsart4(baud, dat, parity, stop); // 串口4 RegisterOne2OneCommFunc(&g_one2onecommCtrl, Usart4SendData, Usart4GetData, IsUsart4SendOver); break; } #endif #ifdef COMM_USART5 case COMM_USART5: { InitUsart5(baud, dat, parity, stop); // 串口5 RegisterOne2OneCommFunc(&g_one2onecommCtrl, Usart5SendData, Usart5GetData, IsUsart5SendOver); break; } #endif default: { break; } } } //----------------------------------------------------------------- // 功能:发送 // 参数: // addr: 数据起始地址: 0000H~FFFFH // data: 数据内容: 单位:字 // len: 数据长度 // steps:-1,同步执行 // 1,发送数据 // 2,等待数据发送完成 // 返回值: // >0:对应步骤执行完成 // 0:数据未发送完成 // -1: 参数错误 // -2: 发送超时 int One2OneCommTx(u16 addr, u16 * pData, u8 len, int steps) { int i, timeout, result; u16 checkcrc; // CRC 校验 u16 data; u8 pSDat[5+2*MAX_REG_WR]; // 待发送数据 i = 0; if (pData == NULL || len > MAX_REG_WR) { return -1; } if (steps == 1 || steps == -1) { i = 0; result = 0; pSDat[i++] = HIBYTE(addr); // ADDR_H pSDat[i++] = LOBYTE(addr); // ADDR_L pSDat[i++] = len; for (int j = 0; j < len; j++) { data = pData[j]; pSDat[i++] = HIBYTE(data); // DATA_H pSDat[i++] = LOBYTE(data); // DATA_L } checkcrc = CalcCrc16(&pSDat[0], i); pSDat[i++] = HIBYTE(checkcrc); // CRC_H pSDat[i++] = LOBYTE(checkcrc); // CRC_L g_one2onecommCtrl.One2OneCommSend(pSDat, i); } if (steps == 2) { if (g_one2onecommCtrl.IsOne2OneCommSendOver() != TRUE) { return 0; } } else if (steps == -1) { timeout = (u8)(i*2) + 4; // 超时时间(每个字节发送时长*2*字节数 + 每个字节发送时长*4 ) do //等待发送完成 { if (g_one2onecommCtrl.IsOne2OneCommSendOver() == TRUE) { break; } if (timeout-- <= 0) { result = -2; break; } DelayUs(g_one2onecommCtrl.modBusWait); }while(1); } if (steps != -1) { return steps; } return result; } //----------------------------------------------------------------- int One2OneCommRx(u8 rDat) { int rst = -1; u32 time; static u32 timeBuf = 0; static u8 rxDat[15+2*MAX_REG_WR]; // 待接收数据缓冲区 static u8 idx = 0; // 有效索引 static u8 num = 0; // 接收到字符数 u16 checkcrc = 0; // crc校验 One2OneCmd newCmd; memset(&newCmd, 0, sizeof(One2OneCmd)); time = Get100UsSoftTimer(); // 100us if (0 || ((time - timeBuf) > g_one2oneCtrl.rsvTimout) || // 读取超时时间, 单位为 100us (idx >= 15+2*MAX_REG_WR) || // 超长复位 0) {// 重新接收数据包 if (num > 1) { printf("data begin, num=%d\r\n", num); } idx = 0; num = 1; } else { num++; } timeBuf = time; if (num < 7) // 接收未完成 { rxDat[idx] = rDat; //printf("num=%d, rxDat[%d] is 0x%x \r\n", num, idx, rxDat[idx]); idx++; } else { rxDat[idx] = rDat; if (num == rxDat[2]*2 + 5) // 接收完成 { //校验数据是否正确 checkcrc = CalcCrc16(&rxDat[0], num-2); if (rxDat[num-2] == HIBYTE(checkcrc) && rxDat[num-1] == LOBYTE(checkcrc)) {//crc校验正确 newCmd.addr = MAKEWORD(rxDat[1],rxDat[0]); // 数据地址 newCmd.rdlen = rxDat[2]; for (int i = 0; i < newCmd.rdlen; i++) { newCmd.rddat[i] = MAKEWORD(rxDat[i*2+4],rxDat[i*2+3]); //数据 } // 执行外部函数 if (g_one2oneCtrl.resvexproc != NULL) { g_one2oneCtrl.resvexproc(&newCmd); } rst = 0; } else { printf("check crc error, calc crc:0x%x 0x%x, receive crc:0x%x 0x%x\r\n", HIBYTE(checkcrc), LOBYTE(checkcrc), rxDat[num-2], rxDat[num-1]); } idx = 0; num = 0; // 重新接收数据包 } else { idx++; } } return rst; } //----------------------------------------------------------------- void InitOne2OneCtrl(int usart, BAUD_TypeDef baud, char dat, char parity, char stop, int rsvtimout) { InitOne2OneComm(usart, baud, dat, parity, stop); memset(&g_one2oneCtrl, 0, sizeof(One2OneCtrl)); g_one2oneCtrl.rsvTimout = rsvtimout; } void RegOne2OneCmdProc(ResvOne2OneExProc proc) { g_one2oneCtrl.resvexproc = proc; } int AddOne2OneCmd(One2OneCmd * pCmd) { if (pCmd != NULL) { if (g_one2oneCtrl.bufCmdNum < MAX_ONE2ONE_CMD && g_one2oneCtrl.bufHead < MAX_ONE2ONE_CMD) { memcpy(&(g_one2oneCtrl.cmdbuf[g_one2oneCtrl.bufHead]), pCmd, sizeof(One2OneCmd)); g_one2oneCtrl.bufHead++; if (g_one2oneCtrl.bufHead >= MAX_ONE2ONE_CMD) { g_one2oneCtrl.bufHead = 0; } g_one2oneCtrl.bufCmdNum++; return g_one2oneCtrl.bufCmdNum; } printf("bufcmd full\r\n"); return -2; } printf("para error\r\n"); return -1; } void One2OneTask(void) { int rslt; // 异步发送数据 if (g_one2oneCtrl.sending == 0 && g_one2oneCtrl.bufCmdNum > 0 && g_one2oneCtrl.steps == 0) { g_one2oneCtrl.sending = 1; g_one2oneCtrl.steps = 1; } if (g_one2oneCtrl.sending != 0) { One2OneCmd *pCmd; pCmd = &(g_one2oneCtrl.cmdbuf[g_one2oneCtrl.bufTail]); if (g_one2oneCtrl.steps > 0 && g_one2oneCtrl.steps < 3) { rslt = One2OneCommTx(pCmd->addr, &pCmd->wrdat[0], pCmd->wrlen, g_one2oneCtrl.steps); if (rslt == g_one2oneCtrl.steps) { g_one2oneCtrl.steps++; } } else if (g_one2oneCtrl.steps == 3) { if (g_one2oneCtrl.bufCmdNum > 0) { g_one2oneCtrl.bufCmdNum--; } g_one2oneCtrl.steps = 0; g_one2oneCtrl.sending = 0; g_one2oneCtrl.bufTail++; if (g_one2oneCtrl.bufTail >= MAX_ONE2ONE_CMD) { g_one2oneCtrl.bufTail = 0; } } } // 接收串口缓冲区内数据 u8 rDat; int len; do { len = g_one2onecommCtrl.One2OneCommReceive(&rDat, 1); // 从缓冲区读取数据 if (len == 1) {// 接收到串口数据 rslt = One2OneCommRx(rDat); if (rslt == 0) {// 接收到一个数据包 break; } } else { break; } }while(1); } //-----------------------------------------------------------------