📄 c8051f340-modbus.c
字号:
//modbus通信协议实现
//
#include <c8051f340.h>
#include <intrins.h>
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define BaudRate 19200//9600,14400,19200,38400,56000可选
#define SYSCLK 12000000
//#define BAUDRATE 9600
//#define SYSCLK 11059200
sbit GREEN = P2^2;
sbit RED = P2^1;
sbit PF = P2^0;
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
#define u16 unsigned int
#define u8 unsigned char
#define MAXNByte 15 //最大字节数
//#define time0 30000
#define MAXREG 100 //最大寄存器数量
//void SYSCLK_Init (void);
void PORT_Init (void); //IO口初始化
void UART0_Init (void); //uart0初始化
void readRegisters(void) ;//读寄存器,功能码03
void beginSend(void) ; //发送子程序
void presetMultipleRegisters(void);//设置多个寄存器,功能码16
void FLASH_ByteWrite(u16 addr, u8 byte);//flash写
void FLASH_PageErase (u16 addr); //flash页擦写
//void Receive_timeout(void); //超时子程序
u16 crc_chk(u8 *dat,u8 length); //CRC校验
u8 FLASH_ByteRead (u16 addr); //flash读
//void presetSingleRegisters(void); //设置单个寄存器,功能码06
void send_err(u8 err,u8 err_code); //发送错误
void Timer0_Init(void); //定时器0初始化
void PCA_Init();
u16 flag;
u8 temp;
u8 count_receiveNByte;//接收字节数
u8 mod_buf[20]; //modubs 数据接收缓冲区
u8 sendBuf[20]; //发送缓冲区
u8 sendCount; //发送字节数
u8 localAddr = 3; //单片机控制板的地址
//u16 Receivetimeout; //定时初值
//bit ReceiveBit;
//unsigned int code baud_code[8] = {};
/*?????*/
/*void delay(unsigned int m)
{
unsigned int n;
n=0;
while(n < m)
{n++;}
return;
} */
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main(void)
{
u16 dat;
u16 tempData;
u16 crcData;
PCA0MD &= ~0x40;
OSCICN |= 0x03;
//SYSCLK_Init ();
PORT_Init ();
UART0_Init ();
PCA_Init();
// Timer0_Init();
EA=1;
ES0=1;
PS0=1;
GREEN=1;
RED=0;
while(1){
if (mod_buf[0]==localAddr)
{
if(count_receiveNByte>4)
{
switch(mod_buf[1])
{
case 0x03:
if(count_receiveNByte>=8)
{
crcData = crc_chk(mod_buf,6); //CRC校验
dat=mod_buf[7];
if(crcData==mod_buf[6]+(dat<<8)) //CRC校验结果比较
readRegisters(); // 如果检验正确,那么就回应数据
count_receiveNByte=0; //接受数据指针归零
}
break;
/* case 0x06:
if(count_receiveNByte>=8)
{
crcData = crc_chk(mod_buf,6); //CRC校验
dat=mod_buf[7];
if(crcData==mod_buf[6]+(dat<<8)) //CRC校验结果比较
presetSingleRegisters();
count_receiveNByte=0; //接受数据指针归零
}
break;*/
case 0x10:
dat=mod_buf[4];
tempData = (dat<<8) + mod_buf[5];
tempData = tempData * 2; //数据个数
tempData += 9;
if(count_receiveNByte >= tempData)
{
crcData = crc_chk(mod_buf,tempData-2);
dat=mod_buf[tempData-1];
if(crcData == (dat<<8)+ mod_buf[tempData-2])
presetMultipleRegisters();
count_receiveNByte=0; //接受数据指针归零
}
break;
default:
break;
}
}
}
else
count_receiveNByte=0; //接受数据指针归零
_nop_();
// Receive_timeout();
PCA0CPH4 = 0x00;
}
}
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use an 22.1184MHz crystal
// as its clock source.
//
//void SYSCLK_Init (void)
//{
// int i;
// OSCXCN = 0x67;
// for (i=0; i < 256; i++) ;
// while (!(OSCXCN & 0x80)) ;
// OSCICN = 0x88;
//}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports
//
void PCA_Init()
{
PCA0CN = 0x40; // PCA counter enable
PCA0MD &= ~0x40 ; // Watchdog timer disabled-clearing bit 6
PCA0MD &= 0xF1; // timebase selected - System clock / 12
PCA0CPL4 = 0xFF; // Offset value
PCA0MD |= 0x40;
PCA0L = 0x00; // Set lower byte of PCA counter to 0
PCA0H = 0x00;
}
void PORT_Init (void)
{
XBR0 = 0x01; //UART TX0, RX0连到端口引脚P0.4和P0.5
XBR1 = 0x40;
XBR2 = 0x00; //UART1的I/O不连到端口引?
P0MDOUT |= 0x01; //TX0输出为推挽方式
P2MDOUT |= 0x3f;
P1MDOUT |= 0xff;
// P0SKIP |= 0xc0;
}
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Configure the UART0 using Timer1, for <baudrate> and 8-N-1.
//
void UART0_Init (void)
{
SCON0 = 0x50;
TMOD = 0x20;
if(BaudRate > 38400)
{
CKCON = 0x08; //定时器使用系统时钟
TH1 = 256-SYSCLK/2/BaudRate;
}
if(BaudRate <= 38400)
{
CKCON = 0x01; //定时器时钟用系统时钟的4分频
TH1 = 256-SYSCLK/4/2/BaudRate;
}
TL1=TH1;
TR1 = 1;
CKCON |= 0x01; //定时器时钟用系统时钟的4分频
PF=0;
}
/*void Timer0_Init(void)
{
TMOD |= 0x01; // 定时器0: 方式1,16位定时器
TF0=0;
TR0=1;// TR0
CKCON |= 0x10; //
TH0 = 0xf1; //256 -((60*SYSCLK/1000/12)/256);
TL0 = 0xc2;//256 -((60*SYSCLK/1000/12)%256);
ET0=1;
}
void timer0() interrupt 1 using 2 //定时器中断
{
TF0=0;
TR0=0;
TH0=0xf1; //3.646ms interrupt
TL0=0xc2;
flag++;
if(flag==15)
{
flag=0;
if(count_receiveNByte<=2) //超时后,若接收缓冲区有数则判断为收到一帧
{
count_receiveNByte=0; //接受数据指针归零 ;
}
}
TR0=1;
}
/***********************************************************
CRC校验
***************************************************************/
u16 crc_chk(u8 *pData,u8 nLen)
{
u16 temp=0xffff,temp1,i,j;
for(i=0;i<nLen;i++)
{
temp^=*(pData+i);
for(j=0;j<8;j++)
{
temp1=temp;
temp>>=1;
if(temp1&0x0001)
temp^=0xa001;
}
}
return(temp);
}
/*功能码03读*/
void readRegisters(void)
{
u16 addr;
u16 tempAddr;
// u16 result;
u16 crcData;
u8 readCount;
u8 byteCount;
// u8 finsh; //
u8 i;
u16 tempData = 0;
tempData=mod_buf[2];
addr = (tempData<<8) + mod_buf[3];
tempAddr = addr ;//& 0xfff;
//addr = mod_buf[3];
//tempAddr = addr;
//readCount = (receBuf[4]<<8) + receBuf[5];
readCount = mod_buf[5];
if(readCount<MAXREG)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -