#pragma once
#include <zephyr/kernel.h>
// 批量发送配置
#define UART_BUF_SIZE 255
extern uint8_t rs485_rx_buf[UART_BUF_SIZE][8];
#define BATCH_SIZE 32
#define MAX_BATCH_TIMEOUT 10 // 秒
typedef struct {
int32_t timestamp; // 时间戳 (ms)
int32_t pressure; // 压力 (milli-kPa)
int32_t temp; // 温度 (centi-°C)
int32_t acc_x; // X加速度 (milli-g)
int32_t acc_y; // Y加速度 (milli-g)
int32_t acc_z; // Z加速度 (milli-g)
int32_t gyro_x; // X陀螺仪 (milli-dps)
int32_t gyro_y; // Y陀螺仪 (milli-dps)
int32_t gyro_z; // Z陀螺仪 (milli-dps)
} sensor_data_point_t;
typedef struct {
sensor_data_point_t data[BATCH_SIZE];
uint16_t count;
int64_t start_timestamp; // 批次起始时间 (ms)
bool ready; // 批次就绪标志
} sensor_batch_t;
typedef struct {
float a0; // 常数项系数
float a1; // 一次项系数
float a2; // 二次项系数
float b; // 压力项系数
int32_t ref_temp; // 参考温度 (centi-°C)
} temp_comp_coeff_t;
extern sensor_batch_t sensor_batch;
extern struct k_mutex data_mutex;
extern struct k_sem batch_ready_sem;
extern sensor_data_point_t sensor_data_rs485;#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/uart.h>
#include <string.h>
#include "GVL.h"
#define LOG_MODULE_NAME rs485_thread
LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_DBG);
#define RS485_DIR_PIN_DELAY_US 100
#define UART_RX_TIMEOUT_MS 100
#define MAX_RETRIES 3
#define COMMAND_TIMEOUT_MS 500
// 获取设备树节点
#define ZEPHYR_USER_NODE DT_PATH(zephyr_user)
// 声明设备
static const struct device *const rs485_uart = DEVICE_DT_GET(DT_ALIAS(myuart));
static const struct gpio_dt_spec direct_pin = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, rs485_gpios);
// 双缓冲结构
static sensor_batch_t tx_buffers[2];
static sensor_batch_t *current_tx_buffer = &tx_buffers[0];
static sensor_batch_t *pending_tx_buffer = &tx_buffers[1];
static bool buffer_ready = false;
// RS485发送函数
// static int rs485_send_batch(const sensor_batch_t *batch)
// {
// if (batch->count == 0) {
// return 0;
// }
// // 切换到发送模式
// gpio_pin_set_dt(&direct_pin, 1);
// k_busy_wait(RS485_DIR_PIN_DELAY_US);
// // 计算实际数据长度
// size_t data_size = sizeof(sensor_data_point_t) * batch->count;
// LOG_INF("Sending batch of %d points (%u bytes)", batch->count, data_size);
// // 发送数据
// int retry_count = 0;
// int err = -EAGAIN;
// while (retry_count < MAX_RETRIES && err != 0) {
// err = uart_tx(rs485_uart, (const uint8_t *)batch->data, data_size, SYS_FOREVER_MS);
// if (err) {
// LOG_ERR("UART TX error (attempt %d): %d", retry_count + 1, err);
// retry_count++;
// k_msleep(10);
// }
// }
// if (err) {
// LOG_ERR("Failed to send after %d attempts", MAX_RETRIES);
// }
// return err;
// }
static int rs485_send_batch(const sensor_data_point_t *sensor_data)
{
// if (batch->count == 0) {
// return 0;
// }
// 切换到发送模式
gpio_pin_set_dt(&direct_pin, 1);
k_busy_wait(RS485_DIR_PIN_DELAY_US);
// 计算实际数据长度
size_t data_size = sizeof(sensor_data_point_t);
LOG_INF("rs485 Sending (%u bytes)", data_size);
// 发送数据
int retry_count = 0;
int err = -EAGAIN;
while (retry_count < MAX_RETRIES && err != 0) {
err = uart_tx(rs485_uart, sensor_data, data_size, SYS_FOREVER_MS);
if (err) {
LOG_ERR("UART TX error (attempt %d): %d", retry_count + 1, err);
retry_count++;
k_msleep(10);
}
}
if (err) {
LOG_ERR("Failed to send after %d attempts", MAX_RETRIES);
}
return err;
}
// 处理接收到的命令
static void process_command(const uint8_t *data, size_t len)
{
if (len < 1) return; // 空命令
switch (data[0]) {
case 0x01: // 请求传感器数据
LOG_DBG("Received data request command");
k_sem_give(&batch_ready_sem);
break;
case 0x02: // 设置采样率
if (len >= 2) {
uint16_t new_rate = data[1] << 8 | data[2];
LOG_INF("Setting new sample rate: %d ms", new_rate);
// 这里可以添加设置采样率的逻辑
}
break;
case 0x03: // 设备状态查询
LOG_DBG("Received status query");
// 这里可以添加状态响应逻辑
break;
default:
LOG_WRN("Unknown command: 0x%02X", data[0]);
break;
}
}
// UART接收回调
static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
static uint8_t rx_buffer[128];
static size_t rx_index = 0;
static int64_t last_rx_time = 0;
switch (evt->type) {
case UART_RX_RDY:
// 检查是否新数据包
int64_t now = k_uptime_get();
if ((now - last_rx_time) > COMMAND_TIMEOUT_MS ||
(rx_index + evt->data.rx.len) > sizeof(rx_buffer)) {
rx_index = 0; // 重置缓冲区
}
// 复制数据到缓冲区
size_t to_copy = MIN(evt->data.rx.len, sizeof(rx_buffer) - rx_index);
memcpy(&rx_buffer[rx_index], evt->data.rx.buf, to_copy);
rx_index += to_copy;
last_rx_time = now;
break;
case UART_RX_DISABLED:
// 处理缓冲区中的数据
if (rx_index > 0) {
process_command(rx_buffer, rx_index);
rx_index = 0;
}
// 重新启用接收
uart_rx_enable(rs485_uart, rs485_rx_buf, sizeof(rs485_rx_buf), UART_RX_TIMEOUT_MS);
break;
case UART_RX_BUF_RELEASED:
// 可以在这里释放缓冲区
break;
case UART_TX_DONE:
LOG_DBG("TX complete");
//发送完成后切换回接收模式
gpio_pin_set_dt(&direct_pin, 0);
break;
case UART_TX_ABORTED:
LOG_WRN("TX aborted");
break;
default:
break;
}
}
// 初始化RS485模块
static int rs485_init(void)
{
int ret;
// 检查设备是否就绪
if (!device_is_ready(rs485_uart)) {
LOG_ERR("UART device not ready");
return -ENODEV;
}
if (!device_is_ready(direct_pin.port)) {
LOG_ERR("GPIO device not ready");
return -ENODEV;
}
// 配置方向控制引脚
ret = gpio_pin_configure_dt(&direct_pin, GPIO_OUTPUT_INACTIVE);
if (ret) {
LOG_ERR("GPIO config error: %d", ret);
return ret;
}
// 配置UART回调
ret = uart_callback_set(rs485_uart, uart_cb, NULL);
if (ret) {
LOG_ERR("UART callback set error: %d", ret);
return ret;
}
// 初始化双缓冲
memset(tx_buffers, 0, sizeof(tx_buffers));
// 启用接收
ret = uart_rx_enable(rs485_uart, rs485_rx_buf, sizeof(rs485_rx_buf), UART_RX_TIMEOUT_MS);
if (ret) {
LOG_ERR("UART RX enable error: %d", ret);
return ret;
}
LOG_INF("RS485 initialized");
return 0;
}
void rs485_thread(void)
{
if (rs485_init() != 0) {
LOG_ERR("RS485 initialization failed");
return;
}
LOG_INF("RS485 thread started");
while (1) {
// // 等待批次数据就绪信号
// if (k_sem_take(&batch_ready_sem, K_FOREVER) == 0) {
// // 安全地获取批次数据
// k_mutex_lock(&data_mutex, K_FOREVER);
// // 检查是否有待处理数据
// if (buffer_ready) {
// LOG_WRN("Previous buffer not sent, overwriting");
// }
// // 复制数据到待发送缓冲区
// *pending_tx_buffer = sensor_batch;
// // 重置主批次
// sensor_batch.count = 0;
// sensor_batch.start_timestamp = 0;
// sensor_batch.ready = false;
// // 标记缓冲区就绪
// buffer_ready = true;
// k_mutex_unlock(&data_mutex);
// }
// // 检查是否有数据需要发送
// if (buffer_ready) {
// // 交换缓冲区指针
// sensor_batch_t *send_buffer = pending_tx_buffer;
// pending_tx_buffer = current_tx_buffer;
// current_tx_buffer = send_buffer;
// // 发送数据
// rs485_send_batch(send_buffer);
// // 重置缓冲区
// send_buffer->count = 0;
// buffer_ready = false;
// }
sensor_data_point_t *send_buffer = &sensor_data_rs485;
rs485_send_batch(send_buffer);
// 处理超时命令
k_sleep(K_MSEC(1000));
}
}
K_THREAD_DEFINE(rs485_thread_id, 4096, rs485_thread, NULL, NULL, NULL, 5, 0, 0);
rs485发送数据// GVL.h
#pragma once
#include <zephyr/kernel.h>
// 批量发送配置
#define BATCH_SIZE 32
#define MAX_BATCH_TIMEOUT_MS 10000
#define UART_BUF_SIZE 256
#define MEM_POOL_SIZE 8
#define RS485_DIR_PIN_DELAY_US 100
#define UART_RX_TIMEOUT_MS 100
#define MAX_RETRIES 3
#define COMMAND_TIMEOUT_MS 500
#define UART_WAIT_FOR_RX 50000
#define DATA_POINT_SIZE 37 // unified_data_point_t大小(字节)
#define MAX_POINTS_PER_PACKET 6 // 每个包最大数据点数(根据MTU计算)
typedef struct {
int32_t timestamp; // 时间戳 (ms)
int32_t pressure; // 压力 (milli-kPa)
int32_t temp; // 温度 (centi-°C)
int32_t acc_x; // X加速度 (milli-g)
int32_t acc_y; // Y加速度 (milli-g)
int32_t acc_z; // Z加速度 (milli-g)
int32_t gyro_x; // X陀螺仪 (milli-dps)
int32_t gyro_y; // Y陀螺仪 (milli-dps)
int32_t gyro_z; // Z陀螺仪 (milli-dps)
} sensor_data_point_t;
// 批处理包头(用于蓝牙传输)
typedef struct __attribute__((packed)) {
uint16_t item_count; // 批处理中数据点数量
int64_t batch_timestamp; // 批处理开始时间戳
uint32_t data_size; // 数据部分总大小(字节)
} batch_header_t;
// 统一的数据点结构
typedef struct {
int32_t timestamp; // 时间戳 (ms)
// 传感器数据
int32_t pressure; // 压力 (milli-kPa)
int32_t temp; // 温度 (centi-°C)
// IMU数据 (来自RS485)
int32_t acc_x; // X加速度 (milli-g)
int32_t acc_y; // Y加速度 (milli-g)
int32_t acc_z; // Z加速度 (milli-g)
int32_t gyro_x; // X陀螺仪 (milli-dps)
int32_t gyro_y; // Y陀螺仪 (milli-dps)
int32_t gyro_z; // Z陀螺仪 (milli-dps)
// 数据来源标识
uint8_t data_source; // 1:本地传感器, 2:RS485设备
} unified_data_point_t;
// 蓝牙数据包结构 - 确保每个包包含完整数据点
typedef struct __attribute__((packed)) {
uint16_t packet_index; // 包序号
uint16_t total_packets; // 总包数
uint16_t points_in_packet; // 本包数据点数
unified_data_point_t data_points[MAX_POINTS_PER_PACKET]; // 数据点数组
} ble_packet_t;
extern struct k_mem_slab uart_tx_pool;
extern struct k_mem_slab batch_pool;
// 批处理容器
typedef struct {
unified_data_point_t data[BATCH_SIZE];
uint16_t count;
int64_t start_timestamp;
bool ready;
} batch_container_t;
typedef struct __attribute__((packed)) {
int32_t pressure; // 压力 (milli-kPa)
int32_t temp; // 温度 (centi-°C)
int32_t acc_x; // X加速度 (milli-g)
int32_t acc_y; // Y加速度 (milli-g)
int32_t acc_z; // Z加速度 (milli-g)
int32_t gyro_x; // X陀螺仪 (milli-dps)
int32_t gyro_y; // Y陀螺仪 (milli-dps)
int32_t gyro_z; // Z陀螺仪 (milli-dps)
} rs485_raw_data_t;
// 双缓冲批处理
extern batch_container_t data_batches[2];
extern uint8_t active_batch_index;
// 同步信号量
extern struct k_sem ble_data_ready_sem;
// 自旋锁保护批处理缓冲区
extern struct k_spinlock batch_lock;
static double atmospheric_pressure;
// #include <zephyr/kernel.h>
// #include <zephyr/device.h>
// #include <zephyr/devicetree.h>
// #include <zephyr/drivers/gpio.h>
// #include <zephyr/logging/log.h>
// #include <zephyr/drivers/uart.h>
// #include "GVL.h"
// #define LOG_MODULE_NAME rs485_thread
// LOG_MODULE_REGISTER(LOG_MODULE_NAME);
// // 获取设备树节点
// #define ZEPHYR_USER_NODE DT_PATH(zephyr_user)
// // 声明设备
// static const struct device *const rs485_uart = DEVICE_DT_GET(DT_ALIAS(myuart));
// static const struct gpio_dt_spec direct_pin = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, rs485_gpios);
// // 延时工作
// static struct k_work_delayable uart_work;
// struct uart_data_t {
// void *fifo_reserved;
// uint8_t data[UART_BUF_SIZE];
// uint16_t len;
// };
// static K_FIFO_DEFINE(fifo_uart_tx_data);
// // RS485接收状态机
// enum rx_state {
// STATE_IDLE,
// STATE_GOT_AA,
// STATE_RECEIVING
// };
// static struct {
// enum rx_state state;
// uint8_t buffer[sizeof(rs485_raw_data_t) + 3]; // AA + BB + payload + CRC
// size_t index;
// } rx_state_machine;
// // CRC校验函数
// static uint8_t calculate_crc(const uint8_t *data, size_t len)
// {
// uint8_t crc = 0;
// for (size_t i = 0; i < len; i++) {
// crc ^= data[i];
// }
// return crc;
// }
// static void process_rs485_packet(uint8_t *packet, size_t len)
// {
// // CRC校验 (最后1字节是CRC)
// if (calculate_crc(packet, len - 1) != packet[len - 1]) {
// LOG_WRN("Invalid RS485 packet CRC");
// return;
// }
// // 解析RS485原始数据(跳过包头AA BB)
// rs485_raw_data_t raw_data;
// memcpy(&raw_data, packet + 2, sizeof(raw_data));
// // 转换为统一数据结构
// unified_data_point_t data_point = {
// .timestamp = k_uptime_get_32(),
// .pressure = raw_data.pressure,
// .temp = raw_data.temp,
// .acc_x = raw_data.acc_x,
// .acc_y = raw_data.acc_y,
// .acc_z = raw_data.acc_z,
// .gyro_x = raw_data.gyro_x,
// .gyro_y = raw_data.gyro_y,
// .gyro_z = raw_data.gyro_z,
// .data_source = 2 // 标记为RS485设备数据
// };
// LOG_INF("sensor module : pressure %.4f,temp %.2f",data_point.pressure,data_point.temp);
// // k_spinlock_key_t key = k_spin_lock(&batch_lock);
// // batch_container_t *batch = &data_batches[active_batch_index];
// // if (batch->count == 0) {
// // batch->start_timestamp = k_uptime_get();
// // }
// // if (batch->count < BATCH_SIZE) {
// // batch->data[batch->count++] = data_point;
// // bool batch_ready = false;
// // if (batch->count >= BATCH_SIZE) {
// // batch_ready = true;
// // } else if (batch->count > 0 &&
// // (k_uptime_get() - batch->start_timestamp) >= MAX_BATCH_TIMEOUT_MS) {
// // batch_ready = true;
// // }
// // if (batch_ready) {
// // batch->ready = true; // 只设置就绪标志
// // active_batch_index = (active_batch_index + 1) % 2; // 切换到另一个缓冲区
// // k_sem_give(&ble_data_ready_sem); // 通知BLE线程
// // }
// // } else {
// // LOG_WRN("Batch buffer overflow");
// // }
// // k_spin_unlock(&batch_lock, key);
// }
// static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
// {
// static size_t aborted_len;
// struct uart_data_t *buf;
// static uint8_t *aborted_buf;
// static bool disable_req;
// switch (evt->type) {
// case UART_TX_DONE:
// LOG_DBG("UART_TX_DONE");
// // 设置方向为接收模式
// gpio_pin_set_dt(&direct_pin, 0);
// if ((evt->data.tx.len == 0) || (!evt->data.tx.buf)) {
// return;
// }
// if (aborted_buf) {
// buf = CONTAINER_OF(aborted_buf, struct uart_data_t, data[0]);
// aborted_buf = NULL;
// aborted_len = 0;
// k_free(buf);
// } else {
// buf = CONTAINER_OF(evt->data.tx.buf, struct uart_data_t, data[0]);
// k_free(buf);
// }
// // 发送下一个数据包
// buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
// if (buf) {
// // 设置方向为发送模式
// gpio_pin_set_dt(&direct_pin, 1);
// k_busy_wait(RS485_DIR_PIN_DELAY_US);
// if (uart_tx(rs485_uart, buf->data, buf->len, SYS_FOREVER_MS)) {
// LOG_WRN("Failed to send data over UART");
// gpio_pin_set_dt(&direct_pin, 0); // 确保切换回接收模式
// k_free(buf);
// }
// }
// break;
// case UART_RX_RDY:
// const uint8_t *data = evt->data.rx.buf;
// size_t len = evt->data.rx.len;
// for (size_t i = 0; i < len; i++) {
// uint8_t byte = data[i];
// switch (rx_state_machine.state) {
// case STATE_IDLE:
// if (byte == 0xAA) {
// rx_state_machine.state = STATE_GOT_AA;
// }
// break;
// case STATE_GOT_AA:
// if (byte == 0xBB) {
// rx_state_machine.state = STATE_RECEIVING;
// rx_state_machine.index = 0;
// rx_state_machine.buffer[rx_state_machine.index++] = 0xAA;
// rx_state_machine.buffer[rx_state_machine.index++] = 0xBB;
// } else {
// rx_state_machine.state = (byte == 0xAA) ? STATE_GOT_AA : STATE_IDLE;
// }
// break;
// case STATE_RECEIVING:
// rx_state_machine.buffer[rx_state_machine.index++] = byte;
// // 检查完整数据包 (AA + BB + payload + CRC)
// if (rx_state_machine.index >= sizeof(rx_state_machine.buffer)) {
// process_rs485_packet(rx_state_machine.buffer, rx_state_machine.index);
// rx_state_machine.state = STATE_IDLE;
// }
// break;
// }
// }
// break;
// case UART_RX_DISABLED:
// LOG_DBG("UART_RX_DISABLED");
// disable_req = false;
// buf = k_malloc(sizeof(*buf));
// if (buf) {
// buf->len = 0;
// uart_rx_enable(rs485_uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT_MS);
// } else {
// LOG_WRN("Not able to allocate UART receive buffer");
// k_work_reschedule(&uart_work, K_MSEC(UART_WAIT_FOR_RX));
// }
// break;
// case UART_RX_BUF_REQUEST:
// LOG_DBG("UART_RX_BUF_REQUEST");
// buf = k_malloc(sizeof(*buf));
// if (buf) {
// buf->len = 0;
// uart_rx_buf_rsp(rs485_uart, buf->data, sizeof(buf->data));
// } else {
// LOG_WRN("Not able to allocate UART receive buffer");
// }
// break;
// case UART_RX_BUF_RELEASED:
// LOG_DBG("UART_RX_BUF_RELEASED");
// buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t, data[0]);
// k_free(buf);
// break;
// case UART_TX_ABORTED:
// LOG_DBG("UART_TX_ABORTED");
// gpio_pin_set_dt(&direct_pin, 0); // 确保切换回接收模式
// if (!aborted_buf) {
// aborted_buf = (uint8_t *)evt->data.tx.buf;
// aborted_len = evt->data.tx.len;
// }
// struct uart_data_t *tx_buf = (struct uart_data_t *)aborted_buf;
// size_t remaining = tx_buf->len - aborted_len;
// if (remaining > 0) {
// gpio_pin_set_dt(&direct_pin, 1);
// k_busy_wait(RS485_DIR_PIN_DELAY_US);
// uart_tx(rs485_uart, &tx_buf->data[aborted_len], remaining, SYS_FOREVER_MS);
// }
// break;
// default:
// break;
// }
// }
// static void uart_work_handler(struct k_work *item)
// {
// struct uart_data_t *buf = k_malloc(sizeof(*buf));
// if (buf) {
// buf->len = 0;
// uart_rx_enable(rs485_uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT_MS);
// } else {
// LOG_WRN("Not able to allocate UART receive buffer");
// k_work_reschedule(&uart_work, K_MSEC(UART_WAIT_FOR_RX));
// }
// }
// static int rs485_init(void)
// {
// int err;
// if (!device_is_ready(rs485_uart)) {
// LOG_ERR("UART device not ready");
// return -ENODEV;
// }
// // 初始化方向控制引脚
// if (!device_is_ready(direct_pin.port)) {
// LOG_ERR("GPIO device not ready");
// return -ENODEV;
// }
// err = gpio_pin_configure_dt(&direct_pin, GPIO_OUTPUT_INACTIVE);
// if (err) {
// LOG_ERR("GPIO config error: %d", err);
// return err;
// }
// // 初始化引脚为接收
// gpio_pin_set_dt(&direct_pin, 0);
// // 初始化接收状态机
// rx_state_machine.state = STATE_IDLE;
// rx_state_machine.index = 0;
// // 初始化UART
// k_work_init_delayable(&uart_work, uart_work_handler);
// err = uart_callback_set(rs485_uart, uart_cb, NULL);
// if (err) {
// LOG_ERR("Cannot set UART callback: %d", err);
// return err;
// }
// // 启动接收
// k_work_schedule(&uart_work, K_NO_WAIT);
// return 0;
// }
// void rs485_send(const uint8_t *data, size_t len)
// {
// struct uart_data_t *tx = k_malloc(sizeof(*tx) + len);
// if (!tx) {
// LOG_ERR("Not enough memory for UART send");
// return;
// }
// memcpy(tx->data, data, len);
// tx->len = len;
// // 如果发送队列为空,直接发送,否则加入队列
// if (k_fifo_is_empty(&fifo_uart_tx_data)) {
// // 设置方向为发送模式
// gpio_pin_set_dt(&direct_pin, 1);
// k_busy_wait(RS485_DIR_PIN_DELAY_US);
// if (uart_tx(rs485_uart, tx->data, tx->len, SYS_FOREVER_MS)) {
// LOG_WRN("Failed to start UART send");
// gpio_pin_set_dt(&direct_pin, 0); // 切换回接收模式
// k_free(tx);
// }
// } else {
// k_fifo_put(&fifo_uart_tx_data, tx);
// }
// }
// void rs485_thread(void)
// {
// if (rs485_init() != 0) {
// LOG_ERR("RS485 initialization failed");
// return;
// }
// LOG_INF("RS485 thread started");
// // 线程主循环
// while (1) {
// LOG_INF("rs485 thread");
// k_sleep(K_FOREVER);
// }
// }
// K_THREAD_DEFINE(rs485_thread_id, 2048, rs485_thread, NULL, NULL, NULL, 5, 0, 0);
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/logging/log.h>
#include <zephyr/drivers/uart.h>
#include "GVL.h"
#define LOG_MODULE_NAME rs485_thread
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
// 获取设备树节点
#define ZEPHYR_USER_NODE DT_PATH(zephyr_user)
// 声明设备
static const struct device *const rs485_uart = DEVICE_DT_GET(DT_ALIAS(myuart));
static const struct gpio_dt_spec direct_pin = GPIO_DT_SPEC_GET(ZEPHYR_USER_NODE, rs485_gpios);
// 延时工作
static struct k_work_delayable uart_work;
struct uart_data_t {
void *fifo_reserved;
uint8_t data[UART_BUF_SIZE];
uint16_t len;
};
static K_FIFO_DEFINE(fifo_uart_tx_data);
// 定义RS485数据包结构
typedef struct {
uint8_t header[2]; // 0xAA, 0xBB
rs485_raw_data_t payload;
uint8_t crc;
} rs485_packet_t;
#define RS485_PACKET_SIZE sizeof(rs485_packet_t)
// CRC校验函数
static uint8_t calculate_crc(const uint8_t *data, size_t len)
{
uint8_t crc = 0;
for (size_t i = 0; i < len; i++) {
crc ^= data[i];
}
return crc;
}
static void process_rs485_packet(const uint8_t *packet)
{
const rs485_packet_t *pkt = (const rs485_packet_t *)packet;
// 检查包头
if (pkt->header[0] != 0xAA || pkt->header[1] != 0xBB) {
LOG_WRN("Invalid packet header: 0x%02X%02X", pkt->header[0], pkt->header[1]);
return;
}
// 计算并验证CRC (不包括CRC自身)
uint8_t crc = calculate_crc(packet, RS485_PACKET_SIZE - 1);
if (crc != pkt->crc) {
LOG_WRN("Invalid CRC: expected 0x%02X, got 0x%02X", crc, pkt->crc);
return;
}
// 转换为统一数据结构
unified_data_point_t data_point = {
.timestamp = k_uptime_get_32(),
.pressure = pkt->payload.pressure,
.temp = pkt->payload.temp,
.acc_x = pkt->payload.acc_x,
.acc_y = pkt->payload.acc_y,
.acc_z = pkt->payload.acc_z,
.gyro_x = pkt->payload.gyro_x,
.gyro_y = pkt->payload.gyro_y,
.gyro_z = pkt->payload.gyro_z,
.data_source = 2 // 标记为RS485设备数据
};
LOG_INF("RS485 sensor: pressure %.4f, temp %.2f",
data_point.pressure, data_point.temp);
// // 添加数据到批处理
// k_spinlock_key_t key = k_spin_lock(&batch_lock);
// batch_container_t *batch = &data_batches[active_batch_index];
// if (batch->count == 0) {
// batch->start_timestamp = k_uptime_get();
// }
// if (batch->count < BATCH_SIZE) {
// batch->data[batch->count++] = data_point;
// bool batch_ready = false;
// if (batch->count >= BATCH_SIZE) {
// batch_ready = true;
// } else if (batch->count > 0 &&
// (k_uptime_get() - batch->start_timestamp) >= MAX_BATCH_TIMEOUT_MS) {
// batch_ready = true;
// }
// if (batch_ready) {
// batch->ready = true;
// active_batch_index = (active_batch_index + 1) % 2;
// k_sem_give(&ble_data_ready_sem);
// }
// } else {
// LOG_WRN("Batch buffer overflow");
// }
// k_spin_unlock(&batch_lock, key);
}
static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
static size_t aborted_len;
struct uart_data_t *buf;
static uint8_t *aborted_buf;
static bool disable_req;
switch (evt->type) {
case UART_TX_DONE:
LOG_DBG("UART_TX_DONE");
gpio_pin_set_dt(&direct_pin, 0); // 切换回接收模式
if ((evt->data.tx.len == 0) || (!evt->data.tx.buf)) {
return;
}
if (aborted_buf) {
buf = CONTAINER_OF(aborted_buf, struct uart_data_t, data[0]);
aborted_buf = NULL;
aborted_len = 0;
k_free(buf);
} else {
buf = CONTAINER_OF(evt->data.tx.buf, struct uart_data_t, data[0]);
k_free(buf);
}
// 发送下一个数据包
buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
if (buf) {
gpio_pin_set_dt(&direct_pin, 1); // 切换到发送模式
k_busy_wait(RS485_DIR_PIN_DELAY_US);
if (uart_tx(rs485_uart, buf->data, buf->len, SYS_FOREVER_MS)) {
LOG_WRN("Failed to send data over UART");
gpio_pin_set_dt(&direct_pin, 0);
k_free(buf);
}
}
break;
case UART_RX_RDY:
// 直接处理接收到的数据
if (evt->data.rx.len == RS485_PACKET_SIZE) {
// 检查包头
if (evt->data.rx.buf[0] == 0xAA && evt->data.rx.buf[1] == 0xBB) {
process_rs485_packet(evt->data.rx.buf);
} else {
LOG_WRN("Invalid packet header");
}
} else if (evt->data.rx.len > 0) {
LOG_WRN("Received unexpected length: %d (expected %d)",
evt->data.rx.len, RS485_PACKET_SIZE);
}
break;
case UART_RX_DISABLED:
LOG_DBG("UART_RX_DISABLED");
disable_req = false;
buf = k_malloc(sizeof(*buf));
if (buf) {
buf->len = 0;
uart_rx_enable(rs485_uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT_MS);
} else {
LOG_WRN("Not able to allocate UART receive buffer");
k_work_reschedule(&uart_work, K_MSEC(UART_WAIT_FOR_RX));
}
break;
case UART_RX_BUF_REQUEST:
LOG_DBG("UART_RX_BUF_REQUEST");
buf = k_malloc(sizeof(*buf));
if (buf) {
buf->len = 0;
uart_rx_buf_rsp(rs485_uart, buf->data, sizeof(buf->data));
} else {
LOG_WRN("Not able to allocate UART receive buffer");
}
break;
case UART_RX_BUF_RELEASED:
LOG_DBG("UART_RX_BUF_RELEASED");
buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t, data[0]);
k_free(buf);
break;
case UART_TX_ABORTED:
LOG_DBG("UART_TX_ABORTED");
gpio_pin_set_dt(&direct_pin, 0);
if (!aborted_buf) {
aborted_buf = (uint8_t *)evt->data.tx.buf;
aborted_len = evt->data.tx.len;
}
struct uart_data_t *tx_buf = (struct uart_data_t *)aborted_buf;
size_t remaining = tx_buf->len - aborted_len;
if (remaining > 0) {
gpio_pin_set_dt(&direct_pin, 1);
k_busy_wait(RS485_DIR_PIN_DELAY_US);
uart_tx(rs485_uart, &tx_buf->data[aborted_len], remaining, SYS_FOREVER_MS);
}
break;
default:
break;
}
}
static void uart_work_handler(struct k_work *item)
{
struct uart_data_t *buf = k_malloc(sizeof(*buf));
if (buf) {
buf->len = 0;
uart_rx_enable(rs485_uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT_MS);
} else {
LOG_WRN("Not able to allocate UART receive buffer");
k_work_reschedule(&uart_work, K_MSEC(UART_WAIT_FOR_RX));
}
}
static int rs485_init(void)
{
int err;
if (!device_is_ready(rs485_uart)) {
LOG_ERR("UART device not ready");
return -ENODEV;
}
// 初始化方向控制引脚
if (!device_is_ready(direct_pin.port)) {
LOG_ERR("GPIO device not ready");
return -ENODEV;
}
err = gpio_pin_configure_dt(&direct_pin, GPIO_OUTPUT_INACTIVE);
if (err) {
LOG_ERR("GPIO config error: %d", err);
return err;
}
// 初始化引脚为接收模式
gpio_pin_set_dt(&direct_pin, 0);
// 初始化UART
k_work_init_delayable(&uart_work, uart_work_handler);
err = uart_callback_set(rs485_uart, uart_cb, NULL);
if (err) {
LOG_ERR("Cannot set UART callback: %d", err);
return err;
}
// 启动接收
k_work_schedule(&uart_work, K_NO_WAIT);
return 0;
}
void rs485_send(const uint8_t *data, size_t len)
{
struct uart_data_t *tx = k_malloc(sizeof(*tx) + len);
if (!tx) {
LOG_ERR("Not enough memory for UART send");
return;
}
memcpy(tx->data, data, len);
tx->len = len;
if (k_fifo_is_empty(&fifo_uart_tx_data)) {
gpio_pin_set_dt(&direct_pin, 1); // 切换到发送模式
k_busy_wait(RS485_DIR_PIN_DELAY_US);
if (uart_tx(rs485_uart, tx->data, tx->len, SYS_FOREVER_MS)) {
LOG_WRN("Failed to start UART send");
gpio_pin_set_dt(&direct_pin, 0);
k_free(tx);
}
} else {
k_fifo_put(&fifo_uart_tx_data, tx);
}
}
void rs485_thread(void)
{
if (rs485_init() != 0) {
LOG_ERR("RS485 initialization failed");
return;
}
LOG_INF("RS485 thread started");
while (1) {
k_sleep(K_FOREVER);
}
}
K_THREAD_DEFINE(rs485_thread_id, 2048, rs485_thread, NULL, NULL, NULL, 5, 0, 0);rs485接收数据[00:49:12.400,446] <wrn> rs485_thread: Received unexpected length: 3 (expected 35)
[00:49:12.401,129] <wrn> rs485_thread: Received unexpected length: 2 (expected 35)
[00:49:12.402,071] <wrn> rs485_thread: Received unexpected length: 3 (expected 35)接收数据时报错,不使用状态机
最新发布