📄 main.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 + -