#include"main.h"
/*******SOC模块**************
ADC起始误差校正
基准电压校正
电流时刻都有可能出现正负值
低电压禁止存储,
无电流禁止存储
SOC通信一次,存储一次?
*/
void main(void) /*main***************/
{
sysinit();
Current_adjust = (float)3000/(float)3712; //计算电流校准系数
//Current_adjust = (float)55000000/(float)3712; //计算电流校准系数
Full_Range_Current = Limit_ADC * Current_adjust; //得出最大电流量程
Battery_Capacity_10_SEC = 0;
while(1)
{
if(Uart3_RX_OK) //如果串口数据接收完成
{
uchar i;
U3_RX_Datas_Proc(); //处理串口1收到的数据
for(i=0; i<Uart3_DATA_Length; i++) //清空接收缓存
{
Uart3_RX_Data_Buf[i] = 0;
}
Uart3_RX_OK = 0;
}
if(Read_CurrentADC_OK) //电流数据读取完成
{
Read_CurrentADC_OK = 0; //清除标志
Current = Current_ADC * Current_adjust; //根据修正值得出 当前的 实际电流值
Battery_Capacity = Battery_Capacity_10_SEC/360; //转换成实际的AH容量
U3_printf("I=%lld,SOC=%lld,over=%d,",Current,Battery_Capacity,(uint)OverLoad_Flag); //输出电流, 是否过载的标志
//控制充放指示灯,和过载标志***************************************************
//-------------
if(Current_ADC > 5)
{LED_G = 0;LED_Y = 1;} //放电,绿灯
else if(Current_ADC < -5)
{LED_G = 1;LED_Y = 0;} //充电,红灯
else
{LED_G = 1;LED_Y = 1;} //无电流,不亮灯
//-----------------
if(Current_ADC > 0) //电流为正值情况下,量程过载判断
{
if(Current_ADC > Limit_ADC) { //ADC值超过限制
OverLoad_Flag = 1;}//做量程过载标志
else {
OverLoad_Flag = 0;} //未过载
}
else //负值情况下,量程过载判断
{
if(Current_ADC < (0-Limit_ADC)) { //ADC值超过限制
OverLoad_Flag = 1;}//做过载标志
else {
OverLoad_Flag = 0;} //未过载
}
}
}
}
void sysinit(void) /*系统初始化********************/
{
delay_X(10000);
P_SW2 = 0X80; //允许访问XSFR
XOSCCR = 0xc0; //启动外部晶振
while(!(XOSCCR & 1)); //等待时钟稳定
CLKDIV = 0x00; //时钟不分频
CKSEL = 0x01; //选择外部晶振
P_SW2 = 0X00; //恢复访问SFR
U3_Init();
IE2 bit3_set_1;//串口3中断打开
Timer0Init();
ET0 = 1; //定时器
EA = 1;
delay_X(10000);
//INA219_WriteReg(0x00, 0x07F9);//重新设置,并触发转换
//INA219_Init();
//i = INA219_GetBusVolt();
//i = INA219_GetPower(); //取这两个值只是为了编译器没有警告,SOC模块并没有使用这个功能
}
void Timer0_ISR() interrupt 1 /*T0中断函数,******************/
{
T_100ms = !T_100ms; //每次中断50毫秒,标志反转一次为100毫秒
if(T_100ms) //如果到达100毫秒
{
Current_ADC = INA219_GetCurrent_ADC(); //每个LSB为10uV
INA219_WriteReg(0x00, 0x07F9);//重新设置,并触发转换
Read_CurrentADC_OK = 1;//电流数据读取完成
Temp_Current_ADC = Temp_Current_ADC + Current_ADC;//累加,用于求平均值
Smaple_Counts++;
if(Smaple_Counts >= 100) //到达100次。每次100毫秒,100次10秒,
{
Smaple_Counts = 0;
Current_10_Sec_Mean = (Temp_Current_ADC/100)*Current_adjust; //取得10秒内的平均值,平均的ADC值,乘以电流校准系数
Battery_Capacity_10_SEC = Battery_Capacity_10_SEC - Current_10_Sec_Mean; //进行容量统计
Temp_Current_ADC = 0;
}
}
T_50ms++;
if(T_50ms >= 20) //50毫秒中断计数
{
T_50ms = 0;
Second++; //秒变量增加
if(Second > 20) Enable_Set_Flag = 0; //上电超过10秒后清除允许设定的标志,秒从0-59循环不会影响程序目的
if(Second == 60) //60的约数最多
{
Second = 0;
}
}
}
void Timer0Init(void) /*T0初始化,50毫秒@11.0592MHz****/
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x4C; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void U3_RX_Datas_Proc(void) /*处理串口1收到的数据****/
{
if((Uart3_RX_Data_Buf[0] == 'o') && (Uart3_RX_Data_Buf[1] == 'k'))
{
//LED1 = 0;
delay_X(65000);
//LED1 = 1;
}
}
void U3_Init(void) //*U3初始化,115200bps@11.0592MHz
{
S3CON = 0x10; //8位数据,可变波特率
S3CON |= 0x40; //串口3选择定时器3为波特率发生器
T4T3M |= 0x02; //定时器3时钟为Fosc,即1T
T3L = 0xE8; //设定定时初值
T3H = 0xFF; //设定定时初值
T4T3M |= 0x08; //启动定时器3
}
void U3_SendData(uchar dat) /*U1发送一个字节*******************************/
{
Uart3_busy = 1;
S3BUF = dat;
while(Uart3_busy);
}
void U3_SendString(uchar *s) /*U1发送一帧,采样总线*/
{
U3_SendData(0xff);//帧开始
while(*s) //检测字符串结束标志,
{
U3_SendData(*s++);//发送字符串
}
U3_SendData(0x00);//帧结束
}
void U3_ISR() interrupt 17 //*U3中断函数,*****
{
if(S3CON & S3RI) //收到一个字节
{
S3CON &= ~S3RI; //清除S2RI位
if(S3BUF == 0xFF) //接收帧开始
{
Uart3_DATA_Sort = 0; //装载变量清零
}
else if(S3BUF == 0x00) //接收帧结束
{
Uart3_RX_OK = 1; // 做标记,主程序中判断1进行处理
}
else
{
Uart3_RX_Data_Buf[Uart3_DATA_Sort] = S3BUF; //数据装入接收缓存
Uart3_DATA_Sort ++; //增加排序标志
if(Uart3_DATA_Sort >= Uart3_DATA_Length) //超出字节长度限制
{
Uart3_DATA_Sort = Uart3_DATA_Length-1; //限制最大值防止溢出
}
}
}
if(S3CON & S3TI) //发送完一个字节
{
S3CON &= ~S3TI; // 清S2TI位
Uart3_busy = 0;
}
}
void U3_printf(uchar *fmt,...) //*U1变量转字符,******
{
/*
%s %d %f %u %c %3.2f %%
用法举例:
int a= 100;
uint b =256;
OLED_printf(0,2,8,"a=%d,b=%u,",a,b);
*/
va_list ap;
uchar xdata string[200];//访问内部拓展RAM,非访问外部RAM,不能超过内部拓展RAM大小(此处为1024)
va_start(ap,fmt);
vsprintf(string,fmt,ap);//此处也可以使用sprintf函数,用法差不多,稍加修改即可,此处略去
U3_SendString(string);
va_end(ap);
}
评论13