⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 单片机c语言程序设计100例--基于PIC+PROTEUS
💻 C
字号:
//-----------------------------------------------------------------
//  名称: MODBUS总线通信仿真(主机程序)
//-----------------------------------------------------------------
//  说明: 本例运行时,主机向各从机发送要求返回A/D转换值的命令码,在主机
//        完整接收到从机A/D数据后,在液晶上刷新显示.
//
//-----------------------------------------------------------------
#define INT8U  unsigned char
#define INT16U unsigned int
#define INT32U unsigned long
#include <pic.h>
#include <stdio.h>
#include "LM041_4BIT.h"
const char* Prompts[17] = 
{
  "****************",
  " RS-485  MODBUS ",
  "  TEST PROGRAM  ",
  "****************"
};
volatile INT8U recv_Data[6];           //串口接收数据缓冲区(6字节)
volatile INT8U recv_idx = 0;           //串口接收数据缓冲区索引
volatile INT8U sl_Addr;                //485从机地址
INT8U  LCD_Buffer[16];                 //LCD显示缓冲             
INT16U CRC;                            //16位CRC校验结果
//-----------------------------------------------------------------
#define  LED_Recv  RB6                 //主机接收指示灯
#define  LED_Send  RB7                 //主机发送指示灯
#define  RDE_485   RC5                 //RS485通信控制端
#define  ADC_REQ   65                  //要求从机返回A/D值的自定义命令码(范围65~72)
//19200波特率每字符时间为: 1/19200*(1+8+2) ≈  572us
//帧  间: 3.5个字符时间为: 572 * (3.5 + 1) ≈ 2574us
//字节间: 1.5个字符时间为: 572 * (1.5 + 1) ≈ 1430us
#define FRAME_SPAN  2574                  //相临帧之间的间隔时间
#define BYTE_SPAN   1430                  //帧内字节之间的间隔时间
bit     b, F_T1, T_BYTE, T_FRAME, Recv_OK;//相关标识位
//-----------------------------------------------------------------
// 宏定义: 发送一字节并等待发送结束
//-----------------------------------------------------------------
#define Send_Byte(x)                  \
{                                     \
    LED_Send = 1; RDE_485 = 1;        \
    TXREG = x; while (TRMT == 0);     \
    __delay_us(9); LED_Send = 0;      \
}

//-----------------------------------------------------------------
// 宏定义: 设置TIMER1的定时初值并设相关标志位
//-----------------------------------------------------------------
#define Set_TIMER1(x)                \
{                                    \
   TMR1H = (65536 - x) >> 8;         \
   TMR1L = (65536 - x) & 0x0F;       \
   TMR1IF = T_BYTE = T_FRAME = 0;    \
   F_T1 = (x == FRAME_SPAN) ? 1 : 0; \
   if (F_T1) recv_idx = 0;           \
}

//-----------------------------------------------------------------
// 串口初始化
//-----------------------------------------------------------------
void Serial_port_init()
{
    SYNC = 0;                            //选择异步通信模式
    BRGH = 1;                            //选择高速波特率发生模式
    TXEN = 1;                            //允许发送数据
    SPBRG = _XTAL_FREQ/16/19200 - 1;     //设置波特率为19200  
    SPEN = 1;                            //串行通信端口打开
    CREN = 1;                            //使能连续接收串行数据
}

//-----------------------------------------------------------------
// 外设初始化(定时器,485等)
//-----------------------------------------------------------------
void Per_Initialize()
{   


}

//-----------------------------------------------------------------
// CRC16校验函数 (基于该函数可得出512字节的校验码表,改用查表法进行校验)
// 多项式: X ^ 16 + X ^ 15 + X ^ 2 + 1, 去高位逆序表示:0xA001
//-----------------------------------------------------------------
void CRC16(INT8U d)
{


}

//-----------------------------------------------------------------
// 主程序     
//-----------------------------------------------------------------
void main()
{
    INT8U i; INT32U  ADC_Result;
    __delay_ms(100);      //等待足够时间,待从机完成初始化
    Per_Initialize();     //外设初始化
    LCD_Initialize();     //LCD初始化
    //输出系统封面文字(4行)




    //延时10*100ms
    i = 10; while (i--) __delay_ms(100);
    ClearScreen();//清屏
    //显示液晶上两行文字
    LCD_ShowString(0,0,(char*)"   A/D Display   ");  
    LCD_ShowString(1,0,(char*)"-----------------"); 
    while(1)
    {  
        //---------------------------------------------------------
        // 循环访问地址为0x01~0x04的4个485从机
        //---------------------------------------------------------
        for (sl_Addr = 0x01; sl_Addr <= 0x04; sl_Addr++)
        {   
           



        }
        __delay_ms(10); //每完成一轮(4个从机)扫描后等待10ms
    }
}

//-----------------------------------------------------------------
// 主机定时中断及485接收中断服务程序
//-----------------------------------------------------------------
void interrupt ISR()
{  
    INT8U R;
    //----------------------TIMER1定时器溢出中断--------------------
    if (TMR1IF)
    {   TMR1IF = 0;
        //F_T1: 标识TIMER1定时器当前用于实现帧间隔时间定时还时字节间隔时间定时
        //F_T1 = 0时,将帧间隔时间(3.5字符)到达设为假,字节间隔时间到达设为真
        //F_T1 = 1时,将帧间隔时间(3.5字符)到达设为真,字节间隔时间到达设为假



    
    }
    //-------------------------串口接收中断-------------------------
    if (RCIF)
    {   
        LED_Recv = ~LED_Recv;                   //主机接收指示灯闪烁
        R = RCREG;                              //从串口(来自485)读取一字节
        RCIF = 0;                               //清标志位(此行可省略)
        Recv_OK = 0;                            //先暂时设接收成功标志为假
        //---------------------------------------------------------
        //如果当前要接收的是第0字节
        if (recv_idx == 0) 
        {   




        }
        //---------------------------------------------------------
        //否则要接收的是第0字节(即地址字节)之后的数据
        else 
        {  


        }
        //---------------------------------------------------------
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -