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

📄 beacon.c

📁 此源码为商用的电力抄表系统的从机端源程序。通过电力载波模块
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *****************************************************************************
				 Becaon send and process module. Used for system debug and test
 *******************************************************************************/
#include "absacc.h"
#include "stdlib.h"
#include "beacon.h"
#include "timer.h"
#include "plc.h"
#include "sart.h"
#include "wr_flash.h"
#define uint unsigned int
#define uchar unsigned char

#define  BUFFER_WR_TXBUF	0x7F
#define  BEACON_FRAME 0xFF
#define	 BEACON_TABLE_NM	   15
#define  BEACON_FRAME_COUNT	   10
#define  BEACON_RX_FRAME_COUNT 10

#define  BEACON_INTERVAL	100	// * 10ms
#define  BEACON_RX_INTERVAL	230	// * 10ms

extern code uchar  METER_ADDR[6];
uchar  code  reg_setting[2]; // reg_setting[0]: Gain, reg_setting[1]: amplitue
//#define  self_address_R 0x00 
//#define  self_address_L 0x01

uchar tm1_count, count1_reload; 
uchar inter1;

void (*beacon_timer_proc)();   // Agilent beacon timer 
idata uchar beacon_timer_count;
idata uchar beacon_timer_val;
bit beacon_timer_enable;

void (*beacon_rx_timer_proc)();   // Agilent beacon timer 
idata uchar beacon_rx_timer_count;
idata uchar beacon_rx_timer_val;
bit beacon_rx_timer_enable;

void delay(uint cnt);


/* transmit beacon contiously from beacon mode PLM, beacon sequence number increase from 0 to beacon_num
  beacon_interval is the timer to control interval between two beacon 	 							*/


extern idata uchar plc_frame[18];
idata char beacon_frame_count,beacon_rx_frame_count;
code struct link_status link_status_1[15];

extern idata uchar thres_ea;

void plc_tx_beacon();

void beacon_time_out();
void enable_beacon_timer();
void disable_beacon_timer(void);

void beacon_rx_time_out();
void enable_beacon_rx_timer();
void disable_beacon_rx_timer(void);

//void write_table(unsigned char i, unsigned char ave_ea, unsigned char ave_eb);

void write_table(uchar i, uchar add_R, uchar add_L, uchar ave_ea, uchar ave_eb,uchar succ_rate);

// beacon_interval * 10ms is the real interval between beacon
void send_beacon()
{
   uchar i, k;
   setup_beacon_timer(BEACON_INTERVAL, beacon_time_out);
   beacon_frame_count = 0;
   enable_beacon_timer();

   while(beacon_frame_count < BEACON_FRAME_COUNT){;}
   	
   disable_beacon_timer();

   // after finish tx beacon, keep on flashing RXOK to indicate this node has finish beacon transmission
   while(1)
   {
		for (k=1; k<=5; k++)
		{
//			clr_wdt();

		 	delay (50000);
			delay (50000);
			//brightening
			for (i=1; i<=100; i++)	// define 100 steps
			{
//				clr_wdt();
				Rxok = 0;	
				delay (i*100);
				Rxok = 1;
				delay (10100-i*100);
			}

			for (i=1; i<=50; i++)
			{				
//				clr_wdt();
				Rxok = 0;
				delay (10200-i*200);
				Rxok = 1;
				delay (i*200);
			}
		}
   }
}

void delay (uint cnt)
{
  while (--cnt);
}

void beacon_time_out()
{
//	 clr_wdt();
     disable_beacon_timer();
	 	
     plc_tx_beacon();
	 beacon_frame_count++;
	 /* set up timer seconds again. */
     enable_beacon_timer();
}

void enable_beacon_timer(void)
{
  beacon_timer_count = 0;
  beacon_timer_enable = 1;
}

void disable_beacon_timer(void)
{
  beacon_timer_count = 0;
  beacon_timer_enable = 0;
}

/**************************************************************************************
					Beacon
 **************************************************************************************/
void plc_tx_beacon(void)
{
	uchar i;
	uchar self_address_R,self_address_L;
	
	self_address_R = METER_ADDR[0];	
	self_address_L = METER_ADDR[1];
	 
	plc_frame[0] = self_address_R; // local address high byte
	plc_frame[1] = self_address_L; // local address low byte
	plc_frame[2] = self_address_R; // local address high byte
	plc_frame[3] = self_address_L; // local address low byte
	
	plc_frame[4] = 0xcc; // beacon command
	plc_frame[5] = 0xBC; // padding
	plc_frame[6] = beacon_frame_count;

	for(i=7;i<18;i++)
	{plc_frame[i] = 0xBC;}

	sync_sendchar(BUFFER_WR_TXBUF);
	send_block(plc_frame, 18);

	send();
	while (TX_BUSY == 0);  // wait tx finish
}

/**************************************************************************************
					Receive Beacon Frame and process, record Ea and Eb, Save to Flash
 **************************************************************************************/

void beacon_rx_process()
{
	unsigned char local_address_R, local_address_L;
	unsigned char average_ea , average_eb;
	unsigned char i,j,min_ea, wr_ea_index;
	bit flag_first_frame; // when the first frame come in, = 1, average_ea  and average_eb do not average
						  // after that, each frame come in, average Ea and Eb with last value.

	unsigned char success_received_frame;
//	unsigned char beacon_reply_frame[18];
	
	local_address_R	= METER_ADDR[0];
	local_address_L = METER_ADDR[1];

	average_ea = 0;
	average_eb = 0;
	beacon_rx_frame_count = 0;

	setup_beacon_rx_timer(BEACON_RX_INTERVAL, beacon_rx_time_out);
	disable_beacon_rx_timer();
    
	// for debug only
	uart_sendchar(0XFF);
	uart_sendchar(0XFF);
	uart_sendchar(0XFF);
	uart_sendchar(0XFF);

	for(i=0;i<BEACON_TABLE_NM;i++)
	{
		uart_sendchar(link_status_1[i].address_R);
		uart_sendchar(link_status_1[i].address_L);
		uart_sendchar(link_status_1[i].average_ea);
		uart_sendchar(link_status_1[i].average_eb);
		uart_sendchar(link_status_1[i].success_rate); 
		
	}

	uart_sendchar(reg_setting[0]);
	uart_sendchar(reg_setting[1]);

	// end of for debug
	while(1)
	{
		if (plc_recved()) 
		{
			plc_getframe(plc_frame);	 //* read  the frame in

		    if(!read_crc())
			{

				RXOK = 0;
				
				// PROCESS BEACON FRAME
				// source address = destination address, 0xCC means beacon beacon frame
				if ((plc_frame[0]==plc_frame[2])&&(plc_frame[1]==plc_frame[3])&& (plc_frame[4]==0xcc))
				{ 	

					// clear the rx_timer, start it once process finished
					disable_beacon_rx_timer(); 

					if(flag_first_frame == 0)
					{
						average_ea = read_reg(0XEA);
						average_eb = read_reg(0xEB);
						flag_first_frame = 1; 		// clear first frame flag
					}
					else
					{	
						average_ea = (average_ea + read_reg(0XEA))>>1;
						average_eb = (average_eb + read_reg(0xEB))>>1;
					}
	
					success_received_frame++;  

					// Synchrnize the rx_count with tx_count
					beacon_rx_frame_count = plc_frame[6];
				   
					uart_sendchar(0x99);
	
					for(i=0;i<18;i++)
					{
						uart_sendchar(plc_frame[i]);
					}
	
					uart_sendchar(average_ea);
					uart_sendchar(average_eb);
					uart_sendchar(success_received_frame);
	
					// once successfully receive a frame, start up rx timer, if tx timer out
					// still not receive another frame, excute beacon_rx_time_out()
					if (beacon_rx_frame_count!= BEACON_RX_FRAME_COUNT-1)
					{
						enable_beacon_rx_timer();
					}
				}

		        // read out link table. 00 00 is source address. 
				// to read out the table, FF as read command
				if ((plc_frame[0]==0x00)&&(plc_frame[1]==0x00)&&(plc_frame[2]==local_address_R)&&(plc_frame[3]==local_address_L)&&(plc_frame[4]==0xFF))
				{
					send_table();
				}
				
				// clear the table, C0 as clear table command. When finish clear table
				// use C1 to reply	
				if ((plc_frame[0]==0x00)&&(plc_frame[1]==0x00)&&(plc_frame[2]==local_address_R)&&(plc_frame[3]==local_address_L)&&(plc_frame[4]==0xC0))
				{
					clear_table();
						
					// send back the ACK to confirm table is cleared. CMD 0xC1
					plc_frame[0] = local_address_R;
					plc_frame[1] = local_address_L;
					plc_frame[2] = 0x00;
					plc_frame[3] = 0x00;
					plc_frame[4] = 0xC1;

					sync_sendchar(BUFFER_WR_TXBUF);
					send_block(plc_frame, 18);
					send();
					while (TX_BUSY == 0);  // wait tx finish
				}

				// change register value through power line
				// the command is 0xC2, repeat the command three times to gerantee no mistakes happen 

				if ((plc_frame[0]==0x00)&&(plc_frame[1]==0x00)&&(plc_frame[2]==local_address_R)&&(plc_frame[3]==local_address_L)&&(plc_frame[4]==0xc2)&&(plc_frame[8]==0xc2)&&(plc_frame[12]==0xc2))
				{
					// check whether the repeated 3 times value are the same.
					if((plc_frame[5]==plc_frame[9])&&(plc_frame[5]==plc_frame[13])&&(plc_frame[6]==plc_frame[10])&&(plc_frame[6]==plc_frame[14]))
					{
						
    					EA = 0; // disable all interrupt when writing flash 
						FLASH_WriteByte((int code *)&reg_setting[0], plc_frame[5]);
						FLASH_WriteByte((int code *)&reg_setting[1], plc_frame[6]);
						EA = 1; // enable all interrupt after finishing writing flash
					
						// send back the ACK to confirm the register write is finished. CMD 0xC3
						plc_frame[0]  = local_address_R;
						plc_frame[1]  = local_address_L;
						plc_frame[2]  = 0x00;
						plc_frame[3]  = 0x00;
						plc_frame[4]  = 0xC3;
						plc_frame[8]  = 0xC3;
						plc_frame[12] = 0xC3;

						// delay for several ms before send reply
						for(i=0;i<250;i++)
						for(j=0;j<250;j++);

						sync_sendchar(BUFFER_WR_TXBUF);
						send_block(plc_frame, 18);
						send();
						while (TX_BUSY == 0);  // wait tx finish
					}
					else
					{
						// if command not correct, reply with cmd 0xC4
						plc_frame[0] = local_address_R;
						plc_frame[1] = local_address_L;
						plc_frame[2] = 0x00;
						plc_frame[3] = 0x00;

⌨️ 快捷键说明

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