在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例Android手机应用开发 → Unity在 android 平台使用串口带环形缓冲区

Unity在 android 平台使用串口带环形缓冲区

Android手机应用开发

下载此实例
  • 开发语言:C/C++
  • 实例大小:5.84KB
  • 下载次数:0
  • 浏览次数:19
  • 发布时间:2025-01-09
  • 实例类别:Android手机应用开发
  • 发 布 人:zzzlxp
  • 文件格式:.cpp
  • 所需积分:2

实例介绍

【实例简介】

  1. 后台串口读取线程:在SerialOpen函数中,我们启动了一个后台线程serialReadThread,它不断地从串口读取数据并将数据写入环形缓冲区。
  2. 环形缓冲区:缓冲区使用互斥锁进行保护,确保在多线程环境下安全地读写数据。
  3. SerialReceive:外部线程可以通过调用SerialReceive函数来检查缓冲区是否包含完整的数据包,如果包含,就将数据包返回。

外部调用:

在外部线程中,你可以通过不断调用SerialReceive来获取串口数据包:

	

【实例截图】

【核心代码】

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <android/log.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <pthread.h>

#define BUFFER_SIZE 1024  // 环形缓冲区大小
#define PACKET_START 0xEF37
#define PACKET_END 0xFE73
#define TAG "SerialPort"  // 日志标签

// 封装日志宏
#define LOGI(fmt, ...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##__VA_ARGS__)
#define LOGE(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##__VA_ARGS__)
#define LOGD(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##__VA_ARGS__)

// 环形缓冲区
unsigned char ringBuffer[BUFFER_SIZE];
int head = 0;  // 缓冲区头指针
int tail = 0;  // 缓冲区尾指针
pthread_mutex_t bufferMutex = PTHREAD_MUTEX_INITIALIZER; // 缓冲区互斥锁

// 串口文件描述符
int fd_ = -1;
pthread_t serialThread; // 串口读取线程

// 向环形缓冲区写入数据
int writeRingBuffer(const unsigned char* data, int size)
{
    int bytesWritten = 0;
    for (int i = 0; i < size; i ) {
        ringBuffer[head] = data[i];
        head = (head 1) % BUFFER_SIZE;  // 环形缓冲区的循环
        bytesWritten ;
    }
    return bytesWritten;
}

// 从环形缓冲区读取数据包
int readPacket(unsigned char* packetBuffer, int maxSize)
{
    int packetStartIndex = -1;
    int packetEndIndex = -1;
    int packetSize = 0;

    // 查找数据包的起始和结束位置
    for (int i = tail; i != head; i = (i 1) % BUFFER_SIZE) {
        // 检查是否找到包的起始字节
        if (i 1 != head && (ringBuffer[i] << 8 | ringBuffer[(i 1) % BUFFER_SIZE]) == PACKET_START) {
            packetStartIndex = i;
        }

        // 如果找到了包的起始字节,继续寻找结束字节
        if (packetStartIndex != -1) {
            if (i 1 != head && (ringBuffer[i] << 8 | ringBuffer[(i 1) % BUFFER_SIZE]) == PACKET_END) {
                packetEndIndex = i;
                break;
            }
        }
    }

    // 如果找到了完整的包
    if (packetStartIndex != -1 && packetEndIndex != -1) {
        packetSize = (packetEndIndex - packetStartIndex BUFFER_SIZE) % BUFFER_SIZE 2;  // 2 for the start and end markers

        // 拷贝数据包到 packetBuffer
        int idx = 0;
        for (int i = packetStartIndex; i != packetEndIndex; i = (i 1) % BUFFER_SIZE) {
            packetBuffer[idx ] = ringBuffer[i];
        }
        packetBuffer[idx ] = ringBuffer[packetEndIndex];  // 末尾字节
        packetBuffer[idx ] = ringBuffer[(packetEndIndex 1) % BUFFER_SIZE];  // 结束字节

        // 更新缓冲区尾指针
        tail = (packetEndIndex 2) % BUFFER_SIZE;

        // 打印日志
        LOGI("Found packet of size %d", packetSize);

        return packetSize;
    }

    return 0;  // 如果没有找到完整的数据包
}

// 串口接收数据模拟函数
int SerialReceive(unsigned char* buff, int len)
{
    pthread_mutex_lock(&bufferMutex);  // 锁住缓冲区
    int packetSize = readPacket(buff, len);
    pthread_mutex_unlock(&bufferMutex);  // 解锁缓冲区

    return packetSize;
}

// 串口读取线程
void* serialReadThread(void* arg)
{
    unsigned char recvBuffer[256];
    
    while (1) {
        if (fd_ < 0) {
            LOGE("Serial port is not open");
            continue;
        }

        int readSize = read(fd_, recvBuffer, sizeof(recvBuffer));
        if (readSize > 0) {
            // 将读取的数据写入环形缓冲区
            pthread_mutex_lock(&bufferMutex);  // 锁住缓冲区
            writeRingBuffer(recvBuffer, readSize);
            pthread_mutex_unlock(&bufferMutex);  // 解锁缓冲区

            LOGI("Read %d bytes from serial port", readSize);
        } else if (readSize < 0) {
            LOGE("Error reading from serial port");
        }

        usleep(100000);  // 稍微延时
    }

    return NULL;
}

extern "C" {
    // 打开串口
    bool SerialOpen(char* sPort, int speed)
    {
        if (fd_ > 0) // already open
            return true;

        // 打开串口
        fd_ = open(sPort, O_RDWR | O_NOCTTY | O_NDELAY);
        if (fd_ == -1) {
            LOGE("Failed to open serial port %s", sPort);
            return false;
        }

        // 恢复串口为阻塞状态
        if (fcntl(fd_, F_SETFL, 0) < 0) {
            LOGE("Failed to set blocking mode");
            return false;
        }

        // 设置串口配置
        if (speed == 0) {
            speed = 38400;
        }

        struct termios newtio;
        bzero(&newtio, sizeof(newtio));
        newtio.c_cflag |= CLOCAL | CREAD;
        newtio.c_cflag &= ~CSIZE;
        newtio.c_cflag |= CS8;  // 8 data bits

        // 设置波特率
        cfsetispeed(&newtio, B38400);
        cfsetospeed(&newtio, B38400);

        // 设置停止位和奇偶校验
        newtio.c_cflag &= ~CSTOPB;
        newtio.c_cflag &= ~PARENB;

        newtio.c_cc[VTIME] = 1;
        newtio.c_cc[VMIN] = 1;

        tcflush(fd_, TCIFLUSH);
        if (tcsetattr(fd_, TCSANOW, &newtio) != 0) {
            LOGE("Failed to configure serial port");
            return false;
        }

        LOGI("Serial port opened successfully");

        // 启动串口读取线程
        if (pthread_create(&serialThread, NULL, serialReadThread, NULL) != 0) {
            LOGE("Failed to create serial read thread");
            return false;
        }

        return true;
    }

    // 关闭串口
    void SerialClose()
    {
        if (fd_ > 0) {
            close(fd_);
            fd_ = -1;
            pthread_cancel(serialThread);  // 取消串口读取线程
            LOGI("Serial port closed");
        }
    }
}


实例下载地址

Unity在 android 平台使用串口带环形缓冲区

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警