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

📄 3201.c

📁 基于PL3201芯片的单相复费率载波通信多功能电表应用程序
💻 C
📖 第 1 页 / 共 2 页
字号:


#include "PL3200.h"
#define	LIMIT_3105    0x30				  // lxw载波序列捕获门限
#define	LIMIT_3200    0x70				  // lxw载波序列捕获门限

#define uchar unsigned char
#define uint  unsigned int

//I/O 口设置
sbit   RS_TLED 	= P0^3;   	        // 串口发送指示灯D3
sbit   RS_RLED 	= P0^4;             // 串口接收指示灯D4
sbit   PLC_TLED = P0^5;	      		  // 载波发送指示灯D5
sbit   PLC_RLED = P1^2; 	    		  // 载波接收指示灯D6

sbit   FUNC_LED	= P0^2;     	      // 载波通讯方式,亮:3200模式;灭:3105模式D2

sbit   function = P1^3;            // 载波通讯方式,0:3200模式;1:3105模式D12

sbit	 PSK_OUT	= P3^7;							// 
sbit	 Rxd_p30	= P3^0;							// 
sbit	 Txd_p31	= P3^1;							// 

// 全局变量设置
uchar  data		 function_now;				// 当前的通讯方式,0:3200方式。0xff:为3105模式
uchar  data		 function_flage;			// time = 6 sec

uchar  data    COM_recv_len;        // 串口接收数据长度
uchar  data    COM_State;						// the state of com receive 
uchar  data    COM_recv_pointer;    // 表示串口接收控制变量
uchar  data    COM_send_timer;      // 延时时间变量

uchar  data    PLC_Rxd_pointer;    	// 载波接收过程中的字节数
uchar  data    PLC_Rxd_tlen;       	// PLC 接收total len
uchar  bdata   PLC_data;            // 发送字节缓冲
uchar  data    PLC_send_pointer;    // 载波发送字节计数
uchar  data    PLC_timer;           // 载波发送延时计数器
uchar  data    PLC_total_len;       // 载波发送字节长度+8
uchar  data    PLC_Rxd_timer;   		// 载波发送延时时间变量
uchar  data    PLC_Rxd_tdata;				// PLC_recieve cusion

uchar  data    WDI;                 // 软狗变量

// 位变量
bit    bdata   PLC_Rxd_flag;      	// 载波有接收标志
bit    bdata   PLC_Rxd_state;      	// 载波接收控制变量
bit    bdata   PLC_Rxd_OK;         	// 载波接收完成标志
bit    bdata   PLC_sending;         // 载波正在发送标志

uchar  xdata   PLC_recv_buf[250];   // 载波接收缓冲区
uchar  xdata   COM_recv_buf[250];   // 串口接收缓冲区

uchar  xdata   R_T_buf_bak[250];    // 通讯数据备份

/**************************************************************************************
 *
 * FUNCTION:    timeint0
 *
 * DESCRIPTION: 定时器0中断程序; 
 *							50 ms 发生一次中断
 *							对延时变量进行减1处理
 *
 * PARAMETERS:  none
 *
 * RETURNED:    none
 *************************************************************************************/
void  timeint0 ( void ) interrupt 1
{
   if ( COM_send_timer!=0 )
   {
      COM_send_timer--;             // 串口发送延时
   }

   if ( PLC_Rxd_timer>0 )
   {
      PLC_Rxd_timer--;
   }
   else
   {
      PLC_Rxd_timer=0;
      PLC_RLED=1;											// turn off the lamp of receiving 
      PLC_Rxd_state=0;								// resume receive state
   }
   
   if ( PLC_timer>0 )									//增加载波发送延时控制lxw2006-3-2
   		PLC_timer--;
   
   if ( function_flage ) function_flage--;
   else
   {
   	 function_flage=10;
	   if ( function )											//载波方式管脚判断
	   	function_now = function_now *2 + 1;	//function_now=0xff为3105方式lxw2006-2-10
	   else
	   	function_now = function_now *2;			//function_now=0为3200方式lxw 2006-2-10
   }
   
   TH0=0x63;                        			// 置定时器计数  50ms 中断一次 ( 12MHz )
   TL0=0xcc;

   if ( WDI == 0x9a )
   {
      WDT_RST=0xa1;                 			// 清看门狗
      WDI=0;
   }
}
/**************************************************************************************
 *
 * FUNCTION:    txdbyte
 *
 * DESCRIPTION: 一字节串口发送函数
 *
 * PARAMETERS:
 *              in:  dachar——要发送的1字节数据
 *              out: none
 *
 *
 * RETURNED:    none
 *
 *************************************************************************************/
void txdbyte ( uchar dachar )          // 单片机串口发送
{
   SBUF=dachar;
   COM_send_timer=10;               	 // 500毫秒钟发送不成功退出

   while ( !TI )
   {
      if ( COM_send_timer == 0 )
        break;
   }
   TI=0;
}
/**************************************************************************************
 *
 * FUNCTION:    PLC_int
 *
 * DESCRIPTION: 载波中断收、发程序
 *
 * PARAMETERS:
 *
 *              out:  PLC_Rxd_OK=1 载波接收成功  
 *										R_T_buf_bak[]  载波接收成功的数据
 *
 * RETURNED:    none
 *************************************************************************************/
void  PLC_int ( void ) interrupt 7
{                                             
   uchar data i;
   uchar  data state;               		// 载波通讯状态
	 uchar data SSC_adr_bak;
	 
	 SSC_adr_bak=SSC_ADR;									//PRTECT
   SSC_ADR=0x00;                    		//选择载波状态寄存器
   
   state= SSC_DAT;
//   if ( ( state&0x80 ) == 0x0 )
//      return;
   if ( ( state&0x01 ) == 1 )              //载波发送状态
   { // 载波发送
    if ( ( PLC_send_pointer < PLC_total_len ) &&
    		  ( PLC_send_pointer < 240 ) )
    {
       SSC_BUF=R_T_buf_bak[PLC_send_pointer];                  //发送下一个字节
       PLC_send_pointer+=1;
    }
    else
    {  //发送完成
      PLC_sending=0;                	// 清正在发送标志
      PLC_data=0;
      PLC_TLED=1;                  		// 发送指示灯灭
    }
  }
  else
  { // 载波接收
  	PLC_Rxd_timer=20;      			// 最大字节接收延时时间为1S
    if ( ( state&0x04 ) == 0x04 )     //如果接收的是祯头标志
    {
      if ( PLC_Rxd_state == 0 )       //如果处于等待接收状态
      {
         PLC_Rxd_tdata=SSC_BUF; 			//接收第一个字节,并准备接收后面的字节
         PLC_Rxd_tlen=PLC_Rxd_tdata;
         PLC_recv_buf[0]=PLC_Rxd_tdata;
         PLC_Rxd_pointer=1;						//lxw2006-3-2 17:07
         //PLC_Rxd_tlen =60;
         PLC_Rxd_state=1;
         PLC_RLED=0;									//接收指示灯亮
      }
      else 														// translate to rec
      {      	
      	PLC_Rxd_state=0;
      	SSC_ADR=0X0;			
        SSC_DAT=0X0;
      }
    }
    else
    {
      if ( PLC_Rxd_state == 1 )       // 如果已经接收了祯头,继续接收后续字节
      {
        PLC_Rxd_tdata=SSC_BUF;
        PLC_recv_buf[PLC_Rxd_pointer]=PLC_Rxd_tdata;

     /*   if ( PLC_Rxd_pointer == 0x04 ) // 接收到了载波字节个数
        {
           PLC_Rxd_tlen=PLC_Rxd_tdata+7;               // 加7的意思是3个地址码+1个控制码+1个长度码+2个校验码
           if ( PLC_Rxd_tlen>100 )
              PLC_Rxd_tlen=100;    			// 接收字节长度限制
        }*/

        PLC_Rxd_pointer+=1;
        if ( PLC_Rxd_pointer>PLC_Rxd_tlen )
        {
           PLC_Rxd_OK=1;
           PLC_RLED=1;							//接收完毕灯灭
           PLC_Rxd_state=0;
           for ( i=0 ; i< ( PLC_Rxd_tlen+1 ) ; i++ )
           {
              R_T_buf_bak[i]=PLC_recv_buf[i];
           }           
           SSC_ADR=0X0;							// translate to rec
           SSC_DAT=0X0;
        }
      }
      else													// translate to rec
      {
      	PLC_Rxd_state=0;
      	SSC_ADR=0X0;			
        SSC_DAT=0X0;
      }
    }
  }
  SSC_ADR=SSC_adr_bak;
}
/**************************************************************************************
 *
 * FUNCTION:    set_PLC_3200
 *
 * DESCRIPTION: set the PLC function of pl3201
 *
 * PARAMETERS:	none
 *              
 * RETURNED:   none
 * EDITION:		 V1.0
 *************************************************************************************/
void set_PLC_3200 (  )
{
	 SSC_ADR=0XFF;        // 2005.11.29 LXW
	 SSC_DAT=0XFF;        // 禁止写保护

	 SSC_ADR=0x03;        // 选择3201载波通讯控制寄存器3	
	 SSC_DAT=0xc0;        // 开启载波通讯功能,打开中断,选择接收状态置为3200模式
	 
	 SSC_ADR=0x04;			 	// 设置捕获门限
	 SSC_DAT=LIMIT_3200;
	 
	 SSC_ADR=0XFF;
	 SSC_DAT=0XAA;        // 使能写保护  
}
/**************************************************************************************
 *
 * FUNCTION:    set_PLC_3105
 *
 * DESCRIPTION: set the PLC function of pl3201 be 3105 
 *
 * PARAMETERS:	none
 *              
 * RETURNED:   none
 * EDITION:		 V1.0
 *************************************************************************************/
void set_PLC_3105 (  )
{
	SSC_ADR=0XFF;        // 2005.11.29 LXW
  SSC_DAT=0XFF;        // 禁止写保护
 	
 	SSC_ADR=0x03;        // 选择3201载波通讯控制寄存器3	
 	SSC_DAT=0xe0;        // 开启载波通讯功能,打开中断,选择接收状态置为3105模式
 		 
 	SSC_ADR=0x04;			 	 // 设置捕获门限
  SSC_DAT=LIMIT_3105;
  
  SSC_ADR=0XFF;
  SSC_DAT=0XAA;        // 使能写保护  
}
/**************************************************************************************
 *
 * FUNCTION:    initsys
 *
 * DESCRIPTION: 初始化设置函数,
 *              进行系统初始化设置
 *
 * PARAMETERS:  none
 *
 * RETURNED:    none
 *
 *************************************************************************************/
void initsys ( void )
{  // 控制看门狗喂狗时间长度
  CKCON=0X3F;
  // 8位/16位运算模式选择位设置
  ALU_MOD=0;      // 设置成8位运算模式
  //载波通讯配置
	//************   3201的载波寄存器设置  **********//
  set_PLC_3105 (  );			//上电为3105模式
  
  SSC_ADR=0xFF;
  SSC_DAT=0xFF;
  SSC_ADR=0x02;
  SSC_DAT=0x1F;
  SSC_ADR=0xFF;
  SSC_DAT=0x00;
  
//************   3201的载波寄存器设置  **********//
  EIE=0X01;       										 //  ( A9H 使能INT2中断(EX2=1)
  IT2=1;          										 //  ( C8H ) 为边沿触发方式(IT2=1)
  
  //串口通讯配置
  TMOD = 0x21 ;     	                 // 设 T/C1 为定时方式2 设置为8位自装载计数器  T/C0 为定时方式 14
  SCON=0x50;                           // 工作方式1
  
  PCON=0X80;                           // 波特率加倍
  TH1=0xf6;
  TL1=0xf6;                            // 加倍设定波特率 9.6MHz ( PL3105按4800计算) 下数 F6H
  TR1=1;                               // 启动定时器1
    
  // 定时器0中断配置
  TH0=0x63; 
  TL0=0xcc;   												 // 定时 50 ms 一个定时中断
  TR0 = 1;               							 // 启动 T0 定时器
  // 中断级别设置
  IP=0x02;              							 // 定时器 T0 中断为高级中断
  EIP=1;                 							 // 外部中断2 为高级中断
  // 中断允许设置
  IE=0x82;							               // 允许ET0=1定时器 T0 中断;  开放中断
}
/**************************************************************************************
 *
 * FUNCTION:    initsys_ref
 *
 * DESCRIPTION: 初始化重置函数,
 *              进行系统初始化重置
 *
 * PARAMETERS:  none
 *
 * RETURNED:    none
 *
 *************************************************************************************/
void initsys_ref( void )
{  // 载波设置重置
   uchar  data s1;
   uchar  data GOLD_KSAMI;

   if ( EIE!=1 )
      EIE=0X01;       					//  ( A9H 使能INT2中断(EX2=1)
   if ( IT2!=1 )	
      IT2=1;  					        //  ( C8H ) 为边沿触发方式(IT2=1)

   SSC_ADR=0x02;
   GOLD_KSAMI=SSC_DAT;
   if ( GOLD_KSAMI!=0x1F )
   {
      SSC_ADR=0xFF;
      SSC_DAT=0xFF;
      SSC_ADR=0x02;
      SSC_DAT=0x1F;
      SSC_ADR=0xFF;
      SSC_DAT=0x00;
   }

   // 串口设置重置
   if ( TMOD!=0x21 )
      TMOD = 0x21 ;   // 设 T/C1 为定时方式2 设置为8位自装载计数器  T/C0 为定时方式 14
   if ( PCON!=0x80 )
      PCON=0X80;      // 波特率加倍

   s1=SCON;
   s1=s1&0xf0;
   if ( s1!=0x50 )
     initsys ();

⌨️ 快捷键说明

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