|
9#
楼主 |
发表于 2011-2-4 22:03:40
|
只看该作者
//********************************************************************
//白光烙铁控制程序
//M16
//2011.2.4
//********************************************************************
#include <iom16v.h>
#include <macros.h>
#pragma interrupt_handler Timer0Int:10
#define twi_stop() TWCR=0x94
#define twi_start() TWCR=0xa4
#define check_TWINT() while(!(TWCR & (1<<TWINT))) //轮询等待TEINT置位
unsigned char TwiStatus;
unsigned char DISP[3]={0x01,0x02,0x03}; //3位数字,高位在前,温度值:XXX℃
unsigned char KDelay; //按键延时定值,快慢变化
unsigned char Set; //设定方式,0-电位器设定,1-按键设定
unsigned char Mod; //显示状态切换,0-停,显示环境温度,1-加热,显示烙铁温度,2-调节
unsigned char Suc; //I2C返回值
unsigned int Ns; //按键计数快慢,40-200ms,4-20ms
unsigned int Num1; //按键延时计数1
unsigned char Num2; //按键延时计数2
unsigned char Num3; //轮流显示
unsigned int Num4; //设定延时切换,2s
unsigned int Ut; //热电偶电压
unsigned int U[110]; //热电偶电压均值计算
unsigned int Ua; //设定电压
unsigned int Tf; //上次设定值
unsigned char Tc; //环境温度数据
unsigned char Tk; //计时
unsigned char Tr; //加热周期,0~4/5
unsigned int Ts; //设定温度值,160~430
unsigned int Tt; //实际温度值,0~430
const unsigned char DIG[]={0x14,0x77,0x4C,0x45,0x27,0x85,0x84,0x57,0x04,0x05,0x26,0xBC};
//从高到低:B、F、A、G、C、DP、D、E
//数字编码:0、1、2、3、4、5、6、7、8、9、H(10)、L(11)
/*****************************************
延时子程序
******************************************/
void Delay(unsigned int n)
{
unsigned int i ;
for(i=0;i<50*n;i++);
}
//--------------------------------------------------
//io_init:初始化IO子程序
//--------------------------------------------------
void io_init(void)
{
DDRA = 0xC2; //PA0\PA2\PA3\PA4\PA5为输入,其余均为输出
PORTA|=0x30; //拉高按键管脚
DDRB = 0xFF;
DDRC = 0xFC; //I2C管脚为定义为输入,再拉高
PORTC|=0x03;
DDRD = 0xF7; //PD3输入
PORTD|=0x08;
}
//-------------------------------------------------------------------
//TIMER_init:初始化定时器 5ms定时 无分频
//-------------------------------------------------------------------
void TIMER_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x64; //set count
TCCR0 = 0x04; //start timer
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x01; //timer interrupt sources 允许定时器零匹配和溢出中断
}
//-------------------------------------------------------------------
//U10:A/D转换
//-------------------------------------------------------------------
void U10(void)
{
unsigned int tmp; //
unsigned char i; //
if(Set==0)
{
ADCSRA = 0x00; //disable adc
ADMUX = 0xC0; //2.56V内部基准,右对齐,通道ADC0单端输入
ACSR = 0x80;
ADCSRA=0xC6;
while(!(ADCSRA&(1<<ADIF)));
ADCSRA|=(1<<ADSC)|(0<<ADIF);
while(!(ADCSRA&(1<<ADIF)));
Ua=ADCL;
Ua=ADCH*256+Ua;
Tf=Ts;
Ts=(2*Ua+1590)/10;
if(Ts>340)Ts=340;
if((Tf>Ts && Tf-Ts>2)||(Ts>Tf && Ts-Tf>2))
{
Mod=2;
Num4=0;
}
}
ADCSRA = 0x00; //disable adc
ADMUX = 0xCF; //2.56V内部基准,右对齐,通道ADC0单端输入
ACSR = 0x80;
ADCSRA=0xC6;
while(!(ADCSRA&(1<<ADIF)));
ADCSRA|=(1<<ADSC)|(0<<ADIF);
while(!(ADCSRA&(1<<ADIF)));
Ut=ADCL;
Ut=ADCH*256+Ut;
for(i=0;i<99;i++)U[i]=U[i+1];
U[99]=Ut;
Ut=0;
for(i=0;i<100;i++)Ut=Ut+U[i];
Ut=Ut/100;
//考虑环境温度
// tmp=74*(Ut+Tc+37);
tmp=156*Ut+80*Tc;
if(tmp>26400)tmp=tmp-26400;
else tmp=0;
Tt=tmp/100;
}
/*****************************************
TWI主接收方式子程序
读取LM75的TEMP寄存器的值
******************************************/
void TWITempRead(unsigned char ReadDeviceAddr,unsigned char WriteDeviceAddr,unsigned char RegAddr)
{
unsigned int j;
Delay(100);
while (TwiStatus != 0x08) //检验TWSR,屏蔽预分频位
{
twi_start(); //发送START信号
Delay(1);
TwiStatus=TWSR & 0xF8;
}
while (TwiStatus != 0x18) //检验TWSR,SLA+W已发出,并收到ACK
{
TWDR = WriteDeviceAddr;//设备地址(写)
TWCR=0x84;
Delay(1);
TwiStatus=TWSR & 0xF8;
}
while (TwiStatus != 0x28) //DATA已发出,并收到ACK
{
TWDR = RegAddr; //写入LM75的TEMP寄存器的地址
TWCR=0x84;
Delay(1);
TwiStatus=TWSR & 0xF8;
}
while (TwiStatus != 0x10) //REPEATED START信号已发出
{
twi_start(); //发REPEATED START信号
Delay(1);
TwiStatus=TWSR & 0xF8;
}
while (TwiStatus != 0x40) //检验TWSR,SLA+R已发出,并收到ACK
{
TWDR =ReadDeviceAddr; //设备地址(读)
TWCR=0x84;
Delay(1);
TwiStatus=TWSR & 0xF8;
}
TwiStatus=0x00;
while (TwiStatus != 0x50) //DATA已收到,ACK已发出
{
TWCR=0xc4; //接收高8位数据,发送ACK
Delay(50);
Tc=TWDR;
TwiStatus=TWSR & 0xF8;
}
while(TwiStatus != 0x58) //DATA已收到,nACK已发出
{
TwiStatus=TWSR & 0xF8;
TWCR=0x84; //接收低8位数据,发送nACK
Delay(50);
// TempLow=TWDR;
}
twi_stop(); //发送STOP 信号
}
//--------------------------------------------------
//主程序
//--------------------------------------------------
void main(void)
{
unsigned int m; //
io_init();
DDRC&=0Xcf;
PORTC|=0X30;
TWCR= 0X00; //disable twi
TWBR= 0x12; //set bit rate
TWSR= 0x01; //set prescale
TWCR= 0x04; //enable twi
TIMER_init();
Tr=1;
PORTA=0xF2;
Ts=200;
Ns=40;
SEI(); // //开中断
Set=0;
if(PIND & 0x08) Set=1;
while(1)
{
if(Set==1)
{
if((PINA & 0x10)==0)
{
Num2=0;
Num4=0;
Mod=2;
Ts++;
if(Ts>430)Ts=430;
while(Num2<Ns);
}
if((PINA & 0x20)==0)
{
Num2=0;
Num4=0;
Mod=2;
Ts--;
if(Ts<160)Ts=160;
while(Num2<Ns);
}
}
if(Mod>1 && Num4>500)
{
if(Ts<160)Mod=0;
else Mod=1;
Num4=0;
}
TWITempRead(0x91,0x90,0);
if(Ts<Tt)
{
Tr=1;
if(Ts>240)Tr=2;
if(Ts>340)Tr=3;
}
else
{
m=(Ts-Tt);
if(m<6) Tr=3;
if(m>5 && m<11) Tr=5;
if(m>10 && m<21) Tr=8;
if(m>20 && m<31) Tr=10;
if(m>30 && m<41) Tr=13;
if(m>40) Tr=16;
if(Ts>240 && m<21)Tr*=2;
if(Ts>340 && m<21)Tr+=4;
}
}
}
//-------------------------------------------------------------------
//Timer0Int:定时中断子程序,用于显示输出及按键延时计时,5ms
//-------------------------------------------------------------------
void Timer0Int(void)
{
unsigned char n; //循环计数,0~19
unsigned char m; //
unsigned int p; //
TCNT0=0x64;//79次计数为10mS
if(((PINA & 0x20)==0) || ((PINA & 0x10)==0))Num1++; //按键延时计数
else
{
Num1=0;
Ns=40;
}
if(Num1>400)Ns=4; //按键加速
Num2++; //按键延时计数
Num3++; //轮显
Num4++; //按键延时计数2
Tk++;
n=Tk%20;
if(n==0)
{
PORTA|=0x02;
U10(); //读温度转换电压
if(Tk%40==0) //0.2s刷新显示
{
p=Tc;
if(Mod==1)p=Tt;
if(Mod==2)p=Ts;
DISP[0]=p/100; //显示温度
DISP[1]=(p%100)/10;
DISP[2]=p%10;
}
}
else
{
if(n<Tr+1 && Mod>0)PORTA&=0xFD; //n/20周期加热
else PORTA|=0x02;
}
PORTD|=0x07;
n=Num3%3;
m=DIG[DISP[n]];
if(Mod==2) m&=0xFB; //设置温度状态
PORTB=m;
if(n==2)PORTD&=0xFE; //输出个位数字
if(n==1)PORTD&=0xFD; //输出十位数字
if(n==0)PORTD&=0xFB; //输出百位数字
}
初步能用了,温度和采集电压的关系暂时没办法仔细校。图中3.3V为5V,LM75A用于测参考温度,矫正热偶温度用的,光耦用于低压驱动高压的隔离,更安全些,直接驱动也行,可能会损坏单片机。调试有改动时再补充,欢迎共同测试,好有改进。
|
|