📄 main.c
字号:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <inttypes.h>
#include <stdio.h>
#include "typedef.h"
//PB3是控制输出端口!
#define POWER_ON() PORTB |= (1 << PB3) //打开输出
#define POWER_OFF() PORTB &= ~(1 << PB3) //关闭输出
//定义延时控制时间(tick是100ms)
#define OPEN_DELAY_TIME 100 //打开计数,10S = 10 * 1000ms = 100 * 100ms(一个tick 是100ms)
#define CLOSE_DELAY_TIME 600 //关闭计数 1分钟,根据自己需要设定这个值
//定义一个门限值
#define SUCCESS_GATE 200 //
/////////////////////////////////////////////////////////////////////////////////////////////
//控制变量定义
volatile uint16 tick; //时钟 tick
bool cur_state; //当前工作状态。 false - 没有输出. true - 已经输出
bool check_open_flag; //
bool check_close_flag; //
/////////////////////////////////////////////////////////////////////////////////////////////
//端口初始化
void port_init(void)
{
PORTB = 0xf0; //输入设置有上拉电阻,输出预设低电平
DDRB = 0x0f; //PB4输入,PB3输出
}
//定时器初始化
void timer_init(void)
{
TCCR0A = 0x00;
TCCR0B = 0x05; //1024分频,模式0 定时器 //时钟内部9.6M/8 = 1.2M 即一个tick = 0.83us * 1024 = 853us 当是1ms吧!
//设定一个100ms的定时器. 100ms = ? tick? 约等于 98个tick. 则初始值为 256 - 98 = 158 = 0x9E
TCNT0 = 0x9E; //初值
TIMSK0 = 0x02; //溢出中断
}
//转换初始化
void adc_init(void)
{
ADCSRA=0x00; //VCC作为模拟参考电压
ADMUX = 0x03; //选择ADC3通道
ACSR = (1 << ACD);//禁用模拟比较器
//使能ADC,终端允许,自由模式,时钟CLK/8
//0x86允许转换ADEN,ADSC,时钟128分频 75KHz@9.6MHz system clock
ADCSRA = (1 << ADEN) | 0x07;//| ( 1 << ADATE )
}
//看门狗初始化
void watchdog_init(void)
{
wdt_enable(WDTO_2S);// Watchdog 使能,Watchdog 定时器2秒超时
wdt_reset();// Watchdog 复位
WDTCR |= 0x08;//使能看门狗
}
//定时器中断100ms的tick
SIGNAL(SIG_OVERFLOW0)
{
TCNT0 = 0x9E; //重装值
if( tick > 0) tick --; //对全局变量计数,直到0
}
//从AD口读入一个值
uint16 GetADC(void)
{
uint16 adc_value;
ADC = 0;
ADCSRA |= (1 << ADSC); //启动AD转换
_delay_us(10);
loop_until_bit_is_set(ADCSRA, ADIF);//等待AD转换结束
ADCSRA |= (1 << ADIF); //写1清除标志位
adc_value = ADC; //读转换结果
return adc_value;
}
//主函数!不用解释了
int main()
{
uint16 adc_rel;
cur_state = false;
check_open_flag = false;
check_close_flag = false;
tick = 0;
//以下初始化硬件
port_init(); //端口初始化
adc_init(); //ADC初始化
timer_init(); //定时器初始化
watchdog_init();//初始化看门狗
sei(); //打开全局中断!
while(1)
{
wdt_reset();//喂狗
//采用查询方式读AD值
adc_rel = GetADC(); //读输入电压
//最好对adc_rel做一些过虑操作。 如怎么样防止干扰? 或把这个变化量经过处理转换为0,1状态
//
//....发挥你的想像力吧!
//
//以下为简单的一种逻辑控制!
if( adc_rel > SUCCESS_GATE) //有信号, 开始计数一定时间, 如果还有就可以输出了
{
if( cur_state == false) //开始计数吧.
{
if( check_open_flag == false)
{
check_open_flag = true;
tick = OPEN_DELAY_TIME;
}
if( tick == 0) //计数到了. 开
{
POWER_ON(); //----> 一个宏定义! 看前面吧
cur_state = true;
}
}
else
{
tick = 0;
check_close_flag = false;
}
}
else //没有信号, 如果原来打开了输出 ,则延时3分钟没有信就关闭
{
if( cur_state == true) //还没开则重置计数
{
if( check_close_flag == false)
{
check_close_flag = true;
tick = CLOSE_DELAY_TIME;
}
if( tick == 0) //计数到了. 关
{
POWER_OFF();
cur_state = false;
}
}
else
{
tick = 0;
check_open_flag = false;
}
}
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -