当前位置:首页 > 用stm32库函数编写的modbus源代码
void PresetSingleReg(u8 *pointer_1,u8 *pointer_2)//pointer_1用作输入,pointer_2用作输出 {
u16 Address=0;//待预制寄存器的起始地址(GPIO_X,X为A,B两个端口,每
个端口16位,对应地址0——31)
if(Address<100) //只要地址小于100,就是合法地址 {
*(pointer_2)=1+1+2+2+2;//有效字节个数等于丛机地址+功能码+
if(*(pointer_1)==8) //如果接收到的字节数不是8个,就是一个错误帧 {
Address=(u16)(*(pointer_1+3))*256+(*(pointer_1+4));//先得到寄存器地址 PresetValue=(u16)(*(pointer_1+5))*256+(*(pointer_1+6));//先得到预制值 *(pointer_2+2)=0x06;//第三个字节为功能码 u16 PresetValue=0;//预制数值
u16 SendKey;//要发送数据的校验值
寄存器地址+寄存器数值+CRC校验
HoldReg[Address]=PresetValue;//将预制值写入保持寄存器
*(pointer_2+3)=*(pointer_1+3);//将地址值写入输出的寄存器中 *(pointer_2+4)=*(pointer_1+4);
*(pointer_2+5)=*(pointer_1+5);//将数值写入输出寄存器中 *(pointer_2+6)=*(pointer_1+6);
//写入校验码
SendKey=CRC16(pointer_2+1,*pointer_2-2); //将计算出来的校验码装入输出数据缓存中 *(pointer_2+(*pointer_2-1))=(u8)(SendKey>>8); *(pointer_2+(*pointer_2))=(u8)(SendKey&0x00FF); //启动数据发送
USART_ITConfig(USART1, USART_IT_TC, ENABLE);//开启数据发送
中断 }
/* 函数功能:强制多个线圈状态
函数输入:两个指针,pointer_1指向用来存放输入信息帧的数组,
pointer_2用来指向存放输出信息帧的数组(两个数组的第一个元
} else { }
Comu_Busy=0;
} else { }
ErrorHandle(2,pointer_2);//错误起始地址
素都用来存放信息帧的有效字节个数)
后面的元素按照Modbus协议组织。
*/
函数输出:无。
void ForceMulCoil(u8 *pointer_1,u8 *pointer_2)//pointer_1用作输入,pointer_2用作输出 {
u16 Address=0;//待强制线圈起始地址(GPIO_X,X为C,D两个端口,每个端
口16位,对应地址0——31)
u16 Num=0;//要强制的线圈个数 u8 ByteCount;//命令值的字节个数
u32 CommandValue;//命令的数值,有效的每个位用来置位或者复位指定地址
的线圈
u32 PortTemp;//用来存放从端口取过来的数据 u32 CalTemp;//临时计算用
u16 ReadData=0;//用来临时存放从端口读来的数据 u16 SendKey;//要发送数据的校验值
u8 CountTemp;//计算实际需要的命令字节数
Address=(u16)(*(pointer_1+3))*256+(*(pointer_1+4));//先得到线圈地址 Num=(u16)(*(pointer_1+5))*256+(*(pointer_1+6));//先得到线圈数量 ByteCount= *(pointer_1+7);//表示命令值的字节数 CountTemp=(u8)(Num/8); if(Num%8!=0)
CountTemp++;
*(pointer_2+2)=0x0F;//第三个字节为功能码
if((*(pointer_1)==9+ByteCount)&&ByteCount>0&&ByteCount<=4&&CountTemp
==ByteCount)//如果接收到的字节数不是预定的个数,或者命令字节数超出允许
范围就是一个错误帧
{
if(Address<32) //只要地址小于32,就是合法地址 {
if(Address+Num<=32&&Num>0) //只要地址加数量大于0小于32,就
是合法数量
//把命令值做一些处理,存入CommandValue CommandValue=0;
for(i=0,j=ByteCount;j>0;i++,j--) {
CommandValue|=((u32)*(pointer_1+8+i))<<8*i;//将输入数据
{
//用于for循环 u8i; u8 j;
缓存中的数据存入CommandValue
}
CommandValue=CommandValue<
位置
*(pointer_2)=1+1+2+2+2;//有效字节个数等于丛机地址+功能码+
线圈起始地址+线圈数量+CRC校验
*(pointer_2+3)=*(pointer_1+3);//将地址值写入输出的寄存器中 *(pointer_2+4)=*(pointer_1+4);
*(pointer_2+5)=*(pointer_1+5);//将线圈数量值写入输出的寄存
器中
*(pointer_2+6)=*(pointer_1+6);
共分享92篇相关文档