?? main.c
字號:
//-----------------------------------------------------------------
// 名稱: MODBUS總線通信仿真(主機(jī)程序)
//-----------------------------------------------------------------
// 說明: 本例運行時,主機(jī)向各從機(jī)發(fā)送要求返回A/D轉(zhuǎn)換值的命令碼,在主機(jī)
// 完整接收到從機(jī)A/D數(shù)據(jù)后,在液晶上刷新顯示.
//
//-----------------------------------------------------------------
#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]; //串口接收數(shù)據(jù)緩沖區(qū)(6字節(jié))
volatile INT8U recv_idx = 0; //串口接收數(shù)據(jù)緩沖區(qū)索引
volatile INT8U sl_Addr; //485從機(jī)地址
INT8U LCD_Buffer[16]; //LCD顯示緩沖
INT16U CRC; //16位CRC校驗結(jié)果
//-----------------------------------------------------------------
#define LED_Recv RB6 //主機(jī)接收指示燈
#define LED_Send RB7 //主機(jī)發(fā)送指示燈
#define RDE_485 RC5 //RS485通信控制端
#define ADC_REQ 65 //要求從機(jī)返回A/D值的自定義命令碼(范圍65~72)
//19200波特率每字符時間為: 1/19200*(1+8+2) ≈ 572us
//幀 間: 3.5個字符時間為: 572 * (3.5 + 1) ≈ 2574us
//字節(jié)間: 1.5個字符時間為: 572 * (1.5 + 1) ≈ 1430us
#define FRAME_SPAN 2574 //相臨幀之間的間隔時間
#define BYTE_SPAN 1430 //幀內(nèi)字節(jié)之間的間隔時間
bit b, F_T1, T_BYTE, T_FRAME, Recv_OK;//相關(guān)標(biāo)識位
//-----------------------------------------------------------------
// 宏定義: 發(fā)送一字節(jié)并等待發(fā)送結(jié)束
//-----------------------------------------------------------------
#define Send_Byte(x) \
{ \
LED_Send = 1; RDE_485 = 1; \
TXREG = x; while (TRMT == 0); \
__delay_us(9); LED_Send = 0; \
}
//-----------------------------------------------------------------
// 宏定義: 設(shè)置TIMER1的定時初值并設(shè)相關(guān)標(biāo)志位
//-----------------------------------------------------------------
#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; //選擇高速波特率發(fā)生模式
TXEN = 1; //允許發(fā)送數(shù)據(jù)
SPBRG = _XTAL_FREQ/16/19200 - 1; //設(shè)置波特率為19200
SPEN = 1; //串行通信端口打開
CREN = 1; //使能連續(xù)接收串行數(shù)據(jù)
}
//-----------------------------------------------------------------
// 外設(shè)初始化(定時器,485等)
//-----------------------------------------------------------------
void Per_Initialize()
{
}
//-----------------------------------------------------------------
// CRC16校驗函數(shù) (基于該函數(shù)可得出512字節(jié)的校驗碼表,改用查表法進(jìn)行校驗)
// 多項式: X ^ 16 + X ^ 15 + X ^ 2 + 1, 去高位逆序表示:0xA001
//-----------------------------------------------------------------
void CRC16(INT8U d)
{
}
//-----------------------------------------------------------------
// 主程序
//-----------------------------------------------------------------
void main()
{
INT8U i; INT32U ADC_Result;
__delay_ms(100); //等待足夠時間,待從機(jī)完成初始化
Per_Initialize(); //外設(shè)初始化
LCD_Initialize(); //LCD初始化
//輸出系統(tǒng)封面文字(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)
{
//---------------------------------------------------------
// 循環(huán)訪問地址為0x01~0x04的4個485從機(jī)
//---------------------------------------------------------
for (sl_Addr = 0x01; sl_Addr <= 0x04; sl_Addr++)
{
}
__delay_ms(10); //每完成一輪(4個從機(jī))掃描后等待10ms
}
}
//-----------------------------------------------------------------
// 主機(jī)定時中斷及485接收中斷服務(wù)程序
//-----------------------------------------------------------------
void interrupt ISR()
{
INT8U R;
//----------------------TIMER1定時器溢出中斷--------------------
if (TMR1IF)
{ TMR1IF = 0;
//F_T1: 標(biāo)識TIMER1定時器當(dāng)前用于實現(xiàn)幀間隔時間定時還時字節(jié)間隔時間定時
//F_T1 = 0時,將幀間隔時間(3.5字符)到達(dá)設(shè)為假,字節(jié)間隔時間到達(dá)設(shè)為真
//F_T1 = 1時,將幀間隔時間(3.5字符)到達(dá)設(shè)為真,字節(jié)間隔時間到達(dá)設(shè)為假
}
//-------------------------串口接收中斷-------------------------
if (RCIF)
{
LED_Recv = ~LED_Recv; //主機(jī)接收指示燈閃爍
R = RCREG; //從串口(來自485)讀取一字節(jié)
RCIF = 0; //清標(biāo)志位(此行可省略)
Recv_OK = 0; //先暫時設(shè)接收成功標(biāo)志為假
//---------------------------------------------------------
//如果當(dāng)前要接收的是第0字節(jié)
if (recv_idx == 0)
{
}
//---------------------------------------------------------
//否則要接收的是第0字節(jié)(即地址字節(jié))之后的數(shù)據(jù)
else
{
}
//---------------------------------------------------------
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -