/**************************************************************************/
/************************基于ICP捕捉的ICL 程序1 ********************/
/*** 判断按键1、2状态,将用来校准的数据存放在eeprom0x0001和0x0002内*******/
/**************************************************************************/
#include<avr/io.h>
#include<util/delay.h>
#include<avr/interrupt.h>
#include<avr/eeprom.h>
#include<stdlib.h>
#include<2401.h>//自定义头文件nrf24l01模块
#include<spi.h>
#define int8u unsigned char
#define int16u unsigned int
volatile unsigned int ICP_time_up=0;
volatile unsigned int ICP_time_down=0;
volatile unsigned char ICP_ok=0;
//共阳数码管显示
const int8u code[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
void seg_init()
{
DDRC=0xff;
DDRC|=0x0f;
}
int8u dispdat[]={0xff, 0xff, 0xff, 0xff};
const int8u dispcom[]={0xe0,0xd0,0xb0,0x70};
void seg_disp(int8u *dispdat,int8u dotloc)
{
for(int8u i=0;i<4;i++)
{
PORTB=*(dispdat+i);
if(dotloc!=0)
{
if(dotloc==i)
{
PORTB&=~(1<<7);
}
}
PORTD=dispcom[i];
_delay_ms(10);
}
}
//将字节变量eepromx分配于EEPROM存储器(地址不透明)
int8u eepromx __attribute__((section("eeprom")));
void work_statue();
//相位修正PWM模式
void PWM_OC2_init()//OC2引脚输出PWM=125K
{
TCCR2=(0<<WGM21)|(1<<WGM20)|(1<<COM21)|(0<<COM20)|(0<<CS22)|(1<<CS21)|(1<<CS20);
TCNT2=0;
OCR2=1;//设置OCR2为1
//OC2脚输出的方波频率为8000000hz/(2*32*1)=125000hz
}
void ICP_init()
{
TIMSK=(1<<TICIE1);
TCCR1B=(0<<CS12)|(1<<CS11)|(1<<CS10)|(1<<ICES1);//fosc/64=125,上升沿ICP使能
TCNT1=0;
asm("sei");//使能全局中断
}
void safeguard()//端口初始化
{
DDRA&=0X00;//设定PA0为输入
PORTA|=0X01;//启动PA0内部上拉电阻
DDRA|=0X0E;//设定PA1,PA2,PA3为输出
DDRC|=0XE0;//设置PC5,PC6,PC7输出
DDRD|=0X80;//设定PD7为输出;
DDRD&=0XF3;//设定PD2,PD3为输入
PORTD|=0X0C;//启动PD2,PD3的内部上拉电阻
}
/****************************/
/*中断服务程序*/
/****************************/
int8u work;
ISR(INT1_vect)
{
int8u SREG_tmp;
SREG_tmp=SREG;
work=0;//A/D正常采集功能
SREG=SREG_tmp;
}
/********************************************/
/* T1输入捕获中断子程序 */
/********************************************/
ISR(TIMER1_CAPT_vect) //输入捕捉中断,TIMER1_CAPT_vect为输入捕获中断向量
{
if(TCCR1B&(1<<ICES1)) //如果是上升沿ICP
{
ICP_time_up=ICR1; //读取ICP捕捉事件的发生时刻
TCCR1B=(0<<CS12)|(1<<CS11)|(1<<CS10)|(0<<ICES1); //改为下降沿ICP使能
}
else
{ ICP_time_down=ICR1; //读取ICP捕捉事件的发生时刻
TCCR1B=(0<<CS12)|(1<<CS11)|(1<<CS10)|(1<<ICES1); //改为上升沿ICP使能
ICP_ok=1; //已经完成一次采集
}
TIFR=(1<<ICF1); //消除标志位
}
//主程序
#define testpol() (PINA&(1<<0))
#define mega16_pa3_1() (PORTA|=(1<<3))
#define mega16_pa3_0() (PORTA&=~(1<<3))
#define mega16_pa4_1() (PORTA|=(1<<4))
#define mega16_pa4_0() (PORTA&=~(1<<4))
#define mega16_pa5_1() (PORTA|=(1<<5))
#define mega16_pa5_0() (PORTA&=~(1<<5))
#define getkey_work() (PIND&(1<<3))
#define EEPROM_0du_key() (PINA&(1<<1))
#define EEPROM_100du_key() (PINA&(1<<2))
#define LED_ON() (PORTD|=(1<<2))
#define LED_OFF() (PORTD&=~(1<<2))
int main()
{
int8u loop_show_flag=0;
int16u count=0;
int16u adtmp;
PWM_OC2_init();
ICP_init();
MCUCR&=0XF0;
MCUCR|=0X0B;
GICR|=0XC0;//使能外部中断0、1
sei();//开启全局中断
mega16_pa3_0();
mega16_pa4_0();
mega16_pa5_0();
while(1)
{
if(ICP_ok==1) //已经完成一次采集
{
ICP_ok=0;
if(ICP_time_up>ICP_time_down)
{
count=0xffff-ICP_time_up+1+ICP_time_down;
}
else
{
count=ICP_time_down-ICP_time_up;
count=count-10001;
}
}
adtmp=-(1000*(count/10000));//adtmp为对应的模拟电压值(mV)
while(!(EEPROM_0du_key()&&EEPROM_100du_key()))//判断是否有按键按下
{
if(EEPROM_0du_key())
{
loop_show_flag=0;
eeprom_busy_wait();
eeprom_write_byte((int8u*)1,(int8u)adtmp);//将转换的数据adtmp写入eeprom中的第一个地址0x0001
LED_ON();
while(EEPROM_0du_key());//直到释放按键
LED_OFF();
}
else if(EEPROM_100du_key())
{
loop_show_flag=0;
eeprom_busy_wait();
eeprom_write_byte((int8u*)2,(int8u)adtmp);//将转换的数据adtmp写入eeprom中的第一个地址0x0002
LED_ON();
while(EEPROM_100du_key());//直到释放按键
LED_OFF();
}
else
{
if(!getkey_work())//等待中断1发生
{
_delay_ms(10);
if(!getkey_work())
{
while(getkey_work());
work=~work;
}
}
if(work)
{
work_statue();//产生中断马上执行子程序
}
}
}
}
}
/******************************************************/
/****** work_statue()工作子程序 ***************/
/******************************************************/
void work_statue()
{
int8u loop_show_flag=1;
int8u obj_temperature_0du;
int8u obj_temperature_100du;
int16u current_read_addr=0x0001;
int16u count=0;
int16u adtmp;
int8u ad_final;
seg_init();
work=0;//初始状态为0
while(1)
{
if(ICP_ok==1) //已经完成一次采集
{
ICP_ok=0;
if(ICP_time_up>ICP_time_down)
{
count=0xffff-ICP_time_up+1+ICP_time_down;
}
else
{
count=ICP_time_down-ICP_time_up;
count=count-10001;
}
}
adtmp=-(1000*(count/10000));//adtmp为对应的模拟电压值(mV)
eeprom_busy_wait();
obj_temperature_0du=eeprom_read_byte((int8u*)current_read_addr);
_delay_ms(5);
obj_temperature_100du=eeprom_read_byte((int8u*)current_read_addr+1);
_delay_ms(5);
while(loop_show_flag--);//开始读取,下面进行运算,此时loop_show_flag=1
ad_final=(100*adtmp/(obj_temperature_100du-obj_temperature_0du));//校准值=100*(A/D结果)/(100度转换值-0度转换值)
//显示部分
dispdat[0]=ad_final/100;
dispdat[1]=(ad_final%100)/10;
dispdat[2]=ad_final%10;
dispdat[3]=0xff;
seg_disp(dispdat,0);
}
}