基于modbus的UART通信2

/*********************************************************************************************************************************

单片机:dspic33FJ128GP206
通信波特率:9600
字符数据格式:1位起始位 8位数据  1位偶校验 1位停止位
帧间最小间隔:3.5个字符
RTU报文帧格式:
   <-------------------------------------------------- MODBUS RTU -------------------------------------------------------->
                   <----------------------------- MODBUS PDU ------------------------>
   +-----------+--------------------+----------------------------------------------------+---------------------------------------+
   | Address   | Function Code | Data(Start Address/Length/Content)        | CRC                                         |
   +-----------+--------------------+----------------------------------------------------+---------------------------------------+
   |                |                          |                                                                  |
   (1byte)     (1byte)                (0-252bytes,8*N bits)                               (2bytes,CRC低|CRC高)

编程思路:
    1.当单片机接收到来自PC机的数据后,进入串口中断,缓存接收到的数据,同时开启并刷新定时器。当没有接收到数据(或者接收完毕)后,跳出串口中断,同时定时器开始计时:若超过3.5个字符时间单片机仍没有接收到新数据,则认为本次接收完成,将接收完成标志置1;若在3.5个字符时间内又接收到新数据,则再次进入串口中断,重复上述操作。

    2.当接收完成标志置1进入接收数据处理:

    (1)首先判断接收的第1个数据(1个字节)与本机地址是否相同,如果不相同不发送任何信息;

    (2)如果接收的第1个数据与本机地址相同,则对接收缓存中的数据进行crc16校验,如果接收的校验数据与本校验结果不相同,同样不发送任何信息;

    (3)如果crc16校验正确则根据数据串中的功能码进行相应的处理。
****************************************************************************************************************************************/

//=========================================头文件引用=================================
#include "modbus.h"
#include "p33FJ128GP206.h"
#include "uart.h"

//==========================================常量定义==================================

#define  BAUDRATE  9600                                     //设置串口1的波特率
#define  FCY    8000000                                        //器件工作速度为8MHz
#define     BRGVAL       ((FCY/16)/BAUDRATE)-1 //设置波特率发生器  

//=========================================初始化振荡器================================
void Init_osc(void)
{
CLKDIVbits.PLLPRE = 0;              //预分频因子为2
CLKDIVbits.PLLPOST = 0;           //后分频因子为2
PLLFBDbits.PLLDIV = 0x00E;      //倍频因子为16
                                                     //晶振频率为4MHz,则振荡器频率为4MHz×16/(2*2)=16MHz,
                                                     //器件工作速度为16MHz/4=8MHz
}

//=========================================初始化串口1==================================
void  Init_uart1(void)
{
U1BRG = BRGVAL;                          //设置波特率发生器  

U1MODEbits.STSEL = 0;                 //1位停止位
U1MODEbits.PDSEL = 1;                 //8位数据,偶校验

IFS0bits.U1RXIF = 0;                       //清除接收中断标志位
IEC0bits.U1RXIE = 1;                      //使能接收中断
IPC2bits.U1RXIP = 4;                      //设置接收中断优先级
U1STAbits.URXISEL = 0;                //接收到1个字符中断标志位置位

IFS0bits.U1TXIF = 0;                      //清除发送中断标志位
IEC0bits.U1TXIE = 0;                     //禁止发送中断

U1MODEbits.UARTEN = 1;            //使能串口
U1STAbits.UTXEN = 1;                  //使能串口发送
}

//========================初始化定时器1===============================================
// 根据波特率和数据位数,可以计算出接收 1 个字符所占用的时间:

//   Char_Time_Value =  11 / Baudrate  =  1145.833 us

//  根据RTU MODBUS规范,报文帧由时长至少为 3.5 个字符时间的空闲间隔区分,因此

//   Frame_Interval_Value_Min = ChTimeValue * 3.5 = 4011us

//  为保证传送数据的可靠性,这里将帧间最小距离设置为 2 倍的规定时长,即

//  4011us * 2 = 8022us


void Init_timer1(void)
{
T1CONbits.TON = 0;       //停止定时器
T1CONbits.TCKPS = 1;  //设置T1的预分频比是8,即T1加一次需要的时间为1/(8M/8)秒,即1uS
TMR1 = 0;                      //定时器寄存器清零
PR1 = 8022;                  //装载定时器周期值,从0开始计数,加到PR1时产生中断
IEC0bits.T1IE = 1;         //使能中断 
IPC0bits.T1IP = 4;         //设置中断优先级
}

//====================================主函数==========================================
void main(void)
{
Init_osc();                         //初始化振荡器
Init_uart1();                      //初始化串口1
Init_timer1();                     //初始化定时器1
   while (1)                         //死循环
   {
  Com1_Communication(); //串口通信
}
}

你可能感兴趣的:(基于modbus的UART通信2)