program.c
/********************************************
program8.c
说明:带CAN通讯功能的两路充电器程序代码
主控芯片:PIC16F887
引脚关系:
芯片时钟:16Mhz
CAN通讯速率:125Kb/s
Author:Alex
Date:2016/01/28 12:09
File:
********************************************/
#include
__CONFIG (CP_OFF &WDTE_OFF& BOREN_OFF&PWRTE_OFF &FOSC_HS&WRT_OFF&LVP_OFF&CPD_OFF);
void main()
{
/****定义临时无符号整形变量****/
/****定义临时整形变量****/
int i;
/****定义临时浮点型整形变量****/
count=0;
CAN_FLAG=0; /*开机复位,清接收到标志*/
canreflag=0;
Init_PWM(); /*初始化配置PWM*/
Init_Int(); /*初始化中断*/
Init_Spi(); /*初始化SPI*/
Init_Can(); /*初始化CAN通讯*/
Usart_init(); /*初始化串口通讯*/
Bat_init(); /*初始化左右侧电池的状态标志位*/
TRISE=0X00;
PORTE=0x00;
ENA=1; /*关掉2路通讯*/
delay(500); /*延时1秒*/
while(1)
{
if(RD2==0) /*左电池盒闭合状态*/
{
delay(30); /*延时去抖*/
if(RD2==0) /*此时开关处于闭合状态,有电池插入电池盒*/
{
Bat_1.in=1; /*将左电池进入充电站标志位置1*/
}
}
else /*左电池盒打开状态*/
{
Bat_1.in=0; /*将左电池进入充电站标志位清零*/
}
if(RD3==0) /*右电池盒闭合状态*/
{
delay(30); /*延时去抖*/
if(RD3==0) /*此时开关处于闭合状态,有电池插入电池盒*/
{
Bat_2.in=1; /*将左电池进入充电站标志位置1*/
}
}
else /*左电池盒打开状态*/
{
Bat_2.in=0; /*将左电池进入充电站标志位清零*/
}
if(Bat_1.in==1) /*左侧电池盒闭合的时候*/
{
if(Bat_1.init==0) /*左侧电池盒初始化未完成*/
{
delay(500); /*延时1秒*/
LeftBattery_Init(); /*左侧电池盒初始化*/
if(Bat_1.init==1) /*左侧电池盒初始化完成*/
{
LeftBattery_Deal(); /*左侧电池盒控制电流充电*/
}
}
else /*左侧电池盒初始化已完成*/
{
LeftBattery_Deal(); /*左侧电池盒控制电流充电*/
}
}
else /*左侧电池盒打开的时候*/
{
Bat_1_Reset(); /*左侧电池状态复位*/
}
if(Bat_2.in==1) /*右侧电池盒闭合的时候*/
{
if(Bat_2.init==0) /*右侧电池盒初始化未完成*/
{
if(Bat_1.init==0) /*左侧电池盒初始化未完成*/
{
//delay(200); /*延时1秒*/
LeftBattery_Init(); /*左侧电池盒初始化*/
if(Bat_1.init==1) /*左侧电池盒初始化完成*/
{
LeftBattery_Deal(); /*左侧电池盒控制电流充电*/
}
}
ENA=0; /*打开2路通讯*/
delay(500); /*延时1秒*/
RightBattery_Init(); /*右侧电池盒初始化*/
if(Bat_2.init==1) /*左侧电池盒初始化完成*/
{
RightBattery_Deal(); /*右侧电池盒控制电流充电*/
}
}
else /*右侧电池盒初始化已完成*/
{
RightBattery_Deal(); /*右侧电池盒控制电流充电*/
}
}
else /*右侧电池盒不在里面的时候*/
{
Bat_2_Reset(); /*右侧电池状态复位*/
}
if(count%20==0) /*采集两路的温度值,根据温度控制风扇。*/
{
show_temp();
}
count++;
}
}
/*****************************************************************/
#ifndef __program8_H__
#define __program8__
#include "pic.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define nop() asm("nop")
#define CS RD1 /*标签为CANCSRH4*/
#define RESET RD0 /*标签为RESETCAN*/
#define FAN RC0 /*定义风扇*/
void Init_Int(void); /*初始化中断*/
void interrupt ISR(void); /*中断处理函数*/
#endif
/********************************************************
MCP2515 CAN通讯程序,测试CAN协议
**********************************************************/
#include
/***************************
函数:void Init_Can(void)
函数描述:初始化CAN通讯
变量:无
*****************************/
void Init_Can(void)
{
RESET=1; /*关闭复位*/
CS=1; /*关闭片选*/
CS=0; /*打开片选,选中MCP2515*/
/**************************************
复位MCP2515 进入配置模式,以便配置寄存器。
****************************************/
SPIReset(); /*SPI复位*/
CS=1; /*关闭片选*/
delay(20); /*延时20ms*/
/**设置为配置模式**/
/*配置验收屏蔽滤波器0*/
CAN_Write(RXM0SIDH, 0x00); //为0时,对应的滤波位不起作用
CAN_Write(RXM0SIDL,0x00);
/*配置验证滤波器0*/
CAN_Write(RXF0SIDH,0x00); //标准标识符高字节
CAN_Write(RXF0SIDL,0x00); //标准标识符低字节
/**设置通讯速率 晶振16M 波特率125Kbps**/
CAN_Write(CNF1,CAN_125Kbps); //CNF1=0x07
//set CNF1,SJW=00,长度为1TQ,BRP=49,TQ=[2*(BRP+1)]/Fsoc=2*50/8M=12.5us,16M
//配置寄存器1,默认CAN波特率为125Kbit/s
CAN_Write(CNF2,0x80|PHSEG1_3TQ|PRSEG_1TQ); //3,1;6,2
//set CNF2,SAM=0,在采样点对总线进行一次采样,PHSEG1=(2+1)TQ=3TQ,PRSEG=(0+1)TQ=1TQ
//配置寄存器2,位时间为3TQ,同步段1TQ
//传播段1TQ,PHSEG1=3TQ,PRSEG=1TQ
CAN_Write(CNF3,PHSEG2_3TQ); //3;7 配置寄存器3,唤醒滤波器使能
//set CNF3,PHSEG2=(2+1)TQ=3TQ,同时当CANCTRL.CLKEN=1时设定CLKOUT引脚为时间输出使能位
//set TXB0,设置发送缓冲器0的标识符和发送的数据,以及发送的数据长度
/*配置发送缓冲区0,发送标准数据帧到ID:0X00的CAN节点*/
CAN_Write(TXB0SIDH,0x06); //标准标识符高字节
CAN_Write(TXB0SIDL,0x00); //标准标识符低字节
CAN_Write(TXB0DLC,DLC_8); //设置发送数据的长度为8个字节,DLC_8
//设置接收缓冲器0的标识符和初始化数据
CAN_Write(RXB0SIDH,0x00); //设置接收缓冲器0的标准标识符,待修改***
CAN_Write(RXB0SIDL,0x60); //用到标准标识符
CAN_Write(RXB0CTRL,0x60); //仅仅接收标准标识符的有效信息,FIILHIT0=0表示RXB0 ,采用FILHIT0
CAN_Write(RXB0DLC,DLC_8); //设置接收数据的长度为8个字节,DLC_8
/*配置验收滤波器*/
CAN_Write(RXF0SIDH,0xFF); //标准标识符高字节
CAN_Write(RXF0SIDL,0xE0); //标准标识符低字节
/*配置验收屏蔽滤波器0*/
CAN_Write(RXM0SIDH,0xFF); //标准标识符高字节
CAN_Write(RXM0SIDL,0xE0); //标准标识符低字节
//设置接收缓冲器0中断
CAN_Write(CANINTF,0x00); //清空中断标志位
CAN_Write(CANINTE,0x01); //接收缓冲器0满中断使能位
CAN_Write(CANCTRL,REQOP_NORMAL|CLKOUT_ENABLED); //设置正常模式
delay(10);
dummy=CAN_Read(CANSTAT); //读取CAN状态寄存器的值
if (OPMODE_NORMAL != (dummy && 0xE0)) //判断进入正常工作模式
CAN_Write(CANCTRL,REQOP_NORMAL | CLKOUT_ENABLED); //设置正常模式
}
/***************************
函数:void CAN_Send(unsigned char *CAN_TX_Buf)
函数描述:CAN发送数据程序
变量:无
*****************************/
void CAN_Send(unsigned char *CAN_TX_Buf)
{
unsigned char tempdata;
tempdata=CAN_Read(CAN_RD_STATUS);
CAN_Write(TXB0D0,CAN_TX_Buf[0]);
CAN_Write(TXB0D1,CAN_TX_Buf[1]);
CAN_Write(TXB0D2,CAN_TX_Buf[2]);
CAN_Write(TXB0D3,CAN_TX_Buf[3]);
CAN_Write(TXB0D4,CAN_TX_Buf[4]);
CAN_Write(TXB0D5,CAN_TX_Buf[5]);
CAN_Write(TXB0D6,CAN_TX_Buf[6]);
CAN_Write(TXB0D7,CAN_TX_Buf[7]);
if(tempdata&0x04)//判断TXREQ标志位
{
delay(5);
CAN_Write(TXB0CTRL,0);//清除TXREQ标志位
while(CAN_Read(CAN_RD_STATUS)&0x04);//等待TXREQ清零
}
CS=0;
SPISendByte(CAN_RTS_TXB0);//发送缓冲器0请求发送
CS=1;
}
/***************************
函数:void CAN_Send_onebyte(unsigned char k)
函数描述:CAN发送一个字节数据程序
变量:无
*****************************/
void CAN_Send_onebyte(unsigned char k)
{
unsigned char tempdata;
tempdata=CAN_Read(CAN_RD_STATUS);
CAN_Write(TXB0D0,k);
if(tempdata&0x04)//判断TXREQ标志位
{
delay(5);
CAN_Write(TXB0CTRL,0);//清除TXREQ标志位
while(CAN_Read(CAN_RD_STATUS)&0x04);//等待TXREQ清零
}
CS=0;
SPISendByte(CAN_RTS_TXB0);//发送缓冲器0请求发送
CS=1;
}
/***************************
函数:void CAN_Receive(unsigned char *CAN_RX_Buf)
函数描述:CAN接收程序
变量:无
*****************************/
void CAN_Receive(unsigned char *CAN_RX_Buf)
{
// unsigned char tempdata;
// tempdata=CAN_Read_SS(CAN_RX_STATUS);
// if(tempdata&0x40)//说明接收的是RXB0中的标准数据帧
// {
// delay(1);
// CS=0;
// SPISendByte(CAN_RX_Buf);//将接收的首地址定为RXB0D0
CAN_RX_Buf[0]=CAN_Read(RXB0D0);
CAN_RX_Buf[1]=CAN_Read(RXB0D1);
CAN_RX_Buf[2]=CAN_Read(RXB0D2);
CAN_RX_Buf[3]=CAN_Read(RXB0D3);
CAN_RX_Buf[4]=CAN_Read(RXB0D4);
CAN_RX_Buf[5]=CAN_Read(RXB0D5);
CAN_RX_Buf[6]=CAN_Read(RXB0D6);
CAN_RX_Buf[7]=CAN_Read(RXB0D7);
CAN_Write(CANINTF,0);
// CS=1;
// }
}
/***************************
函数:unsigned char CAN_Receive_onebyte()
函数描述:CAN接收一个字节函数
变量:tempdata
*****************************/
unsigned char CAN_Receive_onebyte()
{
unsigned char tempdata;
//tempdata=SPIByteRead(CAN_RX_STATUS);
//if(tempdata&0x40)//说明接收的是RXB0中的标准数据帧
//{
// delay_ms(1);
//CS=LOW;
//WriteSPI(CAN_RX_BUFF);//将接收的首地址定为RXB0D0
tempdata=CAN_Read(RXB0D0);
CAN_Write(CANINTF,0);
return tempdata;
//CS=HIGH;
//}
}
/***************************
函数:void CAN_writetxb0id(unsigned int txb0id)
函数描述:位修改指令函数
变量:无
*****************************/
void CAN_writetxb0id(unsigned int txb0id)
{
CAN_Write(TXB0SIDH,(txb0id>>3));//设置发送缓冲器0的标准标识符,待修改***
CAN_Write(TXB0SIDL,(0x00FF&(txb0id<<5)));//用到标准标识符
}
/***************************
函数:void CAN_deal(void)
函数描述:CAN通讯接收处理函数
变量:无
*****************************/
void CAN_deal(void)
{
CAN_FLAG=0; /*清接收到标志*/
canrecebuf[0]=CAN_Read(RXB0D0);
canrecebuf[1]=CAN_Read(RXB0D1);
canrecebuf[2]=CAN_Read(RXB0D2);
canrecebuf[3]=CAN_Read(RXB0D3);
canrecebuf[4]=CAN_Read(RXB0D4);
canrecebuf[5]=CAN_Read(RXB0D5);
canrecebuf[6]=CAN_Read(RXB0D6);
canrecebuf[7]=CAN_Read(RXB0D7);
CAN_Write(CANINTF,0);
}
/***************************
函数:void CAN_0x21(int num)
函数描述:按地址0X21发送并接收数据,初始化第二步
变量:无
*****************************/
void CAN_0x21(int num)
{
/**访问地址0X0021**/
CAN_writetxb0id(0x0021);
if(num==1)
{
cansentbuf[0]=0x01; /*1为左侧电池盒 */
}
else
{
cansentbuf[0]=0x02; /*2为右侧电池盒*/
}
cansentbuf[1]=canrecebuf[0];
cansentbuf[2]=canrecebuf[1];
cansentbuf[3]=canrecebuf[2];
cansentbuf[4]=canrecebuf[3];
cansentbuf[5]=0x00;
cansentbuf[6]=0x00;
cansentbuf[7]=0x00;
CAN_Send(cansentbuf); /*发送数组,发送CAN通讯*/
delay(100); /*延时等待中断接收*/
CAN_deal(); /*接收数组*/
canjudgbuf[5]=canrecebuf[0];
canjudgbuf[6]=canrecebuf[1];
canjudgbuf[7]=canrecebuf[2];
// canjudgbuf[8]=canrecebuf[3];
canjudgbuf[9]=canrecebuf[7];
if(canreflag==1)
{
canreflag=0; /*清接收到标志*/
if(num==1)
{
for(int i=0;i<=4;i++) /*判断初始化过程中,两次接收到的条码是否一致。间接检验通讯是否正确进行*/
{
if(canjudgbuf[i]!=canjudgbuf[i+5])
{
Bat_1.init=0; /*初始化执行失败*/
break; /*若发现两次的的条码不对应,跳出循环,继续初始化 */
}
else
{
Bat_1.init=1; /*初始化执行成功*/
}
}
}
else
{
for(int i=0;i<=4;i++) /*判断初始化过程中,两次接收到的条码是否一致。间接检验通讯是否正确进行*/
{
if(canjudgbuf[i]!=canjudgbuf[i+5])
{
Bat_2.init=0; /*初始化执行失败*/
break; /*若发现两次的的条码不对应,跳出循环,继续初始化 */
}
else
{
Bat_2.init=1; /*初始化执行成功*/
}
}
}
}
else
{
Bat_2.init=0; /*初始化执行失败*/
}
for(int i=0;i<=9;i++) /*将判断的数组进行清零*/
{
canjudgbuf[i]=0;
}
}
/***************************
函数:void CAN_0x25(int num)
函数描述:按地址0X25发送并接收数据,读取电池故障信息。
变量:无
*****************************/
void CAN_0x25(int num)
{
/**访问地址0X0025**/
CAN_writetxb0id(0x0025);
if(num==1)
{
cansentbuf[0]=0x01; /*1为左侧电池盒 */
}
else
{
cansentbuf[0]=0x02; /*2为右侧电池盒*/
}
cansentbuf[1]=0x00;
cansentbuf[2]=0x29;
cansentbuf[3]=0x00;
cansentbuf[4]=0x00;
cansentbuf[5]=0x00;
cansentbuf[6]=0x00;
cansentbuf[7]=0x00;
CAN_Send(cansentbuf); /*发送数组,发送CAN通讯*/
delay(100); /*延时等待中断接收*/
CAN_deal(); /*接收数组*/
// canrecebuf[5]=1; /*模拟发送报文中有错误*/
if(canreflag==1)
{
canreflag=0; /*清接收到标志*/
if(num==1)
{
Bat_1.init=1; /*左电池盒初始化标志位为1*/
}
else
{
Bat_2.init=1; /*右电池盒初始化标志位为1*/
}
if(num==1)
{
for(i=0;i<7;i++) /*将故障数据的值按位或*/
{
Bat_1.error=Bat_1.error||canrecebuf[i];
}
Bat_1.error1=canrecebuf[0]||canrecebuf[2]||canrecebuf[3]; /*左电池过压、温度故障标志位*/
Bat_1.error2=canrecebuf[4]; /*左电池过流故障标志位*/
}
else
{
for(i=0;i<7;i++) /*将故障数据的值按位或*/
{
Bat_2.error=Bat_2.error||canrecebuf[i];
}
Bat_2.error1=canrecebuf[0]||canrecebuf[2]||canrecebuf[3]; /*左电池过压、温度故障标志位*/
Bat_2.error2=canrecebuf[4]; /*左电池过流故障标志位*/
}
for(i=0;i<7;i++) /*清接收数组*/
{
canrecebuf[i]=0;
}
}
else
{
if(num==1)
{
Bat_1.init=0; /*左电池盒初始化未成功,需要重新初始化*/
Bat_1_Reset(); /*左侧电池状态复位*/
}
else
{
Bat_2.init=0; /*右电池盒初始化未成功,需要重新初始化*/
Bat_2_Reset(); /*右侧电池状态复位*/
}
}
}
/***************************
函数:void CAN_0x26(int num)
函数描述:按地址0X26发送并接收数据,读取电池故障信息。
变量:无
*****************************/
void CAN_0x26(int num)
{
/**访问地址0X0026**/
CAN_writetxb0id(0x0026);
if(num==1)
{
cansentbuf[0]=0x01; //1为左侧电池盒
}
else
{
cansentbuf[0]=0x02; //2为右侧电池盒
}
cansentbuf[1]=0x00;
cansentbuf[2]=0x28;
cansentbuf[3]=0x00;
cansentbuf[4]=0x00;
cansentbuf[5]=0x00;
cansentbuf[6]=0x00;
cansentbuf[7]=0x00;
CAN_Send(cansentbuf); //发送数组,发送CAN通讯
delay(100); //延时等待中断接收
CAN_deal(); //接收数组
if(num==1)
{
Bat_1.Soc=canrecebuf[5];
}
else
{
Bat_2.Soc=canrecebuf[5];
}
// delay(100); //延时等待中断接收
canreflag=0; //清接收到标志
for(i=0;i<7;i++) /*清接收数组*/
{
canrecebuf[i]=0;
}
}
/***************************
函数:void Bat_1_Test(void)
函数描述:发0x20指令,判断左电池是否已经完成了初始化
变量:无
*****************************/
void Bat_1_Test(void)
{
/**访问地址0X0020**/
CAN_writetxb0id(0x0020);
cansentbuf[0]=0x01;
cansentbuf[1]=0x00;
cansentbuf[2]=0x27;
cansentbuf[3]=0x00;
cansentbuf[4]=0x00;
cansentbuf[5]=0x00;
cansentbuf[6]=0x00;
cansentbuf[7]=0x00;
CAN_Send(cansentbuf); /*发送数组,发送CAN通讯*/
delay(100); /*延时等待中断接收*/
CAN_deal(); /*接收数组*/
}
/***************************
函数:void Bat_2_Test(void)
函数描述:发0x20指令,判断左电池是否已经完成了初始化
变量:无
*****************************/
void Bat_2_Test(void)
{
/**访问地址0X0020**/
CAN_writetxb0id(0x0020);
cansentbuf[0]=0x02;
cansentbuf[1]=0x00;
cansentbuf[2]=0x27;
cansentbuf[3]=0x00;
cansentbuf[4]=0x00;
cansentbuf[5]=0x00;
cansentbuf[6]=0x00;
cansentbuf[7]=0x00;
CAN_Send(cansentbuf); /*发送数组,发送CAN通讯*/
delay(100); /*延时等待中断接收*/
CAN_deal(); /*接收数组*/
}
#ifndef __CAN_H__
#define __CAN_H__
// write your header here
#include
#include
#include
#include
#include
#include
#include
/*******************************************************************
* 波特率配置 *
*******************************************************************/
#define CAN_10Kbps 0x31
#define CAN_25Kbps 0x13
#define CAN_50Kbps 0x09
#define CAN_100Kbps 0x04
#define CAN_125Kbps 0x07
#define CAN_250Kbps 0x01
#define CAN_500Kbps 0x00
void Init_Can(void); /*初始化CAN通讯*/
void CAN_Send(unsigned char *CAN_TX_Buf); /*CAN发送数据程序*/
void CAN_Send_onebyte(unsigned char k); /*CAN发送一个字节数据程序*/
void CAN_Receive(unsigned char *CAN_RX_Buf); /*CAN接收程序*/
unsigned char CAN_Receive_onebyte(); /*CAN接收一个字节程序*/
void CAN_writetxb0id(unsigned int txb0id); /*位修改指令函数*/
void CAN_deal(void); /*CAN通讯接收处理函数*/
void CAN_0x21(int num); /*按地址0X21发送并接收数据,初始化第二步*/
void CAN_0x25(int num); /*按地址0X25发送并接收数据,读取电池故障信息。*/
void CAN_0x26(int num); /*按地址0X26发送并接收数据,读取电池状态信息。*/
void Bat_1_Test(void); /*发0x20指令,判断左电池是否已经完成了初始化*/
void Bat_2_Test(void); /*发0x20指令,判断右电池是否已经完成了初始化*/
#endif
#include
/****************************
函数:void Usart_init()
函数描述:串口初始化
变量:无
*******************************/
void Usart_init()
{
SPBRG=0X19;//SPBRG=25
BAUDCTL=0X00;//BAUDCTL:波特率控制寄存器,BRG16=0
TXSTA=0X20;//TXSTA:发送状态和控制寄存器,TX9=0,TXEN=1,SYNC=0,BRGH=0
RCSTA=0X80;//RCSTA:接收状态和控制寄存器,SPEN=1
}
/****************************
函数:void Show_array(char array[],int n)
函数描述:显示一个字符型的数组
变量:无
*******************************/
void Show_array(char array[],int n)//显示一个字符型的数组
{
for(j=0;j=1000))
{
flag_2=1; //置标志位,若此标志位为1,则说明是四位数
}
a=NUM/10000;
b=((NUM%10000)/1000);
c=((NUM%1000)/100);
d=((NUM%100)/10);
e=(NUM%10);
if(flag_1==1)
{
NUM1[0]=48; //ASCII码49对应的是数值1
NUM1[1]=48;
NUM1[2]=46;//NUM1[2]='.';显示小数点
NUM1[3]=(c+48);
NUM1[4]=(d+48);
NUM1[5]=(e+48);
NUM1[6]=86;//NUM1[5]='V';显示单位
for(j=1;j<7;j++){
TXREG=NUM1[j];
while(TRMT!=1){ // 不为一说明发送未完成,则等待
}
}
}
if(flag_2==1)
{
NUM1[0]=48; //ASCII码49对应的是数值1
NUM1[1]=(b+48); //ASCII码49对应的是数值1
NUM1[2]=46;//NUM1[2]='.';显示小数点
NUM1[3]=(c+48);
NUM1[4]=(d+48);
NUM1[5]=(e+48);
NUM1[6]=86;//NUM1[5]='V';显示单位
for(j=1;j<7;j++){
TXREG=NUM1[j];
while(TRMT!=1){ // 不为一说明发送未完成,则等待
}
}
}
if((flag_1==0)&&(flag_2==0))
{
NUM1[0]=(a+48); //ASCII码49对应的是数值1
NUM1[1]=(b+48); //ASCII码49对应的是数值1
NUM1[2]=46;//NUM1[2]='.';显示小数点
NUM1[3]=(c+48);
NUM1[4]=(d+48);
NUM1[5]=(e+48);
NUM1[6]=86;//NUM1[5]='V';显示单位
for(j=0;j<7;j++){
TXREG=NUM1[j];
while(TRMT!=1){ // 不为一说明发送未完成,则等待
}
}
}
flag_1=0;
flag_2=0;
}
/*显示采集到的数据,*.***A*/
/*数据显示精确到小数点下两位小数*/
void Show_num_3(int NUM)
{
int a,b,c,d,flag_1,flag_2;
flag_1=0;flag_2=0;
/*flag_1置位,说明数值范围为0~1000*/
/*flag_1置位,说明数值范围为1000~10000*/
char NUM1[6];//定义字符数组
/*判断数值所处的范围*/
if(NUM<1000){
flag_1=1; //置标志位,若此标志位为1,则说明是三位数
}
if((NUM<10000)&&(NUM>=1000)){
flag_2=1; //置标志位,若此标志位为1,则说明是四位数
}
a=NUM/1000;
b=((NUM%1000)/100);
c=((NUM%100)/10);
d=(NUM%10);
if(flag_1==1) /*三位数*/
{
NUM1[0]=48;
NUM1[1]=46;//NUM1[1]='.';显示小数点
NUM1[2]=(b+48);
NUM1[3]=(c+48);
NUM1[4]=(d+48);
NUM1[5]=65;//NUM1[5]='A';显示单位
for(j=0;j<6;j++){
TXREG=NUM1[j];
while(TRMT!=1){ // 不为一说明发送未完成,则等待
}
}
}
if(flag_2==1) /*四位数*/
{
NUM1[0]=(a+48);
NUM1[1]=46;//NUM1[2]='.';显示小数点
NUM1[2]=(b+48);
NUM1[3]=(c+48);
NUM1[4]=(d+48);
NUM1[5]=65;//NUM1[5]='A';显示单位
for(j=0;j<6;j++){
TXREG=NUM1[j];
while(TRMT!=1){ // 不为一说明发送未完成,则等待
}
}
}
flag_1=0;
flag_2=0;
}
/*****************************************************************/
#ifndef __USART_H__
#define __USART__
#include "pic.h"
#include
#include
int j;
void Usart_init();
void Show_array(char array[],int n);
void Show_num_4(int NUM);
void show_CCPRXL(int a,int b);
void Show_num_1(int NUM);/*显示采集到的数据,数据显示精确到小数点下两位小数,电压*/
void Show_num_3(int NUM);/*显示采集到的数据,数据显示精确到小数点下两位小数,电流*/
#endif
delay.c
#include
/********************************
函数名称:void delay(unsigned int n)
函数功能:毫秒延时
返回值:无
*********************************/
void delay(unsigned int n)
{
int j;
char k;
for(j=0;j0;k--)
nop();
}
/*****************************************************************/
#ifndef __DELAY_H__
#define __DELAY__
#define nop() asm("nop")
#include "pic.h"
/*毫秒延时函数*/
void delay(unsigned int n);
#endif
#ifndef _MCP2515_H_
#define _MCP2515_H_
// write your header here
//#pragma nolist
/*********************************************************************
* CAN MCP2510 C definitions file *
*********************************************************************
* Filename: 2515REGS.h *
* Date: 06/17/03 *
* File Version: 1.00 (Beta) *
*********************************************************************
* Functions: *
* Header file *
*********************************************************************
* Revision History: *
* 06/17/03 Updated from MCP2510.inc which was for the 756 board *
*********************************************************************/
/*******************************************************************
* Register Definitions *
* 寄存器定义 *
*******************************************************************/
/* Configuration Registers */
#define CANSTAT 0x0E //CAN状态寄存器
#define CANCTRL 0x0F //CAN控制寄存器
#define BFPCTRL 0x0C //接收引脚控制和状态寄存器
#define TEC 0x1C //发送错误计数器
#define REC 0x1D //接收错误计数器
#define CNF3 0x28 //配置寄存器3
#define CNF2 0x29 //配置寄存器2
#define CNF1 0x2A //配置寄存器1
#define CANINTE 0x2B //中断使能寄存器
#define CANINTF 0x2C //中断标志寄存器,写0则清除相应的中断
#define EFLG 0x2D //错误标志寄存器,最高两位必须由MCU复位
#define TXRTSCTRL 0x0D //发送请求引脚配置寄存器
/* Recieve Filters */
#define RXF0SIDH 0x00 //验收滤波器0标准标识符高字节
#define RXF0SIDL 0x01 //验收滤波器0标准标识符低字节
#define RXF0EID8 0x02 //验收滤波器0扩展标识符高字节
#define RXF0EID0 0x03 //验收滤波器0扩展标识符低字节
#define RXF1SIDH 0x04 //验收滤波器1标准标识符高字节
#define RXF1SIDL 0x05 //验收滤波器1标准标识符低字节
#define RXF1EID8 0x06 //验收滤波器1扩展标识符高字节
#define RXF1EID0 0x07 //验收滤波器1扩展标识符低字节
#define RXF2SIDH 0x08 //验收滤波器2标准标识符高字节
#define RXF2SIDL 0x09 //验收滤波器2标准标识符低字节
#define RXF2EID8 0x0A //验收滤波器2扩展标识符高字节
#define RXF2EID0 0x0B //验收滤波器2扩展标识符低字节
#define RXF3SIDH 0x10 //验收滤波器3标准标识符高字节
#define RXF3SIDL 0x11 //验收滤波器3标准标识符低字节
#define RXF3EID8 0x12 //验收滤波器3扩展标识符高字节
#define RXF3EID0 0x13 //验收滤波器3扩展标识符低字节
#define RXF4SIDH 0x14 //验收滤波器4标准标识符高字节
#define RXF4SIDL 0x15 //验收滤波器4标准标识符低字节
#define RXF4EID8 0x16 //验收滤波器4扩展标识符高字节
#define RXF4EID0 0x17 //验收滤波器4扩展标识符低字节
#define RXF5SIDH 0x18 //验收滤波器5标准标识符高字节
#define RXF5SIDL 0x19 //验收滤波器5标准标识符低字节
#define RXF5EID8 0x1A //验收滤波器5扩展标识符高字节
#define RXF5EID0 0x1B //验收滤波器5扩展标识符低字节
/* Receive Masks */
#define RXM0SIDH 0x20 //验收屏蔽寄存器0标准标识符高字节
#define RXM0SIDL 0x21 //验收屏蔽寄存器0标准标识符低字节
#define RXM0EID8 0x22 //验收屏蔽寄存器0扩展标识符高字节
#define RXM0EID0 0x23 //验收屏蔽寄存器0扩展标识符低字节
#define RXM1SIDH 0x24 //验收屏蔽寄存器1标准标识符高字节
#define RXM1SIDL 0x25 //验收屏蔽寄存器1标准标识符低字节
#define RXM1EID8 0x26 //验收屏蔽寄存器1扩展标识符高字节
#define RXM1EID0 0x27 //验收屏蔽寄存器1扩展标识符低字节
/* Tx Buffer 0 */
#define TXB0CTRL 0x30 //发送缓冲器0控制寄存器
#define TXB0SIDH 0x31 //标准标识符高字节
#define TXB0SIDL 0x32 //标准标识符低字节
#define TXB0EID8 0x33 //扩展标识符高字节
#define TXB0EID0 0x34 //扩展标识符低字节
#define TXB0DLC 0x35 //发送缓冲器0数据长度寄存器
#define TXB0D0 0x36 //发送缓冲器0数据寄存器起始地址
#define TXB0D1 0x37
#define TXB0D2 0x38
#define TXB0D3 0x39
#define TXB0D4 0x3A
#define TXB0D5 0x3B
#define TXB0D6 0x3C
#define TXB0D7 0x3D
/* Tx Buffer 1 */
#define TXB1CTRL 0x40 //发送缓冲器1控制寄存器
#define TXB1SIDH 0x41 //标准标识符高字节
#define TXB1SIDL 0x42 //标准标识符低字节
#define TXB1EID8 0x43 //扩展标识符高字节
#define TXB1EID0 0x44 //扩展标识符低字节
#define TXB1DLC 0x45 //发送缓冲器1数据长度寄存器
#define TXB1D0 0x46 //发送缓冲器1数据寄存器起始地址
#define TXB1D1 0x47
#define TXB1D2 0x48
#define TXB1D3 0x49
#define TXB1D4 0x4A
#define TXB1D5 0x4B
#define TXB1D6 0x4C
#define TXB1D7 0x4D
/* Tx Buffer 2 */
#define TXB2CTRL 0x50 //发送缓冲器2控制寄存器
#define TXB2SIDH 0x51 //标准标识符高字节
#define TXB2SIDL 0x52 //标准标识符低字节
#define TXB2EID8 0x53 //扩展标识符高字节
#define TXB2EID0 0x54 //扩展标识符低字节
#define TXB2DLC 0x55 //发送缓冲器2数据长度寄存器
#define TXB2D0 0x56 //发送缓冲器2数据寄存器起始地址
#define TXB2D1 0x57
#define TXB2D2 0x58
#define TXB2D3 0x59
#define TXB2D4 0x5A
#define TXB2D5 0x5B
#define TXB2D6 0x5C
#define TXB2D7 0x5D
/* Rx Buffer 0 */
#define RXB0CTRL 0x60 //接收缓冲器0控制寄存器
#define RXB0SIDH 0x61 //接收缓冲器0标准标识符高字节
#define RXB0SIDL 0x62 //接收缓冲器0标准标识符低字节
#define RXB0EID8 0x63 //接收缓冲区0扩展标识符高字节
#define RXB0EID0 0x64 //接收缓冲区0扩展标识符低字节
#define RXB0DLC 0x65 //接收缓冲区0数据码长度
#define RXB0D0 0x66 //接收缓冲区0数据寄存器起始地址
#define RXB0D1 0x67
#define RXB0D2 0x68
#define RXB0D3 0x69
#define RXB0D4 0x6A
#define RXB0D5 0x6B
#define RXB0D6 0x6C
#define RXB0D7 0x6D
/* Rx Buffer 1 */
#define RXB1CTRL 0x70 //接收缓冲器1控制寄存器
#define RXB1SIDH 0x71 //接收缓冲器0标准标识符高字节
#define RXB1SIDL 0x72 //接收缓冲器0标准标识符低字节
#define RXB1EID8 0x73 //接收缓冲区0扩展标识符高字节
#define RXB1EID0 0x74 //接收缓冲区0扩展标识符低字节
#define RXB1DLC 0x75 //接收缓冲区1数据码长度
#define RXB1D0 0x76 //接收缓冲区1数据寄存器起始地址
#define RXB1D1 0x77
#define RXB1D2 0x78
#define RXB1D3 0x79
#define RXB1D4 0x7A
#define RXB1D5 0x7B
#define RXB1D6 0x7C
#define RXB1D7 0x7D
/*******************************************************************
* Bit register masks *
* 位寄存器掩码 *
定义TXBnCTRL 寄存器的命令字
*******************************************************************/
/* TXBnCTRL */
#define TXREQ 0x08
#define TXP 0x03
/* RXBnCTRL */
#define RXM 0x60
#define BUKT 0x04
/* CANCTRL */
#define REQOP 0xE0
#define ABAT 0x10
#define OSM 0x08
#define CLKEN 0x04
#define CLKPRE 0x03
/* CANSTAT */
#define REQOP 0xE0
#define ICOD 0x0E
/* CANINTE */
#define RX0IE 0x01
#define RX1IE 0x02
#define TX0IEE 0x04
#define TX1IEE 0x80
#define TX2IEE 0x10
#define ERRIE 0x20
#define WAKIE 0x40
#define MERRE 0x80
/*******************************************************************
* CANINTF *
* 定义MCP2515的中断使能寄存器命令字 *
*******************************************************************/
#define RX0IF 0x01 //接收缓冲器0满中断使能位
#define RX1IF 0x02 //接收缓冲器1满中断使能位
#define TX0IFF 0x04 //发送缓冲器0空中断使能位
#define TX1IFF 0x80 //发送缓冲器1空中断使能位
#define TX2IFF 0x10 //发送缓冲器2空中断使能位
#define ERRIF 0x20 //错误中断使能位
#define WAKIF 0x40 //唤醒中断使能位
#define MERRF 0x80 //报文错误中断使能位
/* BFPCTRL */
#define B1BFS 0x20
#define B0BFS 0x10
#define B1BFE 0x08
#define B0BFE 0x04
#define B1BFM 0x02
#define B0BFM 0x01
/* CNF1 Masks */
#define SJW 0xC0
#define BRP 0x3F
/* CNF2 Masks */
#define BTLMODE 0x80
#define SAM 0x40
#define PHSEG1 0x38
#define PRSEG 0x07
/* CNF3 Masks */
#define WAKFIL 0x40
#define PHSEG2 0x07
/* TXRTSCTRL Masks */
#define TXB2RTS 0x04
#define TXB1RTS 0x02
#define TXB0RTS 0x01
/*******************************************************************
* Bit Timing Configuration *
* 位定时配置 *
*******************************************************************/
/* CNF1 */
#define SJW_1TQ 0x40
#define SJW_2TQ 0x80
#define SJW_3TQ 0x90
#define SJW_4TQ 0xC0
/* CNF2 */
#define BTLMODE_CNF3 0x80
#define BTLMODE_PH1_IPT 0x00
#define SMPL_3X 0x40
#define SMPL_1X 0x00
#define PHSEG1_8TQ 0x38
#define PHSEG1_7TQ 0x30
#define PHSEG1_6TQ 0x28
#define PHSEG1_5TQ 0x20
#define PHSEG1_4TQ 0x18
#define PHSEG1_3TQ 0x10
#define PHSEG1_2TQ 0x08
#define PHSEG1_1TQ 0x00
#define PRSEG_8TQ 0x07
#define PRSEG_7TQ 0x06
#define PRSEG_6TQ 0x05
#define PRSEG_5TQ 0x04
#define PRSEG_4TQ 0x03
#define PRSEG_3TQ 0x02
#define PRSEG_2TQ 0x01
#define PRSEG_1TQ 0x00
/* CNF3 */
#define PHSEG2_8TQ 0x07
#define PHSEG2_7TQ 0x06
#define PHSEG2_6TQ 0x05
#define PHSEG2_5TQ 0x04
#define PHSEG2_4TQ 0x03
#define PHSEG2_3TQ 0x02
#define PHSEG2_2TQ 0x01
#define PHSEG2_1TQ 0x00
#define SOF_ENABLED 0x80
#define WAKFIL_ENABLED 0x40
#define WAKFIL_DISABLED 0x00
/*******************************************************************
* Control/Configuration Registers *
* 控制/配置寄存器 *
*******************************************************************/
/* CANINTE */
#define RX0IE_ENABLED 0x01
#define RX0IE_DISABLED 0x00
#define RX1IE_ENABLED 0x02
#define RX1IE_DISABLED 0x00
#define G_RXIE_ENABLED 0x03
#define G_RXIE_DISABLED 0x00
#define TX0IE_ENABLED 0x04
#define TX0IE_DISABLED 0x00
#define TX1IE_ENABLED 0x08
#define TX2IE_DISABLED 0x00
#define TX2IE_ENABLED 0x10
#define TX2IE_DISABLED 0x00
#define G_TXIE_ENABLED 0x1C
#define G_TXIE_DISABLED 0x00
#define ERRIE_ENABLED 0x20
#define ERRIE_DISABLED 0x00
#define WAKIE_ENABLED 0x40
#define WAKIE_DISABLED 0x00
#define IVRE_ENABLED 0x80
#define IVRE_DISABLED 0x00
/* CANINTF */
#define RX0IF_SET 0x01
#define RX0IF_RESET 0x00
#define RX1IF_SET 0x02
#define RX1IF_RESET 0x00
#define TX0IF_SET 0x04
#define TX0IF_RESET 0x00
#define TX1IF_SET 0x08
#define TX2IF_RESET 0x00
#define TX2IF_SET 0x10
#define TX2IF_RESET 0x00
#define ERRIF_SET 0x20
#define ERRIF_RESET 0x00
#define WAKIF_SET 0x40
#define WAKIF_RESET 0x00
#define IVRF_SET 0x80
#define IVRF_RESET 0x00
/* CANCTRL */
#define REQOP_CONFIG 0x80
#define REQOP_LISTEN 0x60
#define REQOP_LOOPBACK 0x40
#define REQOP_SLEEP 0x20
#define REQOP_NORMAL 0x00
#define ABORT 0x10
#define OSM_ENABLED 0x08
#define CLKOUT_ENABLED 0x04
#define CLKOUT_DISABLED 0x00
#define CLKOUT_PRE_8 0x03
#define CLKOUT_PRE_4 0x02
#define CLKOUT_PRE_2 0x01
#define CLKOUT_PRE_1 0x00
/* CANSTAT */
/* 定义MCP255的CAN工作模式 */
#define OPMODE_CONFIG 0x80 //配置模式
#define OPMODE_LISTEN 0x60 //仅监听模式
#define OPMODE_LOOPBACK 0x40 //环回模式
#define OPMODE_SLEEP 0x20 //休眠模式
#define OPMODE_NORMAL 0x00 //正常工作模式
/* RXBnCTRL */
#define RXM_RCV_ALL 0x60
#define RXM_VALID_EXT 0x40
#define RXM_VALID_STD 0x20
#define RXM_VALID_ALL 0x00
#define RXRTR_REMOTE 0x08
#define RXRTR_NO_REMOTE 0x00
#define BUKT_ROLLOVER 0x04
#define BUKT_NO_ROLLOVER 0x00
#define FILHIT0_FLTR_1 0x01
#define FILHIT0_FLTR_0 0x00
#define FILHIT1_FLTR_5 0x05
#define FILHIT1_FLTR_4 0x04
#define FILHIT1_FLTR_3 0x03
#define FILHIT1_FLTR_2 0x02
#define FILHIT1_FLTR_1 0x01
#define FILHIT1_FLTR_0 0x00
/* TXBnCTRL */
#define TXREQ_SET 0x08 //报文发送请求位
#define TXREQ_CLEAR 0x00
#define TXP_HIGHEST 0x03
#define TXP_INTER_HIGH 0x02
#define TXP_INTER_LOW 0x01
#define TXP_LOWEST 0x00
/*******************************************************************
* Register Bit Masks 寄存器位掩码 *
*******************************************************************/
#define DLC_0 0x00
#define DLC_1 0x01
#define DLC_2 0x02
#define DLC_3 0x03
#define DLC_4 0x04
#define DLC_5 0x05
#define DLC_6 0x06
#define DLC_7 0x07
#define DLC_8 0x08
/*******************************************************************
* CAN SPI commands *
* 定义MCP2515的SPI操作的CAN指令 *
*******************************************************************/
#define CAN_RESET 0xC0 //复位
#define CAN_READ 0x03 //从寄存器中读出数据
#define CAN_WRITE 0x02 //向寄存器中写入数据
#define CAN_RTS 0x80 //发送请求
#define CAN_RTS_TXB0 0x81
#define CAN_RTS_TXB1 0x82
#define CAN_RTS_TXB2 0x84
#define CAN_RD_STATUS 0xA0 //读取寄存器状态
#define CAN_BIT_MODIFY 0x05 //位修改指令
#define CAN_RX_STATUS 0xB0 //快速确定与报文和报文类型相匹配的滤波器
#define CAN_RD_RX_BUFF 0x90 //读RX缓冲器指令
//
#define CAN_LOAD_TX 0X40 //装载TX缓冲器指令
/*******************************************************************
* Miscellaneous 杂项 *
*******************************************************************/
#define DUMMY_BYTE 0x00
#define TXB0 0x31
#define TXB1 0x41
#define TXB2 0x51
#define RXB0 0x61
#define RXB1 0x71
#define EXIDE_SET 0x08
#define EXIDE_RESET 0x00
#endif
#include
/****************************
函数:void Init_Spi(void)
函数描述:初始化SPI
变量:无
*******************************/
void Init_Spi(void)
{
TRISC=0b00010000;//RC5/SDO为输出,RC4/SDI为输入,RC3/SCK为输出
/*
SSPSTAT_SMP=0;//在数据输出时间的中间采样输入数据
CKE:SPI 时钟边沿选择位 CKP = 0: STAT_CKE=1 在SCK 引脚的上升沿发送数据
*/
SSPSTAT=0X40;//在数据输出时间的中间采样输入数据 bit 7,SMP=0,采样位
/*
SSPEN=1;使能串行端口并将SCK、SDO、SDI 和SS 配置为串行端口引脚
CKP=0;空闲时钟为低电平
SSPM<3:0>=0001,SPI 主控模式,时钟 = FOSC/16
*/
SSPCON=0x21;//bit 4,CKP:时钟极性选择位,0 = 时钟空闲状态为低电平
TRISD=0b00001100;//RD0输出,RD1输出;RD2输入,RD3输入;
PORTD=0b00000000;//输出为低,输入高阻态;
}
/****************************
函数:char SPIRecvByte(void)
函数描述:从SPI总线上读取一个字节数据
变量:BUF
*******************************/
char SPIRecvByte(void)
{
char BUF;
SSPBUF=0x00;
delay(2);
BUF=SSPBUF;
delay(20);
return BUF;
}
/****************************
函数:void SPISendByte(unsigned char dat)
函数描述:向SPI总线上发送一个字节数据
变量:无
*******************************/
void SPISendByte(unsigned char dat)
{
SSPBUF=dat;//往缓冲里面写入dat
// while(!SSPIF)//等待写入成功
// SSPIF=0;//SSPIF清零
delay(20);
}
/****************************
函数:void CAN_Write(uchar address ,uchar Value)
函数描述:往MCP2515指定地址addr写一个字节数据value
变量:无
*******************************/
void CAN_Write(uchar address ,uchar Value)
{
CS=0;
SPISendByte(0x02);//写命令
SPISendByte(address);//写地址
SPISendByte(Value);//写数据
CS=1;
}
/****************************
函数:char CAN_Read(uchar address)
函数描述:从MCP2515指定地址addr读取一个字节数据value
变量:BUF
*******************************/
char CAN_Read(uchar address)
{
char BUF;
CS=0;
SPISendByte(0x03);//读命令
SPISendByte(address);//读地址
BUF=SPIRecvByte();//读一个字节数据
CS=1;
return BUF;
}
/****************************
函数:void SPIReset(void)
函数描述:SPI复位
变量:无
*******************************/
void SPIReset(void)
{
SSPBUF=0XC0;//CAN_RESET=0XC0
delay(20);
}
/****************************
函数:void CAN_Set_Var(uchar address,uchar mask,uchar dat)
函数描述:修改寄存器的值,mask为掩码
变量:无
*******************************/
void CAN_Set_Var(uchar address,uchar mask,uchar dat)
{
CS=0;
delay(10);
SPISendByte(0x05);//位修改命令 CAN_BIT_MODIFY
//CANCTRL——CAN 控制寄存器(地址:XFh)
SPISendByte(address);//地址为0fH
SPISendByte(mask);//掩码为E0H,修改CANCTRL的高三位
SPISendByte(dat);
CS=1;//片选
}
spi_887.h
/*****************************************************************/
#ifndef __SPI_h__
#define __SPI_h__
#include
#include
#define uchar unsigned char
#define uint unsigned int
#define CS RD1 //标签为CANCSRH4
#define RESET RD0 //标签为RESETCAN
/************************************************************/
void Init_Spi(void);
char SPIRecvByte(void);
void SPISendByte(uchar dat);
void CAN_Write(uchar address ,uchar Value); //向寄存器地址写入数据
char CAN_Read(uchar address); //从寄存器地址读取数据
void SPIReset(void);
void CAN_Set_Var(uchar address,uchar mask,uchar dat);
#endif
#include
/****************************
函数:unsigned int get_ad()
函数描述:调用AD子程序,获取ADC转换后的值
变量:adval
*******************************/
unsigned int get_ad(){
unsigned int adval,ad;
GO=1;//启动AD转换
// delay(1);
for(i=1;i<10;i++) nop(); /*延时20us*/
while(GO);
adval=ADRESH<<8|ADRESL;
return(adval);
}
/*左侧电池盒电压*/
/*ADC采集端口初始化函数,初始化片内ADC1,采集右路电压*/
/*ADCON0,A/D控制寄存器0,A/D转换时钟选择为八分之一频率,采集端口为RA0,模拟通道选择AN0*/
/*A/D转换完成/或不在进行中,使能ADC.*/
void init_ADC1(void)
{
TRISA=0XFF;//RA0设置为AN0(AD采集端口),端口配置为输入。
ADCON0=0b01000001;//AD时钟选择(与ADCON1的位6一起)
ADCON1=0b10000000;//通道选择,AD模块使能
}
/*左侧电池盒电流*/
/*ADC采集端口初始化函数,初始化片内ADC5,采集R7两端电压*/
/*采集端口为RA5,模拟通道选择AN4.*/
void init_ADC5(void)
{
TRISA=0XFF;//RA5设置为AN4(AD采集端口),端口配置为输入。
ADCON0=0b01010001;//AD时钟选择(与ADCON1的位6一起)
ADCON1=0b10000000;//通道选择,AD模块使能
}
/*右侧电池盒电压*/
/*ADC采集端口初始化函数,初始化片内ADC2,采集左路电压*/
/*ADCON0,A/D控制寄存器0,A/D转换时钟选择为八分之一频率,采集端口为RA1,模拟通道选择AN1*/
/*A/D转换完成/或不在进行中,使能ADC.*/
void init_ADC2(void)
{
TRISA=0XFF;//RA1设置为AN1(AD采集端口),端口配置为输入。
ADCON0=0b01000101;//AD时钟选择(与ADCON1的位6一起)
ADCON1=0b10000000;//通道选择,AD模块使能
}
/*右侧电池盒电流*/
/*ADC采集端口初始化函数,初始化片内ADC6,采集R14两端电压.*/
/*采集端口为RE0,模拟通道选择AN5.*/
void init_ADC6(void)
{
TRISE=0XFF;//RE0设置为AN5(AD采集端口),端口配置为输入。
ADCON0=0b01010101;//AD时钟选择(与ADCON1的位6一起)
ADCON1=0b10000000;//通道选择,AD模块使能
}
/*ADC采集端口初始化函数,初始化片内ADC3,采集R69两端电压*/
/*ADCON0,A/D控制寄存器0,A/D转换时钟选择为八分之一频率,采集端口为RA2,模拟通道选择AN2*/
/*A/D转换完成/或不在进行中,使能ADC.*/
void init_ADC3(void)
{
TRISA=0XFF;//配置PORTA的引脚全为输入。
ADCON0=0b01001001;
ADCON1=0b10000000; /*A/D控制寄存器1,A/D转换结果格式为右对齐*/
}
/*ADC采集端口初始化函数,初始化片内ADC4,采集R70两端电压*/
/*ADCON0,A/D控制寄存器0,A/D转换时钟选择为八分之一频率,采集端口为RA3,模拟通道选择AN3*/
/*A/D转换完成/或不在进行中,使能ADC.*/
void init_ADC4(void)
{
TRISA=0XFF;//配置PORTA的引脚全为输入。
ADCON0=0b01001101;
ADCON1=0b10000000; /*A/D控制寄存器1,A/D转换结果格式为右对齐*/
}
/****************************************
A、名称:递推平均滤波法(又称滑动平均滤波法)
B、方法:
把连续取得的N个采样值看成一个队列,队列的长度固定为N,
每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则),
把队列中的N个数据进行算术平均运算,获得新的滤波结果。
N值的选取:流量,N=12;压力,N=4;液面,N=4-12;温度,N=1-4。
C、优点:
对周期性干扰有良好的抑制作用,平滑度高;
适用于高频振荡的系统。
D、缺点:
灵敏度低,对偶然出现的脉冲性干扰的抑制作用较差;
不易消除由于脉冲干扰所引起的采样值偏差;
不适用于脉冲干扰比较严重的场合;
比较浪费RAM。
E、整理:Alex
*********************************/
int filter()
{
int i;
int filter_sum = 0;
for(i = 0; i < FILTER_N; i++)
{
filter_buf[i] = get_ad(); //AD转换的值赋给数组最后一个值
filter_sum += filter_buf[i];
delay(1);
}
filter_sum=filter_sum/100;
filter_sum=filter_sum*102;
return (int)(filter_sum/FILTER_N);
}
/****************************
函数:void show_temp(void)
函数描述:采集两路的温度值,串口打印输出,根据温度控制风扇。。
变量:无
*******************************/
void show_temp(void)
{
/*ADCOUTV3,ADCOUTV4,R69端电压采集点,R70端电压采集点*/
int ADCOUTV3;
int ADCOUTV4;
/*测量整个电路中的温度,串口打印出输出*/
/*采集1路温度传感器的值*/
init_ADC3(); //ADC采集端口初始化
ADCOUTV3=filter(); //调用AD子程序
/*采集2路温度传感器的值*/
init_ADC4(); //ADC采集端口初始化
ADCOUTV4=filter(); //调用AD子程序
/*风扇的运行,完全靠检测到的温度来控制*/
/*设定控制风扇转动的温度点,45度风扇转。40.4左右。*/
if(((ADCOUTV3<450)||(ADCOUTV4<450))&&(ADCOUTV3!=0)&&(ADCOUTV4!=0)){
FAN=1;//风扇打开
}
/*设定控制风扇转动的温度点,35度风扇停。*/
if((ADCOUTV3>560)&&(ADCOUTV4>560)){
FAN=0;//风扇关闭
}
/*当整个充电电路温度升高到例如60度时,控制充电过程截止。*/
if(((ADCOUTV3<350)||(ADCOUTV4<350))&&(ADCOUTV3!=0)&&(ADCOUTV4!=0)){
CCPR1L=160;//关断充电
CCPR2L=160;//关断充电
}
/*由于采用递推平均滤波法的原因,刚才是数值从0开始增加到稳定值*/
/*会造成刚开机时,风扇的误动作,待稳定输出后,动作无误*/
}
/****************************
函数:void Bat1_Volt(void)
函数描述:检测1路的电压值
变量:无
*******************************/
void Bat1_Volt(void)
{
/*采集和显示部分*/
/*ADCOUTV1,U1路输出从ADC采集的电压;ADC5IV1,R7两端从ADC采集的电压*/
int ADCOUTV1;
/*ADCOUTV1,U1路输出电压用于中间转换的浮点型值;ADC5IV1,R7两端电压用于中间转换的浮点型值*/
float num1;
/*NUM1,U1路输出电压用于串口显示和判断的整型值;NUM2,R7两端的电压用于串口显示和判断的整型值*/
int NUM1;
/**上电后,第一次采集OUTV1的电压,继而判断此时是否有电池接入**/
/*第一路,即电路板右侧,JP1部分充电电路*/
/*采集U1路输出电压,OUTV1,单位为V*/
init_ADC1(); //ADC采集2路电压值
/****调用AD子程序****/
ADCOUTV1=filter(); //调用AD子程序
/*换算出OUTV1的电压值*/
/*对ADCOUTV1进行运算,得到浮点型数num1*/
num1=ADCOUTV1*34.6752; //理论值为34.47561553030303,实测值34.67529820407434
/*将浮点型数num1转换成整形数NUM1*/
Bat_1.volt=(int)num1; //左电池充电电路中的电压
}
/****************************
函数:void Bat1_Curr(void)
函数描述:检测1路的电流值
变量:无
*******************************/
void Bat1_Curr(void)
{
/*采集和显示部分*/
/*ADC5IV1,R7两端从ADC采集的电压*/
int ADC5IV1;
/*ADC5IV1,R7两端电压用于中间转换的浮点型值*/
float num2;
/*采集R7两端的电压,ADC5IV1,单位为V*/
/*首先采集的是与单片机直接相连的ADC5IV1*/
init_ADC5(); //ADC采集ADC5IV1的电压值
/****调用AD子程序****/
ADC5IV1=filter(); //调用AD子程序
/*换算出流经R8电流的值*/
/*对ADCOUTV5进行运算,得到浮点型数num2*/
num2=ADC5IV1*4.883;
/*换算出流经R8电流的值*/
Bat_1.cur=(int)num2; //左电池充电电路中的电流
}
/****************************
函数:void Bat2_Volt(void)
函数描述:检测2路的电压值
变量:无
*******************************/
void Bat2_Volt(void)
{
/*采集和显示部分*/
/*ADCOUTV2,U2路输出从ADC采集的电压;ADC6IV1,R14两端从ADC采集的电压*/
int ADCOUTV2;
/*ADCOUTV2,U2路输出电压用于中间转换的浮点型值;ADC6IV1,R14两端电压用于中间转换的浮点型值*/
float num1;
/**上电后,第一次采集OUTV1的电压,继而判断此时是否有电池接入**/
/*第一路,即电路板右侧,JP1部分充电电路*/
/*采集U1路输出电压,OUTV1,单位为V*/
init_ADC2(); //ADC采集2路电压值
/****调用AD子程序****/
ADCOUTV2=filter(); //调用AD子程序
/*换算出OUTV1的电压值*/
/*对ADCOUTV1进行运算,得到浮点型数num1*/
num1=ADCOUTV2*34.6752; //理论值为34.47561553030303,实测值34.67529820407434
/*将浮点型数num1转换成整形数NUM1*/
Bat_2.volt=(int)num1; //左电池充电电路中的电压
}
/****************************
函数:void Bat2_Curr(void)
函数描述:检测2路的电流值
变量:无
*******************************/
void Bat2_Curr(void)
{
/*采集和显示部分*/
/*ADC6IV1,R14两端从ADC采集的电压*/
int ADC6IV1;
/*ADC6IV1,R14两端电压用于中间转换的浮点型值*/
float num2;
/*采集R7两端的电压,ADC5IV1,单位为V*/
/*首先采集的是与单片机直接相连的ADC5IV1*/
init_ADC6(); //ADC采集ADC5IV1的电压值
/****调用AD子程序****/
ADC6IV1=filter(); //调用AD子程序
/*换算出流经R8电流的值*/
/*对ADCOUTV5进行运算,得到浮点型数num2*/
num2=ADC6IV1*4.883;
/*换算出流经R8电流的值*/
Bat_2.cur=(int)num2; //左电池充电电路中的电流
}
/*****************************************************************/
#ifndef __ADC_h__
#define __ADC_h__
#include
#include
#include
#include
#include
#define FILTER_N 4 /* N值可根据实际情况调整 排序采用冒泡法*/
int filter_buf[FILTER_N + 1];
unsigned int get_ad(); /*调用AD子程序,获取ADC转换后的值*/
int filter(); /*使用递推平均滤波法的滤波函数*/
void init_ADC1(void); /*ADC采集端口初始化函数,初始化片内ADC1,采集左侧1路电池盒输出电压、电路板右边电路*/
void init_ADC2(void); /*ADC采集端口初始化函数,初始化片内ADC2,采集右侧2路电池盒输出电压、电路板左边电路*/
void init_ADC3(void); /*ADC采集端口初始化函数,初始化片内ADC3,采集R69两端电压*/
void init_ADC4(void); /*ADC采集端口初始化函数,初始化片内ADC4,采集R70两端电压*/
void init_ADC5(void); /*ADC采集端口初始化函数,初始化片内ADC5,采集左侧1路电池盒输出电流、电路板右边电路*/
void init_ADC6(void); /*ADC采集端口初始化函数,初始化片内ADC6,采集右侧2路电池盒输出电流、电路板左边电路*/
void show_temp(void); /*采集两路的温度值,串口打印输出,根据温度控制风扇*/
void Bat1_Volt(void); /*检测1路的电压值*/
void Bat1_Curr(void); /*检测1路的电流值*/
void Bat2_Volt(void); /*检测2路的电压值*/
void Bat2_Curr(void); /*检测2路的电流值*/
#endif
pwm.c
#include
/****************************
函数:void Init_PWM(void)
函数描述:初始化配置PWM
变量:无
*******************************/
void Init_PWM(void)
{
/****定义PORTC****/
/*控制PWM脉冲输出部分*/
/*频率25MHZ,晶振选择为16MHZ*/
TRISC=0X00;
PORTC=0x00;
CCP1CON=0;//clear CCP1CON reg
CCP2CON=0;//clear CCP2CON reg
PR2=159;//周期为40us
/*
CCPR1L赋值160;CCP1CON的5、4两位赋值0b00时,占空比为100%;
CCPR1L赋值 0;CCP1CON的5、4两位赋值0b00时,占空比为 0%;
*/
CCPR1L=160;
CCPR2L=160; //此时输出电压OUTV最小为19V左右。
/*将RC1、RC2引脚配置为输出*/
TRISCbits.TRISC1=0; //make PWM pin an output
TRISCbits.TRISC2=0; //make PWM pin an output
T2CON=0X00; //Timer2,1 prescale,no postscaler 0 = 禁止Timer2 Timer2 时钟预分频比 00 = 预分频值为1
CCP1CON=0X0C; //PWM mode, 00 for DC1B1:B0 1100 = PWM 模式; P1A 和P1C 为高电平有效; P1B 和P1D 也为高电平有效
CCP2CON=0X0C; //PWM mode, 00 for DC1B1:B0 1100 = PWM 模式; P1A 和P1C 为高电平有效; P1B 和P1D 也为高电平有效2
TMR2=0; //clear Timer2 Timer2 模块寄存器 8 位定时器寄存器
T2CONbits.TMR2ON=1; //turn on Timer2 使能Timer2
}
/*****************************************************************/
#ifndef __PWM_h__
#define __PWM_h__
#include
#include
void Init_PWM(void); /*初始化PWM*/
#endif
#include
/****************************
函数:void Init_Int(void)
函数描述:初始化中断
变量:无
*******************************/
void Init_Int(void)
{
TRISB=0X01; //RB0为输入,其余为输出
PORTB=0x19; //RB0高阻态, RB3置1,RB4置1
ANSELH=0x00; //将RB0(AN12)引脚被分配给端口或特殊功能。
//必须初始化ANSELH 寄存器以将模拟通道配置为数字输入。配置为模拟输入的引脚将读为0。
/*
GIE = 1; //GIE: 全局中断允许位 1 = 允许所有未被屏蔽的中断
PEIE = 1; //PEIE: 外设中断允许位 1 = 允许所有未被屏蔽的外设中断
INTE = 1; //INTE:INT 外部中断允许位 1 = 允许INT 外部中断
RBIE = 1; //RBIE:PORTB 电平变化中断允许位 1 = 允许PORTB 电平变化中断
INTF=0; //INTF:INT 外部中断标志位 0 = 未发生INT 外部中断
*/
INTCON=0XD8; /*正确的*/
// INTCON=0b11111000; /*测试的*/
WPUB = 0X01;//使能上拉
/*
INTEDG=0; //触发中断的边沿选择位 0 = INT 引脚下降沿触发中断
*/
OPTION_REG=0x00;/*正确的*/
}
//中断服务程序
void interrupt ISR(void)
{
if(INTF==1)//如果是INT中断才执行以下程序
{
INTF=0;
canreflag=1;
}
}
/*****************************************************************/
#ifndef __INT_h__
#define __INT_h__
#include
void Init_Int(void); /*初始化中断*/
char canreflag;
#endif
#include
unsigned char cansentbuf[8]; /*用来存放发送数据的数组*/
unsigned char canrecebuf[8]; /*用来存放接收数据的数组*/
unsigned char canjudgbuf[10]; /*用来存放判断电池初始化是否成功数据的数组*/
char canreflag;
int i;
int count;
unsigned char dummy;
char CAN_FLAG; /*CAN接收标志位*/
struct Bat_stat1 Bat_1; /* 不加extern ,默认认为extern */
struct Bat_stat2 Bat_2; /* 不加extern ,默认认为extern */
/*****************************************************************/
#ifndef __VAR_h__
#define __VAR_h__
#define LEDA RB3 //定义灯1
#define LEDB RB4 //定义灯2
#define ENA RE2 //定义灯2
extern unsigned char cansentbuf[8];
extern unsigned char canrecebuf[8];
extern unsigned char canjudgbuf[10];
extern char canreflag;
extern int i;
extern int count;
extern unsigned char dummy;
extern char CAN_FLAG;//开机复位
/*左侧电池状态*/
// ------------------ 左侧电池状态数据的结构定义 ------------------------ //
extern struct Bat_stat1
{
unsigned int in; //左电池进入充电站标志位
unsigned int init; //左电池初始化完成标志位
unsigned int volt; //左电池充电电路中的电压
unsigned int cur; //左电池充电电路中的电流
unsigned int chg_full; //充电完成标志位
unsigned int Soc; //左电池电量Soc
unsigned int error; //左电池故障标志位
unsigned int error1; //左电池过压、温度故障标志位
unsigned int error2; //左电池过流故障标志位
}Bat_1;
/*右侧电池状态*/
// ------------------ 右侧电池状态数据的结构定义 ------------------------ //
extern struct Bat_stat2
{
unsigned int in; //右电池进入充电站标志位
unsigned int init; //右电池初始化完成标志位
unsigned int volt; //右电池充电电路中的电压
unsigned int cur; //右电池充电电路中的电流
unsigned int chg_full; //右电池充电完成标志位
unsigned int Soc; //右电池电量Soc
unsigned int error; //右电池错误标志位
unsigned int error1; //右电池过压、温度故障标志位
unsigned int error2; //右电池过流故障标志位
}Bat_2;
#endif
#include
/****************************
函数:void Bat_init(void)
函数描述:初始化左右侧电池的状态标志位
变量:无
*******************************/
void Bat_init(void)
{
/*对左右电池进入标志位清零*/
/*对左电池进入标志位清零*/
Bat_1.in=0; /*左电池进入充电站标志位*/
Bat_1.init=0; /*左电池初始化完成标志位*/
Bat_1.error=0; /*左电池错误标志位*/
Bat_1.volt=0; /*左电池充电电路中的电压*/
Bat_1.cur=0; /*左电池充电电路中的电流*/
Bat_1.chg_full=0; /*左电池充电完成标志位*/
Bat_1.Soc=0; /*左电池电池容量*/
Bat_1.error1=0; /*左电池过压、温度故障标志位*/
Bat_1.error2=0; /*左电池过流故障标志位*/
/*对右电池进入标志位清零*/
Bat_2.in=0; /*右电池进入充电站标志位*/
Bat_2.init=0; /*右电池初始化完成标志位*/
Bat_2.error=0; /*右电池错误标志位*/
Bat_2.volt=0; /*右电池充电电路中的电压*/
Bat_2.cur=0; /*右电池充电电路中的电流*/
Bat_2.chg_full=0; /*右电池充电完成标志位*/
Bat_2.Soc=0; /*右电池电池容量*/
Bat_2.error1=0; /*右电池过压、温度故障标志位*/
Bat_2.error2=0; /*右电池过流故障标志位*/
/*对cansentbuf、cansentbuf数组进行初始化*/
for(i=0;i<8;i++)
{
cansentbuf[i]=0;
canrecebuf[i]=0;
}
for(i=0;i<8;i++)
{
canjudgbuf[i]=0;
}
}
/***************************
函数:void Bat_1_Reset(void)
函数描述:左侧电池状态复位
变量:无
*****************************/
void Bat_1_Reset(void)
{
Bat_1.in=0; /*将左电池进入充电站标志位清零*/
Bat_1.init=0; /*电池初始化未完成*/
Bat_1.error=0; /*电池无故障*/
Bat_1.chg_full=0; /*拔出电池盒,该电池充满位清零*/
Bat_1.Soc=0; /*拔出电池盒,该电量SOC位清零*/
Bat_1.error1=0; /*左电池过压、温度故障标志位*/
Bat_1.error2=0; /*左电池过流故障标志位*/
CCPR1L=160; /*占空比的值为满*/
LEDA=1; /*亮绿灯*/
}
/***************************
函数:void Bat_2_Reset(void)
函数描述:右侧电池状态复位
变量:无
*****************************/
void Bat_2_Reset(void)
{
Bat_2.in=0; /*将右电池进入充电站标志位清零*/
Bat_2.init=0; /*右电池初始化未完成*/
Bat_2.error=0; /*右电池无故障*/
Bat_2.chg_full=0; /*拔出电池盒,右电池充满位清零*/
Bat_2.Soc=0; /*拔出电池盒,右电池电量SOC位清零*/
Bat_2.error1=0; /*右电池过压、温度故障标志位*/
Bat_2.error2=0; /*右电池过流故障标志位*/
CCPR2L=160; /*占空比的值为满*/
LEDB=1; /*亮绿灯*/
TRISE2=0; /*定义RE2输出*/
ENA=1; /*关掉2路通讯*/
}
/*当左电池插入到电池盒中后,执行左侧电池处理函数*/
/*此时电池插入充电站中,开关闭合状态,RD2为左侧JP1接插件*/
void LeftBattery_Init(void)
{
Bat_1_Test(); /*发送0X20命令,得到电池初始化完成标志位Bat_1.init。为1初始化完成;为0初始化未完成*/
/*若0x20数据发送完后,有返回值,方可继续执行0x21数据的发送*/
/*判断返回数据的格式,符合标准通讯格式,设备分配符0X01、0X20。*/
if((canreflag==1)&&(canrecebuf[7]==0x01)) /*如果有回复*/
{
canreflag=0; /*清通讯接收到标志*/
canjudgbuf[0]=canrecebuf[0]; /*将数据转存到数组中,用于判断*/
canjudgbuf[1]=canrecebuf[1];
canjudgbuf[2]=canrecebuf[2];
// canjudgbuf[3]=canrecebuf[3];
canjudgbuf[4]=canrecebuf[7];
CAN_0x21(1); /*发送0x21命令,左侧电池盒初始化第二步,1代表左侧。*/
}
else
{
CAN_0x25(1); /*当发0X20没有回复,可能存在着电池未关掉,已经完成初始化的情况*/
}
}
/*当右电池插入到电池盒中后,执行右侧电池处理函数*/
/*此时电池插入充电站中,开关闭合状态,RD2为右侧JP3接插件*/
void RightBattery_Init(void)
{
Bat_2_Test(); /*发送0X20命令,得到电池初始化完成标志位Bat_1.init。为1初始化完成;为0初始化未完成*/
/*若0x20数据发送完后,有返回值,方可继续执行0x21数据的发送*/
/*判断返回数据的格式,符合标准通讯格式,设备分配符0X01、0X20。*/
if((canreflag==1)&&(canrecebuf[7]==0x02)) /*如果有回复*/
{
canjudgbuf[0]=canrecebuf[0]; /*将数据转存到数组中,用于判断*/
canjudgbuf[1]=canrecebuf[1];
canjudgbuf[2]=canrecebuf[2];
// canjudgbuf[3]=canrecebuf[3];
canjudgbuf[4]=canrecebuf[7];
canreflag=0; /*清通讯接收到标志*/
delay(500); /*延时1秒*/
CAN_0x21(2); /*发送0x21命令,左侧电池盒初始化第二步,2代表右侧。*/
}
else
{
delay(500); /*延时1秒*/
CAN_0x25(2); /*当发0X20没有回复,可能存在着电池未关掉,已经完成初始化的情况*/
}
}
/*当左电池插入到电池盒中后,执行左侧电池处理函数*/
/*此时电池插入充电站中,开关闭合状态,RD2为左侧JP1接插件*/
void LeftBattery_Deal(void)
{
if(Bat_1.chg_full==0) /*电池未充满电时*/
{
CAN_0x25(1); /*发送0x25命令,读取电池故障信息*/
if((Bat_1.error1==0)&&(Bat_1.error2==0)) /*无故障时*/
{
Bat1_Volt(); /*检测1路的电压值*/
Bat1_Curr(); /*检测1路的电流值*/
if(Bat_1.volt<=24000)
{
while(Bat_1.cur<500)
{
CCPR1L--; /*duty cycle decrease,减小占空比*/
Bat1_Volt(); /*检测1路的电压值*/
Bat1_Curr(); /*检测1路的电流值*/
if((RD2==1)||(CCPR1L==0)||(Bat_1.volt>24000))
{
break;
}
Show_num_4(CCPR1L);
Show_num_1(Bat_1.volt);
Show_num_3(Bat_1.cur);
}
if(RD2==1)
{
Bat_1_Reset(); /*左侧电池状态复位*/
}
Show_num_4(301);
Show_num_4(CCPR1L);
Show_num_1(Bat_1.volt);
Show_num_3(Bat_1.cur);
}
else if (Bat_1.volt<=28800)
{
while((Bat_1.cur<=3000)||(Bat_1.cur>=3200))
{
if(Bat_1.cur<=3200)
{
CCPR1L--; /*duty cycle decrease,减小占空比*/
}
else if (Bat_1.cur<=3200)
{
CCPR1L=CCPR1L; /*duty cycle unchanged.,占空比不变*/
}
else
{
CCPR1L++; /*duty cycle increase,增加占空比*/
}
Bat1_Volt(); /*检测1路的电压值*/
Bat1_Curr(); /*检测1路的电流值*/
if((RD2==1)||(CCPR1L==0)||(Bat_1.volt>28800))
{
break;
}
Show_num_4(CCPR1L);
Show_num_1(Bat_1.volt);
Show_num_3(Bat_1.cur);
}
if(RD2==1)
{
Bat_1_Reset(); /*左侧电池状态复位*/
}
Show_num_4(302);
Show_num_4(CCPR1L);
Show_num_1(Bat_1.volt);
Show_num_3(Bat_1.cur);
}
else
{
Bat1_Curr(); /*检测1路的电流值*/
if(Bat_1.cur<=300)
{
Bat_1.chg_full=1;
CCPR1L=160; /*切断电池输出,等待拔出电池*/
LEDA=1; /*亮绿灯,指示此时已经充满电*/
}
if(RD2==1)
{
Bat_1_Reset(); /*左侧电池状态复位*/
}
Show_num_4(303);
Show_num_4(CCPR1L);
Show_num_1(Bat_1.volt);
Show_num_3(Bat_1.cur);
}
if(Bat_1.cur>=10) /*当电流大于10mA时*/
{
LEDA=0; /*显示红灯*/
}
CAN_0x26(1); /*发送0x26命令,读取电池状态信息*/
}
else
{
Bat1_Error_Deal(); /*执行错误处理程序*/
}
}
else /*当电池充满电时*/
{
CCPR1L=160; /*切断电池输出,等待拔出电池*/
LEDA=1; /*亮绿灯,指示此时已经充满电*/
}
}
/*右侧电池处理函数*/
/*此时电池插入充电站中,开关闭合状态,RD3为右侧JP3接插件*/
void RightBattery_Deal(void)
{
if(Bat_2.chg_full==0) /*电池未充满电时*/
{
CAN_0x25(2); /*发送0x25命令,读取电池故障信息*/
if((Bat_2.error1==0)&&(Bat_2.error2==0)) /*无故障时*/
{
Bat2_Volt(); /*检测1路的电压值*/
Bat2_Curr(); /*检测1路的电流值*/
if(Bat_2.volt<=24000)
{
while(Bat_2.cur<500)
{
CCPR2L--; /*duty cycle decrease,减小占空比*/
Bat2_Volt(); /*检测1路的电压值*/
Bat2_Curr(); /*检测1路的电流值*/
if((RD3==1)||(CCPR2L==0)||(Bat_2.volt>24000))
{
break;
}
Show_num_4(CCPR2L);
Show_num_1(Bat_2.volt);
Show_num_3(Bat_2.cur);
}
if(RD3==1)
{
Bat_2_Reset(); /*左侧电池状态复位*/
}
Show_num_4(301);
Show_num_4(CCPR2L);
Show_num_1(Bat_2.volt);
Show_num_3(Bat_2.cur);
}
else if (Bat_2.volt<=28800)
{
while((Bat_2.cur<=3000)||(Bat_2.cur>=3200))
{
if(Bat_2.cur<=3000)
{
CCPR2L--; /*duty cycle decrease,减小占空比*/
}
else if (Bat_2.cur<=3200)
{
CCPR2L=CCPR2L; /*duty cycle unchanged.,占空比不变*/
}
else
{
CCPR2L++; /*duty cycle increase,增加占空比*/
}
Bat2_Volt(); /*检测1路的电压值*/
Bat2_Curr(); /*检测1路的电流值*/
if((RD3==1)||(CCPR2L==0)||(Bat_2.volt>28800))
{
break;
}
Show_num_4(CCPR2L);
Show_num_1(Bat_2.volt);
Show_num_3(Bat_2.cur);
}
if(RD3==1)
{
Bat_2_Reset(); /*左侧电池状态复位*/
}
Show_num_4(302);
Show_num_4(CCPR2L);
Show_num_1(Bat_2.volt);
Show_num_3(Bat_2.cur);
}
else
{
Bat2_Curr(); /*检测2路的电流值*/
if(Bat_2.cur<=300)
{
Bat_2.chg_full=1;
CCPR2L=160; /*切断电池输出,等待拔出电池*/
LEDB=1; /*亮绿灯,指示此时已经充满电*/
}
if(RD3==1)
{
Bat_2_Reset(); /*右侧电池状态复位*/
}
Show_num_4(303);
Show_num_4(CCPR2L);
Show_num_1(Bat_2.volt);
Show_num_3(Bat_2.cur);
}
if(Bat_2.cur>=10) /*当电流大于10mA时*/
{
LEDB=0; /*显示红灯*/
}
CAN_0x26(2); /*发送0x26命令,读取电池状态信息*/
}
else
{
Bat2_Error_Deal(); /*执行错误处理程序*/
}
}
else /*当电池充满电时*/
{
CCPR2L=160; /*切断电池输出,等待拔出电池*/
LEDB=1; /*亮绿灯,指示此时已经充满电*/
}
}
/***************************
函数:void Bat1_Error_Deal(void)
函数描述:左侧电池故障处理函数
变量:无
*****************************/
void Bat1_Error_Deal(void)
{
if(Bat_1.error1==1)
{
delay(1000); /*延时2S*/
CAN_0x25(1); /*再次检测故障*/
if(Bat_1.error1==1)
{
CAN_0x26(1); /*发送0x26命令,读取电池状态信息*/
if(Bat_1.Soc>=95) /*电量达到100%时,不处理故障,切断输出,停止充电*/
{
CCPR1L=160; /*切断输出*/
Bat_1.chg_full=1;
LEDA=1; /*亮绿灯,指示此时已经充满电*/
}
else
{
Bat_1_Reset(); /*左侧电池状态复位*/
/*故障灯光提示*/
LEDA=~LEDA; /*闪灯*/
delay(500); /*延时0.5S*/
LEDA=~LEDA; /*闪灯*/
delay(500); /*延时0.5S*/
LEDA=~LEDA; /*闪灯*/
delay(500); /*延时0.5S*/
LEDA=~LEDA; /*闪灯*/
delay(500); /*延时0.5S*/
}
}
}
if(Bat_1.error2==1) /*充电过流故障*/
{
Bat_1_Reset(); /*左侧电池状态复位*/
/*故障灯光提示*/
LEDA=~LEDA; /*闪灯*/
delay(500); /*延时0.5S*/
LEDA=~LEDA; /*闪灯*/
delay(500); /*延时0.5S*/
LEDA=~LEDA; /*闪灯*/
delay(500); /*延时0.5S*/
LEDA=~LEDA; /*闪灯*/
delay(500); /*延时0.5S*/
}
/*其他情况,充电器端忽略故障,电池段会自行处理*/
}
/***************************
函数:void Bat2_Error_Deal(void)
函数描述:右侧电池故障处理函数
变量:无
*****************************/
void Bat2_Error_Deal(void)
{
if(Bat_2.error1==1)
{
delay(1000); /*延时2S*/
CAN_0x25(2); /*再次检测故障*/
if(Bat_2.error1==1)
{
CAN_0x26(2); /*发送0x26命令,读取电池状态信息*/
if(Bat_2.Soc>=95) /*电量达到100%时,不处理故障,切断输出,停止充电*/
{
CCPR2L=160; /*切断输出*/
Bat_2.chg_full=1;
LEDB=1; /*亮绿灯,指示此时已经充满电*/
}
else
{
Bat_2_Reset(); /*左侧电池状态复位*/
/*故障灯光提示*/
LEDB=~LEDB; /*闪灯*/
delay(500); /*延时0.5S*/
LEDB=~LEDB; /*闪灯*/
delay(500); /*延时0.5S*/
LEDB=~LEDB; /*闪灯*/
delay(500); /*延时0.5S*/
LEDB=~LEDB; /*闪灯*/
delay(500); /*延时0.5S*/
}
}
}
if(Bat_2.error2==1) /*充电过流故障*/
{
Bat_2_Reset(); /*左侧电池状态复位*/
/*故障灯光提示*/
LEDB=~LEDB; /*闪灯*/
delay(500); /*延时0.5S*/
LEDB=~LEDB; /*闪灯*/
delay(500); /*延时0.5S*/
LEDB=~LEDB; /*闪灯*/
delay(500); /*延时0.5S*/
LEDB=~LEDB; /*闪灯*/
delay(500); /*延时0.5S*/
}
/*其他情况,充电器端忽略故障,电池段会自行处理*/
}
bat.h
/*****************************************************************/
#ifndef __BAT_h__
#define __BAT_h__
#include "pic.h"
#include
#include
#include
#include
#include
void Bat_init(void); /*初始化左右侧电池的状态标志位*/
void Bat_1_Reset(void); /*左侧电池状态复位*/
void LeftBattery_Init(void); /*左侧电池初始化*/
void LeftBattery_Deal(void); /*左侧电池处理函数*/
void Bat1_Error_Deal(void); /*左侧电池故障处理函数*/
void Bat_2_Reset(void); /*右侧电池状态复位*/
void RightBattery_Init(void); /*右侧电池初始化*/
void RightBattery_Deal(void); /*右侧电池处理函数*/
void Bat2_Error_Deal(void); /*右侧电池故障处理函数*/
#endif