/*-------------------------------------------\
* SC8F072 SOP16
* ----------------
* ------------|1(VDD) (GND)16|-------------
USB_5V* ------------|2(RB0) (RA0)15|-------------ADC
* ------------|3(RB1) (RA1)14|-------------TP4056_7
------------|4(RB2) (RA2)13|-------------
S1 ------------|5(RB3) (RA3)12|-------------LED1
S2 ------------|6(RB4) (RA4)11|-------------LED2
MD_PMW* ------------|7(RB5) (RA5)10|-------------LED3
LED5* ------------|8(RB6) (RB7)9|--------------LED4
* ----------------
-------------------------------------------*/
#include <sc.h> //芯片头文件,会根据工程选项自动寻找对应型号头文件
#define _XTAL_FREQ 16000000 //16MHz,使用内置延时函数必须定义主频,
#define SEG1_IN TRISA3 = 1
#define SEG1_LOW RA3 = 0;TRISA3 = 0
#define SEG1_HIGH RA3 = 1;TRISA3 = 0
#define SEG2_IN TRISA4 = 1
#define SEG2_LOW RA4 = 0;TRISA4 = 0
#define SEG2_HIGH RA4 = 1;TRISA4 = 0
#define SEG3_IN TRISA5 = 1
#define SEG3_LOW RA5 = 0;TRISA5 = 0
#define SEG3_HIGH RA5 = 1;TRISA5 = 0
#define SEG4_IN TRISB7 = 1
#define SEG4_LOW RB7 = 0;TRISB7 = 0
#define SEG4_HIGH RB7 = 1;TRISB7 = 0
#define SEG5_IN TRISB6 = 1
#define SEG5_LOW RB6 = 0;TRISB6 = 0
#define SEG5_HIGH RB6 = 1;TRISB6 = 0
#define KEY1 RB3
#define KEY2 RB4
#define USB_5V RB0
#define TP4056_7 RA1
// 0 1 2 3 4 5 6 7 8 9 关 H F U -
const unsigned char Look_Table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x76,0x71,0x3e,0x40};
volatile bit run_10ms_flag; //10MS定时标志位
volatile unsigned char t_100us_10ms_cnt;
volatile unsigned char t_10ms_cnt;
volatile unsigned char sleep_10ms_cnt;
volatile bit on_off_flag;
volatile unsigned char mode;
volatile bit k1_short_flag;
volatile bit k1_short_en_flag;
volatile unsigned char k1_10ms_yes_cnt;
volatile unsigned char k1_10ms_no_cnt;
volatile bit k2_short_flag;
volatile bit k2_short_en_flag;
volatile unsigned char k2_10ms_yes_cnt;
volatile unsigned char k2_10ms_no_cnt;
volatile unsigned char led_ff;
volatile unsigned char led_dd;
volatile unsigned char led_cnt;
volatile unsigned char led_dang;
volatile unsigned char pwm_data;
volatile unsigned char pwm_data_10ms_cnt;
volatile unsigned char pwm_data_run_10ms_cnt;
volatile unsigned char data1;
volatile unsigned char data2;
volatile unsigned char led_shan_num_cnt;
volatile unsigned char led_shan_10ms_cnt;
volatile bit usb_5v_flag;
volatile unsigned char usb_5v_10ms_no_cnt;
volatile unsigned char usb_5v_10ms_yes_cnt;
volatile bit fu_flag;
volatile unsigned char fu_10ms_cnt;
volatile unsigned int adresult;
volatile unsigned char gl_10ms_cnt;
volatile bit one_flag;
volatile unsigned char battery_percent; //电池电量
volatile unsigned char battery_percent_temp; //电池电量临时
volatile unsigned char battery_percent_10ms_cnt;
volatile unsigned char battery_percent_1s_cnt;
volatile unsigned int data;
volatile unsigned char bat_num;
volatile unsigned int bat_adc_data;
volatile unsigned int bat_max;
volatile unsigned int bat_min;
volatile unsigned char l_3v_10ms_cnt;
volatile bit low_power_off_flag;
volatile unsigned int low_power_shan_10ms_cnt;
volatile unsigned int xs_10ms_cnt;
volatile unsigned int timeing_10ms_cnt;
void My_Ram_Init()
{
on_off_flag = 0;
mode = 1;
data = 0;
bat_num = 0;
bat_adc_data = 0;
bat_max = 0;
bat_min = 5000;
}
void Init_System()// 8/16M
{
asm("nop");
asm("clrwdt");
INTCON = 0; //系统初始化
OSCCON = 0x72; //16MHZ,内部振荡器用作系统时钟,CONFIG关闭WDT时必需软件打开WDT
OPTION_REG = 0x00; //配置TIMER0时间,00为2分频
asm("clrwdt");
WPUA = 0B00000010; //初始化上拉
WPDA = 0B00000000; //初始化下拉
TRISA = 0B00000011; //初始化IO状态
PORTA = 0B00000000; //初始化输出
WPUB = 0B00011000; //初始化上拉
WPDB = 0B00000000; //初始化下拉
TRISB = 0B00011001; //初始化IO状态
PORTB = 0B00000000; //初始化输出
}
void Time2_Init() //100us
{
PR2 = 99; //设定Timer初始值,
TMR2IF = 0;
TMR2IE = 1; //使能Timer2溢出中断
T2CON = 0B00000101; //开启Timer2,预分频为1:4,后分频为1:1,则定时时间为(99+1)*4*(4/16M)=100us
//timer2的时钟源为OSCCON配置的系统时钟/2
INTCON = 0XC0; //开启总中断及外设中断
}
#define FAN_FF 250 //64分频 1K左右
void Pwm_Init() //220K
{
//以下是对PWM功能初始化
/************PWMCON1定义**************************
Bit7~6 PWMIO_SEL[1:0]: PWM IO选择。
11= PWM分配在A组,PWM0-RA0,PWM1-RA1,PWM2-RA2,PWM3-RA3,PWM4-RA4
10= PWM分配在B组,PWM0-RA0,PWM1-RA1,PWM2-RA2,PWM3-RB2,PWM4-RB1
01= PWM分配在C组,PWM0-RA5,PWM1-RB7,PWM2-RB6,PWM3-RB5,PWM4-RB4
00= PWM分配在D组,PWM0-RB0,PWM1-RB1,PWM2-RB3,PWM3-RB4,PWM4-RB2
Bit5 PWM2DTEN: PWM2死区使能位。
1= 使能PWM2死区功能,PWM2和PWM3组成一对互补输出。
0= 禁止PWM2死区功能。
Bit4 PWM0DTEN: PWM0死区使能位。
1= 使能PWM0死区功能,PWM0和PWM1组成一对互补输出。
0= 禁止PWM0死区功能。
Bit3~Bit2 未用。
Bit1~Bit0 DT_DIV[1:0] 死区时钟源分频。
11= FOSC/8
10= FOSC/4
01= FOSC/2
00= FOSC/1
**********************************************************************/
TRISB5 = 1;
PWMCON1 = 0B01000000; //PWM选择C组
PWMTL = FAN_FF; //PWM 周期=[PWMT+1]*Tosc*(CLKDIV 分频值)
PWMT4L = FAN_FF;
PWMTH = 0; //周期选择为0FF,则周期为(255+1)*1/8M,周期的时钟分频在PWMCON0选择
//PWM4周期选择为03FF
PWMD0L = 0; //脉冲宽度 = (PWMDx[9:0]+1)*TOSC*(CLKDIV 分频值)
//必须注意根据公式,即使占空比设为0仍有脉冲输出,如要输出低电平
//需要关闭PWMEN,然后设为输出低
PWMD1L = 0; //互补模式,PWM1的占空比与PWM0互补,和设置值无关
PWMD01H = 0; //配置PWM1,PWM2的占空比,该值不能超过周期,否者为100%输出
PWM01DT = 0; //死区设为2uS,计算为(3+1)*1/8M*4
//死区1的占空比以PWM0设置的占空比为基准
PWMD2L = 0; //PWM2 占空比低位寄存器 该值不能超过周期,否者为100%输出
PWMD3L = 0; //PWM3 占空比低位寄存器 ,互补以PWM0占空比为准
PWMD23H = 0; //PWM2 和 PWM3 占空比高位寄存器 PWMD01H,该值不能超过周期,否者为100%输出
PWMD4L = 0; //PWM4 占空比低位寄存器,PWM4占空比高位在PWMTH的Bit4~5
/***************PWMCON0*************************************
Bit7~Bit5 CLKDIV[2:0]: PWM时钟分频。
111= FOSC/128
110= FOSC/64
101= FOSC/32
100= FOSC/16
011= FOSC/8
010= FOSC/4
001= FOSC/2
000= FOSC/1
Bit4~Bit0 PWMxEN: PWMx使能位。
1= 使能PWMx。
0= 禁止PWMx。
******************************************************************/
PWMCON0 = 0b11000000; //64分频
TRISB5 = 0;
}
void Pwm_Md(unsigned char dd)
{
if(dd)
{
PWMD3L = dd;
PWM3EN = 1;
}
else
{
PWMD3L = 0;
PWM3EN = 0;
RB5 = 0;
}
}
void Led_Data()
{
unsigned char data1_temp,data2_temp;
data1_temp = 0;
data2_temp = 0;
if(xs_10ms_cnt)xs_10ms_cnt--;
if(low_power_shan_10ms_cnt)low_power_shan_10ms_cnt--;
if(xs_10ms_cnt || usb_5v_flag || on_off_flag || low_power_shan_10ms_cnt)
{
if(low_power_shan_10ms_cnt)
{
if(low_power_shan_10ms_cnt > 450)data2_temp |= 0x07;
else if(low_power_shan_10ms_cnt > 400)data2_temp |= 0x00;
else if(low_power_shan_10ms_cnt > 350)data2_temp |= 0x07;
else if(low_power_shan_10ms_cnt > 300)data2_temp |= 0x00;
else if(low_power_shan_10ms_cnt > 250)data2_temp |= 0x07;
else if(low_power_shan_10ms_cnt > 200)data2_temp |= 0x00;
else if(low_power_shan_10ms_cnt > 150)data2_temp |= 0x07;
else if(low_power_shan_10ms_cnt > 100)data2_temp |= 0x00;
else if(low_power_shan_10ms_cnt > 50)data2_temp |= 0x07;
else data2_temp |= 0x00;
data2_temp |= 0xf0;
}
else if(usb_5v_flag == 1) //插入充电
{
led_shan_10ms_cnt++;
if(led_shan_10ms_cnt > 50) //0.5秒闪
{
led_shan_10ms_cnt = 0;
led_shan_num_cnt++;
if(led_shan_num_cnt > 4)led_shan_num_cnt = battery_percent_temp;
if(led_shan_num_cnt == 0)led_shan_num_cnt = 1;
}
if(fu_flag == 0) //充电中
{
if(led_shan_num_cnt == 1)data2_temp |= 0x00;
else if(led_shan_num_cnt == 2)data2_temp |= 0x01;
else if(led_shan_num_cnt == 3)data2_temp |= 0x03;
else if(led_shan_num_cnt == 4)data2_temp |= 0x07;
}
else
{
data2_temp |= 0x07;
}
data2_temp |= 0xf0;
}
else
{
data1_temp = Look_Table[mode];
if(battery_percent_temp == 1)data2_temp |= 0x01;
else if(battery_percent_temp == 2)data2_temp |= 0x03;
else if(battery_percent_temp == 3)data2_temp |= 0x07;
data2_temp |= 0xf0;
}
}
data1 = data1_temp;
data2 = data2_temp;
}
void Led_Scan()
{
if(on_off_flag || usb_5v_flag || xs_10ms_cnt || low_power_shan_10ms_cnt)
{
SEG1_IN;
SEG2_IN;
SEG3_IN;
SEG4_IN;
SEG5_IN;
led_dang++;
if(led_dang > 4)led_dang = 1;
if(led_dang == 1)
{
if(data1 & 0x01)
{
SEG2_HIGH; //a1
}
if(data1 & 0x02)
{
SEG3_HIGH; //b1
}
if(data1 & 0x04)
{
SEG4_HIGH; //c1
}
if(data1 & 0x08)
{
SEG5_HIGH; //d1
}
SEG1_LOW;
}
else if(led_dang == 2)
{
if(data1 & 0x10)
{
SEG1_HIGH; //e1
}
if(data1 & 0x20)
{
SEG3_HIGH; //f1
}
if(data1 & 0x40)
{
SEG4_HIGH; //g1
}
if(data2 & 0x80)
{
SEG5_HIGH;
}
SEG2_LOW;
}
else if(led_dang == 3)
{
if(data2 & 0x40)
{
SEG1_HIGH;
}
if(data2 & 0x20)
{
SEG2_HIGH;
}
if(data2 & 0x10)
{
SEG4_HIGH;
}
if(data2 & 0x04)
{
SEG5_HIGH;
}
SEG3_LOW;
}
else if(led_dang == 4)
{
if(data2 & 0x02)
{
SEG1_HIGH;
}
if(data2 & 0x01)
{
SEG2_HIGH;
}
SEG4_LOW;
}
}
else
{
SEG1_LOW;
SEG2_LOW;
SEG3_LOW;
SEG4_LOW;
SEG5_LOW;
}
}
/***********************************************************
中断服务函数
函数名称:AD_Init()
函数功能:AD初始化处理函数
入口参数:
出口参数:
备 注:第一次打开AD允许位ADON,需延时20uS以上才能进入AD采样
如后继程序不关闭ADON,则不需要延时
***********************************************************/
void AD_Init()
{
ANSEL0 = 0B00000001; //AN0
ANSEL1 = 0B00000000; //
/*********** ADCON0 ****************************
Bit7~Bit6 ADCS<1:0>: AD转换时钟选择位。
00= F HSI /16
01= F HSI /32
10= F HSI /64
11= F HSI /128
Bit5~Bit2 CHS<3:0>: 模拟通道选择位。与ADCON1寄存器CHS4组合CHS<3:0>
CHS<4:0>:
00000= AN0
00001= AN1
00010= AN2
00011= AN3
00100= AN4
00101= AN5
00110= 保留
00111= 保留
01000= AN8
…
01101= AN13
01110= AN14
01111= AN15
11111= 1.2V(固定参考电压)
其他= 保留
Bit1 GO/DONE: AD转换状态位。
1= AD转换正在进行。将该位置1启动AD转换。当AD转换完成以后,该位由硬件自动清零。
当GO/DONE位从1变0或ADIF从0变1时,需至少等待两个TAD时间,才能再次启动AD转换。
0= AD转换完成/或不在进行中。
Bit0 ADON: ADC使能位。
1= 使能ADC;
0= 禁止ADC,不消耗工作电流。
*********************************************/
ADCON0 = 0X41; //ADON开启,AD采样时间选为FSYS/16
/*********** ADCON1 ****************************
Bit7 ADFM: AD转换结果格式选择位;
1= 右对齐;
0= 左对齐。
Bit6 CHS4: 通道选择位
Bit5~Bit3 未用
Bit2 LDO_EN: 内部参考电压使能位。
1= 使能ADC内部LDO参考电压;
当选择内部LDO作参考电压时,ADC最大有效精度为8位。
0= VDD作为ADC参考电压。
Bit1~Bit0 LDO_SEL<1:0>: 参考电压选择位
0X= 2.0V
10= 2.4V
11= 3.0V
*********************************************/
ADCON1 = 0;
}
/**********************************************************
函数名称:AD_Sample
函数功能:AD检测
入口参数:adch - 检测通道
出口参数:无
备 注:采样通道需自行设置为输入口
采样10次,取中间八次的平均值为采样结果存于adresult中
adch 为输入AD通道 0-15,31
31 检测内部1.2V
adldo =5,开启内部LDO 2V 作为ADC 参考
adldo =6,开启内部LDO 2.4V 作为ADC 参考
adldo =7,开启内部LDO 3V 作为ADC 参考
adldo =0,VDD 作为ADC 参考
AD转换结果左对齐
ADC参考电压从VDD切换到LDO时需要延时100us以上,才能进行AD转换
**********************************************************/
unsigned char ADC_Sample(unsigned char adch, unsigned char adldo)
{
volatile unsigned long adsum = 0;
volatile unsigned int admin = 0, admax = 0;
volatile unsigned int ad_temp = 0;
if ((!LDO_EN) && (adldo & 0x04) )
{
//如果AD参考从VDD换到内部LDO,需要延时100US以上
ADCON1 = adldo; //左对齐,AD值取12位
__delay_us(100); //IDE内置延时函数,延时100us
}
else
ADCON1 = adldo; //如果ADCON1.7(ADFM)=1为右对齐,,AD值取10位
if(adch & 0x10)
{
CHS4 = 1;
adch &= 0x0f;
}
unsigned char i = 0;
for (i = 0; i < 10; i++)
{
ADCON0 = (unsigned char)(0X41 | (adch << 2)); //16分频,如果主频为16M,则必须选16分频或以上
asm("nop");
asm("nop");
asm("nop");
asm("nop"); //选择通道后需延时1uS以上
GODONE = 1; //开始转换
unsigned int j = 0;
while (GODONE)
{
__delay_us(2); //延时2us(编译器内置函数)
if (0 == (--j)) //延时0.5ms仍没有AD转换结束,跳出程序
return 0;
}
ad_temp = (unsigned int)((ADRESH << 4) + (ADRESL >> 4)); //计算12位AD值
if (0 == admax)
{
admax = ad_temp;
admin = ad_temp;
}
else if (ad_temp > admax)
admax = ad_temp; //AD采样最大值
else if (ad_temp < admin)
admin = ad_temp; //AD采样最小值
adsum += ad_temp;
}
adsum -= admax;
if (adsum >= admin)
adsum -= admin;
else
adsum = 0;
adresult = adsum >> 3; //8次平均值作为最终结果
adsum = 0;
admin = 0;
admax = 0;
return 0xA5;
}
void Bat_Read() //读电池电压
{
ADC_Sample(31,0); // 1.2V基准, 左对齐,VDD作为参考电压
bat_adc_data += adresult;
if(adresult > bat_max)bat_max = adresult;
if(adresult < bat_min)bat_min = adresult;
bat_num++;
if(bat_num >= 10)
{
bat_adc_data = bat_adc_data - bat_max - bat_min;
bat_adc_data = bat_adc_data >> 3;
if(usb_5v_flag == 0) //放电中
{
if(bat_adc_data <= 1293) //大于3.8 3格
{
l_3v_10ms_cnt = 0;
battery_percent = 3;
}
else if(bat_adc_data > 1585) //小于3.1V
{
l_3v_10ms_cnt++;
if(l_3v_10ms_cnt > 4)
{
l_3v_10ms_cnt = 0;
battery_percent_temp = 0;
battery_percent = 0;
}
}
else if(bat_adc_data < 1404) //大于3.5V 2格
{
battery_percent = 2;
}
else //1格
{
battery_percent = 1;
}
}
else //充电中
{
if(bat_adc_data < 1198) //大于4.1 3格
{
battery_percent = 3;
}
else if(bat_adc_data < 1293) //大于3.8V 2格
{
battery_percent = 2;
}
else if(bat_adc_data < 1404) //大于3.5V 1格
{
battery_percent = 1;
}
else //0格
{
battery_percent = 0;
}
}
if(battery_percent > 3)battery_percent = 3;
if(one_flag == 0) //首次上电
{
battery_percent_temp = battery_percent;
one_flag = 1;
}
if(battery_percent_temp == 0) //没有电了关机
{
if(usb_5v_flag == 0 && low_power_off_flag == 0)
{
on_off_flag = 0;
Pwm_Md(0);
low_power_off_flag = 1; //低压关机标记
low_power_shan_10ms_cnt = 500;
}
}
bat_num = 0;
bat_adc_data = 0;
bat_max = 0;
bat_min = 5000;
}
}
void Bat_Add_Sub() //电池电量加或减
{
unsigned char time_temp;
battery_percent_10ms_cnt++;
if(battery_percent_10ms_cnt >= 100) //1s
{
battery_percent_10ms_cnt = 0;
battery_percent_1s_cnt++;
if(usb_5v_flag == 0) //没在充电
{
time_temp = 3;
if(battery_percent_1s_cnt > time_temp)
{
battery_percent_1s_cnt = 0;
if(battery_percent_temp > battery_percent)battery_percent_temp--;
}
}
else //充电中
{
if(fu_flag == 0)time_temp = 60;//60秒
else time_temp = 10;//10秒
if(battery_percent_1s_cnt > time_temp)
{
battery_percent_1s_cnt = 0;
if(fu_flag == 0) //没充满
{
if(battery_percent_temp < battery_percent)
{
battery_percent_temp++;
}
}
else
{
if(battery_percent_temp < 3)
{
battery_percent_temp++;
}
}
}
}
}
}
void All_Mode()
{
if(mode == 1)pwm_data = 95; //38%
else if(mode == 2)pwm_data = 100; //40%
else if(mode == 3)pwm_data = 100; //40%
else if(mode == 4)pwm_data = 102; //41%
else if(mode == 5)pwm_data = 112; //45%
else if(mode == 6)pwm_data = 117; //47%
else if(mode == 7)pwm_data = 122; //49%
else if(mode == 8)pwm_data = 122; //49%
}
void Key_Scan()
{
if(usb_5v_flag == 0) //不充电的时候按键才有作用
{
if(KEY1 == 0)
{
k1_10ms_no_cnt = 0;
k1_10ms_yes_cnt++;
if(k1_10ms_yes_cnt > 2)
{
if(k1_short_flag == 0)
{
k1_short_flag = 1;
k1_short_en_flag = 1;
}
}
}
else
{
k1_10ms_yes_cnt = 0;
k1_10ms_no_cnt++;
if(k1_10ms_no_cnt > 2)
{
k1_short_flag = 0;
}
}
if(KEY2 == 0)
{
k2_10ms_no_cnt = 0;
k2_10ms_yes_cnt++;
if(k2_10ms_yes_cnt > 2)
{
if(k2_short_flag == 0)
{
k2_short_flag = 1;
k2_short_en_flag = 1;
}
}
}
else
{
k2_10ms_yes_cnt = 0;
k2_10ms_no_cnt++;
if(k2_10ms_no_cnt > 2)
{
k2_short_flag = 0;
}
}
}
if(USB_5V == 1)
{
usb_5v_10ms_no_cnt = 0;
usb_5v_10ms_yes_cnt++;
if(usb_5v_10ms_yes_cnt > 5)
{
usb_5v_flag = 1;
low_power_off_flag = 0;
low_power_shan_10ms_cnt = 0;
on_off_flag = 0;
Pwm_Md(0);
}
}
else
{
usb_5v_10ms_yes_cnt = 0;
usb_5v_10ms_no_cnt++;
if(usb_5v_10ms_no_cnt > 5)
{
usb_5v_flag = 0;
fu_flag = 0;
}
}
if(usb_5v_flag == 1)
{
if(TP4056_7 == 1)
{
fu_10ms_cnt++;
if(fu_10ms_cnt > 200)
{
fu_10ms_cnt = 0;
fu_flag = 1;
}
}
else fu_10ms_cnt = 0;
}
}
void Key_Service()
{
if(k1_short_en_flag == 1) //短按开关
{
k1_short_en_flag = 0;
if(low_power_off_flag == 1) //低压标记
{
low_power_shan_10ms_cnt = 500;
}
else
{
if(on_off_flag == 0)
{
on_off_flag = 1;
xs_10ms_cnt = 0;
All_Mode();
}
else
{
on_off_flag = 0;
Pwm_Md(0);
}
}
}
if(k2_short_en_flag == 1)
{
k2_short_en_flag = 0;
if(on_off_flag == 0 && low_power_shan_10ms_cnt == 0)xs_10ms_cnt = 400; //显示4秒
mode++;
if(mode > 8)mode = 1;
All_Mode();
}
}
void Sleep_Mode()
{
if(on_off_flag == 0 && USB_5V == 0 && KEY1 == 1 && KEY2 == 1 && xs_10ms_cnt == 0 && low_power_shan_10ms_cnt == 0)
{
sleep_10ms_cnt++;
if(sleep_10ms_cnt > 200)
{
sleep_10ms_cnt = 0;
INTCON = 0;
OPTION_REG = 0;
ANSEL0 = 0B00000000;
ANSEL1 = 0B00000000;
ADCON0 = 0; //关闭所有模块
ADCON1 = 0;
PWMCON0 = 0;
OSCCON = 0X70; //配置振荡为8M,关闭WDT,需注意芯片工程选项里WDT必须选为DISABLE,否则无法软件关掉WDT
IOCA = 0B00000000; //
IOCB = 0B00011001; //允许RB034的IO口电平变化中断
RAIE = 0; //
PEIE = 0; //要用RORTA中断唤醒,则PEIE必须设为1
RBIE = 1; //允许PORTB电平变化中断
GIE = 0; //唤醒后执行SLEEP后程序;
PORTA; //读PORTA值并锁存,用电平变化中断必须执行这一步
RAIF = 0; //清PORTA中断标志位
PORTB; //读PORTB值并锁存
RBIF = 0; //清PORTB中断标志位
asm("clrwdt");
asm("sleep"); //进入休眠模式
asm("nop");
asm("clrwdt");
IOCA = 0B00000000;
IOCB = 0B00000000;
RAIE = 0;
PEIE = 0;
RBIE = 0;
OSCCON = 0X72; //配置振荡为8M,开WDT,需注意芯片工程选项里WDT必须选为DISABLE,否则无法软件关掉WDT
asm("clrwdt");
if(RAIF) RAIF = 0; //清中断标志
if(RBIF) RBIF = 0; //清中断标志
AD_Init();
Pwm_Init();
Time2_Init(); //100us 16M
}
}
else sleep_10ms_cnt = 0;
}
void Md_Fun()
{
unsigned char pwm_temp,add_time;
if(on_off_flag == 1)
{
if(mode == 1)
{
add_time = 4;
pwm_temp = 215; //86%
}
else if(mode == 2)
{
add_time = 16;
pwm_temp = 130; //52%
}
else if(mode == 3)
{
add_time = 10;
pwm_temp = 150; //60%
}
else if(mode == 4)
{
add_time = 7;
pwm_temp = 170; //68%
}
else if(mode == 5)
{
add_time = 6;
pwm_temp = 190; //76%
}
else if(mode == 6)
{
add_time = 5;
pwm_temp = 220; //88%
}
else if(mode == 7)
{
add_time = 4;
pwm_temp = 235; //94%
}
else if(mode == 8)
{
add_time = 4;
pwm_temp = 250; //100%
}
pwm_data_10ms_cnt++;
if(pwm_data_10ms_cnt >= add_time)
{
pwm_data_10ms_cnt = 0;
if(pwm_data < pwm_temp)pwm_data++;
}
pwm_data_run_10ms_cnt++;
if(pwm_data_run_10ms_cnt >= 100)pwm_data_run_10ms_cnt = 0;
if((mode == 1) && (pwm_data_run_10ms_cnt > 50))
{
Pwm_Md(0);
}
else
{
Pwm_Md(pwm_data);
}
timeing_10ms_cnt++;
if(timeing_10ms_cnt >= 9000) //开90s关机
{
on_off_flag = 0;
}
ADC_Sample(0,5); //过流保护
if(adresult > 389) //大于0.19V (大约3.8A)
{
gl_10ms_cnt++;
if(gl_10ms_cnt > 60)
{
gl_10ms_cnt = 0;
on_off_flag = 0;
Pwm_Md(0);
}
}
else
{
if(gl_10ms_cnt)gl_10ms_cnt--;
}
}
else
{
Pwm_Md(0);
timeing_10ms_cnt = 0;
}
}
void main()
{
Init_System();
My_Ram_Init();
AD_Init();
Pwm_Init();
Time2_Init();
while(1)
{
asm("clrwdt");
if(run_10ms_flag == 1) //10ms
{
run_10ms_flag = 0;
Key_Scan();
Key_Service();
Md_Fun();
Led_Data();
Bat_Read(); //读电池电压
Bat_Add_Sub(); //电池电量加或减
Sleep_Mode(); //进低功耗
}
}
}
void interrupt Timer_Isr()
{
if(TMR2IF)
{
TMR2IF = 0; //清中断标志位
t_100us_10ms_cnt++;
if(t_100us_10ms_cnt >= 100) //10ms
{
t_100us_10ms_cnt = 0;
run_10ms_flag = 1;
t_10ms_cnt++;
}
led_cnt++;
if(led_cnt > 10)
{
led_cnt = 0;
Led_Scan();
}
}
if(RAIF) RAIF = 0; //清中断标志
if(RBIF) RBIF = 0; //清中断标志
}
最新发布