Browse Source

新增线轴控制板工程

master
Lizongdi 3 days ago
parent
commit
3b944f95c3
  1. 1
      CMakeLists.txt
  2. 15
      Spoolend/CMakeLists.txt
  3. 96
      Spoolend/Spoolend.c
  4. 105
      Spoolend/flash_operation.c
  5. 17
      Spoolend/include/flash_operation.h
  6. 60
      Spoolend/include/modbus.h
  7. 323
      Spoolend/modbus.c

1
CMakeLists.txt

@ -119,6 +119,7 @@ add_module(lua lua OFF ON)
add_module(bspMCU bspMCU OFF OFF)
add_module(RBcore RBcore OFF OFF)
add_module(optional optional OFF OFF)
add_module(Spoolend Spoolend OFF OFF)
if(A_BUILD_MAIN)
add_subdirectory(main)

15
Spoolend/CMakeLists.txt

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.10)
set(COMMON_CMAKE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../library/CMakeLists.txt")
if(EXISTS ${COMMON_CMAKE_PATH})
include(${COMMON_CMAKE_PATH})
else()
message(FATAL_ERROR "Cannot find common build logic at ${COMMON_CMAKE_PATH}")
endif()
if(TARGET bspMCU)
target_link_libraries(Spoolend PUBLIC bspMCU)
else()
message(WARNING "[Spoolend] Dependency 'bspMCU' not found.")
endif()

96
Spoolend/Spoolend.c

@ -0,0 +1,96 @@
/******************************************************************************
(C), 2018-2099, Radkil
******************************************************************************
: Spoolend.c
: 稿
: radkil
: 2026610
:
: 线
:
1. : 2026610
: radkil
:
******************************************************************************/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
TComCtrl *g_ptRS485_1;
TComCtrl *g_ptRS485_2;
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
/*----------------------------------------------*
* *
*----------------------------------------------*/
int RS485_1_Send(char *_pBuffer, uint32_t _iSize)
{
HAL_GPIO_WritePin(RS485_1_DIR_GPIO_Port, RS485_1_DIR_Pin, GPIO_PIN_SET);
TUartUserData *ptUartUserData = (TUartUserData *)g_ptRS485_1->m_pUserData;
int iRet = HAL_UART_Transmit(ptUartUserData->m_uart, (uint8_t *)_pBuffer, _iSize, 100);
HAL_GPIO_WritePin(RS485_1_DIR_GPIO_Port, RS485_1_DIR_Pin, GPIO_PIN_RESET);
return iRet;
}
int RS485_2_Send(char *_pBuffer, uint32_t _iSize)
{
HAL_GPIO_WritePin(RS485_2_DIR_GPIO_Port, RS485_2_DIR_Pin, GPIO_PIN_SET);
TUartUserData *ptUartUserData = (TUartUserData *)g_ptRS485_2->m_pUserData;
int iRet = HAL_UART_Transmit(ptUartUserData->m_uart, (uint8_t *)_pBuffer, _iSize, 100);
HAL_GPIO_WritePin(RS485_2_DIR_GPIO_Port, RS485_2_DIR_Pin, GPIO_PIN_RESET);
return iRet;
}
#ifndef CONFIG_UART_IT_IDLEDMA
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == LPUART1)
{
UART_RX_IRQHandler(g_ptRS485_1);
}
else if (huart->Instance == USART1)
{
UART_RX_IRQHandler(g_ptRS485_2);
}
}
#endif
void SpoolendInit(void)
{
TUartUserData *ptUartUserData = UART_userdata_init(0, -1, 512);
g_ptRS485_1 = rd_ComCreate(check_MK32Data, decode_MK32Data, E28_SBUS_Send, ptUartUserData->m_buf_size, ptUartUserData);
UART_IT_init(g_ptRS485_1);
TUartUserData *ptUartUserData1 = UART_userdata_init(0, -1, 512);
g_ptRS485_1 = rd_ComCreate(check_MK32Data, decode_MK32Data, E28_SBUS_Send, ptUartUserData1->m_buf_size, ptUartUserData1);
UART_IT_init(g_ptRS485_1);
}
void SpoolendTask(void)
{
}

105
Spoolend/flash_operation.c

@ -0,0 +1,105 @@
#include "flash_operation.h"
void Flash_InitInternal(void)
{
// 解锁Flash
HAL_FLASH_Unlock();
// 设置Flash延迟
__HAL_FLASH_SET_LATENCY(FLASH_LATENCY_4);
// 清除所有错误标志
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
}
uint32_t GetFlashPage(uint32_t address)
{
return (address - FLASH_BASE_ADDRESS) / FLASH_PAGE_SIZE;
}
HAL_StatusTypeDef WriteParametersToFlash(int16_t* parameters)
{
HAL_StatusTypeDef status = HAL_OK;
uint32_t flash_address = DATA_FLASH_ADDRESS;
uint32_t primask_bit;
// 关闭全局中断
primask_bit = __get_PRIMASK();
__disable_irq();
// 内部初始化Flash
Flash_InitInternal();
// 擦除Flash页
FLASH_EraseInitTypeDef erase_init;
uint32_t page_error = 0;
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.Banks = FLASH_BANK_1;
erase_init.Page = GetFlashPage(DATA_FLASH_ADDRESS);
erase_init.NbPages = 1;
// 执行擦除
if (HAL_FLASHEx_Erase(&erase_init, &page_error) != HAL_OK)
{
HAL_FLASH_Lock();
// 恢复中断状态
if (!primask_bit) {
__enable_irq();
}
return HAL_ERROR;
}
// 写入4个int16_t数据
for (int i = 0; i < PARAM_COUNT; i++)
{
// 每次写入64位数据(4个int16_t)
if (i % 4 == 0)
{
uint64_t combined_data = 0;
// 组合4个int16_t到一个uint64_t
for (int j = 0; j < 4 && (i + j) < PARAM_COUNT; j++)
{
combined_data |= ((uint64_t)((uint16_t)parameters[i + j]) << (j * 16));
}
// 写入组合后的数据
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,
flash_address + (i * sizeof(int16_t)),
combined_data) != HAL_OK)
{
status = HAL_ERROR;
break;
}
}
}
// 锁定Flash
HAL_FLASH_Lock();
// 恢复中断状态
if (!primask_bit) {
__enable_irq();
}
return status;
}
void ReadParametersFromFlash(int16_t* parameters)
{
uint32_t flash_address = DATA_FLASH_ADDRESS;
// 内部初始化Flash(主要是解锁和配置)
Flash_InitInternal();
// 从Flash读取数据
for (int i = 0; i < PARAM_COUNT; i++)
{
// 读取int16_t数据
parameters[i] = *(int16_t*)(flash_address + (i * sizeof(int16_t)));
}
// 锁定Flash(虽然读取不需要锁定,但为了对称性)
HAL_FLASH_Lock();
}

17
Spoolend/include/flash_operation.h

@ -0,0 +1,17 @@
#ifndef FLASH_OPERATION_H
#define FLASH_OPERATION_H
#include "stm32g4xx_hal.h"
/* 定义Flash存储地址 - 使用最后一页 */
#define FLASH_BASE_ADDRESS 0x08000000
//#define FLASH_SIZE (128 * 1024) // 128KB
//#define FLASH_PAGE_SIZE 0x800 // 2KB per page
#define DATA_FLASH_ADDRESS (FLASH_BASE_ADDRESS + FLASH_SIZE - FLASH_PAGE_SIZE) // 最后一页
#define PARAM_COUNT 12
/* 函数声明 */
HAL_StatusTypeDef WriteParametersToFlash(int16_t* parameters);
void ReadParametersFromFlash(int16_t* parameters);
#endif

60
Spoolend/include/modbus.h

@ -0,0 +1,60 @@
/*
* modbus.h
*
* Created on: Jul 3, 2025
* Author: shiyanlei
*/
#ifndef __MODBUS_SLAVE_H
#define __MODBUS_SLAVE_H
#include "stm32g4xx_hal.h"
/* 定义Modbus相关参数 */
#define MODBUS_SLAVE_ADDRESS 0x34
#define MODBUS_FUNCTION_CODE_03 0x03
#define MODBUS_FUNCTION_CODE_06 0x06
#define MODBUS_FUNCTION_CODE_10 0x10 // 写多个寄存器功能码
#define MODBUS_BUFFER_SIZE 256
#define MODBUS_TIMEOUT_MS 2
#define MODBUS_CRC_OFF 0 //==1关闭CRC校验
/* 定义寄存器相关参数 */
#define REGISTER_START_ADDRESS 0x0000
//#define REGISTER_COUNT 10
#define REGISTER_COUNT 12
extern uint16_t holdingRegisters[REGISTER_COUNT];
extern uint8_t RS485_1_RX;
extern uint8_t RS485_1_Host_Existed;
#define registerWritable_0 1
#define registerWritable_1 1
#define registerWritable_2 1
#define registerWritable_3 1
#define registerWritable_4 1
#define registerWritable_5 1
#define registerWritable_6 1
#define registerWritable_7 1
#define registerWritable_8 1
#define registerWritable_9 1
#define registerWritable_10 1
#define registerWritable_11 1
//holdingRegisters[0]= motor_cmd //0:stop 1:forward 2:reverse
//holdingRegisters[1]= HX711_A_F //int16_t 10g
//holdingRegisters[2]= HX711_K //uint16_t
//holdingRegisters[3]= HX711_D //int16_t 1g
//holdingRegisters[4]= HX711_B_F //int16_t 10g
extern void MB_WriteHoldingReg(uint8_t _addr,
uint16_t _reg, uint16_t _data);
/* 初始化Modbus从机 */
void Modbus_Init(void);
/* 处理Modbus消息 */
void Modbus_Process(void);
#endif /* __MODBUS_SLAVE_H */

323
Spoolend/modbus.c

@ -0,0 +1,323 @@
#include "stm32g4xx_hal.h"
#include <stdint.h>
#include <stdbool.h>
#include "modbus.h"
#include "usart.h"
void Modbus_Master_Send(uint8_t *data, uint8_t length);
uint16_t holdingRegisters[REGISTER_COUNT] = { 0x0032, 0x0032, 0x0032, 0x0032,
0x0032, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 };
// 寄存器可写标志位(1:可写,0:只读)
uint8_t registerWritable[REGISTER_COUNT] = { registerWritable_0,
registerWritable_1, registerWritable_2, registerWritable_3,
registerWritable_4, registerWritable_5, registerWritable_6,
registerWritable_7,
registerWritable_8, registerWritable_9, registerWritable_10,
registerWritable_11 };
/* 全局变量 */
uint8_t modbusBuffer[MODBUS_BUFFER_SIZE];
uint8_t modbus_master_Buffer[MODBUS_BUFFER_SIZE];
uint8_t modbus_master_BufferIndex = 0;
uint32_t last_master_ByteTime = 0;
uint8_t modbusBufferIndex = 0;
uint32_t lastByteTime = 0;
bool messageComplete = false;
uint8_t master_tx_buf[256];
uint8_t response[256];
uint8_t RS485_1_RX = 0;
uint8_t RS485_1_Host_Existed = 0;
char dmk_read_state=0;
/* 函数声明 */
void Modbus_Init(void);
void Modbus_Process(void);
void Modbus_SendResponse(uint8_t *data, uint8_t length);
void Modbus_HandleFunction03(uint16_t startAddress, uint16_t registerCount);
void Modbus_HandleFunction06(uint16_t registerAddress, uint16_t value);
void Modbus_HandleFunction10(uint16_t startAddress, uint16_t registerCount,
uint8_t *data);
void Modbus_SendExceptionResponse(uint8_t exceptionCode);
uint16_t CalculateCRC(uint8_t *data, uint8_t length);
/* 初始化函数 */
void Modbus_Init(void) {
/* 初始化UART */
/* 配置RS485方向控制引脚 */
HAL_UART_Receive_IT(&huart1, (uint8_t*) &modbusBuffer[modbusBufferIndex],
1);
HAL_UART_Receive_IT(&huart2,
(uint8_t*) &modbus_master_Buffer[modbus_master_BufferIndex], 1);
}
/* Modbus处理函数 - 应在主循环中调用 */
void Modbus_Process(void) {
uint16_t startAddress = 0;
uint16_t registerCount = 0;
if (modbusBufferIndex
> 0&& (HAL_GetTick() - lastByteTime) > MODBUS_TIMEOUT_MS) {
/* 超时,标记消息完成 */
messageComplete = true;
}
if (messageComplete) {
uint16_t crcReceived = (modbusBuffer[modbusBufferIndex - 1] << 8)
| modbusBuffer[modbusBufferIndex - 2];
uint16_t crcCalculated = CalculateCRC(modbusBuffer,
modbusBufferIndex - 2);
if (MODBUS_CRC_OFF || crcReceived == crcCalculated) {
RS485_1_Host_Existed = 1;
if (modbusBuffer[0] == MODBUS_SLAVE_ADDRESS) {
RS485_1_RX = 1;
switch (modbusBuffer[1]) {
case MODBUS_FUNCTION_CODE_03:
startAddress = (modbusBuffer[2] << 8) | modbusBuffer[3];
registerCount = (modbusBuffer[4] << 8) | modbusBuffer[5];
Modbus_HandleFunction03(startAddress, registerCount);
break;
case MODBUS_FUNCTION_CODE_06:
startAddress = (modbusBuffer[2] << 8) | modbusBuffer[3];
uint16_t value = (modbusBuffer[4] << 8) | modbusBuffer[5];
Modbus_HandleFunction06(startAddress, value);
break;
case MODBUS_FUNCTION_CODE_10:
startAddress = (modbusBuffer[2] << 8) | modbusBuffer[3];
registerCount = (modbusBuffer[4] << 8) | modbusBuffer[5];
uint8_t byteCount = modbusBuffer[6];
// 检查数据长度是否正确
if (byteCount == registerCount * 2
&& modbusBufferIndex - 2 >= 7 + byteCount) { // 7是功能码10的固定头部长度
Modbus_HandleFunction10(startAddress, registerCount,
&modbusBuffer[7]);
} else {
Modbus_SendExceptionResponse(0x03); // 数据长度错误
}
break;
default:
Modbus_SendExceptionResponse(0x01); // 不支持的功能码
break;
}
}
}
/* 重置缓冲区 */
modbusBufferIndex = 0;
messageComplete = false;
}
}
/* 处理功能码03 */
void Modbus_HandleFunction03(uint16_t startAddress, uint16_t registerCount) {
/* 检查地址和数量是否合法 */
if (startAddress < REGISTER_START_ADDRESS
|| startAddress + registerCount
> REGISTER_START_ADDRESS + REGISTER_COUNT
|| registerCount > 0x7D) {
Modbus_SendExceptionResponse(0x02); // 地址错误
return;
}
uint8_t byteCount = registerCount * 2;
uint8_t index = 0;
response[index++] = MODBUS_SLAVE_ADDRESS;
response[index++] = MODBUS_FUNCTION_CODE_03;
response[index++] = byteCount;
for (uint16_t i = 0; i < registerCount; i++) {
uint16_t regValue = holdingRegisters[(startAddress
- REGISTER_START_ADDRESS) + i];
response[index++] = (regValue >> 8) & 0xFF;
response[index++] = regValue & 0xFF;
}
uint16_t crc = CalculateCRC(response, index);
response[index++] = crc & 0xFF;
response[index++] = (crc >> 8) & 0xFF;
Modbus_SendResponse(response, index);
}
/* 处理功能码06 */
void Modbus_HandleFunction06(uint16_t registerAddress, uint16_t value) {
/* 检查地址是否合法 */
if (registerAddress < REGISTER_START_ADDRESS
|| registerAddress >= REGISTER_START_ADDRESS + REGISTER_COUNT) {
Modbus_SendExceptionResponse(0x02); // 地址错误
return;
}
/* 写入寄存器值 */
holdingRegisters[registerAddress - REGISTER_START_ADDRESS] = value;
/* 准备响应帧 - 功能码06的响应是原请求帧的原样返回 */
uint8_t index = 0;
response[index++] = MODBUS_SLAVE_ADDRESS;
response[index++] = MODBUS_FUNCTION_CODE_06;
response[index++] = (registerAddress >> 8) & 0xFF; // 寄存器地址高8位
response[index++] = registerAddress & 0xFF; // 寄存器地址低8位
response[index++] = (value >> 8) & 0xFF; // 写入值高8位
response[index++] = value & 0xFF; // 写入值低8位
/* 计算CRC并添加到响应帧 */
uint16_t crc = CalculateCRC(response, index);
response[index++] = crc & 0xFF;
response[index++] = (crc >> 8) & 0xFF;
/* 发送响应 */
Modbus_SendResponse(response, index);
}
// 添加功能码0x10处理函数
void Modbus_HandleFunction10(uint16_t startAddress, uint16_t registerCount,
uint8_t *data) {
// 检查地址和数量是否合法
if (startAddress < REGISTER_START_ADDRESS
|| startAddress + registerCount
> REGISTER_START_ADDRESS + REGISTER_COUNT
|| registerCount == 0 || registerCount > 0x7B) {
Modbus_SendExceptionResponse(0x02); // 地址错误
return;
}
// 处理每个寄存器
for (uint16_t i = 0; i < registerCount; i++) {
uint16_t regIndex = (startAddress - REGISTER_START_ADDRESS) + i;
uint16_t value = (data[i * 2] << 8) | data[i * 2 + 1];
// 只有可写寄存器才更新值
if (registerWritable[regIndex]) {
holdingRegisters[regIndex] = value;
}
// 只读寄存器保持原有值,不做处理
}
// 准备响应帧 - 功能码0x10的响应包含起始地址和写入数量
uint8_t index = 0;
response[index++] = MODBUS_SLAVE_ADDRESS;
response[index++] = MODBUS_FUNCTION_CODE_10;
response[index++] = (startAddress >> 8) & 0xFF; // 起始地址高8位
response[index++] = startAddress & 0xFF; // 起始地址低8位
response[index++] = (registerCount >> 8) & 0xFF; // 写入数量高8位
response[index++] = registerCount & 0xFF; // 写入数量低8位
// 计算CRC并添加到响应帧
uint16_t crc = CalculateCRC(response, index);
response[index++] = crc & 0xFF;
response[index++] = (crc >> 8) & 0xFF;
// 发送响应
Modbus_SendResponse(response, index);
}
/* 发送异常响应 */
void Modbus_SendExceptionResponse(uint8_t exceptionCode) {
response[0] = MODBUS_SLAVE_ADDRESS;
response[1] = modbusBuffer[1] | 0x80; // 异常功能码
response[2] = exceptionCode;
uint16_t crc = CalculateCRC(response, 3);
response[3] = crc & 0xFF;
response[4] = (crc >> 8) & 0xFF;
Modbus_SendResponse(response, 5);
}
/* 发送响应 */
void Modbus_SendResponse(uint8_t *data, uint8_t length) {
/* 使能RS485发送 */
/* 发送数据 */
HAL_UART_Transmit_DMA(&huart1, data, length);
/* 切换到接收模式 */
}
/* 发送响应 */
void Modbus_Master_Send(uint8_t *data, uint8_t length) {
/* 使能RS485发送 */
/* 发送数据 */
HAL_UART_Transmit_DMA(&huart2, data, length);
/* 切换到接收模式 */
}
/* CRC计算 */
uint16_t CalculateCRC(uint8_t *data, uint8_t length) {
uint16_t crc = 0xFFFF;
for (uint8_t i = 0; i < length; i++) {
crc ^= (uint16_t) data[i];
for (uint8_t j = 0; j < 8; j++) {
if ((crc & 0x0001) != 0) {
crc >>= 1;
crc ^= 0xA001;
} else {
crc >>= 1;
}
}
}
return crc;
}
/* UART接收中断回调函数 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart1) {
if (modbusBufferIndex < MODBUS_BUFFER_SIZE) {
modbusBuffer[modbusBufferIndex++] = huart->Instance->RDR;
} else {
modbusBufferIndex = 0;
}
lastByteTime = HAL_GetTick();
/* 重新启动接收中断 */
HAL_UART_Receive_IT(&huart1,
(uint8_t*) &modbusBuffer[modbusBufferIndex], 1);
} else if (huart == &huart2) {
if (modbus_master_BufferIndex < MODBUS_BUFFER_SIZE) {
modbus_master_Buffer[modbus_master_BufferIndex++] =
huart->Instance->RDR;
} else {
modbus_master_BufferIndex = 0;
}
last_master_ByteTime = HAL_GetTick();
/* 重新启动接收中断 */
HAL_UART_Receive_IT(&huart2,
(uint8_t*) &modbus_master_Buffer[modbus_master_BufferIndex], 1);
}
}
void MB_WriteHoldingReg(uint8_t _addr,
uint16_t _reg, uint16_t _data) {
uint16_t TxCount = 0;
uint16_t crc = 0;
master_tx_buf[TxCount++] = _addr; /* 从站地址 */
master_tx_buf[TxCount++] = 0x06; /* 功能码 */
master_tx_buf[TxCount++] = _reg >> 8; /* 寄存器地址 高字节 */
master_tx_buf[TxCount++] = _reg; /* 寄存器地址 低字节 */
master_tx_buf[TxCount++] = _data >> 8; /* 寄存器(16bits)个数 高字节 */
master_tx_buf[TxCount++] = _data; /* 低字节 */
crc = CalculateCRC(master_tx_buf, TxCount);
master_tx_buf[TxCount++] = crc & 0xFF;
master_tx_buf[TxCount++] = (crc >> 8) & 0xFF;
Modbus_Master_Send(master_tx_buf,TxCount);
dmk_read_state=0;
}
void calculate_dmk()
{
if (modbus_master_BufferIndex
> 0&& (HAL_GetTick() - last_master_ByteTime) > MODBUS_TIMEOUT_MS)
{
/* 接收标记消息完成 */
dmk_read_state=1;//返回成功
}
}
Loading…
Cancel
Save