这个项目是我在一家公司里面实现的,所以大部分代码不能开源出来,不够有些细节还是可以讨论。
SetTxMsg 构造发送命令,利用 SendMsg 将命令打包成字节流经串口发送,再经 ProcessUartResponse 解析接收数据。接收数据采用环形缓冲区,串口中断时将数据写入缓冲区,另创建读取缓冲区处理函数读取数据。该通信协议的波特率为 9600,采用 16 进制接收和发送,包含以下部分: - 帧头 - 数据长度 - 数据地址位 - 数据位 - 校验位
此外,还制作了一些光电检测电路,例如 OPT4001。关于如何提高灵敏度: - 首先需要屏蔽掉外接的光噪声 - 加入滤波电路减少参考电压噪声 - 或者采用前置放大器放大信号增加分辨率 - 同时在软件上采用滑动窗口平均滤波
这个项目从方案调研、、芯片选型和硬件的制作、还有系统的设计都是我自己查阅资料和文献得来的,所以有问题可以邮箱联系我,或者可以看我GitHub上的开源代码。
SMBUS通信并非一种常见的通信方式,因此需要查阅SMBUS通信的源码,这里我是看的ST公司的源码文档,里面详细记录了SMBUS通信。 SMBUS通信是什么?SMBus(System Management Bus)是由Intel于1995年推出的两线制串行通信总线,专为系统管理任务(如电源控制、温度监控等)设计,其基于I2C协议但针对可靠性和管理功能进行了优化。物理层采用开漏设计的SMBCLK(时钟线)和SMBDATA(数据线),需外接上拉电阻(通常至3.3V或5V),并遵循严格的电压阈值(如VIL=0.8V, VIH=2.1V)以增强抗噪能力,标准速率范围为10 kHz至100 kHz。协议层通过强制超时机制(如35ms无响应自动复位)、PEC校验(数据包错误检查)和预定义命令集(如0x44读取温度、0x14控制风扇)提升可靠性,同时支持扩展功能如SMBALERT#中断信号和主机通知协议,允许从设备主动上报事件。相较于I2C,SMBus在电气规范、超时限制及校验机制上更为严格,但速率通常较低(I2C可达5 MHz)。其广泛应用于笔记本电脑电池管理、服务器散热控制及嵌入式系统硬件监测等场景,开发时需注意上拉电阻匹配、协议合规性及工具调试,成为高可靠系统管理的核心通信方案
其他接口用于 FPC 排线连接到功率板上
顶层和底层走线,第二层走 PGND,第三层走电源
遇到的问题:通道转换过程中会发生数据错误
同时封装了很多检错 TPS546D24 的函数,读取相应寄存器即可获取数据
配置 PH/EN 模式和 PWM 模式
增加了积分限幅、输出限幅等设置,并且给调节过程配置了缓上升调节,以达到安全性,可以设置步长、斜率速度。
自整定 PID: - 利用 ZN 法,改变输入输出,获取 PID 波形的一个震荡周期 - 根据 ZN 公式计算 PID 参数
自适应 PID: - 当误差很大时,只采用 P 调节 - 当误差逐渐变小时,引入积分 - 当误差最小时,加入微分
使用 MATLAB 系统函数辨别工具箱,将输入输出数据传给 MATLAB,获取 PID 控制器的系统函数,然后进一步获取 P、I、D 参数。
先找大致的 P、I、D 参数,然后再微调。
比例项用于快速响应误差,积分项用于消除稳态误差,微分项用于抑制系统的振荡。 其实PID有很多高级的用法,但是我觉得最适合工程的PID才是最好的,模糊控制、神经网络等等都可以结合PID
包含串口收发数据解析、PID 参数设定协议解析。
定义接收环形缓冲区,包含以下内容: - 数据指针 - 头指针 - 尾指针 - 当前缓冲区存储的数据量 - 队列最大的数据量
数据帧格式: - 帧头:0x59485a43 - 命令码 - 数据 - 校验和
接收缓冲区同样使用环形缓冲区,包含以下内容: - 数据指针 - 头指针 - 尾指针 - 当前帧的长度 - 是否找到帧头的标志位
对于这部分的软件架构设计呢,我主要是分成三部分的大内容,首先是恒流任务和恒温任务,他们的优先级都是一样的,然而串口的优先级是最高的。我们都知道Freertos是基于优先级调度任务的,同等优先级是基于时间片的,所以这里用二值信号量去判断是否串口中断是否来临,那么这样就可以有效的阻塞串口处理函数。串口触发时间呢,则采用事件组去触发任务,数据的传输则用消息队列,获取电流,获取温度,获取风扇的转速等等这些。
-Wall 或 -Wextra 选项。这些选项会启用更多的警告提示。CFLAGS:C 编译器的选项CC:C 编译器SRC:源文件目录OBJ:目标文件目录%:匹配任意文件名$<:表示依赖中的第一个文件$@:表示目标文件virtual,通过基类的指针或引用来调用派生类的函数。派生类可以重写(override)这些虚函数,从而实现不同的行为。这个项目需要用到一个IMX6ULL开发板,正点原子和韦东山的都可以,然后买一个usb摄像头,就可以了。
QMediaPlayer 类,通过 stateChanged(QMediaPlayer::State state) 判断状态实现播放、暂停、停止,需提前知晓路径。QMediaPlayer 类,但需 setVideoOutput(QVideoWidget*) 设置视频输出。USB 相机 :经 yuv_to_jpeg 转格式,V4l2_open() 函数打开摄像头设备,配置 MJPG、分辨率,申请内核缓冲区并 mmap 映射到用户空间,Vide_Show() 定时器(30ms)读帧数据显示在 QLabel 上,按钮槽函数实现拍照、保存及跳转相册界面。
天气界面:用 IP 地址获取天气信息,调用中华万年历 API(数据与中国天气网一致、JSON 格式、查询方便),QNetworkAccessManager 发送网络请求,解析 JSON 数据,定时器(1 小时)更新天气数据。
语音识别界面申请语音识别账号,QT 开发录音功能,创建 QAudioRecorder,用 QAudioEncoderSettings 设音频参数,调用 record()、pause()、stop() 函数录音,录音数据上传服务端识别。
i2c_transfer 传输。strsplit 分割字符串写入结构体。主要用到了 QMediaPlayer 这个类,通过 stateChanged(QMediaPlayer::State state) 判断状态,从而知道媒体何时暂停、播放或停止(前提是知道路径)。
同样用到了 QMediaPlayer 类,但需要使用 setVideoOutput(QVideoWidget*) 设置视频输出。
显示 AP3216 读取的光传感器距离,通过 500ms 的定时器实时读取距离信息,并传递到 QString 上显示。
yuv_to_jpeg 转换格式。V4l2_open() 函数:打开摄像头设备(如 /dev/video2),配置 MJPG 格式、分辨率,申请内核缓冲区并通过 mmap 映射到用户空间。Vide_Show():30ms 触发的定时器槽函数,从摄像头缓冲区读取帧数据并显示在 QLabel 上。On_pushButton_take_clicked():按钮槽函数,实现拍照并保存 JPG 文件到 ./photo/。On_pushButton_photos_clicked():关闭摄像头并跳转至相册界面。QImage),可能需要进行 YUV 转 RGB 的步骤。QLabel 或 QGraphicsView 的内容。利用 IP 地址实现对天气的获取: - 使用 IP 地址归属地查询当前位置,位置信息在查询天气时也会用到。 - 调用与天气相关的 API(例如中华万年历 API)获取本地天气信息。 - 推荐使用中华万年历 API 的原因: - 数据与中国天气网一致。 - 返回的数据是 JSON 格式,方便解析。 - 查询方便,支持城市名称或城市 ID 查询。 - 使用 QNetworkAccessManager 发送网络请求,解析 JSON 数据。 - 定时器(1 小时触发一次)用于定时更新天气数据。
QAudioRecorder。supportedAudioCodecs() 获取可用的编码方式,使用 QAudioEncoderSettings 设置输入音频参数(编码格式、采样率、通道数、音频质量等)。record()、pause() 和 stop() 函数完成录音。i2c_transfer 函数进行数据传输。copy_to_user 将数据传递给用户空间strsplit(&s, ",") 分割字符串,将数据写入结构体中。在 LCDinfo 节点下,修改为适配自己分辨率型号的配置。
问题:你如何实现音乐播放器的播放、暂停和停止功能?
答案:音乐播放器主要使用了 QMediaPlayer 类。通过监听 stateChanged 信号,可以判断播放器的状态(播放、暂停、停止)。当状态变化时,根据 state 的值执行相应的操作,例如播放时调用 play(),暂停时调用 pause(),停止时调用 stop()。播放器需要提前知道媒体文件的路径。
问题:视频播放器和音乐播放器的区别是什么?
答案:视频播放器同样使用 QMediaPlayer 类,但需要通过 setVideoOutput(QVideoWidget*) 设置视频输出的显示界面。音乐播放器只需要处理音频流,而视频播放器需要同时处理音频和视频流。
问题:倒车界面如何实时更新光传感器的距离信息?
答案:倒车界面通过定时器(500ms 触发一次)实时读取 AP3216 光传感器的距离信息。读取到的数据通过 QString 传递到界面上显示。
问题:如何实现 USB 相机的视频显示?
答案:使用 V4L2_open() 函数打开摄像头设备(如 /dev/video2),配置为 MJPG 格式,并设置分辨率。通过 mmap 将内核缓冲区映射到用户空间。定时器(30ms 触发一次)从缓冲区读取帧数据,并显示在 QLabel 上。
问题:如何通过 IP 地址获取天气信息?
答案:使用 QNetworkAccessManager 发送网络请求,调用中华万年历 API 获取天气信息。API 返回的数据是 JSON 格式,通过解析 JSON 数据获取天气信息。定时器(1 小时触发一次)用于定时更新天气数据。
问题:为什么选择中华万年历 API?
答案:中华万年历 API 的数据与中国天气网一致,返回的数据是 JSON 格式,方便解析,且查询方便(支持城市名称或城市 ID)。
问题:如何实现语音识别功能?
答案:使用 QAudioRecorder 类实现录音功能。通过 QAudioEncoderSettings 设置音频参数(编码格式、采样率、通道数等)。调用 record()、pause() 和 stop() 函数完成录音。录音数据上传到语音识别服务端进行识别。
问题:如何配置 WM8960 音频驱动?
答案:使用 I2S 接口配置 WM8960 音频编解码芯片。修改内核配置,使能 WM8960 驱动。移植 alsa-lib 和 alsa-utils 源码,确保设备节点路径一致。通过配置实现录音、播放音乐和播放视频的功能。
问题:如何实现 AP3216 距离读取?
答案:在 I2C1 节点下添加 AP3216 设备子节点,包含 compatible 和 reg 信息。编写 AP3216 驱动,通过 i2c_transfer 函数读取传感器数据。 DHT11 温湿度传感器的单总线协议编写: - 在进行数据读取过程中需要 local_irq_disable 屏蔽中断标志位,从而禁止内核的抢占。
问题:如何解析 GPS 数据?
答案:使用 Eco 模块通过串口通信,解析 GPS 数据(例如 RMC、GGA、VTG 等)。通过 strsplit 函数分割字符串,将数据写入结构体中。
问题:USB 摄像头驱动的定时器为什么要每隔 30ms 读取一次数据?
答案:30ms 定时器对应每秒 30 帧,这是常见的流畅视频显示的帧率。 USB 摄像头帧格式转换: - 摄像头读取的帧格式需要从 YUV 转换为 JPEG 格式
问题:对于摄像头读取的格式有没有做变换?
答案:做了变换。通常 USB 摄像头读取的是 YUV 格式的视频数据,需要编写一个 YUV 转 JPEG 格式的函数进行读取。关键函数是 libjpeg 库中的 jpeg_compress 函数。
开源项目,b站随便找一个就可以,这个主要是让我熟悉操作系统的一些条件变量、自旋锁和socket套接字概念的。
线程池分为三部分: 1. 任务队列:用于存储待处理的任务,工作线程从队列中获取任务进行处理。 - 通过线程池的 API 接口,将待处理的任务添加到任务队列中。 - 已处理的任务会被从任务队列中删除。 - 线程池的使用者(调用线程池函数往队列添加任务的线程)是生产者线程。
服务器端的通信流程: 1. 创建 socket 描述符。 2. 使用 bind 绑定 IP 和端口。 3. 调用 listen 进入监听状态。 4. 调用 accept 接受客户端的连接请求。 5. 通过 connect 与客户端建立连接,完成通信。
服务端主线程在这里的主要任务是:按照Socket通信流程往下走,并发操作在哪里呢? 第四步的accept接受到客户端的连接请求后,创建子线程pthread_create让通信的处理流程则是在子线程中运行,然后调用pthread_detach去回收子线程资源 注意是用detach而不是用join函数 阻塞。然后再close(fd)关闭文件描述符。通信的流程都在子线程的working里面。 那么需要给子线程传进去一些参数:信息结构体sockinfo{sockadd_in addr,int fd} 需要有socket的地址和 文件描述符fd。
线程同步体现在那里? 多个线程对同一个资源需要同时读写操作,就需要同步操作了。 之前提到声明了一个全局的结构体数组sockinfo infos[512] 在主线程中要确定数组fd的数量 而这里是不需要线程同步的。 在线程池中是需要进行线程同步的。
这个项目是我结合实验室的一个成像模型的预训练,就是需要通过实验室特有的成像模型获取数据,然后对数据进行处理分类。大家有时间可以去看看关联成像,这部分也是我实验室的一个研究方向,但是这个跟嵌入式没啥关系,当作一个拓展吧。
输入数据为尺寸 526×345×111 的光谱图像,设计轻量化卷积神经网络:
这个比赛离我很久远了,很多内容都想不起来了,但是还是去翻翻往年题目去作了一些总结,为什么我要写这个呢,因为某菊厂给我免笔试就是因为这个,哈哈哈是不是很值得?菊厂的笔试还是很难的,所以大家有时间要多比赛。
以经纬度为输入,用 K-means 聚类算法划成 8 区域,参考火势强度作权重,轮廓系数评指标,输出中心坐标、火点数量、总火势强度。设计单位区域无人机需求数公式,指标含火势总量、无人机灭火能力、紧急系数、火势扩散速度。用模拟退火算法求全局最优分配,随机分配无人机,满足总数量约束,目标函数为灭火时间 + 权重因子 × 未覆盖惩罚,引入交叉验证评聚类模型。
虽然画得一般,但也是自己设计的,也花了一点心思: