|
发表于 2008-6-11 15:45:26
|
显示全部楼层
/* m818b20.c 2008-05-03
本程序为采用mega8 和18b20的温度采集程序
选用mega8内部8M RC震荡,18b20 数据线接pd4,数据线和vcc间接一4.7k上拉电阻
感谢www.ouravr.com
qq:61870905
msn:houliang@foxmail.com
*/
#include <iom8v.h> //和单片机类型相对应的头文件,选择Atmega8做实验;
#include <macros.h>
#include <stdio.h>
#include <eeprom.h>
#include <MATH.H>
#include <stdlib.h>
#include <STRING.H>
#define uchar unsigned char
#define uint unsigned int
#define LED_NUM PORTD //数码管公共端
#define LED_VALUE PORTB //数码管数据位
#define ADC_KEY 3
#define SOUND_OUT 0x08
#define FAN_OUT1 0x01
#define FAN_OUT2 0x02
#define FAN_OUT3 0x04
#define DELAY_MIN 1100
uint v = 0;
uchar adc_channel = 0;
uchar hot_warning[4]={34,34,34,45};
uint temper[3]={5,5,5};//存放温度
uchar setting_mode = 0;
uchar auto_mode = 0x00;
uchar timeh=0x06;
uchar temp2=0;
uchar PWF1=0;
uchar PWFS1=0,PWFS2=0,PWFS3=0;//是否进行调速标志
uchar Fc1,Fc2,Fc3;//计数
void init_1820();//初始化1820
write_1820(uchar x); //写参数到1820
uchar read_1820(); //读温度
void delay(uint x);
void disp_led(uchar buffer,uchar control);
void test(void);
long count;
void delay_1ms(void);
//uchar hot_warning[4]={30,35,40,45};//设定风扇启动温度
void delay_nms(unsigned int n);
unsigned int wendu[4]={21,22,23,24};//定义温度存放数组
void temph(unsigned int tx); //电压转换成温度
void display(void);// 显示数据
void display_mode(uchar mo);//模式显示,花样显示
void scandisplay(uint value);//扫描显示数码管
void dc_save(void);//dc 转换结果存储后用
void init_port();//初始化端口
void output(uchar channel,uchar power);//风扇控制 函数 通道 风力
unsigned int uiVref_preset=4996; // 参考电压=2665mV
uchar Lednum[3]={0xDF,0xBF,0x7F};//数码管公共端口
uchar disp_table[16] = {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x40};
//共阴数码管
const uint v_table[135]={
950,1000,1050,1100,1150,1200,1250,1300,1350,1400,//-10-1
1450,1500,1550,1600,1650,1700,1750,1800,1850,1900//0-9
,1950,2000,2050,2100,2150,2200,2230,2260,2290,2320//10-19
,2350,2380,2410,2440,2470,2520,2590,2600,2617,2670//20-29
,2725,2800,2855,2935,2990,3041,3100,3148,3206,3260
,3302,3354,3414,3450,3504,3554,3600,3650,3680,3748
,3778,3818,3850,3889,3936,3986,4008,4015,4059,4089
,4116,4124,4146,4170,4200,4224,4248,4275,4296,4314
,4332,4353,4374,4395,4416,4428,4444,4461,4476,4488
,4502,4528,4544,4552,4562,4574,4584,4594,4602,4612
,4622,4632,4642,4652,4660,4668,4672,4680,4690,4698
,4704,4713,4723,4728,4733,4738,
};
const uchar sound[]={ //?Ρ?誹
0x45,0x48,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x49,0x4a,
0x49,0x48,0x48,0x48,0x48,0x48,0x45,0x48,0x4a,0x4a,
0x48,0x4a,0x4c,0x4c,0x4b,0x4a,0x49,0x49,0x49,0x49,
0x49,0x4c,0x4b,0x4a,0x4a,0x4a,0x49,0x48,0x48,0x49,
0x4a,0x4c,0x4b,0x4b,0x4b,0x4b,0x4b,0x46,0x46,0x45,
0x45,0x45,0x47,0x48,0x49,0x49,0x4a,0x49,0x48,0x48,
0x48,0x48,0x48,0x48,
0x00,0x00
};
uchar temp1[6];
//uint count;
#define PWM0 3 //OC0 PB3
#define PWM1A 5 //OC1A PD5
#define PWM1B 4 //OC1B PD4
#define PWM2 7 //OC2 PD7
#define Fosc_TIME2 (64*10) //TIME2 比较中断频率=采样率*AD通道数*工频50Hz的倍数
volatile unsigned char T2PWM;
void main(void)
{
uint i,k;
uchar temh,teml;
int j;
init_port();//初始化
hot_warning[0] = EEPROMread(0x01); //读取报警温度
hot_warning[1] = EEPROMread(0x02);
hot_warning[2] = EEPROMread(0x03);
for(k=0;k<4;k++) //初始化
{
if (hot_warning[k]>120)
hot_warning[k]=32;
}
while(1)
{ // temp_setting(); // 設定
WDR();
// scandisplay(3000);
//for(i=0;i<1000;i++) //每次转换需要延时200ms以上
// delay(1000);
init_1820(); //复位18b20
write_1820(0xcc); // 发出转换命令
write_1820(0x44);
delay(400);
scandisplay(count);
init_1820();
WDR();
write_1820(0xcc); //发出读命令
//scandisplay(count);
write_1820(0xbe);
teml=read_1820(); //读数据
temh=read_1820();
count=((temh*256+teml)*6.25)/10; //计算具体温度
scandisplay(count);
WDR();
scandisplay(count);
// disp_led(0,1); //显示温度
scandisplay(count);
for(i=0;i<20;i++) //每次转换需要延时200ms以上
{
scandisplay(count);
//delay(1000);
}
//scandisplay(temper[adc_channel]);
}
}
//io口初始化
void init_port()
{
OSCCAL=0X9d; //系统时钟校准,不同的芯片和不同的频率,
//DDRB=0x03; //定义B口的PB0、PB1为输出口
//DDRC=0x30; //定义C口的PC4和PC5为输出口
//PORTD = 0x01; //pd2.pd3.pd4输入 pd0 输出
//DDRD = 0x01;
//CLKPR = 0x80;
// CLKPR = 0x00;
DDRB = 0xff;
PORTB = 0x00;
DDRC = 0xff;
PORTC = 0x00;
DDRB = 0xff;
PORTB = 0xff;
DDRD = 0xFF;//定义PD0喇叭输出 PD2 PD3 PD4 按键输入 PD5 PD6 PD7 风扇输出
PORTD = 0xF7; //初始化 端口 数据
WDR(); //看门狗计数清零
WDTCR=0x0F; //使能watchdog,并且,采用2048K分频,典型溢出时间5V时2.1S
//adc_init(); // 使能ADC
//timer2_init(); // 使能AD转换
CLI();
ADMUX = (1<<REFS0); //选择基准
ADCSRA = (1<<ADEN)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1);
MCUCR = 0x00;
GICR = 0x00;
TIMSK = 0x15; //timer interrupt sources
SEI(); //开放中断
//WDTCSR = 0x0F;
//PORTB=0B00000010; //PB1口输出高电平,PB0口输出低电平,关闭绿灯,红灯亮
//delay_nms(500); //延时1秒
temp1[1]=1;
temp1[2]=2;
temp1[3]=3;
//test();
timer0_init();
timer1_init();
}
void delay(uint x) //1.5us左右
{
while(x)
{
x--;
}
}
//TIMER0 initialize - prescale:1024
// desired value: 60mSec
// actual value: 59.904mSec (0.2%)
void timer0_init(void)
{
TCCR0 = 0x00; //stop
TCNT0 = 0x16; //set count
TCCR0 = 0x05; //start timer
}
#pragma interrupt_handler timer0_ovf_isr:10
void timer0_ovf_isr(void)
{
TCNT0 = 0x16; //reload counter value
}
//数码管 扫描显示
void scandisplay(uint value)
{
uchar i,j,k,l;
uint tempvalue;
uchar led_data[3];
if ((value & 0x8000)==0x8000)
{
value &= 0x7fff;
led_data[2] = 15; // 顯示負號
}
else
{
value &= 0x7fff;
if(value<999)//需要加小数点
{
k=1;
led_data[2] = value/100;
}
else//大于100度去掉小数点
{
k=0;
value=value/10;
led_data[2] = value/100;
}
};
led_data[1] = value%100/10;
led_data[0] = value%100%10;
if((led_data[2]==0)&&(led_data[1]==0))
{//如果只有1位数的时候,将高位的0去掉
led_data[2]=16;
led_data[1]=16;
k=0;//去掉小数点
}
for (j=0;j<10;j++) //刷新20次 避免数据跳动
{
for (i=0;i<3;i++)
{
LED_VALUE = disp_table[led_data];
if((i==1)&&(k==1))
{
LED_VALUE |= 0x80; // 加上小數點
}
LED_NUM&=Lednum;//对应位数码管点亮
delay_nms(10);
LED_NUM|= 0xE0;//只保留高3位为1
};
};
}
void delay_1ms(void)//1ms延时函数
{
unsigned int i;
for (i=0;i<150;i++);
WDR(); //清看门狗
}
void delay_nms(unsigned int n)//延时n毫秒
{
unsigned int i;
for (i=0;i<n;i++)//执行n次1毫秒延时
delay_1ms();
}
#pragma interrupt_handler adc_isr:iv_ADC
void adc_isr(void)
{ uint temp;
temp = ADCL;
temp |= (int)ADCH<<8;
temp = (48*temp)/10;
v += temp;
}
void get_adc_value(uchar adc_pin)
{
uchar i;
v = 0x0000;
ADMUX = (1<<REFS0)|adc_pin;
{
ADCSRA |= (1<<ADSC);
delay_nms(1);
ADCSRA &= ~(1<<ADSC);
}
}
uint get_degree(void)
{
uchar x,y;
uint v_big,v_small,v_step;
if (v<100) return 0x83E7; // 當沒有信號時顯示-99.9錯誤
for (x=0;x<135;x++) // 查表
{
if ( v>= v_table[x]) // 找出電壓區域 //
{
v_big = v_table[x+1]; // 區域 高段
v_small = v_table[x]; //區域 低段
v_step = (v_big - v_small)/10; // 把區域細分成10份
for (y=0;y<10;y++) // 細分比較
{
v_small += v_step;
if (v < v_small) // 得出結果
{
v = x*10+y;// 其中x*10 為整數部分, y 為小數部分
if (x<10) // 少於10時為負溫度
{
// v -= 400; // 0 度修正
v |= 0x8000; // 加入負號標記
//v=v;
}
else
{
v -= 100; // 0 度修正
}
return v; //返回温度
};
};
};
WDR();
}
return v;
}
uchar get_key_value(void)
{
get_adc_value(ADC_KEY);
if (v < 250)
{
return 0;
}
else
{
if ((v > 1000)&&(v < 1300))
{
return 1;//1150mv
}
else
{
if ((v > 1300)&&(v < 2200))
{
return 2;//1948
}
else
{
if ((v > 2200)&&(v < 3500))
{
return 3;//3000mv
}
else
{
return 0;
}
}
}
}
}
void temp_setting(void)
{
uchar key;
key = get_key_value();
if(key==2)
{
adc_channel++;
if (adc_channel>2) //切换显示路数
{
adc_channel = 0;
}
scandisplay(adc_channel+1);
scandisplay(adc_channel+1);
scandisplay(adc_channel+1);
scandisplay(adc_channel+1);
}
if(key==3)
{
if (auto_mode==0xff) // 自動模式
{
auto_mode = ~auto_mode;//退出 自动模式
}
if (adc_channel==0) //设置模式
{
adc_channel = 1;
auto_mode = ~auto_mode;//3路自动切换
}
adc_channel--;
}
while(1)
{
get_adc_value(ADC_KEY);
if(v < 200) //退出当前模式
{
break;
};
};
if (key==1)
{
scandisplay(1+adc_channel);
scandisplay(1+adc_channel);
scandisplay(1+adc_channel);
scandisplay(1+adc_channel);
setting_mode = 1;
}
while(setting_mode==1)
{
key = get_key_value();
if(key==1)
{
adc_channel++;
if (adc_channel>2)
{
adc_channel = 0;
setting_mode = 0;
EEPROMwrite(0x01, hot_warning[0]);
delay_nms(5);
EEPROMwrite(0x02, hot_warning[1]);
delay_nms(5);
EEPROMwrite(0x03, hot_warning[2]);
delay_nms(5);
}
scandisplay(1+adc_channel);
scandisplay(1+adc_channel);
scandisplay(1+adc_channel);
scandisplay(1+adc_channel);
}
else
{
if(key==2)
{
if(hot_warning[adc_channel]>105)
{
hot_warning[adc_channel]=30;
}
else
{
++hot_warning[adc_channel];
}
}
else
{ if(key==3)
{
if(hot_warning[adc_channel]<1)
{
hot_warning[adc_channel]=30;
}
else
{
--hot_warning[adc_channel];
}
}
};
};
while(1)
{
get_adc_value(ADC_KEY);
if(v < 200)
{
break;
};
};
scandisplay(hot_warning[adc_channel]*10);
}
}
//TIMER1 initialize - prescale:1024
// WGM: 0) Normal, TOP=0xFFFF
// desired value: 500mSec
// actual value: 499.968mSec (0.0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xFF; //setup
TCNT1L = 0xFC;
OCR1AH = 0x07;
OCR1AL = 0xA1;
OCR1BH = 0x07;
OCR1BL = 0xA1;
ICR1H = 0x07;
ICR1L = 0xA1;
TCCR1A = 0x00;
TCCR1B = 0x05; //start Timer
}
void init_1820()
{
PORTD|=(1<<4);
PORTD&=~(1<<4);
delay(3000); //480us以上
PORTD|=(1<<4);
DDRD&=~(1<<4);
delay(40); //15~60us
while(PIND&(1<<4))
{
// disp_led(3,0);
// for(;;)
//{}
}
DDRD|=(1<<4);
PORTD|=(1<<4);
delay(150); //60~240us
}
write_1820(uchar x)
{
uchar m;
for(m=0;m<8;m++)
{
PORTD&=~(1<<4);
if(x&(1<<m)) //写数据,从低位开始
PORTD|=(1<<4);
else
PORTD&=~(1<<4);
delay(40); //15~60us
PORTD|=(1<<4);
}
PORTD|=(1<<4);
}
uchar read_1820()
{
uchar temp,k,n;
temp=0;
for(n=0;n<8;n++)
{
PORTD&=~(1<<4);
//delay(2);
PORTD|=(1<<4);
//delay(3);
DDRD&=~(1<<4);
k=(PIND&(1<<4)); //读数据,从低位开始
if(k)
temp|=(1<<n);
else
temp&=~(1<<n);
delay(50); //60~120us
DDRD|=(1<<4);
}
return (temp);
}
#pragma interrupt_handler timer1_compa_isr:7
void timer1_compa_isr(void)
{
//compare occured TCNT1=OCR1A
}
#pragma interrupt_handler timer1_ovf_isr:9
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
//TCNT1H = 0xF8; //reload counter high value
TCNT1H = 0xFF;
TCNT1L = 0xFC; //reload counter low value
//PORTD=bitcpl(PORTD,2);// 取反 。。。
// scandisplay(995);
Fc1++;
pwm1();
Fc2++;
Fc3++;
//pwm2();
}
void pwm1(void) // pwm 控制函数
{
//开始 调速控制
if(PWFS1)
{
//输出
if(Fc1<45)
{
PORTD=bitset(PORTD,0);//打开风扇
}
else
{
PORTD=bitclr(PORTD,0);//关闭风扇
}
if(Fc1>90)
{
Fc1=0;
}
}
//输出
if(PWFS2)
{
if(Fc2<45)
{
PORTD=bitset(PORTD,1);//打开风扇
}
else
{
PORTD=bitclr(PORTD,1);//关闭风扇
}
if(Fc2>90)
{
Fc2=0;
}
}
//输出
if(PWFS3)
{
if(Fc3<45)
{
PORTD=bitset(PORTD,2);//打开风扇
}
else
{
PORTD=bitclr(PORTD,2);//关闭风扇
}
if(Fc3>90)
{
Fc3=0;
}
}
}
uchar bitclr(uchar num,uchar bit) /*清除某一位*/
{
uchar bit_value[]={1,2,4,8,16,32,64,128};
return num&~bit_value[bit];
}
uchar bitset(uchar num,uchar bit) /*设置某一位*/
{
uchar bit_value[]={1,2,4,8,16,32,64,128};
return num|bit_value[bit];
}
uchar bitcpl(uchar num,uchar bit) /*取反某一位*/
{
uchar bit_value[]={1,2,4,8,16,32,64,128};
if(num>>bit&0x01==1)
return num&~bit_value[bit];
else
return num|bit_value[bit];
} |
|