OpenEdv-开源电子网

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

利用modbus rtu通信协议让STM32F103和显控的触摸屏做通信怎么连接不上?????????(急急急!!!!)

[复制链接]

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
发表于 2013-3-16 23:27:38 | 显示全部楼层 |阅读模式
现在我老板让我利用STM32做一个案子(小弟我以前没有使用过STM32),就是把STM32F103和深圳显控的SA-7A的触摸屏利用MODBUS RTU协议通信起来,现在我的STM32的程序也写好了,但是就是不能和触摸屏进行通信,各位大哥能不能帮小弟看看我的程序哪里有错误????(我的思路是让定时器定时2ms,然后接收串口数据)

小弟的串口中断程序
void USART_ITHandle(void)
{
 if(USART_GetITStatus(USART1, USART_IT_RXNE)== SET) //接收中斷
 {
  USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除接收中斷位
  if(receTimeOut>1)
  {
   receCount = 0;
   Timer2_enable();
   receTimeOut = 0;
  }
  receBuf[receCount] = USART_ReceiveData(USART1);
  receCount++;
  Timer2_enable();
  receCount &= 0x0f;
 }
 else if(USART_GetITStatus(USART1, USART_IT_TC) == SET)  //檢驗發送完成中斷
 {
  USART_ClearFlag(USART1, USART_FLAG_TC);  //清除發送完成標志位
  if(sendPosi < sendCount)
  {
   sendPosi++;
   USART_SendData(USART1, sendBuf[sendPosi]);
  }
  else
  {
   receCount = 0;
  }
 }
}


小弟的定时程序如下:
void TIM2_Configuration(void)  //定時1ms
{

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);  //配置RCC,使能TIM2
  TIM_TimeBaseStructure.TIM_Prescaler = 7199;  //時鐘預分頻數
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上計數
  TIM_TimeBaseStructure.TIM_Period = 9; //自動重裝載寄存器周期的值
  TIM_TimeBaseStructure.TIM_ClockDivision = 0; //時間分割值
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定時器2
  TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除標志
 }   

/*******************************************/
/*******************************************/
/*******************************************/
void Timer2_enable(void)
{
 TIM_ClearFlag(TIM2, TIM_FLAG_Update);   //清除標志
 TIM_SetCounter(TIM2, 0x00);   //設置寄存器值為0
 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);   //使能中斷
 TIM_Cmd(TIM2, ENABLE);   //開啟定時器
}

/*******************************************/
/*******************************************/
/*******************************************/
void Timer2_disable(void)
{
// TIM_ITConfig(TIM2, TIM_IT_Update |TIM_IT_Trigger, DISABLE);
 TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);
 TIM_Cmd(TIM2, DISABLE);
}

/*******************************************/
/*******************************************/
/*******************************************/
void TIM2_ITHandle(void)                                  //定时中断程序
{
 if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) //檢測是否發生溢出更新事件
 {
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除更新標志位
//  checkComm0Modbus();
  if(receTimeOut<2)
  {
   receTimeOut++;
  }
  else
  {
   Timer2_disable();
   receCount = 0;
   bitflag = 1;
  }
 }
}





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

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2015-5-6
在线时间
1 小时
发表于 2015-5-6 08:48:35 | 显示全部楼层
现在我在搞威纶通触摸屏与STM32F103ZET6  modbus协议通讯问题,现在第一步不知道威纶通触摸屏怎样先跟modbus调试软件通讯,例如modbus slave软件,modscan32软件等。
回复 支持 1 反对 0

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-3-17 00:01:29 | 显示全部楼层
串口屏?
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-17 17:33:45 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
串口屏??? 
原子哥,什么意思??
我是使用的RS232串口呀,显控的SA-7A的触摸屏也是使用的RS232串口呀
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-3-17 17:56:55 | 显示全部楼层
就是说你的屏幕是串口通信的。
是串口,你就可以直接连接电脑,发送相关数据测试,这样好找问题。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-17 22:20:24 | 显示全部楼层
回复【4楼】正点原子:
---------------------------------
原子哥,我做过实验,我把触摸屏和MODBUS OLL模拟软件相互通信,他们是可以通信的,如果我把我的STM32程序和MODBUS OLL模拟软件相互通信,他们也是可以通信的,但是如果我把触摸屏和STM32程序连接,再让他们相互通信,此时就没有办法通信了,我怀疑是我的STM32的程序在定时处理接收数据时不对,但是我又没有好的办法,就不知道该怎么办了??
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-3-17 23:27:00 | 显示全部楼层
回复【5楼】jason_chdsh:
---------------------------------
分析下他们的通信数据.可以利用串口监视软件,监视一下.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-18 22:31:49 | 显示全部楼层
回复【6楼】正点原子:
---------------------------------
呵呵,原子哥,通信数据我也分析过,触摸屏发送给STM32的数据是正确的,但是STM32反馈给触摸屏的数据错误,我的STM32串口处理函数我现在能不清楚错误在哪里,我们这里有谁做过利用STM32做MODBUS RTU通信的吗?能给指导一下吗,或者给一个范例也行,也学习一下
回复 支持 反对

使用道具 举报

4

主题

12

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2012-11-7
在线时间
3 小时
发表于 2013-3-19 12:46:26 | 显示全部楼层
MODBUS是一主多从
回复 支持 反对

使用道具 举报

5

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2011-9-24
在线时间
9 小时
发表于 2013-3-19 16:56:30 | 显示全部楼层
貌似modbus判断一个消息是否结束是用的3.5个字符时间间隔判断,而不是你定义的1ms,这个数值是根据波特率的不同而不同的
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-19 22:24:02 | 显示全部楼层
回复【9楼】song19881218:
---------------------------------
呵呵,楼上的两位大哥,modbus协议定义帧结束符是不小于3.5个字符时间间隔,位之间是不大于1.5个字符时间间隔,我现在是不知道该怎么使用中断处理串口接收的信息(在不小于3.5个字符时间和不大于1.5个字符时间接收到的串口数据怎么编程)?? 能否给指教一下???
回复 支持 反对

使用道具 举报

5

主题

49

帖子

0

精华

初级会员

Rank: 2

积分
119
金钱
119
注册时间
2011-9-24
在线时间
9 小时
发表于 2013-3-20 09:15:20 | 显示全部楼层
串口接收里就是当有数据时,一直置位定时器,不让进入中断,如果大于3.5个间隔,证明一个消息接收完成,则会进入定时器中断,定时器里处理一下就行了。根据你的程序改一下就行
void USART_ITHandle(void)
{
 if(USART_GetITStatus(USART1, USART_IT_RXNE)== SET) //接收中斷
 {
  USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除接收中斷位
   receBuf[receCount] = USART_ReceiveData(USART1);
  if(receTimeOut)
  {
    receCount = 0;
    Timer2_enable();
    receTimeOut = 0;
  }
  else
  {
    receCount++;
    Timer2_enable();
    receTimeOut = 0;
  }
 }
}

void TIM2_ITHandle(void)                                  //定时中断程序
{
 if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)  //檢測是否發生溢出更新事件
 {
  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);  //清除更新標志位
   Timer2_disable();
   receCount = 0;
   receTimeOut = 1;
   bitflag = 1;                         //证明这次数据接收完成
 }
}
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-20 22:50:20 | 显示全部楼层
回复【11楼】song19881218:
---------------------------------
谢谢楼上的大哥,我试试
回复 支持 反对

使用道具 举报

30

主题

705

帖子

1

精华

新手上路

积分
21
金钱
21
注册时间
2013-3-14
在线时间
52 小时
发表于 2013-3-21 11:31:17 | 显示全部楼层
stm32发送数据配置是 9位数据,才是8位数据位一位停止位。我的modbus可以和威纶通的触摸屏通信。我成功了。要注意一点的是:触摸屏是主机,stm32得是从机。
原子哥是不是又要出黑科技了呀。^_^...
回复 支持 反对

使用道具 举报

30

主题

705

帖子

1

精华

新手上路

积分
21
金钱
21
注册时间
2013-3-14
在线时间
52 小时
发表于 2013-3-21 11:34:21 | 显示全部楼层
checkComm0Modbus();---这个函数里面要开关串口的。一开始我也通信不了,在这个里面要操作串口,就是接受完数据后要关闭接收,发送完了再打开接收中断。
原子哥是不是又要出黑科技了呀。^_^...
回复 支持 反对

使用道具 举报

36

主题

1263

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1612
金钱
1612
注册时间
2012-6-15
在线时间
39 小时
发表于 2013-3-21 13:31:09 | 显示全部楼层
你怎么在中断里面 Send...

看你程序处理的感觉很复杂, 

本人应用的部分代码 共享下: <3 4 6 16号命令>
struct
{
union
{
u8 buf[5+(NumOfIR+NumOfHR)*2  ];
struct {// 3/4号 命令
u8  addr; //地址
u8  cmd; //命令
u16 shift; //偏移地址
u16 number;  //寄存器数量
u16 crc;    //校验
}msg_3_4;

struct{//16号命令
u8  addr; //地址
u8  cmd; //命令
u16 shift; //偏移地址
u16 number;  //寄存器数量
u8  bytecnt; //字节数量
u16 *data; //数据
//u16 crc;
}msg_16;
          //.....其他指令定义
}Buf;
u8  rcS; //超时计数
u16 rcIndex; //数据指针
bool rcOK; //接收完成
}uartRMsg; //接收缓冲区

//检测超时函数 供定时器中断调用-1ms一次
// t为超时时间
__inline void Chk_TimeOut(u8 t)
{
if(!uartRMsg.rcOK && (uartRMsg.rcIndex>=8) && (++uartRMsg.rcS >=t) ) //超时之后,开始重新解码
uartRMsg.rcOK = true;
}
//接收函数, 供USART中断调用
__inline void Recieve_MSG(char ch)

uartRMsg.rcS = 0;    //如果接收到数据,则清除超市检测计数,
if(!uartRMsg.rcOK)
{
uartRMsg.Buf.buf[uartRMsg.rcIndex ++] = ch;     //赋值
if(uartRMsg.rcIndex>=8 && uartRMsg.Buf.msg.cmd!=16)// 16号命令接收到的数据长度不是 固定的
uartRMsg.rcOK = true;
}
}

//供主函数调用
void MSGTransfer(void)
{

if(!uartRMsg.rcOK) return;
// if(uartRMsg.rcIndex<8) return;

if((uart_Address==uartRMsg.Buf.msg.addr) || (uartRMsg.Buf.msg.addr==0))//设备地址
{
WORD crc = CRC16(uartRMsg.Buf.buf ,
(uartRMsg.Buf.msg.cmd!=16)? 6 : (uartRMsg.Buf.msg_16_1.bytecnt + 7));
if(crc.Value != ((uartRMsg.Buf.msg.cmd!=16)? \
Message_R3R4.crc : \
(*(u16*)((u8*)uartRMsg.Buf.buf + uartRMsg.Buf.msg_16_1.bytecnt + 7 ))) )
{//CRC校验错误
uartRMsg.rcOK = false;
uartRMsg.rcIndex = 0;
return;
}

// if(uartRMsg.Buf.msg.addr==0) //广播地址
// {
// return;
// }

u16 shift,number;
shift = DATA_CHG_INT16(Message_R3R4.shift);
number= DATA_CHG_INT16(Message_R3R4.number);
SendBuf[0] = Message_R3R4.addr;
SendBuf[1] = Message_R3R4.cmd;

switch(Message_R3R4.cmd & 0xff ) //modbus命令
{
case 0: //
break;
case 1:   //读取线圈状态  
break;
case 2: //读取输入状态
break;  
case 3: //读取保持寄存器(标定数据)
case 4:   //读取输入寄存器(采样数据)

SendBuf[2] = number*2;

if((shift + number) <= ((Message_R3R4.cmd==3)?NumOfHR:NumOfIR))
{  
u8 *p = (u8*)(((Message_R3R4.cmd==3)?DatasOfBD.bufatasOfDT.buf) + shift*2);

for(int i=0; i< number; i++) //读取信息
{
SendBuf[3+ 2*i ] = p[2*i+1];
SendBuf[3+ 2*i+1] = p[2*i ];
}

crc.Value = 0xffff;
crc = CRC16(crc, SendBuf, 3 + number*2) ;
SendBuf[3 + number*2]=crc.cV[0] ;
SendBuf[4 + number*2]=crc.cV[1] ;

SendMessage(5 + number*2) ; 
}   
break;

case 5: //强制单线圈
break;
case 6:   //强制单个寄存器
DatasOfBD.Datas[shift] = number;
            EE.WriteByte(EE_BD_START + shift*2 + 0, DatasOfBD.buf[2*shift+0]);
            EE.WriteByte(EE_BD_START + shift*2 + 1, DatasOfBD.buf[2*shift+1]);

for(int i=2;i<8;i++)
SendBuf = uartRMsg.Buf.buf;
SendMessage(8);
break;
case 16:   //预置多个寄存器
if(shift + number < NumOfHR)
{
u16 *p =  (u16*)((u8*)uartRMsg.Buf.buf + 7); //数据起始地址
for(int i=0; i<number; i++)
{
DatasOfBD.Datas[shift+i] = DATA_CHG_INT16(p);
            EE.WriteByte(EE_BD_START + (shift+i)*2 + 0, DatasOfBD.buf[2*(shift+i)+0]);
            EE.WriteByte(EE_BD_START + (shift+i)*2 + 1, DatasOfBD.buf[2*(shift+i)+1]);
}

for(int i=2; i<6;i++)
SendBuf = uartRMsg.Buf.buf;
crc = CRC16(SendBuf, 6) ;
SendBuf[6]=crc.cV[0] ;
SendBuf[7]=crc.cV[1] ;
SendMessage(8);

}
break;
default:
break;
}
}
uartRMsg.rcOK = false;
uartRMsg.rcIndex = 0;
}


仅供参考
回复 支持 反对

使用道具 举报

36

主题

1263

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1612
金钱
1612
注册时间
2012-6-15
在线时间
39 小时
发表于 2013-3-21 13:39:24 | 显示全部楼层
中断里面处理的内容尽量要少
回复 支持 反对

使用道具 举报

36

主题

1263

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1612
金钱
1612
注册时间
2012-6-15
在线时间
39 小时
发表于 2013-3-21 13:49:33 | 显示全部楼层
对 了,  上述 是stm32 做从机的程序
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-21 22:10:37 | 显示全部楼层
回复【17楼】aleda303:
---------------------------------
10楼的大哥,我按照你的方法修改程序,怎么还是不能通信呀,在通信是我设置的触摸屏是主站, STM32是从站呀
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-21 22:28:47 | 显示全部楼层
回复【18楼】jason_chdsh:
---------------------------------
14楼的大哥,我在串口中断中使用send,是因为担心如果在发送中断时,发送数据没有全部发送,就把未发送完的数据继续发送完成,现在我的STM32程序如果和modbus OLL模拟软件通信,就能够很好的通信,但是如果和触摸屏通信时,触摸屏就接收不到数据了,触摸屏就会提示“设备没响应”,这个案子我已经搞了好久了,一直卡在了这个地方,老板已经催我了好多次了,搞得我头都大了。我想应该是我的定时T35和T15的定时有关,在这两个定时内,串口接收数据和发送数据处理的方法不对,但是我现在想不到好的方法怎么去处理,怎么办??
回复 支持 反对

使用道具 举报

36

主题

1263

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1612
金钱
1612
注册时间
2012-6-15
在线时间
39 小时
发表于 2013-3-22 11:24:16 | 显示全部楼层

用485 的时候要注意, 发送完成的时候 千万不要立即将 485芯片使能端置为输入 , 而是要一定的延时
否则 会丢数据!



//ModbusRTU发送信息
void MODBUS::SendMessage( int len)
{
#if MODBUS_USE_DMA //如果DMA模式发送
u8 t =10;
while(!this->TransOk && t--) //检测上次发送情况
delay_ms(1);
this->TransOk = false; //清除标志
DmaEn = false;
RS485_OUTPUT(); //置为输出
IO485_5_OUT();
mDMASendChanel->StartTransf(len); //开始发送
                //在DMA发送中断中 需调用定时器,周期2ms,定时器中断 置IO为输入状态

#else //非DMA模式
RS485_OUTPUT(); //置为输出
delay_us(1);
mUsart->SendHex(SendBuf,len); //发送数据
delay_ms(2); //延时等待发送完成
RS485_INPUT(); //置为输入
#endif
}

回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-22 13:08:26 | 显示全部楼层
回复【20楼】aleda303:
---------------------------------
我使用的是RS232串口,触摸屏和STM32都是使用的RS232,触摸屏做主站,STM32做从站,触摸屏就是接收不到STM32反馈回来的数据,不知道我的中断程序哪里出问题了,
回复 支持 反对

使用道具 举报

36

主题

1263

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1612
金钱
1612
注册时间
2012-6-15
在线时间
39 小时
发表于 2013-3-22 13:52:05 | 显示全部楼层
如果是RS232 的 就不需要延时了。 

触摸屏能装个串口监控软件吗, 

或者,你将你的串口的发送线和GND,接入另一根串口线到电脑里, 然后看看返回数据的格式正不正确
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-22 21:54:08 | 显示全部楼层
回复【22楼】aleda303:
---------------------------------
我做过实验,就是检查串口的发送端发送出来的数据,器数据和数据格式都不正确,再检查串口的接收端(其数据从触摸屏发出),其接收端的数据和数据格式都是正确的,我怀疑是我的定时器中断和串口中断的处理函数不对,在定时器中断中对T3.5个字符时间间隔和T1.5个字符时间间隔的处理不当,在接收到的数据帧间不小于T3.5个时间间隔和在字符间不大于T1.5个时间间隔的函数怎么编写?在串口中断中对接收到的数据和发送的数据处理函数不对,又应该怎么编写呢?
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-22 21:55:49 | 显示全部楼层
回复【23楼】jason_chdsh:
---------------------------------
我定义的通信格式是9600pbs, 8位数据,1位停止位
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-25 21:53:29 | 显示全部楼层
回复【24楼】jason_chdsh:
---------------------------------
该怎么办呢???有谁知道吗
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-27 12:11:47 | 显示全部楼层
回复【25楼】jason_chdsh:
---------------------------------
有谁用过吗??能给个例子吗
回复 支持 反对

使用道具 举报

32

主题

123

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
311
金钱
311
注册时间
2011-8-15
在线时间
33 小时
发表于 2013-3-27 17:17:16 | 显示全部楼层
回复【26楼】jason_chdsh:
---------------------------------
你这个貌似有点不对吧,触摸屏可以和modbus poll通信,说明触摸屏是从机程序,M32也是从机程序,2个从机不能通信
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-27 20:35:01 | 显示全部楼层
回复【27楼】abnerle:
---------------------------------
呵呵,搞错了,触摸屏可以和modbus slaver通信,STM32可以和modbus poll通信,但是触摸屏和STM32通信时(触摸屏做主站,STM32做从站),他们之间就没有办法通信了,我检查了我的STM32的程序,不知道是那个地方不对才造成无法通信的,知道的请帮我看看我的程序,到底是哪里的问题,拜托了
回复 支持 反对

使用道具 举报

1

主题

22

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2013-3-27
在线时间
0 小时
发表于 2013-3-28 09:30:11 | 显示全部楼层
用modbus先输入命令,计算好CRC校验,然后拷贝出来粘贴到串口调试程序,
然后和从站通讯,若成功,就是主站的问题,否则就是从站的接受有问题,
当年我就是这样调试modbus和modbus/tcp的,调试的时候,要知道你需要的结果
是什么样,一步一步来,就可以找到问题!
回复 支持 反对

使用道具 举报

22

主题

110

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
295
金钱
295
注册时间
2012-11-11
在线时间
24 小时
发表于 2013-3-28 09:51:52 | 显示全部楼层
回复【28楼】jason_chdsh:
---------------------------------
奇偶校验有没对,触摸屏通讯协议是奇校验还是偶校验,或者是无校验,不对也会通不上
回复 支持 反对

使用道具 举报

0

主题

35

帖子

0

精华

初级会员

Rank: 2

积分
122
金钱
122
注册时间
2013-1-30
在线时间
10 小时
发表于 2013-3-28 10:46:01 | 显示全部楼层
学习!!
回复 支持 反对

使用道具 举报

7

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
84
金钱
84
注册时间
2013-1-29
在线时间
4 小时
 楼主| 发表于 2013-3-28 21:12:34 | 显示全部楼层
回复【31楼】fayuanye:
---------------------------------
我让触摸屏和STM32分别和modbus模拟软件modbus slave和modbus poll通信,他们是可以通信的(波特率 数据位 CRC校验都是一样的),不就说明设置是没有问题的吗,但是如果让触摸屏和STM32做modbus通信,就没有办法通信了,搞不懂了,怎么会这样呀
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
22
金钱
22
注册时间
2012-11-17
在线时间
0 小时
发表于 2013-9-8 15:27:58 | 显示全部楼层
估计是楼主接收完一帧后等待另一帧数据的延时不对,两 帧数据的间隔要大于3.5个字节的传送时间,,如果你用的是9600的波特率,此时的延时时间为3.5*8/9600约为2.91ms,而不是你所延时的2ms.
回复 支持 反对

使用道具 举报

29

主题

92

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
228
金钱
228
注册时间
2013-5-4
在线时间
0 小时
发表于 2014-4-17 16:08:32 | 显示全部楼层
回复【13楼】fanghuiopenedv:
stm32发送数据配置是 9位数据,才是8位数据位一位停止位。我的modbus可以和威纶通的触摸屏通信。我成功了。要注意一点的是:触摸屏是主机,stm32得是从机。
---------------------------------
您好,我现在在学习STM32和威纶通的触摸屏通信,看到你的通信成功了想学习一下你的代码,可以吗
回复 支持 反对

使用道具 举报

30

主题

705

帖子

1

精华

新手上路

积分
21
金钱
21
注册时间
2013-3-14
在线时间
52 小时
发表于 2014-4-24 08:43:58 | 显示全部楼层
回复【34楼】lixulongren:
---------------------------------
void uart_init(u32 bound){
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);
     //USART1_TX   A.9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
   
    //USART1_RX   A.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);  

   //Usart1 NVIC 配置

    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//3 //先占优先级3级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //3

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器USART1

USART_InitStructure.USART_BaudRate = bound;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_Even;//USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART1, &USART_InitStructure);
   
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    USART_Cmd(USART1, ENABLE);
}

void USART1_IRQHandler(void)
{
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//接收中断
{
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
Res = USART_ReceiveData(USART1);

receTimeOut = 50;
receBuf[receCount] = Res;
receCount++;
    //receCount &= 0x0f;//16位缓冲限制
receCount &= 0x7f;//128位缓冲限制
 
    }
if(USART_GetITStatus(USART1, USART_IT_TXE) == SET) //TC=1发送完成
{
USART_ClearITPendingBit(USART1, USART_IT_TXE);
if(sendPosi < sendCount)
{
Res = USART_ReceiveData(USART1);
sendPosi++;
USART_SendData(USART1, sendBuf[sendPosi]);
}
else
{
receCount = 0;
checkoutError = 0;
USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
//MB_SerialEnable(TRUE,FALSE);
}


}
这个是我的串口配置。
原子哥是不是又要出黑科技了呀。^_^...
回复 支持 反对

使用道具 举报

29

主题

92

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
228
金钱
228
注册时间
2013-5-4
在线时间
0 小时
发表于 2014-4-29 09:45:43 | 显示全部楼层
回复【35楼】fanghuiopenedv:
---------------------------------
配置好串口后,威纶通的触摸屏是不是也要设置一下呢,该怎么设置啊,给个大致思路吧,还有你的这个串口代码看着和原子哥的串口函数没有区别吧?只不过是寄存器版本和库函数版本的区别吧
回复 支持 反对

使用道具 举报

30

主题

705

帖子

1

精华

新手上路

积分
21
金钱
21
注册时间
2013-3-14
在线时间
52 小时
发表于 2014-4-29 11:18:33 | 显示全部楼层
我用的是寄存器版本的。维伦通的设置和编写一下子也说不清楚的,可以去维伦通官网下载范例的modbus通信的范例。
原子哥是不是又要出黑科技了呀。^_^...
回复 支持 反对

使用道具 举报

29

主题

92

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
228
金钱
228
注册时间
2013-5-4
在线时间
0 小时
发表于 2014-4-30 16:52:49 | 显示全部楼层
回复【37楼】fanghuiopenedv:
我用的是寄存器版本的。维伦通的设置和编写一下子也说不清楚的,可以去维伦通官网下载范例的modbus通信的范例。
---------------------------------
我也用的寄存器版本的,能不能把你的代码发我看一下啊,我和师弟做了很久都没有完成,万分感谢啊
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
24
金钱
24
注册时间
2014-12-18
在线时间
0 小时
发表于 2014-12-18 21:35:23 | 显示全部楼层
回复【37楼】fanghuiopenedv:
---------------------------------
哥们,我最近也在做威纶通与stm32的通信啊,能否把代码发我看一看啊,搞了很久了也没搞好啊,万分感谢
回复 支持 反对

使用道具 举报

30

主题

705

帖子

1

精华

新手上路

积分
21
金钱
21
注册时间
2013-3-14
在线时间
52 小时
发表于 2014-12-19 17:07:48 | 显示全部楼层
回复【39楼】lin1408:
---------------------------------
你可以去维伦通官网下载modbus通信的范例
原子哥是不是又要出黑科技了呀。^_^...
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
24
金钱
24
注册时间
2014-12-18
在线时间
0 小时
发表于 2014-12-19 21:48:52 | 显示全部楼层
回复【40楼】fanghuiopenedv:
---------------------------------
好的,谢谢,我找到了一个与51单片机通信的实例╰( ̄▽ ̄)╮
回复 支持 反对

使用道具 举报

30

主题

705

帖子

1

精华

新手上路

积分
21
金钱
21
注册时间
2013-3-14
在线时间
52 小时
发表于 2014-12-20 10:49:10 | 显示全部楼层
回复【41楼】lin1408:
---------------------------------
我也是从51上的代码修改的。就是多加了个MB_SerialEnable(TRUE,FALSE);   开关串口收发的函数。
原子哥是不是又要出黑科技了呀。^_^...
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
24
金钱
24
注册时间
2014-12-18
在线时间
0 小时
发表于 2015-1-3 19:30:53 | 显示全部楼层
回复【42楼】fanghuiopenedv:
---------------------------------
大神,我移植到stm32上却一直没法通信,我看51示例代码中并没有设置帧与帧之间3.5个字节的间隔,请问是不是因为这个原因没法通信呢,是不是要在程序中自己加上判断开头的程序呢
回复 支持 反对

使用道具 举报

30

主题

705

帖子

1

精华

新手上路

积分
21
金钱
21
注册时间
2013-3-14
在线时间
52 小时
发表于 2015-1-4 15:41:47 | 显示全部楼层
回复【43楼】lin1408:
---------------------------------
应该不是帧与帧之间的问题。估计是你没有处理好打开接收和关闭接收。
给你看下我的函数吧:
//检查uart0数据
void checkComm0Modbus(void)
{
u16 crcData;
u16 tempData;
if(receCount > 4)
{
switch(receBuf[1])
{
case 1: //读取线圈状态(读取点 16位以内) 
case 2: //读离散输入
case 3: //读取保持寄存器(一个或多个)
      case 4:                     //读离散输入寄存器
case 5: //强制单个线圈 
case 6: //设置单个寄存器
if(receCount >= 8)
{ //接收完成一组数据
//应该关闭接收中断
MB_SerialEnable(FALSE,TRUE);
if(receBuf[0]==localAddr && checkoutError==0)
{
crcData = crc16(receBuf,6);
if(crcData == receBuf[7]+(receBuf[6]<<8))
{ //校验正确
if(receBuf[1] == 1)
{ //读取线圈状态(读取点 16位以内)
//MB_SerialEnable(FALSE,TRUE);
readCoil();
}
else if(receBuf[1] == 2)
{
//MB_SerialEnable(FALSE,TRUE);
readinput();
}
else if(receBuf[1] == 3)
{ //读取保持寄存器(一个或多个)
//MB_SerialEnable(FALSE,TRUE);
readRegisters();
}
else if(receBuf[1] == 4)
{
//MB_SerialEnable(FALSE,TRUE);
readinputRegisters();
}
else if(receBuf[1] == 5)
{ //强制单个线圈
//MB_SerialEnable(FALSE,TRUE);
forceSingleCoil();
}
else if(receBuf[1] == 6)
{
//MB_SerialEnable(FALSE,TRUE);
presetSingleRegister();
}
}
}
receCount = 0;
checkoutError = 0;
//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//MB_SerialEnable(TRUE,FALSE);
MB_SerialEnable(TRUE,TRUE);
}
break;
case 15: //设置多个线圈
tempData = receBuf[6]; 
tempData += 9; //数据个数
if(receCount >= tempData)
{
//MB_SerialEnable(FALSE,TRUE);
if(receBuf[0]==localAddr && checkoutError==0)
{
crcData = crc16(receBuf,tempData-2);
if(crcData == (receBuf[tempData-2]<<8)+ receBuf[tempData-1])
{

forceMultipleCoils();
}
}
receCount = 0;
checkoutError = 0;
//MB_SerialEnable(TRUE,FALSE);
MB_SerialEnable(TRUE,TRUE);
}
break;
case 16: //设置多个寄存器
tempData = (receBuf[4]<<8) + receBuf[5];
tempData = tempData * 2; //数据个数
tempData += 9;
if(receCount >= tempData)
{
//MB_SerialEnable(FALSE,TRUE);//
if(receBuf[0]==localAddr && checkoutError==0)
{
crcData = crc16(receBuf,tempData-2);
if(crcData == (receBuf[tempData-2]<<8)+ receBuf[tempData-1])
{

presetMultipleRegisters();
}
}
receCount = 0;
checkoutError = 0;
//MB_SerialEnable(TRUE,FALSE);
MB_SerialEnable(TRUE,TRUE);
}
break;
default:
break;
}
}
}//void checkComm0(void)
原子哥是不是又要出黑科技了呀。^_^...
回复 支持 反对

使用道具 举报

30

主题

705

帖子

1

精华

新手上路

积分
21
金钱
21
注册时间
2013-3-14
在线时间
52 小时
发表于 2015-1-4 15:44:17 | 显示全部楼层
回复【43楼】lin1408:
---------------------------------
void MB_SerialEnable(u8 Rx_Enable, u8 Tx_Enable)
{
if(TRUE==Rx_Enable)
{
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
}
else
{
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
}
if(TRUE==Tx_Enable)
{
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
}
else
{
    USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
}
}
原子哥是不是又要出黑科技了呀。^_^...
回复 支持 反对

使用道具 举报

0

主题

4

帖子

0

精华

新手入门

积分
24
金钱
24
注册时间
2014-12-18
在线时间
0 小时
发表于 2015-1-5 22:01:19 | 显示全部楼层
回复【45楼】fanghuiopenedv:
---------------------------------
谢谢啊!您的这个checkComm0Modbus()的函数跟源码中的功能码处理函数command()功能是一样的把,我今天试了在其中加入串口开关还是不行啊,我从元旦调到现在都没调出来(┬_┬),请问能否把您的完整代码发给我学习一下呢(zlin90@126.com),我只是用于导师给我的一个任务,绝对不外传,万分感谢啊!
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-22 20:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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