/**************************************************************************
程序功能说明:
从机程序
**************************************************************************/
#include "pic18.h"
#include "delay.c"
#define rs485_out 1 //
#define rs485_in 0 //
#define work_check1 RB0 //机器1工作状态
#define work_check2 RB1 //机器2工作状态
#define work_check3 RB2 //机器3工作状态
#define clr_mem_key RC5 //清除内部记忆数据
#define rs458_control RB4 //RS485发射/接收控制脚
#define DISPLAY RA4 //指示
//********************************15秒定时器*******************************
unsigned char TIMER15S1; //输出刷新时间
unsigned char TIMER15S2; //电压电流采样间隔时间
unsigned char TIMER15S3; //功采样时间----6秒一次
unsigned char TIMER15S4; //清除数据按键按下时间
unsigned char TIMER15S5;
unsigned char TIMER15S6;
//********************************1小时定时器*******************************
unsigned int TIMER1H1;
unsigned int TIMER1H2;
unsigned int TIMER1H3;
//*******************************系统内部数据*******************************
unsigned char machine_status[3]; //3台机器的工作状态
unsigned int total_machine_time[3]; //3台机器的连续工作时间---单位是1小时
unsigned int study_per; //交流电功率因数
unsigned int u_data; //电压
unsigned int i_data; //电流
unsigned int s_data; //视在功率
unsigned int w_data; //6秒钟用掉的瓦*秒
unsigned char watt_data[7]; //瓦特
unsigned char rec_cout; //串口接收到的字节数
unsigned char rec_ok; //接收正确完成
unsigned char rec_data[4]; //串口接收到的数据
unsigned char self_address; //从机自身地址
/***************************************************************************
初始化输入输出IO
***************************************************************************/
void init_input(void)
{
TRISA=0xef; //
PORTB=0x00;
TRISB=0xef; //
PORTB=0x00; //
TRISC=0xff;
PORTC=0x00; //
}
/***************************************************************************
初始化定时器0用做定时器延迟用
***************************************************************************/
void init_timer0(void)
{
T0CON=0x08; //设定TMR0工作在16位定时器方式,使用内部时钟,不分频
INTCON=INTCON|0x20; //设置允许TMR0中断
INTCON=INTCON&0xfb; //清除TMR0中断标志
TMR0IP=1; //设置TMR0中断为高优先级
TMR0ON=1; //打开定时器0
}
/***************************************************************************
初始化定时器1用做捕捉用
***************************************************************************/
void init_timer1(void)
{
T1CON=0x89; //打开定时器1
}
/***************************************************************************
初始化捕捉
***************************************************************************/
void init_ccp(void)
{
TRISC2=1;
PEIE=1;
CCP1IE=1;
CCP1IP=1;
}
/***************************************************************************
设置捕捉方式---上升沿下降沿都捕捉,来检测脉冲的宽度
***************************************************************************/
void init_ccp_hi_lo(unsigned char hi_lo)
{
switch(hi_lo)
{
case 1: //设置成下降沿捕捉
{
CCP1CON=0x04;
TMR1L=0;
TMR1H=0;
TMR1L=0;
break;
}
case 2: //设置成上升沿捕捉
{
CCP1CON=0x05;
TMR1L=0;
TMR1H=0;
TMR1L=0;
break;
}
}
}
/***************************************************************************
初始化AD
***************************************************************************/
void init_ad(void)
{
ADCON1=0x85; //右对齐格式,并且使能2个通道。
ADCON0=0x81; //打开AD模块
}
/***************************************************************************
切换电压---电流采样通道
***************************************************************************/
void change_ad_channel(unsigned char channel)
{
switch(channel)
{
case 1: //选择AD通道1
{
CHS0=0;
break;
}
case 2:
{
CHS0=1; //选择AD通道2
break;
}
}
}
/***************************************************************************
读取电压或者电流的数据
***************************************************************************/
unsigned int ad_value(void)
{
unsigned int temp;
GODONE=1;
while(GODONE);
temp=ADRESL+(ADRESH<<8);
return (temp);
}
/***************************************************************************
初始化串口
***************************************************************************/
void init_com(void)
{
TXSTA=0x04;
RCSTA=0x80;
TRISC|=0x80;
TRISC&=~0x40;
SPBRG=25;
PIR1=0;
PIE1|=0x20;
RCIP=1;
CREN=1;
TXEN=1;
}
/***************************************************************************
上电初始化从机
***************************************************************************/
void init_slave(void)
{
init_input();
init_timer0();
init_timer1();
init_ccp();
CCP1CON=0x04;
TMR1L=0;
TMR1H=0;
TMR1L=0;
init_ad();
init_com();
self_address=PORTC&0x03;
self_address+=1;
IPEN=1; //中断优先使能
ei();
}
/***************************************************************************
电压---电流相位差检测,采用捕捉功能,捕捉电压电流共同存在的时间,最大为10MS
***************************************************************************/
void interrupt HI_ISR()
{
unsigned int temp;
unsigned char temp_8;
if(TMR0IF)//60MS中断
{
TMR0IF=0;
TMR0H=0x15;
TMR0L=0x9f;
TIMER15S1++;
TIMER15S2++;
TIMER15S3++;
TIMER15S4++;
TIMER15S5++;
TIMER15S6++;
TIMER1H1++;
TIMER1H2++;
TIMER1H3++;
}
if(CCP1IF)
{
CCP1IF=0;
switch(CCP1CON)
{
case 0x04: //下降沿捕捉
{
init_ccp_hi_lo(2); //设置成上升沿捕捉
temp=CCPR1L+(CCPR1H<<8);
temp=temp%10000;
study_per=temp/10; //功率因数为千分数
break;
}
case 0x05: //上升沿捕捉
{
init_ccp_hi_lo(1); //设置成下降沿捕捉
temp=CCPR1L+(CCPR1H<<8);
break;
}
}
}
if(RCIF)
{
RCIF=0;
temp_8=RCREG;
if(temp_8=='{')//一包数据的开始
{
rec_cout=0;
}
else if(temp_8=='}')//一包数据的结束
{
if(rec_cout==3)
{
if((((rec_data[0]-48)+(rec_data[1]-48))%10)==(rec_data[2]-48))
{
if((((rec_data[0]-48)*10)+(rec_data[1]-48))==(self_address))
{
rec_ok=1;
}
}
}
}
else
{
rec_data[rec_cout++]=temp_8;
}
if(rec_cout>4)
{
rec_cout=0;
}
}
}
/***************************************************************************
发一个字节到串口
***************************************************************************/
void send_char(unsigned char data)
{
TXREG=data;
while(!TXIF);
TXIF=0;
}
/***************************************************************************
发字符串到串口
***************************************************************************/
void send_string(const unsigned char *add)
{
while(*add)
{
send_char(*add);
add++;
}
}
/***************************************************************************
计算视在功率
***************************************************************************/
void caculate_p(void)
{
unsigned long temp_32;
temp_32=u_data;
temp_32=temp_32*i_data;
temp_32=(temp_32*study_per)/16000;
s_data=temp_32;
}
/***************************************************************************
保存电度数
***************************************************************************/
void write_watt(void)
{
unsigned long temp_32;
unsigned char n;
temp_32=s_data;
temp_32=(temp_32*6)/10;
temp_32=temp_32+w_data;
n=temp_32/36000;
w_data=temp_32%36000;
if(n)
{
watt_data[6]+=n;
if(watt_data[6]>9)
{
watt_data[6]=watt_data[6]%10;
watt_data[5]++;
if(watt_data[5]>9)
{
watt_data[5]=0;
watt_data[4]++;
if(watt_data[4]>9)
{
watt_data[4]=0;
wa
- 1
- 2
前往页