Modbus RTU驱动程序开发指引
驱动开发
摘要
这篇笔记主要介绍基于飞思卡尔kv4x系列MCU的modbus RTU(Remote Terminal Unit)驱动程序开发,以搭载飞思卡尔kv46MCU的飞思卡尔官方塔式系统开发板为例,阅读这篇文章前,基于你已经了解modbus协议要求,以及数据帧格式。
UART
UART(Universal Asynchronous Receiver Transmitter)通用收发器,现在基本上所有的MCU都会含有UART模块,有的甚至不止一路UART,今天我们要讲的飞思卡尔Kv46MCU就含有两路UART模块。
飞思卡尔kv4xMCU除含有UART的基本功能外,还包含支持RS-485操作,硬件流控制,数据端可配置,支持FIFO(Fisrt In First Out),等功能,更多功能介绍可以参阅官方参考手册描述,这里不再赘述。
Kv46MCU的UART模块比51单片机的UART要复杂的多,操作的时候要按照手册上的要求,仔细配置寄存器。
从框图中可以看出,发送器主要包含数据寄存器,波特率产生,发送移位寄存器,发送控制,校验,中断等子模块构成。
从框图可以看出,接收器主要包含数据缓冲区,波特率生成,移位寄存器,接收控制,中断,接收检测等子功能块。
在了解了kv46MCU的UART构成后,开发标准Midbus RTU的驱动程序主要的工作就是如何根据Mosbud标准要求来驱动UART模块,准确的检测通信帧。最主要的就是帧间大于3.5个字符的时间间隔,字节之间的时间间隔不能超过1.5个字节间隔,否则为错误帧。
ge:ZH-CN'>操作,硬件流控制,数据端可配置,支持FIFO(Fisrt In First Out),等功能,更多功能介绍可以参阅官方参考手册描述,这里不再赘述。
Kv46MCU的UART模块比51单片机的UART要复杂的多,操作的时候要按照手册上的要求,仔细配置寄存器。
硬件平台
任何含有kv46MCU的支持UART通信的硬件板件都可以,本文以飞思卡尔官方塔式系统为例,塔式系统应用的时候要注意,它是将MCU的UART1通过USB输出的,所以要按照硬件原理图跳线到正确的硬件上,如果你的硬件平台本身就含有这部分硬件电路,则可以完全用自己的平台实现
软件实现
软件方面主要是初始化和中断的程序开发,以及用于检测t3.5和t1.5时间间隔的定时器中断开发。
初始化主要包含
使能串口时钟
管脚映射
定时器配置
校验位配置
波特率配置
使能发送接收
难点是要懂得根据不同的波特率计算t3.5和t1.5的时间间隔
以9600bps为例, modbus每一个字节的发送接收有11位,所以每一位的时间
t = 1/9600
T3.5 = 3.5*t*11= 4.0104ms,根据这个值和定时器的时钟来配置定时器的装载值。
中断实现
Modbus驱动的中断也就是UART的中断实现主要是根据UARTx_S1寄存器的检测来区分是发送中断和接收中断,以及帧错去中断,校验错误中断等。需要注意的是错误中断和正常的接收发送中断不是一个中断向量,所以要分别在不同的中断函数检测状态寄存器的位来实现中断程序
如发送接收中断
void Uart_vISR1(void)
{
if(UART1_S1 & UART_S1_RDRF_MASK) //receive data register full flag
{
if(…..)/*9位模式*/
{
}
else/*8位模式*/
{
}
}
else if(UART1_S1 & UART_S1_TDRE_MASK) // transmit data register empty flag
{
if(….)/*发送完成*/
{
}
else
{
}
}
else
{
}
}
嵌入式
程序猿
微信号:InterruptISR
- Kruscal(最小生成树)算法模版
- BZOJ 3680: 吊打XXX【模拟退火算法裸题学习,爬山算法学习】
- 区块链概况:什么是比特币
- 简化版桶排序操作模版
- BZOJ 3670: [Noi2014]动物园【KMP变形 】
- 【延迟注入】A5站长网某站存在SQL注入漏洞
- hihoCoder #1498 : Diligent Robots【数学】
- Codeforces Round #336 (Div. 2)【A.思维,暴力,B.字符串,暴搜,前缀和,C.暴力,D,区间dp,E,字符串,数学】
- 【防护】如何阻止SELECT * 语句
- COGS 862. 二进制数01串【dp+经典二分+字符串】
- 【AlphaGo Zero 核心技术-深度强化学习教程代码实战03】编写通用的格子世界环境类
- 冒泡排序简单操作模版及实例分析
- COGS 1299. bplusa【听说比a+b还要水的大水题???】
- python学习笔记之运算符
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 高可用的Redis主从复制集群,从理论到实践
- SpringBoot实战(一):使用Lombok简化你的代码
- Kubernetes Ingress入门指南和实践练习
- [译]Go语言常用文件操作汇总
- Redis常用数据类型对应的数据结构
- 详解卷积中的Winograd加速算法
- SpringMVC源码学习(一) - DispatcherSerlet和相关组件
- SpringMVC源码学习(二) - DispatcherServlet和相关组件
- 微服务使用 Hystrix 实现服务降级
- SpringMVC源码学习(三) - 请求处理的流程
- Hadoop框架:集群模式下分布式环境搭建
- 微服务 Hystrix 实现服务熔断
- 微服务 Gateway 的基本配置
- 有赞营销逆向域的探索与实践
- RabbitMQ 启动报错:Error: unable to perform an operation on node ‘rabbit@***‘. Please see diagnostics...