|

楼主 |
发表于 2021-7-9 15:07:54
|
显示全部楼层
/*********************************************************************************
Sys_Basic.c 文件
* 修改此程序请保留上述版权声明,引用程序请注明出处!
**********************************************************************************/
#include "config.h"
/********************** 全局变量定义 ************************/
PWM_s PWM = {0,Disable}; //PWM相关变量
IRON_STATUS_e IronStateFlag = NORMAL; //烙铁工作状态标志位
TIMER_s Timer = {0,0,0}; //定时计数器
IRONUSE_STATUS_s IronUse_Status = {FREE,FREE}; //烙铁使用状态标志位
/************************************************************
* 函数名 : timer0_int
* 功能说明 : 定时器0中断,生成PWM波,蜂鸣器响
*
* 输入参数 : 无
* 输出参数 : 无
*
*************************************************************/
void timer0_int (void) interrupt TIMER0_VECTOR
{
static unsigned int BeepCounter = 0;
//蜂鸣器响
//旋转或按下后BeepCounterFlag被置位,开始计数
if(BeepCounterFlag)
{
BeepCounter++;
}
//计数小于设定值时打开,大于时关闭,Beep_Volume的值决定了占空比
if((BeepCounter > 0) && (BeepCounter <= MENU_DATA_Table.Other_s.Beep_Volume*BEEP_TIME))
{
BEEP_ON;
}
else
{
BEEP_OFF;
}
//清零
if(BeepCounter == BEEP_TIME*10)
{
BeepCounter = 0;
BeepCounterFlag = 0;
}
}
/************************************************************
* 函数名 : timer1_int
* 功能说明 : 定时器1中断,主要控制
*
* 输入参数 : 无
* 输出参数 : 无
*
*************************************************************/
void timer1_int (void) interrupt TIMER1_VECTOR
{
static unsigned int IronUseCounter[2]={0,0};
static unsigned int ShutDownCounter = 0;
static unsigned char Sleep_Old = 0;
static unsigned char PWM_counter = 0;
static unsigned char SetTempCounter = 0;
//烙铁PWM生成
PWM_counter=Timer.mSec%100;
if((PWM_counter<PWM.Duty) && PWM.Run)
IRON = 1;
else
IRON = 0;
//1ms处理部分
Timer.mSec++; //定时器0分段计数器自加
EC11_Capture(); //捕捉EC11信息
//10ms处理部分
if(Timer.mSec%10 == 0)
{
if(IronUse_Status.Handle || IronUse_Status.Coder)//烙铁或编码器用了,那要看看现在是不是休眠什么的状态了
{
if(IronStateFlag && MENU_DATA_Table.Time_s.Slp_Time > 0)
{
Timer.Sec = 0;
Timer.Min = 0;
ec11_state.Key = KEY_FREE;
ec11_state.Coder = CODER_FREE;
IronStateFlag = NORMAL;
#if SCREEN == 2
LED_ON;//LCD背光打开
#else
Screen_Contrast(FAC_DATA_Table.Adjust_s.Lightness);
#endif
Beep(MENU_DATA_Table.Other_s.Beep_Volume);
}
else if(IronStateFlag && MENU_DATA_Table.Time_s.Slp_Time == 0)
{
Timer.Sec = 0;
Timer.Min = 0;
ec11_state.Coder = CODER_FREE;
IronStateFlag = NORMAL;
#if SCREEN != 2
Screen_Contrast(FAC_DATA_Table.Adjust_s.Lightness>>2);
#else
LED_ON;//LCD背光打开
#endif
Beep(MENU_DATA_Table.Other_s.Beep_Volume);
}
}
}
if(Timer.mSec%25 == 0)
{
//如果正在设定温度,那么大字显示设定温度值
if(SetTempFlag == 1)
{
SetTempCounter++;
}
if(SetTempCounter == 50)
{
SetTempCounter = 0;
SetTempFlag = 0;
if((MENU_DATA_Table.Temp_s.Default_Temp == 0) || (MENU_DATA_Table.Temp_s.Default_CH == 0))
{
EEPROM_SectorErase(0x0);
EEPROM_write_n(0x0,(unsigned char *)&MENU_DATA_Table,sizeof(MENU_DATA_Table));
}
}
//读室温和电压
RoomTemp = GetRoomTemp();
VCCVoltage = GetVoltage();
//按键扫描
Key_Scan();
}
//100ms处理部分
if(Timer.mSec%100 == 0)
{
//大于0按时间休眠
if(MENU_DATA_Table.Time_s.Slp_Time > 0)
{
//水银开关跳变沿检测并计数
if(SLEEP != Sleep_Old)
{
IronUseCounter[0]++;
}
Sleep_Old = SLEEP;
}
//等于零按电平休眠
else
{
if(SLEEP == 0)
{
IronUseCounter[1]++;
}
}
//温度控制(正常工作按IronTemp_AM控制,休眠按Slp_Temp控制,否则关烙铁)
if(IronStateFlag == NORMAL)
{
IronTempControl(IronTemp.Set);
}
else if(IronStateFlag==SLEEPING)
{
IronTempControl(MENU_DATA_Table.Temp_s.Slp_Temp);
}
else
{
IronTempControl(0);
}
}
//1s处理部分
if(Timer.mSec == 1000)
{
//如果休眠时间大于零,那么按时间休眠
if(MENU_DATA_Table.Time_s.Slp_Time > 0)
{
//一秒内看10次跳变沿,如果这10次有N次烙铁手柄状态发生变化,那么认为是确实在使用
if(IronUseCounter[0]>MENU_DATA_Table.Other_s.Shock_Sensor)
{
IronUse_Status.Handle = USING;
}
else
{
IronUse_Status.Handle = FREE;
}
//看完后清计数器
IronUseCounter[0] = 0;
}
else//否则按电平休眠
{
//1s内看10次电平,如果10次电平有N次都是低电平,认为该休眠了
if((IronUseCounter[1]>MENU_DATA_Table.Other_s.Shock_Sensor) && (IronStateFlag == NORMAL) &&(ShutdownCounterFlag==0))
{
IronUse_Status.Handle = FREE;
IronStateFlag = SLEEPING;
Beep(MENU_DATA_Table.Other_s.Beep_Volume);
//清计时器为待机做准备
Timer.Sec = 0;
Timer.Min = 0;
}
else if((IronUseCounter[1]<=MENU_DATA_Table.Other_s.Shock_Sensor) && (IronStateFlag == SLEEPING))
{
IronUse_Status.Handle = USING;
IronStateFlag = NORMAL;
}
IronUseCounter[1] = 0;
}
//如果认为没有使用,那么开始计时,只要用了就清零(烙铁没有使用&&编码器没有使用&&没有进菜单)
if(IronUse_Status.Handle == FREE && IronUse_Status.Coder == FREE && ShutdownCounterFlag==0)
{
Timer.Sec++;
}
else
{
Timer.Sec = 0;
Timer.Min = 0;
IronUse_Status.Coder = FREE;
}
Timer.mSec = 0;
}
//1min处理部分
if(Timer.Sec == 55)//定时不准
{
Timer.Min++;
Timer.Sec = 0;
//以下是休眠、关屏、和软关机
//如果 (睡眠时间不为0&&在正常工作状态)
if((MENU_DATA_Table.Time_s.Slp_Time > 0) && (IronStateFlag == NORMAL))
{
if(Timer.Min == MENU_DATA_Table.Time_s.Slp_Time)
{
#if SCREEN != 2
Screen_Contrast(FAC_DATA_Table.Adjust_s.Lightness>>2);
#endif
IronStateFlag = SLEEPING;
Beep(MENU_DATA_Table.Other_s.Beep_Volume);
//清计时器为待机做准备
Timer.Sec = 0;
Timer.Min = 0;
}
}
//如果软关机时间>=0&&已经休眠
if((MENU_DATA_Table.Time_s.Shutdown_Time > 0) && (IronStateFlag == SLEEPING))
{
if(Timer.Min == MENU_DATA_Table.Time_s.Shutdown_Time)
{
//清计时器为掉电唤醒做准备
Timer.Sec = 0;
Timer.Min = 0;
//置烙铁状态标志位
IronStateFlag = STANDBY;
#if SCREEN == 2
LED_OFF;//LCD背光关
#endif
//蜂鸣器响,确保烙铁关到位了
BEEP_ON;
Delay_ms(100);
OLED_Init();//进中断时可能屏幕指针不在初始位置,顺便初始化一下
OLED_CLS();
PWM.Run = Disable;
IRON = 0;
BEEP_OFF;
Delay_ms(150);
OLED_CLS();
BEEP_ON;
Delay_ms(150);
OLED_CLS();
BEEP_OFF;
//如果关机时间大于零,则初始化掉电唤醒定时器为16s,并且进入掉电模式,否则直接掉电
if(MENU_DATA_Table.Time_s.Suicide_Time > 0)
{
//掉电唤醒定时器初始化
WKTCL = 0xfe; //设置唤醒周期16s
WKTCH = 0xff; //使能掉电唤醒定时器
PCON |= 0x02;//掉电
_nop_();
_nop_();
}
else
{
PCON |= 0x02;//掉电
_nop_();
_nop_();
}
while(MENU_DATA_Table.Time_s.Suicide_Time > 0)
{
//记录掉电次数,如果等于定时时间则自杀,否则继续掉电
ShutDownCounter++;
if(ShutDownCounter > MENU_DATA_Table.Time_s.Suicide_Time*4+1)
{
SHUTDOWN = 0;
}
//如果是由掉电唤醒定时器唤醒,则继续掉电;否则清计数器跳出循环
if(WKTCL==0xff && WKTCH==0xff)
{
PCON |= 0x02;//掉电
}
else
{
ShutDownCounter = 0;
break;
}
_nop_();
_nop_();
}
IronUse_Status.Coder = USING;
}
}
}
}
/************************************************************
* 函数名 : timer2_int
* 功能说明 : 大字设定温度和扩展按键扫描,读室温和电压
*
* 输入参数 : 无
* 输出参数 : 无
*
*************************************************************/
void timer2_int (void) interrupt TIMER2_VECTOR
{
}
void exint0() interrupt 0 //INT0中断入口
{
}
void exint4() interrupt 16
{}
//void Uart() interrupt 4 using 1
//{
// if (RI)
// {
// RI = 0; //清除RI位
// SendChar(SBUF);
// }
//}
//void SendChar(unsigned char dat)
//{
// SBUF = dat; //发送数据
// while(!TI); // 等待数据发送完成中断
// TI = 0; //清中断
//}
//float ADC_BandGap_Volt(void) //读取ADC内部电压数据,转化为10位
//{
// unsigned int BangGap=0;
// unsigned char code *BandAddr;
//
// BandAddr=BangGap_Addr;
// BangGap=*BandAddr++;
// BangGap=BangGap<<8;
// BangGap+=*BandAddr;
//
// return (float)BangGap / 4.88f;
//}
//u16 ADC_GetDat(u8 Ch,u8 ChASF) //读ADC数据
//{
// u16 ADC_Dat=0;
// P1ASF=ChASF;
// ADC_CONTR&=~(0x07<<0);
// ADC_CONTR|=(Ch&0x07)<<0;
// ADC_CONTR&=~(1<<4);
// ADC_RES=0;
// ADC_RESL=0;
// ADC_CONTR|=1<<3; //启动ADC转换
//
// while((ADC_CONTR&0x10)==0); //等待ADC转换完成
// ADC_CONTR&=~(1<<4);
//
// ADC_Dat=ADC_RES<<8;
// ADC_Dat+=ADC_RESL;
//
// return ADC_Dat;
//}
//u16 ADC_BandGap_Dat() //读取ADC基准电压
//{
// u16 AD_Return = 0;
// u8 i;
//
// ADC_GetDat(0,0x00); //读取2次取得稳定
// ADC_GetDat(0,0x00);
//
// EA = 0;
// for (i = 0 ; i <DATA_SUM ; i++ ) //连续读取DATA_SUM次基准电压 求和取得平均值
// {
// AD_Return += ADC_GetDat(0,0x00);
// }
// EA = 1;
// return AD_Return >> DATA_DIV;
//}
//u16 ADC_ReadCH_Dat(u8 CH) //读取通道电压
//{
// u16 AD_Return = 0;
// u8 i;
//
// ADC_GetDat(CH,0xff); //读取2次取得稳定
// ADC_GetDat(CH,0xff);
//
// EA = 0;
// for (i = 0 ; i <DATA_SUM ; i++ ) //连续读取DATA_SUM次基准电压求和取得平均值
// {
// AD_Return += ADC_GetDat(CH,0xff);
// }
// EA = 1;
// return AD_Return >> DATA_DIV;
//}
/************************************************************
* 函数名 : Get_ADC10bitResult
* 功能说明 : 读ADC值
*
* 输入参数 : channel,ADC通道号(0-7)
* 输出参数 : 返回ADC值(0-1023)
*
*************************************************************/
unsigned int Get_ADC10bitResult(unsigned char channel)
{
u16 adc;
u8 i;
ADC_RES = 0;
ADC_RESL = 0;
ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel;
NOP(4); //对ADC_CONTR操作后要4T之后才能访问
for(i=0; i<250; i++) //超时
{
if(ADC_CONTR & ADC_FLAG)
{
ADC_CONTR &= ~ADC_FLAG;
adc = (u16)(ADC_RES & 3);
adc = (adc << 8) | ADC_RESL;
return adc;
}
}
return 1024; //错误,返回1024,调用的程序判断
}
/************************************************************
* 函数名 : DisableEEPROM
* 功能说明 : 失能EEPROM
*
* 输入参数 : 无
* 输出参数 : 无
*
*************************************************************/
void DisableEEPROM(void)
{
ISP_CONTR = 0; //禁止ISP/IAP操作
ISP_CMD = 0; //去除ISP/IAP命令
ISP_TRIG = 0; //防止ISP/IAP命令误触发
ISP_ADDRH = 0xff; //清0地址高字节
ISP_ADDRL = 0xff; //清0地址低字节,指向非EEPROM区,防止误操作
}
/************************************************************
* 函数名 :
* 功能说明 : 从指定EEPROM首地址读出n个字节放指定的缓冲.
*
* 输入参数 : EE_address读出EEPROM的首地址,DataAddress读出数据放缓冲的首地址,number读出的字节长度.
* 输出参数 : 无
*
*************************************************************/
void EEPROM_read_n(u16 EE_address,u8 *DataAddress,u16 number)
{
EA = 0; //禁止中断
ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //设置等待时间,允许ISP/IAP操作,送一次就够
ISP_READ(); //送字节读命令,命令不需改变时,不需重新送命令
do
{
ISP_ADDRH = EE_address / 256; //送地址高字节(地址需要改变时才需重新送地址)
ISP_ADDRL = EE_address % 256; //送地址低字节
ISP_TRIG(); //先送5AH,再送A5H到ISP/IAP触发寄存器,每次都需要如此
//送完A5H后,ISP/IAP命令立即被触发启动
//CPU等待IAP完成后,才会继续执行程序。
_nop_();
*DataAddress = ISP_DATA; //读出的数据送往
EE_address++;
DataAddress++;
}while(--number);
DisableEEPROM();
EA = 1; //重新允许中断
}
/************************************************************
* 函数名 : EEPROM_SectorErase
* 功能说明 : 把指定地址的EEPROM扇区擦除
*
* 输入参数 : EE_address:要擦除的扇区EEPROM的地址.
* 输出参数 : 无
*
*************************************************************/
void EEPROM_SectorErase(u16 EE_address)
{
EA = 0; //禁止中断
//只有扇区擦除,没有字节擦除,512字节/扇区。
//扇区中任意一个字节地址都是扇区地址。
ISP_ADDRH = EE_address / 256; //送扇区地址高字节(地址需要改变时才需重新送地址)
ISP_ADDRL = EE_address % 256; //送扇区地址低字节
ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //设置等待时间,允许ISP/IAP操作,送一次就够
ISP_ERASE(); //送扇区擦除命令,命令不需改变时,不需重新送命令
ISP_TRIG();
_nop_();
DisableEEPROM();
EA = 1; //重新允许中断
}
/************************************************************
* 函数名 : EEPROM_write_n
* 功能说明 : 把缓冲的n个字节写入指定首地址的EEPROM.
*
* 输入参数 : EE_address写入EEPROM的首地址,DataAddress写入源数据的缓冲的首地址,number写入的字节长度.
* 输出参数 : 无
*
*************************************************************/
void EEPROM_write_n(u16 EE_address,u8 *DataAddress,u16 number)
{
EA = 0; //禁止中断
ISP_CONTR = (ISP_EN + ISP_WAIT_FREQUENCY); //设置等待时间,允许ISP/IAP操作,送一次就够
ISP_WRITE(); //送字节写命令,命令不需改变时,不需重新送命令
do
{
ISP_ADDRH = EE_address / 256; //送地址高字节(地址需要改变时才需重新送地址)
ISP_ADDRL = EE_address % 256; //送地址低字节
ISP_DATA = *DataAddress; //送数据到ISP_DATA,只有数据改变时才需重新送
ISP_TRIG();
_nop_();
EE_address++;
DataAddress++;
}while(--number);
DisableEEPROM();
EA = 1; //重新允许中断
}
/************************************************************
* 函数名 : Delay_ms
* 功能说明 : ms级延时
*
* 输入参数 : ms
* 输出参数 : 无
*
*************************************************************/
void Delay_ms(unsigned char ms) //@24MHz
{
unsigned char i = 22,j = 128,k;
for(k=0;k<ms;k++)
{
i = 22;
j = 128;
do
{
while (--j);
} while (--i);
}
}
|
|