Clock F : 8M
*******************************************************************************/
#include
#include
//#include "LCD1602.h"
//#include "port_init.h"
//#include "display.h"
//#include "temp_set.h"
//#pragma interrupt_handler SET:6;
#define uchar unsigned char
#define uint unsigned int
#define RS_CLR PORTG &= ~(1 << PG0)
#define RS_SET PORTG |= (1 << PG0)
#define RW_CLR PORTG &= ~(1 << PG1)
#define RW_SET PORTG |= (1 << PG1)
#define EN_CLR PORTG &= ~(1 << PG2)
#define EN_SET PORTG |= (1 << PG2)
#pragma interrupt_handler TC3:30
float target;
int temperature;
unsigned char zhi[3]={0,0,0},flag,f,t;
unsigned char *p="0123456789.";
unsigned char Z;
unsigned char a,b,c,k;
float gap;
unsigned int adc_da
void port_init()
{
DDRA=0xff;//A口为输出端口
PORTA=0x00;//不带上拉电阻
DDRB=0xff;//B口为输出口
DDRD=0xff;//带上拉电阻
PORTD=0x03;//D口为输入口
DDRF=0x00;//为输入口
PORTF=0x00;//不带上拉电阻
DDRG=0xff;//G口为输出口
PORTG=0x00;//不带上拉电阻
DDRC=0X00;
PORTC=0X00;
DDRE=0x00;
PORTE=0x00;
}
//us延时函数
void delay_us(uint n) //8*0.125=1us
{
int i,j;
for(j=0;j<8;j++)
{
for (i=0;i
}
}
//ms延时函数
void delay_ms(uint i)
{
while(i--)
{
uint j;
for(j=1;j<=1332;j++)
;
}
}
//显示屏初始化函数
void LCD_init(void)
{
DDRA = 0xFF; //I/O口方向设置
DDRD|=(1<
Write_Instruction(0x38); //8bit interface,2line,5*7dots
delay_ms(5);
Write_Instruction(0x38);
delay_ms(5);
Write_Instruction(0x38);
Write_Instruction(0x08); //关显示,不显光标,光标不闪烁
Write_Instruction(0x01); //清屏
delay_ms(5);
Write_Instruction(0x04); //写一字符,整屏显示不移动
//Write_Instruction(0x05); //写一字符,整屏右移
//Write_Instruction(0x06); //写一字符,整屏显示不移动
//Write_Instruction(0x07); //写一字符,整屏左移
delay_ms(5);
//Write_Instruction(0x0B); //关闭显示(不显示字符,只有背光亮)
Write_Instruction(0x0C); //开显示,光标、闪烁都关闭
//Write_Instruction(0x0D); //开显示,不显示光标,但光标闪烁
//Write_Instruction(0x0E); //开显示,显示光标,但光标不闪烁
//Write_Instruction(0x0F); //开显示,光标、闪烁均显示
}
//控制LCD写时序
void LCD_en_write(void) //EN端产生一个高电平脉冲,控制LCD写时序
{
EN_SET;
delay_us(3);
EN_CLR;
delay_us(3);
}
//清屏函数
void LCD_clear()
{
Write_Instruction(0x01);
delay_ms(5);
}
//写指令函数
void Write_Instruction(uchar command)
{
RS_CLR;
RW_CLR;
EN_SET;
PORTA=command;
LCD_en_write();//写入指令数据
}
//写数据函数
void Write_Da
{
RS_SET;
RW_CLR;
EN_SET;
PORTA=Wdata;
LCD_en_write();//写入数据
}
//字符显示初始地址设置
void LCD_SET_XY(uchar X,uchar Y)
{
uchar address;
if(Y==0)
address=0x80+X;//Y=0,表示在第一行显示,地址基数为0x80
else
address=0xc0+X;//Y非0时,表时在第二行显示,地址基数为0XC0
Write_Instruction(address);//写指令,设置显示初始地址
}
//在第X行Y列开始显示,指针*S所指向的字符串
void LCD_write_str(uchar X,uchar Y,uchar *s)
{
LCD_SET_XY(X,Y);//设置初始字符显示地址
while(*s)//逐次写入显示字符,直到最后一个字符"/0"
{
Write_Da
s++;//地址指针加1,指向下一个待写字符
}
}
//在第X行Y列开始显示Wdata所对应的单个字符
void LCD_write_char(uchar X,uchar Y,uchar Wdata)
{
LCD_SET_XY(X,Y);//写地址
Write_Da
}
///////////////////////i2c通信子程序///////////////////////
///////////////////////////////////////////////////////////
//初始化
void i2c_init()
{
PORTD&=~0x80;
TWBR=0x01 ; //速率=16M/(16+2*16)=33.3k
TWSR=0x01 ; //分频因子=4
}
//开始信号
void i2c_start()
{
TWCR=0xa4 ;
while(!(TWCR&0x80));
}
//写数据
void i2c_wrdata(uchar i2c_da
{
TWDR=(i2c_da
TWCR=0x84 ;
while(!(TWCR&0x80));
}
//读数据noack
uchar i2c_redata()
{
uchar i2c_da
TWCR=0x84 ;
while(!(TWCR&0x80));
//delay_ms(20);
i2c_da
return(i2c_da
}
//读数据ack
uchar i2c_redataack()
{
uchar i2c_da
TWCR=0xc4 ;
while(!(TWCR&0x80));
i2c_da
return(i2c_da
}
//停止信号
void i2c_stop()
{
TWCR=0x94 ;
}
//i2c的写字节子程序
void i2c_wrbyte(uchar i2c_da
{
do
{
i2c_start();
i2c_wrdata(0xa0);
}
while((TWSR&0xf8)!=0x18); //判断总线是否可以操作
i2c_wrdata(i2c_add);
i2c_wrdata(i2c_da
i2c_stop();
}
//i2c的页写子程序
//参数1:要写入的数组指针
//参数2:写入的首地址
//参数3:数组的单元数
void i2c_wrpage(uchar *i2c_da
{
uchar i;
do
{
i2c_start();
i2c_wrdata(0xa0);
}
while((TWSR&0xf8)!=0x18);
//判断总线是否可以操作
i2c_wrdata(i2c_add);
for(i=0;i
i2c_wrdata(*i2c_da
}
i2c_stop();
}
//i2c读一个字节子程序
uchar i2c_rebyte(uchar i2c_add)
{
uchar i2c_da
do
{
i2c_start();
i2c_wrdata(0xa0);
}
while((TWSR&0xf8)!=0x18);
//判断总线是否可以操作
i2c_wrdata(i2c_add);
i2c_start();
i2c_wrdata(0xa1);
i2c_da
i2c_stop();
return(i2c_da
}
//i2c连续读子程序
//参数1:16位地址
//参数2:读取字节数 注:<=64
//读出的数据只能从全局数组变量获得
void i2c_rese(uchar *i2c_da
{
uchar i;
do
{
i2c_start();
i2c_wrdata(0xa0);
}
while((TWSR&0xf8)!=0x18);
//判断总线是否可以操作
i2c_wrdata(i2c_add);
i2c_start();
i2c_wrdata(0xa1);
for(i=0;i
{
*i2c_da
i2c_da
}
*i2c_da
i2c_stop();
}
/************************************
用 途:矩阵键盘扫描子程序
Taget :mega128
crystal :8M
介 绍:用的是C口
入口参数:
出口参数:没有是16不然是0-15
*************************************/
void delay(uint ms)
{
uint i,j;
for(i=0;i
for(j=0;j<1141;j++);
}
}
char key_vetrix()
{
uchar key,i=0X7F,j;
delay(10);
if(key_press())
{
do
{
i=(i<<1|i>>7);
PORTC=i;
DDRC=0X0F;
key=PINC;
j=key&0XF0;
}while(j==0XF0);
while(key_press());
switch(key)
{
case 0xEE:
key=0x0;
break;
case 0xDE:
key=0x1;
break;
case 0xBE:
key=0x2;
break;
case 0x7E:
key=0x3;
break;
case 0xED:
key=0x4;
break;
case 0xDD:
key=0x5;
break;
case 0xBD:
key=0x6;
break;
case 0x7D:
key=0x7;
break;
case 0xEB:
key=0x8;
break;
case 0xDB:
key=0x9;
break;
case 0xBB:
key=0xA;
break;
case 0x7B:
key=0xB;
break;
case 0xE7:
key=0xC;
break;
case 0xD7:
key=0xD;
break;
case 0xB7:
key=0xE;
break;
case 0x77:
key=0xF;
break;
default:
key=16;
}
}
else
{
key=16;
}
return key;
}
uchar key_press()
{
uchar i;
DDRC=0XFF;
PORTC=0XF0;
DDRC=0X0F;
i=PINC;
if(i==0XF0)
{
DDRC=0XFF;
return 0;
}
else
{
DDRC=0XFF;
return 1;
}
}
//********************************
float ADC0()
{ unsigned char adc_l0,adc_h0;
unsigned int qianwei0,baiwei0,shiwei0,gewei0;
float temp;
ADCSRA=0x00;
ADMUX=0x40;//01000000在
ADCSRA=(1<
//delay_ms(5);
while(!((ADCSRA)&(BIT(ADIF)))); //给出转换的时间
adc_l0=ADCL;
adc_h0=ADCH;
adc_da
temp=adc_da
temp=temp/4;
adc_da
if(adc_da
{
adc_da
}
else if(adc_da
{
adc_da
}
if(t==1)
{
gewei0 = (int) adc_da
qianwei0 = (int) adc_da
baiwei0 = (int) adc_da
shiwei0 = (int) adc_da
//LCD_write_char(10,1,p[qianwei0]);
LCD_write_char(11,1,p[baiwei0]);
LCD_write_char(12,1,p[shiwei0]);
LCD_write_char(13,1,p[gewei0]);
t=0;
}
return adc_da
}
void PID()
{
unsigned int a;
unsigned int wanwei0,qianwei0,baiwei0,shiwei0,gewei0;
float kp=1.0,ki=0.9,kd=2.0;
float piancha1,piancha2,piancha3,leiji;
piancha3=target-ADC0();//target 是一个目标温度,是一个全局变量
temperature=leiji+(kp+ki+kd)*piancha3+kd*piancha1-(kp+2*kd)*piancha2;
piancha1=piancha2;
piancha2=piancha3;
leiji=temperature;
if(f==1)
{
if(temperature<0)
{
// LCD_write_char(1,1,);
temperature=0-temperature;
}
else
//LCD_write_char(1,1,);
wanwei0 = temperature/10000;
qianwei0 = temperature%10000/1000;
baiwei0 = temperature%1000/100;
shiwei0 = temperature%100/10;
gewei0 = temperature%10;
LCD_write_char(20,1,p[qianwei0]);
LCD_write_char(21,1,p[qianwei0]);
LCD_write_char(22,1,p[baiwei0]);
LCD_write_char(23,1,p[shiwei0]);
LCD_write_char(24,1,p[gewei0]);
f=0;
}
OCR1B=1250-20* temperature;
/* gap=(target-ADC0())/target*100;
/* if(gap<0)
OCR1B=1249;
else if(gap=0)
OCR1B=1200;
else if(gap>0&&gap<=2)
OCR1B=500;
else if(gap>2)
OCR1B=10;
/*if (gap>0)
{
if(gap>80)
OCR1B=100;
if(gap<=80&&gap>=70)
OCR1B=200;
if(gap<=70&&gap>=60)
OCR1B=300;
if(gap<=60&&gap>=50)
OCR1B=400;
if(gap<=50&&gap>=40)
OCR1B=500;
if(gap<=40&&gap>=30)
OCR1B=600;
if(gap<=30&&gap>=20)
OCR1B=700;
if(gap<=20&&gap>=10)
OCR1B=900;
if(gap<=10&&gap>=0)
OCR1B=500;
}*/
/*if(gap<=0)
OCR1B=1249;
if(gap>0)
OCR1B=12;*/
//return a;
}
void setxianshi()
{ a=(int)target/100;
b=(int)target%100/10;
c=(int)target%10;
LCD_write_char(11,0,0x30+a);
LCD_write_char(12,0,0x30+b);
LCD_write_char(13,0,0x30+c);
}
void SET()
{
//ETIMSK&=~BIT(2);//关定时中断
//if((Z=key_vetrix())!=16)
//while(1)
//{
//setxianshi();
Z= key_vetrix();
if (Z==12)
{ char t=1;
while(t)
{Z=key_vetrix();
setxianshi();
LCD_write_str(0,0," SET TEMP:");
if(Z==14)
{
target++;
//Z=16;
}
if(Z==15)
{
target--;
//Z=16;
}
if(0<=Z&&Z<=9)
{ if(k==0)
target=(int)target%100+Z*100;
if(k==1)
target=(int)target-(int)target/10%10*10+Z*10;
if(k==2)
target=(int)target-(int)target%10+Z;
k++;
if(k==3)
k=0;
}
if(Z==13)
t=0;
}
}
LCD_write_str(0,0,"TARGET IS:");
// }
}
void kaijixianshi()
{ char i;
LCD_write_str(0,0," WELCOME TO THE ");
LCD_write_str(0,1," DEVICE ");
PORTB&=~BIT(0);
PORTB|=BIT(1);
/*for(i=0;i<20 ;i++ )
{
Write_Instruction(0x18);
delay_ms(100);
}*/
delay_ms(3000);
PORTB|=BIT(0);
PORTB&=~BIT(1);
}
void main ()
{
int num1;
port_init();
LCD_init(); //LCD初始化
i2c_init(); //初始化
target=i2c_rebyte(0x05); //读出地址0x12的字节
LCD_clear();//清屏
kaijixianshi();
LCD_clear();//清屏
//LCD_write_str(0,1,"TEMP IS: .C");
EICRB=0x00;
TCCR1A=0x63;
TCCR1B=0x13;
OCR1A=1249;
OCR1B=31;
/**** 定时器3的普通模式*******/
TCCR3A=0X00;
TCCR3B=0X05;
TCNT3H=0X85;
TCNT3L=0XE0;
ETIMSK|=BIT(2);
SREG|=BIT(7);//2秒钟发生一次中断
a=(unsigned char)target/100;
b=(unsigned char)target%100/10;
c=(unsigned char)target%10;
LCD_write_str(0,0,"TARGET IS: .C");
LCD_write_str(0,1," TEMP IS: .C");
LCD_write_char(11,0,p[a]);
LCD_write_char(12,0,p[b]);
LCD_write_char(13,0,p[c]);
while(1)
{
/*target=a*100+b*10+c*1;
if((target-temperature)>=0)
{
// LCD_write_char(11,0,p[a]);
//LCD_write_char(12,0,p[b]);
//LCD_write_char(13,0,p[c]);
SET();
num1=PID();
if(num1>40)
OCR1B=100;
else
num1=PID();
if(num1>30&&num1<40)
OCR1B=200;
else
num1=PID();
if (num1>20&&num1<30)
OCR1B=300;
else
num1=PID();
if(num1>10&&num1<20)
OCR1B=500;
else
num1=PID();
if(num1>0&&num1<10)
OCR1B=700;
else
num1=PID();
OCR1B=1000;
}
}*/
SET();
PID();
i2c_wrbyte((unsigned char)target,0x05); //字节写入
}
}
void TC3()
{
t=1;
f=1;
TCNT3H=0X85;
TCNT3L=0XE0;
}
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』