- // 方案005
- /*
- 上电后 进入中转待机模式 发送一次脉冲 启动外部中断下降沿检测 启动5分钟倒计时
-
- 当外部中断检测到下降沿以后 改为启动工作模式 查询反馈信号是否是低电平 是否被锁定 查询上一次脉冲是否完成
- 上一次脉冲未完成则直接停机
-
- 当低电平 没锁定 且上一次脉冲完成 则发送一次脉冲 然后检测脉冲是否完成
- 脉冲完成则然后进入中转待机模式
-
- 同时 5分钟计时到以后 启动ADC检测硬件电压 当低于0.1V时 默认无设备在充电 停机锁定
- 反之不干涉
- */
- // 头文件
- #include "STC8Hxxx.h"
-
-
- // 引脚定义
- sbit Pulse = P3^4; // PWM脉冲输出引脚
- sbit OUT_INT0 = P3^2; // 外部中断0输入引脚
- sbit CMP = P3^7; // 比较器正输入端
- sbit ADC13 = P3^5; // ADC13输入引脚
-
-
- // 宏定义
- #define MAIN_Fosc 35000000L // 主频35MHz
-
-
- // 声明
- // 数组
- // 函数
- void Ext_Init(void);
- void ADC_INIT(void);
- u16 GET_ADC_DATA(void);
- void Timer1_Init(void);
- void PWMB_config(void);
- // 变量
- bit trigger_lock = 1; // 锁存标志:0=允许触发,1=已触发等待解锁
- bit cmp_now = 1; // 0表示 正输入 小于 负输入 1表示 正输入 大于 负输入
- bit FiveMinuteFlag = 0; // 5分钟标志位
-
- u8 low_cnt = 0; // 连续低电平计数
- u8 mode = 1; // 0 锁定停机 1 中转待机 2 工作模式
- u8 count_20ms = 0;
- u8 count_200ms = 0;
- u8 count_2000ms = 0;
-
- u16 ADC_value = 0; // ADC转换值
- u16 voltage = 0; // 实际电压值
-
-
- // 函数模块
- // 描述: PWM配置函数
- void PWMB_config(void)
- {
- P_SW2 |= 0x80; // SFR enable
-
- PWMB_PSCR = 0; // 预分频寄存器, 分频 Fck_cnt = Fck_psc/(PSCR[15:0]+1), 边沿对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1))
- // 中央对齐PWM频率 = SYSclk/((PSCR+1)*(AAR+1)*2).
- PWMB_DTR = 0; // 死区时间配置, n=0~127: DTR= n T, 0x80 ~(0x80+n), n=0~63: DTR=(64+n)*2T
- // 0xc0 ~(0xc0+n), n=0~31: DTR=(32+n)*8T, 0xE0 ~(0xE0+n), n=0~31: DTR=(32+n)*16T
- PWMB_ARR = 205; // 自动重装载寄存器, 控制PWM周期
- PWMB_CCER1 = 0;
- PWMB_CCER2 = 0;
- PWMB_SR1 = 0;
- PWMB_SR2 = 0;
- PWMB_ENO = 0;
- PWMB_PS = 0;
- PWMB_IER = 0;
- PWMB_CR1 = 0;
-
- PWMB_CCR4 = 103; // 计数器比较值, 匹配时刻. 输出单脉冲延时1750us, 宽度=2000-1750=250us.
- // 通道1模式配置: 0: 无输出, 1:匹配时输出高, 2:匹配时输出低, 3:匹配时输出翻转, 4:固定输出低, 5:固定输出高, 6:PWM模式1(正脉冲), 7:PWM模式2(负脉冲).
- // +8:允许CCRn预装载, +0:禁止预装载. +4:允许输出比较快速使能, +0:禁止. +0:输出, +1:输入映射在TI1FP1, +3:输入映射在TI2FP1, +3:输入映射在TRC.
- PWMB_CCMR4 = (7<<4)+8;
- PWMB_CCER2 |= 0x50; // 开启比较输出, 高电平有效
- PWMB_PS |= (1<<6); // 选择IO, 0:选择P2.3, 1:选择P3.4, 2:选择P0.3, 3:选择P7.7
- PWMB_ENO |= 0x40; // IO输出允许, bit6: ENO8P, bit4: ENO7P, bit2: ENO6P, bit0: ENO5P
-
- PWMB_BKR = 0x80; // 主输出使能 相当于总开关
- PWMB_CR1 |= 0x08; // 单脉冲模式
- }
-
- // 外部中断0初始化 (下降沿触发)
- void Ext_Init(void)
- {
- IT0 = 1; // 下降沿触发
- EX0 = 1; // 允许INT0中断
- }
-
- // ADC初始化函数
- void ADC_INIT(void)
- {
- ADC_CONTR = 0x8D; // 使能ADC电源,选择P3.5(ADC13)
- ADCCFG &= ~0x0F; // 清速度设置位
- ADCCFG |= 0x02; // 50KSPS采样速率
- ADCTIM = 0x35; // 采样保持参数设置
- ADC_CONTR &= 0xDF; // 清转换完成标志
- EADC = 0; // 禁止ADC中断
- ADCCFG |= 0x20; // 左对齐(10位有效)
- ADC_CONTR |= 0x40; // 启动第一次ADC转换
- }
-
- // 获取ADC转换值函数
- u16 GET_ADC_DATA(void)
- {
- u16 AD_DATA = 0;
- ADC_CONTR &= 0xDF; // 清完成标志
- ADC_CONTR &= 0xBF; // 停止ADC转换
- AD_DATA = ADC_RES; // 读取高8位
- AD_DATA <<= 8;
- AD_DATA |= ADC_RESL; // 读取低2位
- ADC_CONTR |= 0x40; // 启动下一次转换
- return AD_DATA;
- }
-
- // TIM1初始化
- void Timer1_Init(void) // 20毫秒@35.000MHz
- {
- AUXR &= 0xBF; // 定时器时钟12T模式
- TMOD &= 0x0F; // 设置定时器模式
- TL1 = 0x23; // 设置定时初始值
- TH1 = 0x1C; // 设置定时初始值
- TF1 = 0; // 清除TF1标志
- TR1 = 1; // 定时器1开始计时
- ET1 = 1; // 使能定时器1中断
- }
-
-
- // 主函数
- void main(void)
- {
- P_SW2 |= 0x80; // 允许XFR访问
-
- // I/O 初始化
- P3M0 = (P3M0 & ~0xa4) | 0x10; P3M1 = (P3M1 & ~0x10) | 0xa4; // P3.4 推挽输出 P3.5 P3.6 P3.7 高阻输入
-
- Pulse = 0;
-
- EA = 1; // 全局中断开
-
- // 模块初始化
- Ext_Init();
- ADC_INIT();
- Timer1_Init();
- PWMB_config();
-
- PWMB_CR1 |= 0x01; // 触发一次单脉冲输出
-
- while (1)
- {
- // ========== mode ========== //
- if(mode == 0) // 锁定停机模式
- {
- TR0 = 0; // 停止定时器0
- ET0 = 0; // 禁止定时器0中断
-
- TR1 = 0; // 停止定时器1
- ET1 = 0; // 禁止定时器1中断
-
- EX0 = 0; // 禁止外部中断0
- CMPCR1 &= ~0x80; // 关闭比较器模块
- ADC_CONTR &= ~0x80; // 关闭ADC电源
-
- EA = 0; // 关闭全局中断,系统完全锁定
- }
-
- if(mode == 2) // 工作模式
- {
- //if(CMP == 0) // 反馈信号低电平
- //{
- // cmp_now = 0;
- //}
-
- if (/*cmp_now == 0 && */ !trigger_lock) // 未锁定
- {
- // 输出一个脉冲信号
- PWMB_CR1 |= 0x01; // 触发一次单脉冲输出
-
- trigger_lock = 1;
- cmp_now = 1;
- mode = 1;
- }
- }
- // ========== mode ========== //
-
-
- // ========== ADC-test ========== //
- if(FiveMinuteFlag == 1)
- {
- ADC_value = GET_ADC_DATA();
- voltage = (((float)ADC_value / 1023) * 5000); // 10位ADC 参考电压5V
-
- if(voltage < 100) // 低于0.1V
- {
- // 关闭设备
- mode = 0; // 锁定停机模式
- }
- }
- // ========== ADC-test ========== //
- }
- }
-
-
- // 中断服务函数
- // 外部中断0服务函数
- void INT0_Isr(void) interrupt 0
- {
- trigger_lock = 0;
- mode = 2; // 工作模式
- }
-
- // 定时器1中断函数:用于5分钟检测
- void Timer1_Isr(void) interrupt 3
- {
- count_20ms++; // 每次中断 20ms
-
- if(count_20ms >= 10) // 200ms
- {
- count_20ms = 0;
- count_200ms++;
-
- if(count_200ms >= 10) // 2000ms = 2s
- {
- count_200ms = 0;
- count_2000ms++;
-
- if(count_2000ms >= 150) // 150 × 2s = 300s = 5分钟
- {
- count_2000ms = 0; // 重新计数
-
- TR1 = 0; // 停止定时器1
- ET1 = 0; // 禁止定时器1中断
-
- FiveMinuteFlag = 1; // 设置标志位,主循环检测
- }
- }
- }
- }
复制代码 这个程序
用的是AI8H1K08 SOP16芯片
现在 的问题是大部分的检测已经去掉了 只剩下了 一个为了保证没次只能发送一次脉冲的一个bit锁和一个下降沿检测
结果还是出现了第一个下降沿检测到以后有一段类似要出脉冲的抖动 然后第二个下降沿来的时候发送一次脉冲了 然后又缺失一个下降沿 再下一个下降沿发出脉冲
而不是每个下降沿都会发送一次脉冲
|