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

📄 temp_control.c

📁 采用ATMEGA单片机实现的智能温度控制。
💻 C
字号:
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include "char_model.h"

#define LcdCtrl_Port  PORTB
#define Lcd_Res       PB2
#define Lcd_A0        PB3
#define Lcd_RW        PB4
#define Lcd_E1        PB5
#define Lcd_E2        PB6
#define LcdData_Port  PORTC

#define TCNT0_NOH     0xfc
#define TCNT0_NOL     0xc1


uint8_t disp_buf[20];//显示缓存

uint8_t bw,sw,gw,sf,bf, led	= 0,bw_s=0,sw_s=0,gw_s=0,key_enter,key_down,key_up,key_set=1;
uint16_t ADC_rel = 0;
uint8_t flag_adc = 0;
uint8_t a = 0;
uint8_t flag0 = 1;
uint16_t temp_bj;
uint8_t flag1 = 1;
uint16_t temp_h = 0;
uint16_t temp_l = 0;
uint8_t w = 0;
uint8_t TCNT2_NO = 90, OCR2_NO = 0;
//延时
void Delay(uint32_t usecond)
{
	uint8_t j = 8;
	uint32_t i;
	for(i = 0; i < usecond; i++)
	{
		while(j--);
	}
}

//微控制器初始化
void MCUInit(void)
{
	PORTA = 0x0f;
	DDRA = 0x0f;
	
	PORTB = 0x00;
	DDRB = 0xff;
	
	PORTC = 0x00;
	DDRC = 0xff;
	
	PORTD = 0xff;
	DDRD = 0xf0;
	
	/*TCCR1A = 0x00;                           //定时1初始化
	TCCR1B = (1 << CS12) ;//| (1 << CS10);
	//TCCR0 = (1 << CS02) | (1 << CS00) ;
	TIMSK = 1 << TOIE1;
	//TCNT0 = TCNT0_NO;
	TCNT1H = TCNT0_NOH;
	TCNT1L = TCNT0_NOL;*/
	
	
}




//命令-数据发送模块
//temp:命令或数据暂存变量,m_s:指令(0)—数据(1) 信号,l_r:左屏(0)-右屏(1)-全屏(2) 选择
void LcdDataSend(uint8_t temp, uint8_t m_s, uint8_t l_r)
{
	Delay(2);//不使用忙线,所以延迟2us,等待LCD空闲
	if(m_s == 0) //判断是指令还是数据:0-指令,1-数据
	{
		cbi(LcdCtrl_Port, Lcd_A0);
	}
	else
	{
		sbi(LcdCtrl_Port, Lcd_A0);
	}
	
	if(l_r == 0) //判断屏幕:0-左屏,1-右屏,2-全屏
	{
		sbi(LcdCtrl_Port, Lcd_E1);
		cbi(LcdCtrl_Port, Lcd_E2);
	}
	else if(l_r == 1)
	{
		cbi(LcdCtrl_Port, Lcd_E1);
		sbi(LcdCtrl_Port, Lcd_E2);
	}
	else if(l_r == 2)
	{
		sbi(LcdCtrl_Port, Lcd_E1);
		sbi(LcdCtrl_Port, Lcd_E2);
	}
	
	Delay(5);
	LcdData_Port = temp;//送如指令或数据
	Delay(5);
	cbi(LcdCtrl_Port, Lcd_E1);//关闭液晶,防止干扰
	cbi(LcdCtrl_Port, Lcd_E2);				
}

//通用显示模块
//addr:发送代码表的地址,page:显示的页,row:显示的列
void WordSend(uint8_t addr, uint8_t page, uint8_t row, uint8_t zy)
{
	uint8_t width;//字模宽度为12*12
	uint8_t hig;//字模高度为2页
	for(hig = 0; hig < 2; hig++)
	{
	    LcdDataSend(page, 0, zy);
	    LcdDataSend(row, 0, zy);
	    for(width = 0; width < 12; width++)
	    {
	        if(hig < 1)
			LcdDataSend(PRG_RDB(&CBYTE[addr][width]), 1, zy);
			else
			LcdDataSend(PRG_RDB(&CBYTE[addr][width + 12]), 1, zy);
		}
		page++;
	}
}

//lcd初始化
void LcdInit(void)
{
	cbi(LcdCtrl_Port, Lcd_Res);
	Delay(1000);
	sbi(LcdCtrl_Port, Lcd_Res);
	cbi(LcdCtrl_Port, Lcd_RW);
	
	LcdDataSend(0xe2, 0, 2);//reset
	LcdDataSend(0xae, 0, 2);//display on/off: off
	//LcdDataSend(0xc0, 0, 2);//display start line : 1
	LcdDataSend(0xa4, 0, 2);//static drive on/off: off
	//LcdDataSend(0x00, 0, 2);//column address set: 0
	//LcdDataSend(0xb8, 0, 2);//page address set: 1
	LcdDataSend(0xa9, 0, 2);//duty select: 1/32
	LcdDataSend(0xa0, 0, 2);//adc select: rightward outpu
	LcdDataSend(0xee, 0, 2);//read modify write: off 
	LcdDataSend(0xaf, 0, 2);//display on off: ON	
}	
	
//清屏
//
void LcdClear(void)
{
	uint8_t temp1, temp2;
	uint8_t leaf = 0xb8;
	for(temp1 = 0; temp1 < 4; temp1++)
	{
		LcdDataSend(leaf, 0, 2);
		LcdDataSend(0, 0, 2);
		for(temp2 = 0; temp2 < 60; temp2++)
		{
			LcdDataSend(0, 1, 2);
		}
		leaf++;
	}
	Delay(1000);
}
//PWM波输出初始化
void PWM_Init(void)
{
	TCCR2 = 0x6f;
	OCR2 = OCR2_NO;
	TCNT2 = TCNT2_NO ;
	}

//ADC初始化
void ADC_Init(void)
{
  ADMUX = 0x07;
  ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADIE)|(1<<ADATE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
  //使能AD,128分频。
}
//AD中断服务
SIGNAL(SIG_ADC)
{
uint16_t h=0,l=0;
	//ADCSRA=0x00;
	//ADMUX=0x00;
	l = ADCL;
	h = ADCH;
	ADC_rel = (h<<8)+l;//读取AD数据寄存器内的数据
	flag1 = 1;
	
	
}
//INT0初始化
void INT0_init(void)
{
	MCUCR = 0x10;
	GICR = 0x40;
	
}
//中断0,用来选通4路温度采集
SIGNAL(SIG_INTERRUPT0)
{
		Delay(5000);
		a++;
		if(a == 5)  a = 1;
		flag0 = 1;	
}
//中断1
/*SIGNAL(SIG_INTERRUPT1)
{
		 Delay(1800);
		 w++;
		 if(w == 3){w=1;}
		 flag0 = 1;
}*/
/*******************************
        键盘扫描函数

********************************/
void Key_scan(void)
	{
	uint8_t temp0,temp1;
	temp0 = PIND & 0x0f;
	Delay(5);
	temp1 = PIND & 0x0f;
	if(temp0 == temp1);
	{
	//key_set = temp0&0x04;
	key_up = temp0&0x08;//设定的数据增大
    key_down = temp0&0x01;//设定的数据减小
    key_enter = temp0&0x02;//确定键
    
	/*if(key_set == 0)
		{
		
		//Delay(10);
		a++;
		if(a==5)  a=1;
		flag0 = 1;
        }*/
	if(key_down == 0)
	   {
	   //Delay(10);
	   if(temp_bj>0)
		  {temp_bj--;}
		   flag0 = 1;
	   }
	if(key_up == 0)
	   {
	   //Delay(10);
	   if(temp_bj < 200)
		  {temp_bj++;}
		  flag0 = 1;
	   }
	if(key_enter == 0)
		{
		 w++;
		 if(w == 3){w = 1;}
		 flag0 = 1;
		}
	}
}
/*//记数器益出中断服务
SIGNAL(SIG_OVERFLOW1)
{
	TCNT1H = TCNT0_NOH;
	TCNT1L = TCNT0_NOL;
	//TCNT0 = TCNT0_NO;
	ADMUX=0x07;
	ADCSRA=0xe8;//(1<<ADEN)|(1<<ADSC)(1<<ADIE)|(1<<ADATE);
}*/
//4路选通函数
void select_ways(uint8_t w)
	{
	 switch(w)
	 {
		 case 1: 
		 {
		 	cbi(PORTD,PD5);
		  	cbi(PORTD,PD6);
		  	break;
		  }
		 case 2: 
		 {
		 	sbi(PORTD,PD5);
		  	cbi(PORTD,PD6);
		  	break;
		  }
		 case 3: 
		 {
		 	cbi(PORTD,PD5);
		  	sbi(PORTD,PD6);
		  	break;
		  }
		 case 4: 
		 {
		 	sbi(PORTD,PD5);
		  	sbi(PORTD,PD6);
		  	break;
		  }
		 default:break;
	 }
	}

//AD值处理函数
void ADCtoBCD(uint16_t temp)
	{   
		
		bw = temp/1000;
		sw = (temp%1000)/100;
		gw = (temp%100)/10;
		sf = temp%10;
	}
	
//设置值处理函数
void BJtoBCD(uint16_t b)
	{   
		
		bw_s = b/100;
		sw_s = (b%100)/10;
		gw_s = b%10;
	}
//enter键处理函数
void control_set(uint8_t q)

	{
	switch(q)
	{
	case 1://确认键处理函数
			{
				temp_h = temp_bj;
				WordSend(37, 0xba, 36, 1);
			 	WordSend(36, 0xba, 48, 1);
			 	break;
			 }
	case 2://重设键处理函数
			{
				WordSend(34, 0xba, 36, 1);
			 	WordSend(35, 0xba, 48, 1);
			 	temp_bj = 0;
			 	temp_h = 0;
			 	w = 0;
			 	break;
			 }
	default:break;		 
	}
	
	}

//灯驱动,利用A口驱动4个发光二极管
void leddis(uint8_t a)
	{
	switch(a)
	{
	case 1: PORTA = 0x0e;break;
	case 2: PORTA = 0x0d;break;
	case 3: PORTA = 0x0b;break;
	case 4: PORTA = 0x07;break;
	//case 5: PORTA &= ~(1<<4);break;
	default:break;
	}
	}
//显示函数
void disp(uint8_t i)
	{
	if(i == 0)//显示欢迎界面
	{
		WordSend(26, 0xb8, 24, 0);	WordSend(27, 0xb8, 36, 0);
		WordSend(12, 0xb8, 48, 0);	WordSend(13, 0xb8, 0, 1);
		WordSend(28, 0xb8, 12, 1);	WordSend(29, 0xb8, 24, 1);
		WordSend(30, 0xb8, 36, 1);
		
		WordSend(38, 0xba, 48, 0);	WordSend(39, 0xba, 0, 1);
		WordSend(15, 0xba, 12, 1);	WordSend(40, 0xba, 24, 1);
		WordSend(41, 0xba, 36, 1);	WordSend(42, 0xba, 48, 1);
	}
	else //温度显示
	{
		leddis(i);
		WordSend(i, 0xb8, 0, 0);	WordSend(11, 0xb8, 12, 0);
		WordSend(15, 0xb8, 24, 0);	WordSend(bw, 0xb8, 36, 0);
		WordSend(sw, 0xb8, 48, 0);	WordSend(gw, 0xb8, 0, 1);
		WordSend(16, 0xb8, 12, 1);	WordSend(sf, 0xb8, 18, 1);
		WordSend(25, 0xb8, 30, 1);	WordSend(25, 0xb8, 42, 1);
		WordSend(19, 0xb8, 48, 1);
	
		WordSend(36, 0xba, 0, 0);	WordSend(35, 0xba, 12, 0);
		WordSend(15, 0xba, 24, 0);	WordSend(bw_s, 0xba, 36, 0);
		WordSend(sw_s, 0xba, 48, 0);WordSend(gw_s, 0xba, 0, 1);
		WordSend(19, 0xba, 12, 1);	WordSend(25, 0xba, 24, 1);
		WordSend(34, 0xba, 36, 1);	WordSend(35, 0xba, 48, 1);
	}
	}


//主函数
int main(void)
{
	

	MCUInit();
	LcdInit();
	LcdClear();
	sei();
	ADC_Init();
	INT0_init();
	while(1)
	{
	
	 
	 Key_scan();
	  
	   if(flag0|flag1)//当有按键按下或AD值更新时才更新显示和输出信号
	   {
	      select_ways(a);
		  BJtoBCD(temp_bj);
		  ADCtoBCD(ADC_rel);
		  disp(a);
		  control_set(w);
		  //PWM_Init();
		  if((ADC_rel/10) < temp_h )//控制信号输出
			{
				/*if(OCR2_NO < 255)
				{OCR2_NO++;}*/
				sbi(PORTD,PD7);
			}
		  else
			{
				/*if(OCR2_NO > 0)
				{OCR2_NO--;}*/
				cbi(PORTD,PD7);
			}
		  flag0 = 0;
		  flag1 = 0;
		  
	    }
	   
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -