⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rs232.c

📁 利用FIFO数据结构,在8051单片机上实现全双工通讯,实现MODBUS通讯协议
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************
*                  串行通信模块
*功能:完成通信协议的组合和解释执行,发送和接收数据
*占用资源:串行通信口
**********************************************************************/

/*********************************************************************
*                      通信协议(数据格式)
*可读寄存器 12个
*读寄存器指令:0x03
*           地址              内容
*           0x00              A相电压值
            0x01              B相电压值
            0x02              C相电压值
            0x03              A相电流值
            0x04              B相电流值
            0x05              C相电流值
            0x06              三相总有功功率
            0x07              三相总视在功率
            0x08              三相平均功率因数
            0x09              三相总有功率电能
            0x0a              三相总视在率电能
            0x0b              当前浪涌个数
            0x0c              当前电流互感器所设置的变比大小

*可写寄存器 18个
*写寄存器指令:0x10
*           地址              内容
*           100               A相电流补偿寄存器
            101               B................
            102               C................
            103               A相电压补偿寄存器
            104               B................
            105               C................
            106               A相电流校准寄存器
            107               B................
            108               C................
            109               A相电压补偿寄存器
            110               B................
            111               C................
            112               A相有功电能校准寄存器
            113               B....................
            114               C....................
            115               A相视在电能校准寄存器
            116               B....................
            117               C....................
            118               改变当前电流互感器变比的大小
***********************************************************************/
#define MODE422  


#include "REG52.H"

#include "ade7758.h"
//#include "stdio.h"


#define NULL 0

#define uchar unsigned char
#define uint unsigned int

#define RECEIVE_BUF_SIZE  50

extern bit bWorkModel;//工作模式标志位 1:校准模式;0:正常工作模式;启动时检测键盘口状态,确定该位状态

unsigned char xdata receive_buff[RECEIVE_BUF_SIZE];

unsigned char idata begin_trans_buff,end_trans_buff;
unsigned char idata end_rec_buff,begin_rec_buff;

uchar tran_buf_size = 0;

bit tr_begin_flag = 0;

void transmit(void);
void receive(void);
void putchar(char c);
unsigned char getchar();
unsigned int CRC_16(unsigned char * p,unsigned char len);

/****************************************************************************************
*                 串行中断服务程序
*功能:负责接收和发送数据
****************************************************************************************/
sbit rec_led  = P3^6;
sbit trx_led  = P3^7;

void serial() interrupt 4  using 3
{
	//EA = 0;
	if(TI)
	{
		
	    TI = 0;
	    transmit();
	    
	}
	if(RI)
	{
		rec_led = 0;
		
	    RI = 0;
	    receive();
	    
	    rec_led = 1;
	}
	EA = 1;
}

/**************************************************************************************
           数据发送子函数,在串口中断中调用
***************************************************************************************/
bit bSendingData = 0;            //正在发数据,这时不允许改变缓冲区中的数据

uchar xdata *pComData = &rwdata;//将指针指向数据结构体

uchar data pOffset = 0;

void transmit(void) using 3             /*  serial interrupt routine  */
{
	if( /*( pComData != NULL )*/ 1 && ( pOffset < tran_buf_size) )
	{//指针不为空,并且没有结束
		trx_led = 0;
		
		SBUF = *( pComData + pOffset );
		
		pOffset++;
	}//end of if( pComData != NULL && pOffset < tran_buf_size )

	else
	{//发送完成,恢复数据接收功能
	
		trx_led = 1;
		
		bSendingData = 0;//数据发送完成
		
		///////////////////
		rwdata.working.surge.data32 = 0;//浪涌值清零,重新开始计数 
		
		////////////////////
		
	    #ifdef MODE422
	    REN = 1;//Enable receiver
	    #endif
	}//end of else
}//end of transmit(void)


/**************************************************************************************
           数据接收子函数,在串口中断中调用
***************************************************************************************/
void receive(void) using 3              /*  serial interrupt routine  */
{
    if( end_rec_buff + 1  ==  begin_rec_buff || ( end_rec_buff  ==  RECEIVE_BUF_SIZE-1 &&
	    !begin_rec_buff )  )
    {
        ;  /*  input overrun code  */
    }
    else
    {
        /*   The next statement makes the buffer circular by starting over when the
        index reaches the end of the buffer.   */

        if( ++end_rec_buff > RECEIVE_BUF_SIZE - 1 )
        end_rec_buff  =  0;
        
        receive_buff[end_rec_buff] = SBUF;  /*    place character in buffer  */
        
    }

}


void putchar(char c)
{
    uchar i;

	i =  c;

}

unsigned char getchar()
{
    unsigned char c_temp = 0;
    while(begin_rec_buff==end_rec_buff);  /*  remain in loop01 while there is
					      not a character avaliable. */
    if(++begin_rec_buff>RECEIVE_BUF_SIZE - 1)  /*  make buffer appear    */
         begin_rec_buff=0;                     /*  circular.  */

    return(receive_buff[begin_rec_buff]);      /*  return the character in
    					                      buffer.    */
}

//**************************
//接收缓冲区空返回1
//**************************
unsigned char rc_buf_empty()
{
    if(begin_rec_buff==end_rec_buff)
    return (1);
    
	else 
	return (0);
}


/*********************************************************************
*            串行口初始化程序
*功能:设置波特率,将相关标志置位
*晶振:11.0592MHz
*波特率:9600
*波特率发生器:T2
**********************************************************************/
void init_UART()
{
	ES = 0;
	RI = 0;
	TI = 0;
	
	end_rec_buff     = 0;          /* initialize buffer pointers        */
	begin_rec_buff   = 0;
	end_trans_buff   = 0;
	begin_trans_buff = 0;

	tr_begin_flag = 0;

	T2CON = 0x30;

	RCAP2H= 0xFF;
	RCAP2L= 0xDC;

	TH2   = 0xFF;
	TL2	  = 0xDC;

	T2CON = 0x30;
	TR2	  = 1;						//开时钟

	SCON = 0x50;		//SHIFT REGETER
	PCON = 0x80;
	ES  = 1;			  //开中断

}//end of init_UART()


/***************************************************************************************
                     软件产生中断,启动数据发送功能
****************************************************************************************/
void send_data()
{
	bSendingData = 1;//正在发送数据
	
	TI = 1;
	
	#ifdef MODE422

	REN = 0;//Disable receiver

	#endif
	
}//end of send_data()

//key value table
#define KeyUp		  0xfd
#define KeyDown		0xfb
#define KeyEnter	0xf7
#define KeyCancel	0xef

/*******************************************************************
*                 获取并返回本机地址
*地址存放在EEPROM中
********************************************************************/
uchar slave_address=8;
unsigned char address()
{
	uchar temp;
	P2 = 0xff;
	temp = P2;
	return (~temp);//本机地址由P2口的拨码开关状态确定
}//end of address()


//*********************************************************
//串行通讯数据定义
//*********************************************************
#define CORRECT_START_ADDRESS    200

unsigned char idata loop01  = 0;

unsigned char idata data_num1   = 0;
unsigned char idata function_code1   = 0;

bit data_ok1    = 0;
bit begin_flag1 = 0;
bit end_flag1   = 0;

//read register
#define READ_REGISTER       0X03   //order of read register
#define READ_DATA_START     0
#define READ_DATA_END       12
#define READ_DATA_LONG      13     //可以读操作的寄存器的最多个数

//write register
#define WRITE_REGISTER      0X10   //order of write register
#define WRITE_DATA_START    100    //写寄存器的开始地址
#define WRITE_DATA_END      113    //写寄存器的结束地址
#define WRITE_DATA_LONG     14     //可以连续写的数据长度

#define broadcast_addr 0x00



bit bit_read_order = 0;
bit bit_write_order = 0;

unsigned char xdata rc_buf[50];

/************************************************************************
*                  串口通讯程序
*功能:将从下位机接收到的数据,按昭MODBUS协议的数据格式存放到RAM中
*
*************************************************************************/
void command_receive_explain()
{

	union read_16add
	{
		unsigned int add16;
		unsigned char add8[2];
	};
	
	union read_16add  begin_address;
	union read_16add  register_num;  //read or write register's start address and long
	union read_16add  crc_temp;    //

	unsigned char i;

    if( !data_ok1 )
    {//命令解释处理未完
        while( ( loop01 < 50 ) && ( !rc_buf_empty() ) && ( !end_flag1 ) )
        {

            if(!rc_buf_empty())
            {
                if( begin_flag1 == 1 )
                {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -