OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8374|回复: 4

求懂modbus协议的大神 救命 我modbus发送报文写完了 我现在要整如何接收到返回的报文 然后解析出来 怎么写

[复制链接]

26

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
159
金钱
159
注册时间
2015-10-12
在线时间
0 小时
发表于 2015-11-22 20:04:57 | 显示全部楼层 |阅读模式
5金钱
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"
#include "delay.h"
#include "crc.h"
#include "stdio.h"
u8 counter;
u8 recvBuff[256]={0};
int MODBUS(u8* recvBuff,int len,u8 id,u8 D,u8 reg);
void UART2Write(u8* data,int len);
void UART2_SendByte(u8 Data);
void USART_config(u32 bound)
{
 GPIO_InitTypeDef GPIO_InitStructure; 
 USART_InitTypeDef USART_InitStructure;
 NVIC_InitTypeDef NVIC_InitStructure;
//RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2|RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO,ENABLE); //这里一定要配置复用 AFIO
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 ,ENABLE);
USART_DeInit(USART2);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;    
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING;    
GPIO_Init(GPIOA, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = bound;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;  //字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;   // 一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验位  
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  //为硬盘数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //接收发送模式
NVIC_InitStructure.NVIC_IRQChannel  = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE); 
}
void Timer_Config(void)
{
 TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//Timer3_Clock=APB1*2;
    TIM_DeInit(TIM3);                          //复位定时器
    TIM_TimeBaseStructure.TIM_Period=4999;        //定时器初始值
    TIM_TimeBaseStructure.TIM_Prescaler=(7200-1);        //时钟预分频
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;   // 时钟分割
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);      //初始化定时器的值
    TIM_ClearFlag(TIM3,TIM_FLAG_Update);                //清除定时器中断标志 
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);        //使能中断
    TIM_Cmd(TIM3,ENABLE);                        //开启时钟
}
void NVIC_Config(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}
void TIM3_IRQHandler(void)//定时器中断函数
{

if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) // 跟下面一句连在一起用的 判断是否中断有触发,出发后就清除
{   
TIM_ClearITPendingBit(TIM3, TIM_IT_Update); //清除中断标志
counter++;

}
}
/*串口中断函数  什么时候用的到的呢 就是说main函数里面一直在执行自己的东西
 然后突然有东西给单片机啦 下面判断if()发送寄存器空 被触发  就暂停工作 执行中断函数*/
void USART2_IRQHandler(void)
{
  u8 RX_dat;  
  if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)  //判断发生接收中断
   {
RX_dat = USART_ReceiveData(USART2);
   }
}
int main(void)
{
    int len = 0;
Timer_Config();
NVIC_Config();
SystemInit();
USART_config(9600);
delay_init(72);
while(1)
{
 MODBUS( recvBuff,8, 0x01, 0x02, 0x08);
len =8 ;
      UART2Write(recvBuff,len);
 delay_ms(50);
    }
}

/* 下面是一个发送数组的函数 首先先传递 第二个函数 是一个字节一个字节的发送*/
void UART2Write(u8* data,int len)  
{
   u8 i;
   for(i =0;i<8;i++)
{
UART2_SendByte(data);
   }
}
 void UART2_SendByte(u8 Data)  //把上面收到的字节一个一个的发送出去 

   while (!(USART2->SR & USART_FLAG_TXE)); //usart2->SR是串口状态寄存器 USART_FLAG_TXE传输数据寄存器空标记   
   USART_SendData(USART2, Data); 
}
int MODBUS(u8* recvBuff,int len,u8 id,u8 D,u8 reg)
{
if(len >= 8)
{
u16 crc;
recvBuff[0] = id;
recvBuff[1] = 3;
   recvBuff[2] = (unsigned char)(D >> 8); //右移八位[2][3]是起始地址 占两个字节 右移八位取高八位 
recvBuff[3] = (unsigned char)(D & 0xFF); 
recvBuff[4] = (unsigned char)(reg >> 8); //同上
recvBuff[5] = (unsigned char)(reg & 0xFF);
crc=CRC16(recvBuff,6) ; // 校验前面的数字CRC的计算函数
recvBuff[6] = (crc>>8); // 计算出的高八位给第六位
recvBuff[7] = (u8)crc; //计算出的第八位给第七位
}
else
return 0;
return 8;
}

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

8

主题

193

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
303
金钱
303
注册时间
2012-12-19
在线时间
16 小时
发表于 2015-11-22 20:27:38 | 显示全部楼层
接收到的数据按照通信格式进行判断,将数据都出来就可以。
MODBUS有固定的通信格式格式,是标准的。
回复

使用道具 举报

70

主题

6769

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
13157
金钱
13157
注册时间
2012-11-26
在线时间
3817 小时
发表于 2015-11-22 20:39:14 | 显示全部楼层
楼主问modbus,都问了有一个月了,要是真自己好好查资料,顶多一个星期也就搞定了


只会问,而不自己查资料思考,只能呵呵
学无止境
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2015-11-22 21:50:32 | 显示全部楼层
我对楼主已无话可说。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复

使用道具 举报

0

主题

30

帖子

0

精华

初级会员

Rank: 2

积分
98
金钱
98
注册时间
2015-9-1
在线时间
29 小时
发表于 2015-11-24 14:42:34 | 显示全部楼层
当初我看modbus协议简单内容和发送接收例程程序,2天就搞起来和触摸屏通讯了,在网上多找资料
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-16 09:26

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表