用stm32库函数编写的modbus源代码
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
用stm32库函数编写的modbus源代码
说在前面的话:
1.请勿盲目抄袭。这个协议使用了一个定时器,所以在别处请不要再使用,如果定时器不够用,可以做虚拟定时器。也就是采用一个物理的定时器产生时基。在这个定时器的中断函数中可以给相应的多个定时器自加1.每个虚拟定时器可以用两个变量分别控制打开关闭,和计时。这个已经试验通过了可行的。其实就跟我们使用物理的定时器一样,只不过物理的定时器是用晶振产生时基。
2.这段代码已经调试通过了,也硬件试验过,没有问题,如果你出现问题了,看看你在主函数的的各种基本配置有没有完成。如果要使用06和10号功能,你还需要在主函数中建立一个100个元素的数组,每个元素是16位。
3.写这个文档的时候,这个协议已经是半年前完成的了。所以有些东西记得不是很清楚了,如果说错了,请以实际为准。只是不想让这份代码死在电脑中了,所以才想起来要拿出来分享,支持开源精神。
4.如果实在实在是没有弄出来,请联系我,可以共同交流,我的邮箱:***********************
#include"stm32f10x.h"
/* 此Modbus协议暂时只支持RTU模式,只支持作为Modbus从设备。
暂时支持的功能码(16进制)如下表所示:
01.读线圈状态(读多个输出位的状态,有效地位为0-31)
02.读输入位状态(读多个输入位的状态,有效地位为0-31)
03.读保持寄存器(读多个保持寄存器的数值,有效地位为0-99)
04.读输入寄存器(读多个输入寄存器的数值,有效地址为0-1)
05.强制单个线圈(强制单个输出位的状态,有效地位为0-31)
06.预制单个寄存器(设定一个寄存器的数值,有效地址为0-99)
0F.强制多个线圈(强制多个输出位的状态,有效地址为0-31)
10.预制多个寄存器(设定多个寄存器的数值,有效地址为0-99)
暂时支持的错误代码为:
01 不合法功能代码从机接收的是一种不能执行功能代码。发出查询命令后,该代码指示无程序功能。(不支持的功能代码)
02 不合法数据地址接收的数据地址,是从机不允许的地址。(起始地址不在有效范围内)
03 不合法数据查询数据区的值是从机不允许的值。(在起始地址的基础上,这个数量是不合法的)
供用户调用的函数有:
1.void ModInit(u8 Id);//用于Modbus初始化,在函数调用前,必须初始化函数,用于Main函数中
2.void ModRcv(void);//用于modbus信息接收,放在串口接收中断
3.void ModSend(void);//用于modbus信息接收,放在串口发送中断
例如:void USART1_IRQHandler(void) //USART1中断
{
if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
{
void ModRcv(void);
……
……
……
}
if(USART_GetITStatus(USART1,USART_IT_TC)!=RESET)
{
void ModSend(void);//用于modbus信息接收
……
……
……
}
}
*/
//modbus用通讯参数
u8 Tim_Out;//大于3.5个字符时间,保守取3ms (波特率9600的时候大约2点几毫秒)
u8 Rcv_Complete;//一帧是否已经接受完成
u8 Send_Complete;//一帧是否已经发送完成
u8 Com_busy;//通讯繁忙,表示上一帧还未处理结束
u8 Rcv_Buffer[210];//用来存放接收到的完整的一帧数据(第一个字节用来存放接收到的有效字节数,也就是数组中的有效字节数)
u8 Send_Buffer[210];//用来存放待发送的完整的一帧数据(第一个字节用来存放待发送的有效字节数,也就是数组中的有效字节数)
u8 Rcv_Data;//用来存放接收的一个字节
u8 Send_Data;//用来存放要发送的一字节
u8 Mod_Id;//用来标志作为从站的站号
u8 Rcv_Num;//用来表示接收的一帧的有效字节数(从功能码到CRC校验)
u8 Send_Num;//用来表示待发送的一帧的字节数
u8 *PointToRcvBuf;//用来指向接收的数据缓存
u8 *PointToSendBuf;//用来指向带发送的数据缓存
u8 Comu_Busy;//用来表示能否接收下一帧数据
u8 HaveMes;
extern u16 HoldReg[100];
//CRC校验查表用参数
/* CRC 高位字节值表*/
static u8 auchCRCHi[] = {
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,
0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,0x81,0x40,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,
0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x00,0xC1,
0x81,0x40,0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,
0x00,0xC1,0x81,0x40,0x01,0xC0,0x80,0x41,0x01,0xC0,
0x80,0x41,0x00,0xC1,0x81,0x40,0x00,0xC1,0x81,0x40,
0x01,0xC0,0x80,0x41,0x01,0xC0,0x80,0x41,0x00,0xC1,