各路大神,看看这个STM8S的程序是否能实现单片机与电脑之间的modbus rtu通讯协议,如有问题,还请各路大神不吝赐教!!!此程序是把51的程序改成STM8S的
//File name: modbusMain.c
//Function : modbus rtu
//Programed by peirui 2013.6.25
/*********************************************************************************/
//#include <iostm8s105k4.h>
//#include <intrins.h>
/*********************************************************************************/
/*********************************************************************************/
#define GlobalIntEnable() asm("rim")
#define GlobalIntDisable() asm("sim")
#define SerialIntEnable() UART2_CR1_PIEN=1
#define SerialIntDisable() UART2_CR1_PIEN=0
/*********************************************************************************/
#define MIN_TIME_INT 2
#define MAX_TIME_INT 4
#define MAX_REC_COUNT 60
#define MY_ADDR 0x01
#define MAX_PACKET 100
#define MAX_ADDR_NUM 255
#define FUNC_NUM_ERR 0x01
#define REG_ADDR_ERR 0x02
#define REG_NUM_ERR 0x03
#define OSFREQ 2000000
unsigned char DI[]={0x00, // coils 8-1 //Input Coils
0x00, // coils 16-9
0x68, // coils 24-17
0x5E, // coils 32-25
0x93, // coils 40-33
0x75, // coils 48-41
0xD8, // coils 56-49
0x00,}; // coils 64-57
unsigned char DO[]={0x00, // coils 8-1 //Output Coils
0x00, // coils 16-9
0x68, // coils 24-17
0x5E, // coils 32-25
0x93, // coils 40-33
0x75, // coils 48-41
0xD8, // coils 56-49
0x00,}; // coils 64-57
unsigned char AI[]={0xF1,0xF2, // address 0 //Input Registers
0xF3,0xF4, // address 1
0xF5,0xF6,
0xF7,0xF8,
0xF9,0xFA,
0xFB,0xFC,
0xFD,0xFE,
0xFF,0xF0,
0xE1,0xE2,
0xE3,0xE4,
0xE5,0xE6,
0xE7,0xE8,
0xE9,0xEA,
0xEB,0xEC,
0xED,0xEE,
0xEF,0xE0}; // address 15
unsigned char AO[]={0x01,0x02, // address 0 //Hold Registers
0x03,0x04, // address 1
0x05,0x06, // address 2
0x07,0x08, // address 3
0x09,0x0A, // address 4
0x0B,0x0C, // address 5
0x0D,0x0E, // address 6
0x0F,0x10, // address 7
0x11,0x12, // address 8
0x13,0x14, // address 9
0x15,0x16, // address 10
0x17,0x18, // address 11
0x19,0x1A, // address 12
0x1B,0x1C, // address 13
0x1D,0x1E, // address 14
0x1F,0x20}; // address 15
unsigned char ReceiveData[MAX_PACKET];
unsigned char sendbuf[MAX_PACKET];
unsigned char g_RecCounter = 0;
unsigned char g_RecDisable = 0;
unsigned char g_TimeInterval=0;
/*********************************************************************************/
void SendStringToCom(unsigned char *pStrToSend,unsigned int sendLength);
unsigned int Cal_CRC16(unsigned char *puchMsg, unsigned char usDataLen);
//unsigned int cal_crc(unsigned char *ptr, unsigned int len);
static unsigned char GetBit(unsigned int address,unsigned char function);
static void ProcessFun1_2(unsigned char address, unsigned char len);
static void ProcessFun3(unsigned char address, unsigned char len);
static void ProcessFun4(unsigned char address, unsigned char len);
static void SendMbError(char ErrorCode);
void ModbusFunProcess();
void InitTimer0();
void InitSerial();
void SendByteToCom(unsigned char dataToSend);
void SendStringToCom(unsigned char *pStrToSend,unsigned int sendLength);
/*********************************************************************************/
static unsigned char Cal_CRC_Hi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
static unsigned char Cal_CRC_Lo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
};
/*********************************************************************************/
unsigned int Cal_CRC16(unsigned char *puchMsg, unsigned char usDataLen)
{
unsigned char uchCRCHi = 0xFF ;
unsigned char uchCRCLo = 0xFF ;
unsigned int uIndex ;
while (usDataLen--)
{
uIndex = uchCRCHi ^ *puchMsg++ ;
uchCRCHi = uchCRCLo ^ Cal_CRC_Hi[uIndex] ;
uchCRCLo = Cal_CRC_Lo[uIndex] ;
}
return (uchCRCHi << 8 | uchCRCLo) ;
}
/*********************************************************************************/
/*
main()
{
InitSerial();
InitTimer0();
GlobalIntEnable();
SerialIntEnable();
g_RecDisable = 0;
while(1)
{
if (g_RecDisable)
{
ModbusFunProcess();
g_RecDisable=0;
g_RecCounter=0;
}
}
}
*/
/*********************************************************************************/
//void RecIntProcess() interrupt 4 using 3
__interrupt void UART2_R_OR_IRQHandler(void)
{
//GlobalIntDisable();
asm("sim");
//if(RI)
if(UART2_SR_RXNE)
{
if((g_TimeInterval>MIN_TIME_INT)&&(g_TimeInterval<=MAX_TIME_INT))
{
g_RecCounter=0;
}
if(g_RecCounter>MAX_REC_COUNT)
{
g_RecCounter=0;
}
ReceiveData[g_RecCounter++]=UART2_DR;
g_TimeInterval=0;
//RI=0;
UART2_SR_RXNE=0;
}
//GlobalIntEnable();
//ET0=1;
asm("rim");
TIM2_IER = 0x01;
}
/*--------------------------------------------------------------------------*/
//void Timer0IntProcess() interrupt 1 using 2
__interrupt void UART2_R_OR_Timer4IntProcess(void)
{
/*
ET0=0;
TL0 = 0x18 ; //0xFC40=65536-((11059200/12)/9600)*10
TH0 = 0xFC;
g_TimeInterval++;
if((g_TimeInterval>MAX_TIME_INT) && (g_RecCounter>0))
{
g_RecDisable=1;
}else
{
ET0=1;
}
*/
TIM2_IER = 0x00;
TIM2_CNTRH = 0x03; // 设定计数器的初值
TIM2_CNTRL = 0xE8;
g_TimeInterval++;
if((g_TimeInterval>MAX_TIME_INT) && (g_RecCounter>0))
{
g_RecDisable=1;
}else
{
TIM2_IER = 0x01;
}
}
/*********************************************************************************/
static unsigned char GetBit(unsigned int address,unsigned char function)
{
unsigned char Offset;
unsigned char temp;
unsigned char *Myaddress;
Offset=(char)address&0x07;
switch (function)
{
case 2:
Myaddress=DI;
break;
case 1:
Myaddress=DO;
break;
default:
return 2;
}
temp=(char)(address>>3);
temp=*(Myaddress+temp);
temp>>=(Offset);
if (temp&0x01)
return 1;
else
return 0;
}
/*********************************************************************************/
//ProcessFun1_2
/*********************************************************************************/
static void ProcessFun1_2(unsigned char address, unsigned char len)
{
unsigned char i;
unsigned char j;
unsigned char length;
unsigned char function;
unsigned int temp;
length=0;
sendbuf[0]=ReceiveData[0];
sendbuf[1]=ReceiveData[1];
function=sendbuf[1];
for (i=1;i<=len;i++)
{
length++;
sendbuf[2+length]=0;
for (j=0;j<8;j++)
{
sendbuf[2+length]=sendbuf[2+length]|(GetBit(address,function)<<j);
address++;
i++;
if(i>len)break;
}
i--;
}
sendbuf[2]=length;
temp=Cal_CRC16(sendbuf,length+3);
sendbuf[3+length]=(char)(temp>>8);
sendbuf[4+length]=(char)temp;
SendStringToCom(sendbuf,length+5);
}
/*********************************************************************************/
//ProcessFun3
/*********************************************************************************/
static void ProcessFun3(unsigned char address, unsigned char len)
{
unsigned char i;
unsigned char msendbuf[MAX_PACKET];
unsigned int temp;
msendbuf[0]=ReceiveData[0];
msendbuf[1]=ReceiveData[1];
msendbuf[2]=2*len;
address=2*address;
for(i=0;i<len;i++)
{
msendbuf[3+2*i]=AO[address++];
msendbuf[4+2*i]=AO[address++];
}
temp=Cal_CRC16(msendbuf,2*len+3);
msendbuf[3+2*len]=temp>>8;
msendbuf[4+2*len]=(char)temp;
SendStringToCom(msendbuf,2*len+5);
}
/*********************************************************************************/
//ProcessFun4
/*********************************************************************************/
static void ProcessFun4(unsigned char address, unsigned char len)
{
unsigned char i;
unsigned int temp;
sendbuf[0]=ReceiveData[0];
sendbuf[1]=ReceiveData[1];
sendbuf[2]=2*len;
address=2*address;
for(i=0;i<len;i++)
{
sendbuf[3+2*i]=AI[address++];
sendbuf[4+2*i]=AI[address++];
}
temp=Cal_CRC16(sendbuf,2*len+3);
sendbuf[3+2*len]=(char)(temp>>8);
sendbuf[4+2*len]=(char)temp;
SendStringToCom(sendbuf,2*len+5);
}
/*********************************************************************************/
//ProcessFun5
/*********************************************************************************/
static void ProcessFun5(unsigned char address)
{
unsigned int temp;
unsigned char Offset;
unsigned char *sendbuf;
unsigned char *pDO;
pDO=DO;
Offset=(unsigned char)address&0x07;
temp=address>>3;
if((0x00==ReceiveData[4])&&(0x00==ReceiveData[5]))
pDO[temp]&=~(1<<Offset);
else if((0xFF==ReceiveData[4])&&(0x00==ReceiveData[5]))
pDO[temp]|=(1<<Offset);
else
{};
sendbuf=ReceiveData;
SendStringToCom(sendbuf,8);
}
/*********************************************************************************/
//ProcessFun6
/*********************************************************************************/
static void ProcessFun6(unsigned char address)
{
unsigned int temp;
unsigned char *sendbuf;
unsigned char *pAO;
temp=2*address;
pAO=AO;
pAO[temp]=ReceiveData[4];
pAO[temp+1]=ReceiveData[5];
sendbuf=ReceiveData;
SendStringToCom(sendbuf,8);
}
/*********************************************************************************/
//ProcessFun15
/*********************************************************************************/
static void ProcessFun15(unsigned char address, unsigned char len)
{
unsigned char i;
unsigned char j;
unsigned int temp;
unsigned char Offset,test;
unsigned char byteNum;
unsigned char *sendbuf;
unsigned char *pDO;
unsigned char tempdata;
Offset=(unsigned char)address&0x07;
temp=address>>3;
pDO=DO;
byteNum=((len-1+Offset)>>3) + 1;
for(i=0;i<byteNum;i++)
{
for(j=0;j<8;j++)
{
test=(Offset+j)>>3;
tempdata=ReceiveData[7+i]>>j;
tempdata&=0x01;
if(len==(j+8*i))
break;
else
{
if(tempdata)
pDO[temp+i+test]|=(0x01<<((Offset+i*8+j)&0x07));
else
pDO[temp+i+test]&=(~(0x01<<((Offset+i*8+j)&0x07)));
}
}
}
sendbuf=ReceiveData;
temp=Cal_CRC16(sendbuf,6);
sendbuf[6]=temp>>8;
sendbuf[7]=temp&0xFF;
SendStringToCom(sendbuf,8);
}
/*********************************************************************************/
//ProcessFun16
/*********************************************************************************/
static void ProcessFun16(unsigned char address, unsigned char len)
{
unsigned char i;
unsigned char *pSendBuf;
unsigned int temp;
pSendBuf=ReceiveData;
address=2*address;
for(i=0;i<len;i++)
{
AO[address++]=ReceiveData[7+2*i];
AO[address++]=ReceiveData[8+2*i];
}
temp=Cal_CRC16(pSendBuf,6);
pSendBuf[6]=(char)(temp>>8);
pSendBuf[7]=(char)temp;
SendStringToCom(pSendBuf,8);
}
/*********************************************************************************/
static void SendMbError(char ErrorCode)
{
unsigned int temp;
sendbuf[0]=ReceiveData[0];
sendbuf[1]=ReceiveData[1]|0x01;
sendbuf[2]=ErrorCode;
temp=Cal_CRC16(sendbuf,3);
sendbuf[3]=(unsigned char)(temp>>8);
sendbuf[4]=(unsigned char)temp;
SendStringToCom(sendbuf,5);
}
/*********************************************************************************/
void ModbusFunProcess()
{
unsigned int temp;//temp1;
unsigned char address;
unsigned char length;
unsigned char *pRecBuf;
unsigned char mb_function;
//unsigned char tmp[2];
if(g_RecCounter<=3) return;
pRecBuf=ReceiveData;
temp=pRecBuf[g_RecCounter-2]<<8;
temp|=pRecBuf[g_RecCounter-1];
mb_function=pRecBuf[1];
if(MY_ADDR==pRecBuf[0]&&temp==Cal_CRC16(pRecBuf,g_RecCounter-2))
{
address=pRecBuf[3];
length=pRecBuf[5];
if(address<MAX_ADDR_NUM)
{
switch(mb_function)
{
case 1:
case 2:
ProcessFun1_2(address,length);
break;
case 3:
ProcessFun3(address,length);
break;
case 4:
ProcessFun4(address,length);
break;
case 5:
ProcessFun5(address);
break;
case 6:
ProcessFun6(address);
break;
case 15:
ProcessFun15(address,length);
break;
case 16:
ProcessFun16(address,length);
break;
default:
SendMbError(0x81);
break;
}
}
else
{
SendMbError(0x82);
}
}
else
{
SendMbError(0x83);
}
g_RecCounter=0;
return;
} |
|