WTZSSoftWare/Src/Communicaion.c

494 lines
16 KiB
C
Raw Normal View History

2025-09-29 02:42:07 +00:00
#include "cmsis_os.h"
#include "cmsis_os2.h"
#include "main.h"
#include "stdio.h"
#include "usb_device.h"
#include <math.h>
#include <stdint.h>
#include <string.h>
typedef struct
{
const char *cmd;
int cmd_id;
} CmdTable;
/*
0xAA 55
1
1
1
N字节
1
| | | | | (128B) | CRC16 |
|--------|------|--------|------|-------------|--------|
| AA 55 | 01 | 00 80 | 01 | [0xXX...] | 2 |
| | | | | (128B) | CRC16 |
|--------|------|--------|------|-------------|--------|
| AA 55 | 04 | 00 80 | FF | 00 |
*/
// extern uint8_t Uart_ReadCache[128];
// extern _Bool ReadFlag;
// uint8_t CPk = 0; // 当前包计数
// void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
// {
// UNUSED(huart);
// __HAL_UART_CLEAR_OREFLAG(huart);
// __HAL_UART_CLEAR_IDLEFLAG(huart);
// if(__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) != RESET) //
// 空闲中断标记被置位
// {
// __HAL_UART_CLEAR_IDLEFLAG(huart); // 清除中断标记
// HAL_UART_DMAStop(huart); // 停止DMA接收
// CPk = __HAL_DMA_GET_COUNTER(huart->hdmarx); // 总数据量
// HAL_UARTEx_ReceiveToIdle_DMA(huart, Uart_ReadCache, 128); //
// 重新启动DMA接收
// }
// // if ((Uart_ReadCache[0] == 'C') && (Uart_ReadCache[1] == 'M') &&
// (Uart_ReadCache[2] == 'D'))
// // {
// // char buf[10];
// // uint16_t i,j,k= 0;
// // HAL_GPIO_WritePin( GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
// // for( k = 0; k < 8; k ++ )
// // {
// // for( i = 0; i < 3; i ++)
// // {
// // for( j = 0; j < 98; j ++)
// // {
// // sprintf( buf, "%.4f\r\n", OutPut1[k][i][j]);
// // HAL_UART_Transmit(&huart, (uint8_t
// *)buf,strlen(buf),0xFFFF);
// // while(HAL_UART_GetState(&huart) ==
// HAL_UART_STATE_BUSY_TX);//锟斤拷锟経ART锟斤拷锟酵斤拷锟斤拷
// // }
// // }
// // }
// // ReadFlag = 1;
// // HAL_GPIO_WritePin( GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
// // }
// // HAL_UARTEx_ReceiveToIdle_IT(&huart1, (uint8_t *)&Uart_ReadCache, 100);
// //锟劫匡拷锟斤拷锟斤拷锟斤拷锟叫讹拷
// }
// #include "command.h"
// 假设每个通道每个频率点4字节(float)每帧最大数据长度为120字节(30个float)
#define MAX_FRAME_DATA_LEN 120
// 指令的最小长度
#define COMMAND_MIN_LENGTH 4
// 循环缓冲区大小
#define BUFFER_SIZE 121
// 循环缓冲区
uint8_t buffer[BUFFER_SIZE];
// 循环缓冲区读索引
uint8_t readIndex = 0;
// 循环缓冲区写索引
uint8_t writeIndex = 0;
/**
* @brief
* @param length
*/
void Command_AddReadIndex(uint8_t length)
{
readIndex += length;
readIndex %= BUFFER_SIZE;
}
/**
* @brief i位数据
* @param i
*/
uint8_t Command_Read(uint8_t i)
{
uint8_t index = i % BUFFER_SIZE;
return buffer[index];
}
/**
* @brief
* @return
* @retval 0
* @retval 1~BUFFER_SIZE-1
* @retval BUFFER_SIZE
*/
// uint8_t Command_GetLength() {
// // 读索引等于写索引时,缓冲区为空
// if (readIndex == writeIndex) {
// return 0;
// }
// // 如果缓冲区已满,返回BUFFER_SIZE
// if (writeIndex + 1 == readIndex || (writeIndex == BUFFER_SIZE - 1 &&
// readIndex == 0)) {
// return BUFFER_SIZE;
// }
// // 如果缓冲区未满,返回未处理的数据长度
// if (readIndex <= writeIndex) {
// return writeIndex - readIndex;
// } else {
// return BUFFER_SIZE - readIndex + writeIndex;
// }
// }
uint8_t Command_GetLength() { return (writeIndex + BUFFER_SIZE - readIndex) % BUFFER_SIZE; }
/**
* @brief
* @return
* @retval 0
* @retval 1~BUFFER_SIZE-1
* @retval BUFFER_SIZE
*/
uint8_t Command_GetRemain() { return BUFFER_SIZE - Command_GetLength(); }
/**
* @brief
* @param data
* @param length
* @return
*/
uint8_t Command_Write(uint8_t *data, uint16_t length)
{
// 如果缓冲区不足 则不写入数据 返回0
if (Command_GetRemain() < length)
{
return 0;
}
// 使用memcpy函数将数据写入缓冲区
if (writeIndex + length < BUFFER_SIZE)
{
memcpy(buffer + writeIndex, data, length);
writeIndex += length;
}
else
{
uint8_t firstLength = BUFFER_SIZE - writeIndex;
memcpy(buffer + writeIndex, data, firstLength);
memcpy(buffer, data + firstLength, length - firstLength);
writeIndex = length - firstLength;
}
return length;
}
/**
* @brief
* @param command
* @return
* @retval 0
*/
uint8_t Command_GetCommand(uint8_t *command)
{
/*
| | | | | (128B) | CRC16 |
|--------|------|--------|------|-------------|--------|
| AA 55 | 04 | 80 | FF | 00 |
*/
// 寻找完整指令
while (1)
{
// 如果缓冲区长度小于COMMAND_MIN_LENGTH 则不可能有完整的指令
if (Command_GetLength() < COMMAND_MIN_LENGTH)
{
return 0;
}
// 如果不是包头 则跳过 重新开始寻找
if (((Command_Read(readIndex) != 0xAA) || (Command_Read(readIndex + 1) != 0x55)))
{
Command_AddReadIndex(1);
continue;
}
// 如果缓冲区长度小于指令长度 则不可能有完整的指令
uint8_t length = Command_Read(readIndex + 3);
if (Command_GetLength() < length)
{
return 0;
}
// 如果校验和不正确 则跳过 重新开始寻找
uint16_t sum = 0;
for (uint8_t i = 0; i < length - 2; i++)
{
sum += Command_Read(readIndex + i);
}
if (sum != (Command_Read(readIndex + length - 2) << 8 | Command_Read(readIndex + length - 1)))
{
Command_AddReadIndex(1);
continue;
}
// 如果找到完整指令 则将指令写入command 返回指令长度
for (uint8_t i = 0; i < length; i++)
{
command[i] = Command_Read(readIndex + i);
}
Command_AddReadIndex(length);
return length;
}
}
extern osSemaphoreId_t Command_Semaphore;
extern UART_HandleTypeDef huart1;
extern uint16_t CLKHZ[98];
extern void CLKHZSET(uint16_t Deep);
extern float LineCheckF[32];
union
{
float ufloat;
uint32_t u32;
uint16_t u16[2];
uint8_t u8[4];
} uDataCover;
uint16_t FramePack(uint8_t *buf, uint8_t cmd, uint8_t frameNum, uint8_t *data, uint16_t dataLength)
{
uint8_t Lenth = 0;
uint16_t crcSum = 0;
memset(buf, 0, 128);
buf[0] = 0xAA; // 帧头
buf[1] = 0x55; // 帧头
buf[2] = cmd; // 命令
buf[3] = 0x00; // 长度
buf[4] = frameNum; // 帧号
Lenth = 7;
for (uint8_t i = 0; i < 5; i++)
{
crcSum += buf[i];
}
for (uint8_t i = 0; i < dataLength; i++)
{
buf[i + 5] = data[i];
crcSum += data[i];
Lenth += 1;
}
buf[3] = Lenth; // 更新长度
crcSum +=Lenth;
buf[Lenth - 2] = crcSum >> 8; // CRC高字节
buf[Lenth - 1] = crcSum & 0xFF; // CRC低字节
return Lenth;
}
struct uCommunication CommunicationData;
extern float OutPut1[8][4][98];
extern float OutPut2[8][4][98];
extern float OutPut3[8][4][98];
extern float OutPut4[8][4][98];
extern uint8_t Uart_ReadCache[128];
uint8_t command[50];
uint8_t SendBuf[128];
int commandLength = 0;
uint8_t dtime = 10;
void Command_Deal(void)
{
osSemaphoreAcquire(Command_Semaphore, osWaitForever); // 等待命令信号量
do
{
memset(command,0,50);
commandLength = Command_GetCommand(command);
if (commandLength == 0)
{
return;
}
uint8_t cmd = command[2]; // 获取命令
uint8_t SenDataLenth = 0;
switch (cmd)
{
case 1: // 开始测试命令
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_7, GPIO_PIN_RESET);
osDelay(50);
HAL_GPIO_WritePin(GPIOI, GPIO_PIN_7, GPIO_PIN_SET);
CommunicationData.MeasurementPrecision = 0;
CommunicationData.MeasurementFlag = 1;
break;
case 2: // 终止测试命令
CommunicationData.MeasurementPrecision = 0;
CommunicationData.MeasurementFlag = 0;
break;
case 3: // 设定深度
CommunicationData.Deep = (command[5] << 8) | command[6];
CLKHZSET(CommunicationData.Deep);
break;
case 4: // 设置增益
CommunicationData.Gain = command[5];
break;
case 5: // 设定通道数量
CommunicationData.ChannelNum = command[5];
break;
case 6: // 道接地信号强度测试命令
CommunicationData.SingelStrengthMeasurementFlag = 1;
CommunicationData.MeasurementPrecision = 0;
break;
case 7: // 获取通道接地信号强度
if (CommunicationData.MeasurementPrecision == 100.0f)
{
SenDataLenth = FramePack(SendBuf, 0x07, 0x01, (uint8_t *)LineCheckF, 16 * 4);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
HAL_UART_Transmit(&huart1, SendBuf, SenDataLenth, HAL_MAX_DELAY);
while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX)
; // 等待UART发送完成
osDelay(50);
SenDataLenth = FramePack(SendBuf, 0x07, 0xFF, (uint8_t *)(LineCheckF + 16), 16 * 4);
HAL_UART_Transmit(&huart1, SendBuf, SenDataLenth, HAL_MAX_DELAY);
while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX)
;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
osDelay(100);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, Uart_ReadCache, 128); // 重新启动DMA接收
}
break;
case 8: // 获取测量进度
{
SenDataLenth = FramePack(SendBuf, 0x08, 0xFF, (uint8_t *)&CommunicationData.MeasurementPrecision, 1);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
HAL_UART_Transmit(&huart1, SendBuf, SenDataLenth, HAL_MAX_DELAY);
while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX)
; // 等待UART发送完成
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
break;
}
case 9: // 获取测量结果
if (CommunicationData.MeasurementPrecision == 100.0f)
{
uint8_t totalChannels = CommunicationData.ChannelNum;
uint8_t totalFreqs = 0;
for (uint8_t i = 0; i < 98; i++)
{
if (CLKHZ[i] != 0)
totalFreqs++;
else
break;
}
uint32_t totalDataLen = totalChannels * totalFreqs * 4;
uint8_t frameNum = 1;
uint32_t sentLen = 0;
while (sentLen < totalDataLen)
{
/**
*
*
* 1. sendLen MAX_FRAME_DATA_LEN
* 2. dataBuf
* 3. float 4 float globalIdx ch freq
* 4. ch OutPut val
* - ch < 8: OutPut1
* - ch < 16: OutPut2
* - ch < 24: OutPut3
* - ch < 32: OutPut4
* 5. float val dataBuf
*
*
* - totalDataLen:
* - sentLen:
* - MAX_FRAME_DATA_LEN:
* - totalChannels:
* - OutPut1~4:
*/
uint32_t remain = totalDataLen - sentLen;
uint8_t sendLen = (remain > MAX_FRAME_DATA_LEN) ? MAX_FRAME_DATA_LEN : remain;
uint8_t dataBuf[MAX_FRAME_DATA_LEN];
// 组装数据
uint32_t dataIdx = 0;
uint32_t globalIdx = sentLen / 4;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
osDelay(dtime);
for (uint8_t i = 0; i < sendLen / 4; i++)
{
uint8_t ch = (globalIdx % totalChannels);
uint8_t freq = (globalIdx / totalChannels);
float val = 0.0f;
if (ch < 8)
val = OutPut1[ch][0][freq];
else if (ch < 16)
val = OutPut2[ch - 8][0][freq];
else if (ch < 24)
val = OutPut3[ch - 16][0][freq];
else if (ch < 32)
val = OutPut4[ch - 24][0][freq];
memcpy(&dataBuf[dataIdx], &val, 4);
dataIdx += 4;
globalIdx++;
}
uint8_t thisFrameNum = (sentLen + sendLen >= totalDataLen) ? 0xFF : frameNum;
SenDataLenth = FramePack(SendBuf, 0x09, thisFrameNum, dataBuf, sendLen);
HAL_UART_Transmit(&huart1, SendBuf, SenDataLenth, HAL_MAX_DELAY);
while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX)
;
sentLen += sendLen;
frameNum++;
}
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
osDelay(100);
HAL_UARTEx_ReceiveToIdle_DMA(&huart1, Uart_ReadCache, 128); // 重新启动DMA接收
}
break;
case 10: // 获取电池电压
SenDataLenth = FramePack(SendBuf, 0x0A, 0x01, (uint8_t *)&CommunicationData.BatteryVoltage, 4);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
HAL_UART_Transmit(&huart1, SendBuf, SenDataLenth, HAL_MAX_DELAY);
while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX)
; // 等待UART发送完成
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
break;
case 11: // 获取电流
SenDataLenth = FramePack(SendBuf, 0x0B, 0x01, (uint8_t *)&CommunicationData.BatteryCurrent, 4);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
HAL_UART_Transmit(&huart1, SendBuf, SenDataLenth, HAL_MAX_DELAY);
while (HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX)
; // 等待UART发送完成
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
break;
}
}
while(commandLength != 0);
}
/*
| | | | | (128B) | CRC16 |
|--------|------|--------|------|-------------|--------|
| AA 55 | 04 | 80 | FF | 00 |
CmdTable cmd_table[] = {
{"CMD_START", 1}, // 开始测试命令
{"CMD_STOP", 2}, // 终止测试命令
{"CMD_SET_FREQ", 3}, // 设定深度
{"CMD_SET_GAIN", 4}, // 设置增益
{"CMD_SET_CHANNELS", 5}, // 设定通道数量
{"CMD_TEST_GROUND", 6}, // 道接地信号强度测试命令
{"CMD_GET_GROUND", 7}, // 获取通道接地信号强度
{"CMD_GET_PROGRESS", 8}, // 获取测量进度
{"CMD_GET_RESULT", 9}, // 获取测量结果
{"CMD_GET_BATTERY_VOLTAGE", 10}, // 获取电池电压
{"CMD_GET_CURRENT", 11}, // 获取电流
// ...更多命令
};
*/