📄 chongdianqi.c
字号:
//---------------------------------------------------------------------
//#include <REG52.H>
#include <intrins.H>
#include "NEW_8051.H"
//WDT_CONTR //狗
//---------------------------------------------------------------------
typedef unsigned char INT8U;
typedef unsigned int INT16U;
//定义常量
//pulse_width_MAX = pulse_width_MIN 时, 输出脉冲宽度不变。
#define pulse_width_MAX 0x65 //PWM 脉宽最大值, 占空比 =75%
#define pulse_width_MIN 0x45 //PWM 脉宽最小值, 占空比 =25%
//#define step 0x38 //PWM 脉宽变化步长
#define pulse_width 0x30H
#define ADC_Power_On_Speed_Channel_0 0xE0 //P1.0 作为 A/D 输入
#define ADC_Power_On_Speed_Channel_1 0xE1 //P1.1 作为 A/D 输入
#define ADC_Power_On_Speed_Channel_2 0xE2 //P1.2 作为 A/D 输入
#define ADC_Power_On_Speed_Channel_3 0xE3 //P1.3 作为 A/D 输入
#define ADC_Power_On_Speed_Channel_4 0xE4 //P1.4 作为 A/D 输入
#define ADC_Power_On_Speed_Channel_5 0xE5 //P1.5 作为 A/D 输入
#define ADC_Power_On_Speed_Channel_6 0xE6 //P1.6 作为 A/D 输入
#define ADC_Power_On_Speed_Channel_7 0xE7 //P1.7 作为 A/D 输入
sbit B_LED = P3^4;//
sbit B_LED2 = P1^4;
sbit B_ON = P3^5;
sbit B_PW = P3^7;
INT8U con_state,ADC_Channel_2_Result_date,T_N;
INT16U AD_date,S_N;
//#define ADC_YUCHONGDIAN 0x39 //1.12V,6V
//#define ADC_YUCHONGDIAN_0 0x3E //1.21,6.4V
//#define ADC_JIESHU 0x51 //1.58,8.4V
//#define ADC_YUCHONGDIAN 0x4D //1.51V,8V
//#define ADC_YUCHONGDIAN_0 0x55 //1.65,8.8V
//#define ADC_JIESHU 0x74 //2.26,12V
//#define ADC_KONG 0x8D //2.82,15V
//#define ADC_DUANLU 0x30
//#define ADC_YUCHONGDIAN 0x40 //1.12V,6V
//#define ADC_YUCHONGDIAN_0 0x44 //1.21,6.4V
//#define ADC_JIESHU 0x58 //1.58,8.4V
#define ADC_21 0x89 //21V
#define ADC_24 0x9c //24V
#define ADC_27 0xB0 //27V
#define ADC_28 0xB7 //28V
#define ADC_KONG 0xC8 //2.82,15V
#define ADC_DUANLU 0x30
#define ADC_135 0x58 //21V
#define ADC_13 0x54 //0.153,21V
/***********************
init port
***********************/
void INITAL_port(void)
{
P0=0xff;
P1=0xff;
P2=0xff;
P3=0xff;
}
/***********************
init PCA
************************/
void initiate_pca (void);
void delay(INT8U delay_time) // 延时函数
{
INT16U n;
while(delay_time--)
{
n = 6000;
while(--n);
}
}
/***********************
init AD
************************/
//--------------------------------------------------------------
void ADC_Power_On(void)
{
ADC_CONTR|=0x80; //开 A/D 转换电源
delay(20); //开 A/D 转换电源后要加延时,1mS 以内就足够了
}
void Set_P12_Open_Drain(void) //设置 P1.2,设置 A/D 通道所在的 I/O 为开漏模式
{
P1M0|= 0x4;
P1M1|= 0x4;
}
void Set_ADC_Channel_2(void)
{
ADC_CONTR=ADC_Power_On_Speed_Channel_2;
//选择 P1.2 作为 A/D 转换通道
//更换 A/D 转换通道后要适当延时, 使输入电压稳定
//以后如果不更换 A/D 转换通道的话, 不需要加延时
delay(5); //切换 A/D 转换通道,加延时 20uS~200uS 就可以了,与输入电压源的内阻有关
//如果输入电压信号源的内阻在 10K 以下,可不加延时
}
void initiate_AD (void)
{
ADC_Power_On (); //开 ADC 电源, 第一次使用时要打开内部模拟电源 ;开 ADC 电源, 可适当加延时,1mS 以内就足够了
Set_P12_Open_Drain (); //设置 P1.2 为开漏
Set_ADC_Channel_2(); //设置 P1.2 作为 A/D 转换通道
}
//----------------------------------------------------------
INT8U Get_AD_Result(void)
{
ADC_DATA=0;
//ADC_CONTR = AD_SPEED;
//ADC_CONTR = 0xE0; //1110,0000 清 ADC_FLAG, ADC_START 位和低 3 位
//ADC_CONTR |= channel; //选择 A/D 当前通道
Set_ADC_Channel_2();
delay(1);
ADC_CONTR|= 0x08; //启动 AD 转换
//判断 AD 转换是否完成
while (1) //等待A/D转换结束
{
if (ADC_CONTR & 0x10) //0001,0000 测试A/D转换结束否
{ break; }
}
ADC_CONTR&=0xE7; //清 0 ADC_FLAG, ADC_START 位, 停止 A/D 转换
return ADC_DATA;
}
//---------------------------------------------------------------------
void Send_Byte(INT8U one_byte) //发送一个字节
{
TI = 0; //清零串口发送中断标志
SBUF = one_byte;
while (TI == 0);
TI = 0; //清零串口发送中断标志
}
//------------------------------------------------------------
void timer_start(void)
{
ET0 =1;
TR0 =1;
}
void timer_stop(void)
{
ET0 =0;
TR0 =0;
}
//------------------------------------------------------------
void PWM (INT8U width)
{
CCAP0H=width; // 示例程序核心语句
PCA_PWM0=0x00 ; //示例程序核心语句P3.7
PCA_PWM1=0x03;
delay(5);
}
void pwm_stop(void)
{
PCA_PWM0=0x03 ;//释放本行注释,PWM输出就一直是0,无脉冲;-------------------------
PCA_PWM1=0x03 ;
delay(250);
}
//------------------------------------------------------------
void initiate_RS232 (void) //串口初始化
{
SCON = 0x50; //可变波特率. 8位无奇偶校验
TMOD = 0x21;
TH1 = 0xe7;//5.8mhz 600/s
TL1 = 0xe7;
AUXR &= 0xBF;
TR1 =1;
ES = 0; //禁止串口中断
}
//---------------------------------------------------------------------
void initiate_pca (void)
{
CMOD=0x82;
//PCA 在空闲模式下停止 PCA 计数器工作 ;PCA 时钟模式为fosc/12
//禁止 PCA 计数器溢出中断
CCON=0x00; //禁止 PCA 计数器工作, 清除中断标志、计数器溢出标志
CL =0x00; //清 0 计数器
CH =0x00;
//设置模块 0 为 8 位 PWM 输出模式, PWM 无需中断支持。脉冲在 P3.7(第 11 脚)输出
CCAPM0 =0x42; //示例程序核心语句 0100,0010
//PCA_PWM0=0x00H; //示例程序核心语句P3.7;
PCA_PWM0=0x03; //释放本行注释,PWM输出就一直是0,无脉冲;-------------------------
//设置模块 1 为 8 位 PWM 输出模式, PWM 无需中断支持。脉冲在 P3.5(第 9 脚)输出
//CCAPM1=0x42; //示例程序核心语句 0100,0010
//PCA_PWM1=0x00; //示例程序核心语句 P3.5
//PCA_PWM1=0x03; //释放本行注释, PWM 输出就一直是 0, 无脉冲。
//B_MO_1=0;
EPCA_LVD=1; //开pca中断
EA=1;
CR=1; //将 PCA 计数器打开
}
//---------------------------------------------------------------------
//**********************************************
void Initial_T0(void)
{
TH0=0x4C ;//设置定时器0 自动重装数 11M
TL0=0x00 ;//500uS
//AUXR&=0xBF; //定时器1 工作在12T 模式,与普通的8051 相同
ET0=0;
TR0=0; //启动定时器1
}
void timer_init(void)
{
TH0=0x4C ;//设置定时器0 自动重装数 11M
TL0=0x00 ;//50MS
ET0=1;
TR0=1;
}
//---------------------------------------
void con (void)
{
AD_date=AD_date+Get_AD_Result();
AD_date=AD_date>>1;
if (AD_date<ADC_DUANLU)
{
con_state=4;
}
switch(con_state)
{
case 0:
if (AD_date < ADC_21)
{
S_N=60000;
PWM(pulse_width_MAX) ;//为输出脉冲宽度设置初值。
timer_init();
con_state=1;
}
else
{
if (AD_date<ADC_28)
con_state=2;
}
break;
case 1:
if (AD_date>ADC_21)
{
con_state=2;
}
if (S_N==0)
{
con_state=2;
}
break;
case 2:
S_N=60000;
PWM(pulse_width_MAX) ;//为输出脉冲宽度设置初值。
timer_init();
con_state=3;
break;
case 3:
if(AD_date>ADC_28)
{
con_state=4;
}
if (S_N==0)
{
con_state=4;
}
break;
case 4: //如果没有电池或者在很长一段时间后重新启动初始化
pwm_stop();
TR0=0;
ET0=0;
con_state=5;
B_LED=0;
B_LED2=0;
break;
case 5: //如果没有电池或者在很长一段时间后重新启动初始化
if (AD_date>ADC_KONG )
{
con_state=0;
B_LED=1;
B_LED2=1;
}
break;
default:
break;
}
}
//---------------------------------------
void timer0(void) interrupt 1
{
INT8U ACC_temp;
ACC_temp= ACC;
TR0=0;
if(S_N!=0)
{
S_N--;
}
if(T_N==0&con_state!=5)
{
B_LED=~B_LED;
B_LED2=~B_LED2;
T_N=10;
}
T_N--;
timer_init();
ACC= ACC_temp;
}
//------------------------------------------------------------
void serial()interrupt 4
{ INT8U ACC_temp;
if(RI==0)
TI=0;
else
{
RI=0;
ES=0;
ACC_temp=ACC ;
//RS_do(SBUF);
ACC=ACC_temp ;
ES=1;
}
}
//---------------------------------------------------------------------
void main()
{ INT8U n;
INITAL_port();
T_N=0;
B_PW= 0 ;
n=0;
initiate_pca();
initiate_RS232(); //波特率 = 600
initial_T0();
//Send_Byte(0xAA); //为便于观察, 发送 2 个 0xAA
B_LED=0;
B_LED2=0;
delay(0x250);
B_LED=1;
B_LED2=1;
initiate_AD();
ES=1;
con_state=0;
AD_date=Get_AD_Result();
//Send_Byte(AD_date);
while(1)
{
con();
WDT_CONTR=0x3f; //看门狗
if(n>10)
{
Send_Byte(AD_date);
n=0;
}
n++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -