494 lines
16 KiB
C
494 lines
16 KiB
C
|
||
#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}, // 获取电流
|
||
// ...更多命令
|
||
};
|
||
*/
|