STM32F407

STM32F407移植FreemodbusV1.6

准备工作 工具介绍 软件 Keil5: 代码编译调试 CubeMX: 代码生成工具 VSCode: 代码编辑器 Modbus Poll && Slave: 调试工具 硬件 STM32F407ZGT6: 普中麒麟F407开发板 两个串口转USB: 用于连接主机和从机 创建工程 CubeMX工程创建 选择芯片型号 设置时钟(外部晶振) 设置调试接口和基准时钟 配置串口(USART1~3) 开启FreeRTOS 创建3个任务 生成项目 Keil工程整合 将下载的Freemodbus源码复制到项目根目录,添加所需源文件: modbus/functions/ 下所有文件 modbus/rtu/ 下所有文件 mb.c 和 mb_m.c 移植详解 port.c - 临界区实现 #include "FreeRTOS.h" #include "task.h" #include "semphr.h" void EnterCriticalSection(void) { taskENTER_CRITICAL(); } void ExitCriticalSection(void) { taskEXIT_CRITICAL(); } portevent.c - 事件标志 使用FreeRTOS事件组实现Modbus事件通知。 portserial.c - 串口收发 实现串口初始化、收发控制,使用FIFO缓冲区接收数据。 porttimer.c - 定时器 实现Modbus帧间隔检测,波特率大于19200时固定为1750us。 主机移植 主机移植与从机类似,主要区别在于: portevent_m.c 中添加了响应事件标志 使用信号量实现主机操作同步 主机使用示例 void MasterTaskFun(void *argument) { for(;;) { eMBMasterPoll(); } } void MasterSendTaskFun(void *argument) { uint16_t data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; for(;;) { eMBMasterReqWriteMultipleHoldingRegister(1, 0, 10, data, 100); for (uint16_t i = 0; i < 10; i++) { data[i] += 1; } osDelay(1000); } } 从机使用示例 void Slave_TaskFun(void *argument) { for(;;) { eMBPoll(); } } 测试 使用Modbus Poll和Modbus Slave软件进行测试: ...

September 13, 2024 · 1 min · Embedded Engineer
环形队列

理解环形队列

解读环形队列-C语言实现 环形队列(Circular Queue)是一种特殊的队列数据结构。与普通的线性队列不同,环形队列在物理存储上表现为一个首尾相连的环状结构,在逻辑上则仍然遵循先进先出(FIFO)的原则。 特点 循环利用空间:当队列中的元素被删除后,原来的空间可以被重新使用 队头队尾指针:使用head和end两个指针标识队列的头部和尾部 队满与队空判断:需要特殊处理,通常预留一个位置不使用 动态调整:可以动态调整数组大小来适应数据量变化 应用场景 缓冲区管理:在网络编程或硬件驱动程序中管理固定大小的缓冲区 生产者消费者模型:在多线程环境中用作数据共享的数据结构 滑动窗口算法:实现高效的数据处理策略 串口接收:STM32中常用于串口接收,实现数据异步使用 图解 非循环队列 非循环队列由一个头指针head和一个尾指针end构成。 入队操作: end = end + 1,然后将数据存入end指向的空间: 出队操作: 出队就是将head指向空间的数据抛出,然后head加一: 判断队空: end = -1 表示队空 end + 1 = head 表示队空 判断队满:end + 1 = MAX_SIZE 循环队列 循环队列的head指针并不指向数据头,而是指向上一次被删除的数据地址。 下标范围控制: end = (end+1) % MAX_SIZE head = (head+1) % MAX_SIZE 入队操作: 出队操作: 判断队满:head = (end+1) % MAX_SIZE 判断队空:head == end ...

September 1, 2024 · 2 min · Embedded Engineer