标题:
8051F340单片机MODBUS源程序
[打印本页]
作者:
ADETEGA
时间:
2018-3-9 16:05
标题:
8051F340单片机MODBUS源程序
8051F340MODBUS程序,学习学习
单片机源程序如下:
#include"C8051F120.h"
#include"VVVF.h"
#include"UART.h"
#include"DataProcess.h"
sbit S_SL=P5^5;
/*------------------------------------------------------------------------------------
函数名:Send485Data()
函数功能:发送一个字节485数据
参数:uchar dat;
返回:void
-------------------------------------------------------------------------------------*/
void Send485Data(uchar xdata dat){
uchar xdata old_SFRPAGE;
old_SFRPAGE=SFRPAGE;
SFRPAGE = CONFIG_PAGE;
UART0_Init(9600);
S_SL=1;/////关闭485发送 防止在不需要的时候数据写
UART0SendOneByte(dat);
//P4&=0xEF;/////关闭485发送 防止在不需要的时候数据写,???????????影响串口中断
UART0_End();
S_SL=0;
SFRPAGE=old_SFRPAGE;
}
void SendVVVFCommand(uchar xdata comm, uint xdata StartAddr,uint xdata para){
uchar xdata commstr[8],i;
uint xdata CRC;
commstr[0]=0x01;//命令机号
commstr[1]=comm;//命令
commstr[2]=StartAddr/256;//起始地址高在前地在后
commstr[3]=StartAddr%256;
commstr[4]=para/256;
commstr[5]=para%256;//参数
CRC=VVVF_CRC_CHK(commstr,6);
commstr[6]=CRC%256;
commstr[7]=CRC/256;
for(i=0;i<8;i++){
Send485Data(commstr[i]);
}
}
/*------------------------------------------------------------------------------------
函数名:MotorRun()
函数功能:启动电机 即启动变频器
参数: void
返回:void
-------------------------------------------------------------------------------------*/
void MotorRun(){
SendVVVFCommand(0x06,0x2000,0x0002);
}
/*------------------------------------------------------------------------------------
函数名:MotorStop()
函数功能:停止电机 即停止变频器
参数: void
返回:void
-------------------------------------------------------------------------------------*/
void MotorStop(){
SendVVVFCommand(0x06,0x2000,0x0001);
}
/*------------------------------------------------------------------------------------
函数名:MotorFWD()
函数功能:电机正转命令
参数: void
返回:void
-------------------------------------------------------------------------------------*/
void MotorFWD(){
SendVVVFCommand(0x06,0x2000,0x0010);
}
/*------------------------------------------------------------------------------------
函数名:MotorREV()
函数功能:电机反转命令
参数: void
返回:void
-------------------------------------------------------------------------------------*/
void MotorREV(){
SendVVVFCommand(0x06,0x2000,0x0020);
}
/*------------------------------------------------------------------------------------
函数名:SetFrequnce()
函数功能:设置频率
参数: float xdata freq
返回:void
-------------------------------------------------------------------------------------*/
void SetFrequence(float xdata freq){
SendVVVFCommand(0x06,0x2001,freq*100);
}
// MotorStop();
/*SetFrequence(40);
MotorFWD();
MotorREV();
SetFrequence(60);
SetFrequence(50);
SetFrequence(45);
SetFrequence(61);
SetFrequence(65);
SetFrequence(66);
SetFrequence(150);
SetFrequence(180);*/
// SendVVVFCommand(0x06,0x2001,5000);
//SendVVVFCommand(0x06,0x2000,0x0002);
//SendVVVFCommand(0x06,0x2000,0x0001);
//Num=UART0ReceiveOneByte();
复制代码
//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)
{
byteCount = readCount* 2 ;//;
for(i=0;i<byteCount;i++,tempAddr++)
{
tempData=FLASH_ByteRead(tempAddr);
//getRegisterVal(tempAddr,&tempData);
sendBuf[i+3] = tempData;// & 0xff;
}
sendBuf[0] = localAddr;
sendBuf[1] = 3;
sendBuf[2] = byteCount;
byteCount += 3;
crcData = crc_chk(sendBuf,byteCount);
sendBuf[byteCount] = crcData & 0xff;
byteCount++;
sendBuf[byteCount] = crcData >> 8;
sendCount = byteCount + 1;
beginSend();
}
else
{
send_err(0x83,0x03);
}
}//void readRegisters(void)
/*****************************************************************
功能码6 设置单个寄存器
******************************************************************
void presetSingleRegisters(void)
{
u16 addr;
u16 tempAddr;
u16 crcData;
u16 tempData;
// uint8 finsh; //为1时完成 为0时出错
tempData=mod_buf[2];
addr = (tempData<<8) + mod_buf[3];
tempAddr = addr;// & 0xfff;
//addr = mod_buf[3];
//tempAddr = addr & 0xff;
//setCount = (receBuf[4]<<8) + receBuf[5];
//setCount = mod_buf[5];
//byteCount = mod_buf[6];
FLASH_PageErase (tempAddr);
// tempData = (modbuf[i*2+7]<<8) + modbuf[i*2+8];
tempData=mod_buf[4];
// setRegisterVal(tempAddr,tempData);
FLASH_ByteWrite (tempAddr, tempData);
sendBuf[4] = tempData ;
tempData=mod_buf[5];
FLASH_ByteWrite (tempAddr+1, tempData);
sendBuf[5] = tempData;
sendBuf[0] = localAddr;
sendBuf[1] = 6;
sendBuf[2] = addr >> 8;
sendBuf[3] = addr & 0xff;
crcData = crc_chk(sendBuf,6);
sendBuf[6] = crcData & 0xff;
sendBuf[7] = crcData >> 8;
sendCount = 8;
beginSend();
}
/****************************************************************
功能码16,设置多个功能寄存器
******************************************************************/
void presetMultipleRegisters(void)
{
u16 addr;
u16 tempAddr;
u8 byteCount;
u8 setCount;
u16 crcData;
u16 tempData;
// uint8 finsh; //为1时完成 为0时出错
u8 i;
//addr = mod_buf[3];
tempData=mod_buf[2];
addr = (tempData<<8) + mod_buf[3];
tempAddr = addr;// & 0xfff;
//tempAddr = addr & 0xff;
//setCount = (receBuf[4]<<8) + receBuf[5];
setCount = mod_buf[5];
if(setCount<=0x78)
{
byteCount = mod_buf[6];
sendBuf[0] = localAddr;
sendBuf[1] = 16;
sendBuf[2] = addr >> 8;
sendBuf[3] = addr & 0xff;
sendBuf[4] = setCount >> 8;
sendBuf[5] = setCount & 0xff;
crcData = crc_chk(sendBuf,6);
sendBuf[6] = crcData & 0xff;
sendBuf[7] = crcData >> 8;
sendCount = 8;
beginSend();
FLASH_PageErase (0x7c00);
for(i=0;i<byteCount;i++,tempAddr++)
{
// tempData = (modbuf[i*2+7]<<8) + modbuf[i*2+8];
tempData=mod_buf[7+i];
// setRegisterVal(tempAddr,tempData);
FLASH_ByteWrite (tempAddr, tempData);
}
}
else//寄存器数量>120
{
send_err(0x90,0x03);
}
}//void presetMultipleRegisters(void)
/*UART0中断处理*/
void UART0_ISR (void) interrupt 4
{
ES0=0;
if(!TI0)
{
// Receivetimeout=time0;
RI0 = 0;
mod_buf[count_receiveNByte] = SBUF0; //获取数据
count_receiveNByte++; //接收字节数目
// Receivetimeout=350;
if(count_receiveNByte >= MAXNByte) //如果接收满
count_receiveNByte = 0; //接受满 归0
}
TI0 = 0;
ES0=1;
}
//发送子程序
void beginSend(void)
{ u8 i;
ES0=0;
GREEN=0;
RED=1;
PF=1; //485允许发送
for(i=0;i<sendCount;i++)
{
SBUF0 = sendBuf[i];
while(TI0==0);
TI0=0;
}
PF=0; //485允许接收
GREEN=1;
RED=0;
ES0=1;
}
void send_err(u8 err,u8 err_code)//发送错误
{
u16 crc_tmp;
sendBuf[0]=localAddr;
sendBuf[1]=err;
sendBuf[2]=err_code;
crc_tmp=crc_chk(mod_buf,3);
sendBuf[3]=crc_tmp;
sendBuf[4]=crc_tmp>>8;
sendCount=5;
beginSend();
}
/*****************************************************
接收超时判断
调用条件:
((Receivetime_flag=1)&&(count_receiveNByte>0)) 1ms定时时间到
并且 有接收到的字符,调用此模块,判定是否接收超时
*****************************************************
void Receive_timeout(void)
{
Receivetimeout--;
if((Receivetimeout==0)&&(count_receiveNByte>0)) //说明接收超时
{
count_receiveNByte=0; //接受数据指针归零
SCON0|=0x10; //允许UART0接收,REN0=1;
}
}*/
void FLASH_PageErase (u16 addr)
{
bit EA_SAVE = EA; // Preserve EA
char xdata * data pwrite; // FLASH write pointer
EA = 0; // Disable interrupts
// change clock speed to slow, then restore later
VDM0CN = 0x80; // Enable VDD monitor
RSTSRC |= 0x02; // enable VDD monitor as a reset source
FLKEY = 0xA5; // Key Sequence 1
FLKEY = 0xF1; // Key Sequence 2
PSCTL |= 0x03; // PSWE = 1; PSEE = 1
VDM0CN = 0x80; // Enable VDD monitor
RSTSRC |= 0x02; // Enable VDD monitor as a reset source
pwrite = (char xdata *) addr;
VDM0CN = 0x80; // Enable VDD monitor
*pwrite = 0; // Initiate page erase
PSCTL &= ~0x03; // PSWE = 0; PSEE = 0
EA = EA_SAVE; // Restore interrupts
}
/********************************************************************
读寄存器值
********************************************************************/
u8 FLASH_ByteRead (u16 addr)
{
bit EA_SAVE = EA; // Preserve EA
char code * data pread; // FLASH read pointer
unsigned char byte;
EA = 0; // Disable interrupts
pread = (char code *) addr;
byte = *pread; // Read the byte
EA = EA_SAVE; // Restore interrupts
return byte;
}
/************************************************************
Flash写
************************************************************/
void FLASH_ByteWrite (u16 addr, u8 byte)
{
bit EA_SAVE = EA; // Preserve EA
char xdata * data pwrite; // FLASH write pointer
EA = 0; // Disable interrupts
// change clock speed to slow, then restore later
VDM0CN = 0x80; // Enable VDD monitor
RSTSRC |= 0x02; // Enable VDD monitor as a reset source
pwrite = (char xdata *) addr;
PFE0CN &= 0XFE; //设定单字节写入FLASH方式
PSCTL |= 0x01; // PSWE = 1
FLKEY = 0xA5; // Key Sequence 1
FLKEY = 0xF1; // Key Sequence 2
VDM0CN = 0x80; // Enable VDD monitor
RSTSRC |= 0x02; // Enable VDD monitor as a reset source
VDM0CN = 0x80; // Enable VDD monitor
*pwrite = byte; // Write the byte
PSCTL &= ~0x01; // PSWE = 0
EA = EA_SAVE; // Restore interrupts
}
复制代码
0.png
(48.18 KB, 下载次数: 50)
下载附件
2018-3-10 00:45 上传
所有资料51hei提供下载:
340.zip
(51.69 KB, 下载次数: 55)
2018-3-9 16:03 上传
点击文件名下载附件
modbus编程
下载积分: 黑币 -5
作者:
wadz3652002
时间:
2018-7-12 01:14
正好需要。。。。。。。。。。。。。。。。。。。。。。。。。
作者:
竹子开花
时间:
2018-8-12 10:31
需要。。。。。。。。。。。。。。。。。。。。。。。
作者:
WFX777888
时间:
2018-8-12 12:07
谢谢分享资料
作者:
yanfeng082
时间:
2020-10-29 14:42
请问这个怎么能移植到c51单片机上用来控制变频器
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1