⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 一个简单使用AT13来音频信号并判断是否有信号与否来控制一个外部的开关量.
💻 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 + -