STM32-modbus rtu 之从机程序

xiaoxiao2021-02-27  275

STM32-modbus rtu 之从机程序

以前移植过freemodbus,这次是自己重新写,只实现保持寄存器的读写。

一、串口

这部分跟上一篇文章主机程序一样,DMA接收,直接发送。

二、错误反馈

/* 发送 错误反馈 */ void  mb_sentACK( u8 cm,u8 err) {     u16 temp;     serialTXbuf_st.buf[0] = local_addr;     serialTXbuf_st.buf[1] = cm+0x80;     serialTXbuf_st.buf[2] =  err;     temp=usMBCRC16(  serialTXbuf_st.buf,  3 );     serialTXbuf_st.buf[3] = temp;    //低     serialTXbuf_st.buf[4] = temp>>8; } 错误码为命令F+0X80

三、对 F=0X03的反馈

/* 回应 读保持寄存器,命令0X03 */  void  mb_sentfor_readHoldingReg(const _mbdata_st mbd) {     u16 temp;     u8 len = mbd.len*2+5;     serialTXbuf_st.buf[0] = local_addr;     serialTXbuf_st.buf[1] = 0x03;     serialTXbuf_st.buf[2] = mbd.len*2;     /*用户数据*/     for(temp=0;temp< (len-5)/2;temp++)     {         serialTXbuf_st.buf[3+temp*2] = mbd.buf[mbd.start+temp] >>8;         serialTXbuf_st.buf[4+temp*2] = mbd.buf[mbd.start+temp] ;     }     temp=usMBCRC16(  serialTXbuf_st.buf,  len-2 );     serialTXbuf_st.buf[len-2] = temp;    //低     serialTXbuf_st.buf[len-1] = temp>>8;     myUSART_Sendarr(  USART1,   serialTXbuf_st.buf , len) ;       while( (USART1->SR&0X40)==0 ); //等待发送完成  }

四、对F=0X10的反馈

/* 回应 写保持寄存器,命令0X10 */ void  mb_sentfor_writeHoldingReg( _mbdata_st *pmb) {     u16 temp;     u8 i;     temp=usMBCRC16(  serialRXbuf_st.buf,  6 );     serialTXbuf_st.buf[0]=temp;     serialTXbuf_st.buf[1]=temp>>8;     //发送8字节反馈     myUSART_Sendarr(  USART1,   serialRXbuf_st.buf ,  6) ; //前6字节      myUSART_Sendarr(  USART1,   serialTXbuf_st.buf ,  2) ; //CRC     //修改保持寄存器     for(i=0;i< pmb->len ;i++)     {        pmb->buf [ pmb->start +i] = (u16)(serialRXbuf_st.buf[i*2+7]<<8 ) + serialRXbuf_st.buf[i*2+8];     }     while( (USART1->SR&0X40)==0 ){}; //等待发送完成  }

五、接收处理

/*帧检测*/ u8 frm_cheak(_serialbuf_st *rx, _mbfrm_st *pfrm) {     u16 t,len;     if( rx->len < 4   ) return res_ERR1;     len=rx->len;     rx->len = 0 ;          pfrm->addr=rx->buf[0];     if( pfrm->addr != local_addr ) return res_ERR2;     pfrm->crc= (u16)(rx->buf[ len-1]<<8) + (rx->buf[ len-2]) ;     t= usMBCRC16( rx->buf,  len-2 );     if( pfrm->crc !=  t ) return  res_ERR3;     pfrm->cmd=rx->buf[1];      pfrm->start=( u16)(rx->buf[2] <<8 ) + rx->buf[3] ;     pfrm->rlen= ( u16)(rx->buf[4] <<8 ) + rx->buf[5] ;     if( pfrm->start > 0x7d) return res_ERR4;//超出地址     if( pfrm->rlen + pfrm->start > 0x7d) return res_ERR5;//超出长度     return res_OK; } //接收  u8 smb_recvHoldingReg( _mbdata_st *pmb  ) {     u8 rel;     u16 temp ;     _mbfrm_st frm;          rel=frm_cheak( &serialRXbuf_st , &frm);     if( rel == res_OK)     {         mb_setMODRXorTX(0);//转为发送模式         //延时,给主机准备时间         delay_ms(10);         pmb->len =  frm.rlen;         pmb->start =  frm.start;         switch( frm.cmd)         {         case 0x03://读寄存器             mb_sentfor_readHoldingReg( *pmb );         break ;         case 0x10://写寄存器             mb_sentfor_writeHoldingReg( pmb);         break ;         }         mb_setMODRXorTX(0);//转为接收模式     }     else      if(rel == res_ERR3)     {        mb_sentACK(  frm.cmd ,  rel) ;     }     return rel;  } /*主循环调用*/ void mb_poll() {    smb_recvHoldingReg( &HoldingReg_st  ) ; } 在主循环里调用mb_poll()函数即可。

六、验证

将STM32的串口与电脑连接,打开PC端软件MODBUS POLL ,设置好参数,OK,如下图

F=0X03

F=0X10

转载请注明原文地址: https://www.6miu.com/read-10167.html

最新回复(0)