This repository has been archived on 2025-01-02. You can view files and clone it, but cannot push or open issues or pull requests.
torsion/User/board/laser.c

325 lines
8.9 KiB
C

/*
* @Author: shenghao.xu
* @Date: 2023-04-13 22:39:28
* @LastEditors: shenghao.xu
* @LastEditTime: 2023-04-24 12:34:05
* @Description: HL-G103-S-J
* email:545403892@qq.com
* Copyright (c) 2023 by shenghao.xu, All Rights Reserved.
*/
#include <stdio.h>
#include "laser.h"
extern size_t strlen(const char *);
extern uart_t *uarts[UART_NUM_MAX];
const char FRAME_HEAD_RSP = '$';
const char FRAME_TAIL = '\r';
const char FRAME_HEAD[] = "%01#";
const char FRAME_TRUE[] = "+00001";
const char FRAME_FALSE[] = "+00000";
const char FRAME_BCC[] = "**";
const char REQ_DEVICE_ONLINE[] = "WCSR03001";
const char REQ_OPEN_STATUS[] = "RLR"; // 激光开启状态查询
const char REQ_OPEN_STATUS_WRITE[] = "WLR"; // 激光开启状态设置
const char REQ_DISTANCE_READ[] = "RMD"; // 测定值读出
const char REQ_ZERO_STATUS[] = "RZS"; // 调零状态查询
const char REQ_ZERO_STATUS_WRITE[] = "WZS"; // 调零状态设置
static uart_t *handle;
static char request_buf[RS485_REC_LEN];
static uint8_t uart_buf[RS485_REC_LEN];
static uint8_t *response_ptr;
static uint8_t response_ptr_offset = 0;
laser_t laser_handle;
static void laser_rx_cb(uint8_t uart_index, uint8_t *data, uint16_t len);
static void laser_send(uint8_t *data, uint8_t length)
{
laser_handle.send_data_cb(RS485_PORT, data, length);
}
// 是否在线
static void command_device_connect_req(void)
{
snprintf(request_buf, sizeof(request_buf), "%s%s%s%c", FRAME_HEAD, REQ_DEVICE_ONLINE, FRAME_BCC, FRAME_TAIL);
laser_send((uint8_t *)request_buf, strlen(request_buf));
}
// 激光开启状态查询
static void command_open_status_req(void)
{
snprintf(request_buf, sizeof(request_buf), "%s%s%s%c", FRAME_HEAD, REQ_OPEN_STATUS, FRAME_BCC, FRAME_TAIL);
laser_send((uint8_t *)request_buf, strlen(request_buf));
}
// 激光开启状态设置
static void command_open_status_write_req(BOOL open)
{
if (open)
{
snprintf(request_buf, sizeof(request_buf), "%s%s%s%s%c", FRAME_HEAD, REQ_OPEN_STATUS_WRITE, FRAME_TRUE, FRAME_BCC, FRAME_TAIL);
}
else
{
snprintf(request_buf, sizeof(request_buf), "%s%s%s%s%c", FRAME_HEAD, REQ_OPEN_STATUS_WRITE, FRAME_FALSE, FRAME_BCC, FRAME_TAIL);
}
laser_send((uint8_t *)request_buf, strlen(request_buf));
}
// 测定值读出
static void command_distance_read_req(void)
{
snprintf(request_buf, sizeof(request_buf), "%s%s%s%c", FRAME_HEAD, REQ_DISTANCE_READ, FRAME_BCC, FRAME_TAIL);
laser_send((uint8_t *)request_buf, strlen(request_buf));
}
// 调零状态查询
static void command_zero_status_req(void)
{
snprintf(request_buf, sizeof(request_buf), "%s%s%s%c", FRAME_HEAD, REQ_ZERO_STATUS, FRAME_BCC, FRAME_TAIL);
laser_send((uint8_t *)request_buf, strlen(request_buf));
}
// 调零状态开启
static void command_zero_status_write_req(BOOL open)
{
if (open)
{
snprintf(request_buf, sizeof(request_buf), "%s%s%s%s%c", FRAME_HEAD, REQ_ZERO_STATUS_WRITE, FRAME_TRUE, FRAME_BCC, FRAME_TAIL);
}
else
{
snprintf(request_buf, sizeof(request_buf), "%s%s%s%s%c", FRAME_HEAD, REQ_ZERO_STATUS_WRITE, FRAME_FALSE, FRAME_BCC, FRAME_TAIL);
}
laser_send((uint8_t *)request_buf, strlen(request_buf));
}
static void command_zero_status_close_req(void)
{
command_zero_status_write_req(FALSE);
}
static void command_zero_status_open_req(void)
{
command_zero_status_write_req(TRUE);
}
// 处理数据
static void laser_data_process(uint8_t *data, uint8_t length)
{
char cmd[3] = {0};
// 向右偏移4个位置获取指令部分
response_ptr_offset = 0;
response_ptr = data;
response_ptr_offset += 4;
if (!laser_handle.connect)
{
osel_memcpy((uint8_t *)cmd, response_ptr + response_ptr_offset, 2);
response_ptr_offset += 2;
}
else
{
osel_memcpy((uint8_t *)cmd, response_ptr + response_ptr_offset, 3);
response_ptr_offset += 3;
}
cmd_parsing(cmd);
}
static void command_device_connect_rsp(void)
{
laser_handle.connect = TRUE;
if (laser_handle.state != LASER_READY)
{
laser_handle.state = LASER_CONNECT;
}
}
static void command_open_status_rsp(void)
{
uint8_t status[5] = {0};
response_ptr_offset++; // 跳过符号
osel_memcpy(status, response_ptr + response_ptr_offset, 5);
const char *cs = FRAME_TRUE;
if (IsEqual(status, (cs + 1), 5))
{
laser_handle.open_status = TRUE;
if (laser_handle.state != LASER_READY)
{
laser_handle.state = LASER_OPEN_STATUS;
}
}
else
{
laser_handle.open_status = FALSE;
}
#if STATUS_DEFAULT == 1
if (laser_handle.state == LASER_CONNECT)
{
if (!laser_handle.open_status)
{
command_open_status_write_req(TRUE);
}
}
#endif
}
static void command_open_status_write_rsp(void)
{
}
#define PRECISION 10000 // 精度,即小数点后的位数
static float32 to_float(uint8_t *arr)
{
int num = arr[0] * 1000000 + arr[1] * 100000 + arr[2] * 10000 + arr[3] * 1000 + arr[4] * 100 + arr[5] * 10 + arr[6]; // 数字部分的值
float32 result = (float32)num / PRECISION; // 将数字部分和小数部分合并成浮点数
return result;
}
static void command_distance_read_rsp(void)
{
uint8_t distance[10] = {0};
float32 f = 0;
osel_memcpy(distance, response_ptr + response_ptr_offset, 10);
for (uint8_t i = 1; i <= 7; i++)
{
CHAR_TO_NUM(distance[i], distance[i]);
}
f = to_float(&distance[1]);
if (distance[0] == '-')
{
f = -f;
}
if (laser_handle.state != LASER_READY)
{
laser_handle.state = LASER_DISTANCE;
}
laser_handle.distance = f * 1000;
}
static void command_zero_status_rsp(void)
{
uint8_t status[5] = {0};
response_ptr_offset++; // 跳过符号
osel_memcpy(status, response_ptr + response_ptr_offset, 5);
const char *cs = FRAME_TRUE;
if (IsEqual(status, (cs + 1), 5))
{
laser_handle.zero_status = TRUE;
}
else
{
laser_handle.zero_status = FALSE;
}
}
static void command_zero_status_write_rsp(void)
{
#if STATUS_DEFAULT == 1
if (laser_handle.state == LASER_OPEN_STATUS)
{
laser_handle.zero_status = FALSE;
laser_handle.state = LASER_ZERO_STATUS_CLOSE;
}
else if (laser_handle.state == LASER_ZERO_STATUS_CLOSE)
{
laser_handle.zero_status = TRUE;
laser_handle.state = LASER_ZERO_STATUS_OPEN;
}
else
{
laser_handle.zero_status = FALSE;
laser_handle.state = LASER_CONNECT;
}
#endif
}
static void _laser_ready(void)
{
laser_handle.state = LASER_READY;
}
REGISTER_CMD(WC, command_device_connect_rsp, "");
REGISTER_CMD(RLR, command_open_status_rsp, "");
REGISTER_CMD(WLR, command_open_status_write_rsp, "");
REGISTER_CMD(RMD, command_distance_read_rsp, "");
REGISTER_CMD(RZS, command_zero_status_rsp, "");
REGISTER_CMD(WZS, command_zero_status_write_rsp, "");
laser_event_t laser_event[] = {
{LASER_IDEL, command_device_connect_req},
{LASER_CONNECT, command_open_status_req},
{LASER_OPEN_STATUS, command_zero_status_close_req},
{LASER_ZERO_STATUS_CLOSE, command_zero_status_open_req},
{LASER_ZERO_STATUS_OPEN, command_distance_read_req},
{LASER_DISTANCE, _laser_ready},
};
static void uart5_init(void)
{
if (uarts[RS485_PORT] == NULL)
{
uarts[RS485_PORT] = uart_create(USART5, FALSE, 1, laser_rx_cb, FALSE, 0, NULL);
uarts[RS485_PORT]->uart_index = RS485_PORT;
uart_recv_en(uarts[RS485_PORT]);
}
}
void laser_init(send_data_cb_t cb)
{
cmd_init(); /* 命令初始化 */
uart5_init();
handle = uarts[RS485_PORT];
DBG_ASSERT(handle != NULL __DBG_LINE);
GPIO_SET(RS485_EN3_GPIO_Port, RS485_EN3_Pin); // 485使能
osel_memset((uint8_t *)&laser_handle, 0, sizeof(laser_t));
laser_handle.state = LASER_IDEL;
laser_handle.send_data_cb = cb;
laser_handle.command_device_connect_req = command_device_connect_req;
laser_handle.command_open_status_req = command_open_status_req;
laser_handle.command_open_status_write_req = command_open_status_write_req;
laser_handle.command_distance_read_req = command_distance_read_req;
laser_handle.command_zero_status_req = command_zero_status_req;
laser_handle.command_zero_status_write_req = command_zero_status_write_req;
}
// 串口接收中断回调函数,激光
static void laser_rx_cb(uint8_t uart_index, uint8_t *data, uint16_t len)
{
if (data[0] == '\r')
{
if (uart_buf[0] == 0x25 && uart_buf[3] == FRAME_HEAD_RSP) // '%' is the start of the data
{
laser_data_process(uart_buf, handle->rx_sta & 0X3FFF);
handle->rx_sta = 0;
}
else
{
handle->rx_sta = 0;
}
}
else
{
uart_buf[handle->rx_sta & 0X3FFF] = data[0];
handle->rx_sta++;
if (handle->rx_sta > (RS485_REC_LEN - 1))
{
handle->rx_sta = 0;
}
}
}