STM32做从机之modbus rtu接收

STM32做从机之modbus rtu接收

  •  STM32中的RS485:

      在STM32中采用RS485,因为STM32的串口输出为全双工,输出电压为3.3V或0V,而RS485为半双工,需要甚至-6V到+6V的电压,因此STM32串口的数据不能直接通过RS485进行递。因此在使用过程中,常常通过485芯片来对电平进行转换。例如SP3485或MAX3485等芯片。
     485芯片中,和STM32相连的有一个发送引脚、一个输出引脚、和一个使能引脚,当使能引脚为0时,485此时为接收态,AB中的压差会作为数据发送给STM32。当使能引脚为1时,485为发送态,STM32发送的数据会改变AB线的压差。

  • Modbus简介:

      ModbusRTU是一种主从通讯模式的通讯协议,也就是说,Modbus有一个主机,可以进行通讯的主动要求,其他从机只能对主机进行响应而不能主动发送数据到通讯总线中。这种方法规定了通讯过程中的通讯次序等关系,避免了多个设备同时工作的情况下通讯冲突的产生。
Modbus协议不规定一个字节如何传输,而是规定如何进行一次数据帧的传输。数据帧可以理解为若干个具有特殊功能意义的字节的组合。那么Modbus如何定义一个数据帧?对于Modbus来说,当进行数据传输过程中,出现空闲时间超过3.5个字节持续时间,就认为一次数据帧的结束,之前接收到的字节就是这次数据帧的所有字节。之后再接收到的字节则为下一个数据帧的字节。例如,在9600bit/s的传输速率下,一个字节传输的时间约为0.8ms,那么当数据传输中,出现约3ms的空闲时间时,设备就认为一帧数据接收完成。
     每一帧数据要实现功能,传递信息,就需要通讯双方采用相同的语法规则,因此对于每个数据帧的构成,Modbus进行了一些规定,例如一个主机发送的具有寄存器读取功能的数据帧,其组成为:

 

 

STM32做从机之modbus rtu接收_第1张图片

具体可以去参照modbus的手册。

  • 代码的总体框架:

           STM32实现RS485的Modbus通讯过程。我们会用到STM32的串口功能(用于收发数据)、I/O功能(用于使能和失能485的收发)、定时器功能(用于对接收的数据的间隔进行计时,以判断数据帧是否接收完成)、CRC功能(进行CRC校验)以及Modbus的服务函数。
    整体的代码框架为:如果STM32作为从机,在进行串口初始化后,通过I/O使485常态处于接收态,并采用串口中断读取接收到的每一个字节,在每次接收字节时,开启计时器,如果计时器计时溢出,表明时间间隔大于3.5个字节接收时间,即一帧接收完成,此时进入计时器中断服务函数,再进行Modbus的处理函数。Modbus的处理函数首先会判断数据是否接收完成,再判断设备是否是该设备(也就是设备地址),如果不是就跳出程序(如果有需要,可以自行完善)。如果是,则会进行CRC校验,校验通过后,就进入到对应的功能服务函数。如果CRC校验不正确,这里没有写,有需要可以自行完善。
          当STM32需要发送数据时,先把485置于发送态,然后通过串口发送数据即可。

1.串口以及485的初始化部分

//初始化IO 和串口3
//pclk1:PCLK1时钟频率(Mhz)
//bound:波特率      
void RS485_Init(u32 pclk1,u32 bound)//485初始化
{
    
    float temp;//临时变量
    u16 mantissa;//整数
    u16 fraction;       //小数
    temp=(float)(pclk1/2*1000000)/(bound*16);//得到USARTDIV=
    mantissa=temp;                 //得到整数部分
    fraction=(temp-mantissa)*16; //得到小数部分     
    mantissa<<=4;//高四位
    mantissa+=fraction; //得到波特率
    
    RCC->APB2ENR|=1<<2;       //使能PORTA口时钟 ,15 
     GPIOA->CRH&=0X0FFFFFFF;    //IO状态设置
    GPIOA->CRH|=0X30000000;    //IO状态设置      
 
    RCC->APB2ENR|=1<<3;       //使能PORTB口时钟  
    GPIOB->CRH&=0XFFFF00FF;    //IO状态设置
    GPIOB->CRH|=0X00008B00;    //IO状态设置      

    RCC->APB1ENR|=1<<18;      //使能串口时钟       
    RCC->APB1RSTR|=1<<18;   //复位串口3
    RCC->APB1RSTR&=~(1<<18);//停止复位              
    //波特率设置
     USART3->BRR=mantissa;     // 波特率设置     。USART3->BRR波特率寄存器
    USART3->CR1|=0X200C;      //1位停止,无校验位.USART3->CR1控制寄存器,使能发送或接收

#ifdef EN_USART3_RX              //如果使能了接收
    //使能接收中断
    USART3->CR1|=1<<8;        //PE中断使能
    USART3->CR1|=1<<5;        //接收缓冲区非空中断使能            
    MY_NVIC_Init(3,3,USART3_IRQn,2);//组2,最低优先级 
    
#endif
    RS485_TX_EN=0;            //默认为接收模式    
    //SYS_LED =!SYS_LED;
    //Test();
}

2.串口中断服务函数

STM32做从机之modbus rtu接收_第2张图片

3.定时器初始化函数

STM32做从机之modbus rtu接收_第3张图片

4.定时器中断服务函数

STM32做从机之modbus rtu接收_第4张图片

5.MODBUS的处理函数

STM32做从机之modbus rtu接收_第5张图片

STM32做从机之modbus rtu接收_第6张图片

7.CRC校验

STM32做从机之modbus rtu接收_第7张图片

这里只有03和06,有需要者可以对应modbus的手册进行程序的填写

你可能感兴趣的:(stm32系列,stm32,嵌入式)