仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
基于AVR單片機的汽車空調控制系統 摘要: AVR單片機功能強大,用AVR單片機開發各種控制系統只需很少的外部器件就可以實現強大的功能。本文介紹的就是利用Atmega16、CodeVisionAVR C開發環境、Proteus仿真軟件開發汽車空調自動控制系統。
Atmega16是美國ATMEL公司的高檔8位單片機,采用Flash存儲器,可以擦寫10000次以上、內部集成 、四通道PWM、集成8路10位精度ADC、片內經過標定的RC振蕩器、采用精簡指令集,具有32個通用工作寄存器,具有只需兩個時鐘周期的硬件乘法器,運算速度快等。由于其集成度高、處理速度快,使得利用AVR單片機進行系統開發只需很少(甚至沒有)的外部器件即可實現強大的功能,逐漸在各種場合得到廣泛應用,取代其它8位單片機。利用它來開發汽車空調控制系統,只需熱電阻、液晶顯示模塊和一些繼電器及其驅動芯片即可實現。 本系統可以分為五大部分:熱電阻溫度采集、運行狀態顯示、繼電器控制、鍵盤輸入、風向步進電機控制。 熱電阻傳感器以其溫度特性穩定、測量精 
圖1 Pt1000熱電阻溫度測量電路 度高的特點,在大型中央空調得到了廣泛的應用。 采用Pt1000熱電阻作為溫度傳感器的測量電路原理圖如圖1 所示。熱電阻Rt與三個電阻接成電橋。當溫度變化時,使得運算放大器的同相輸入端的電位發生變化,經過運算放大器放大之后輸入到Atmega16單片機進行AD轉換。由于單片機采用5V電壓作為ADC的參考電源,而電橋在溫度變化為0~100°C時,輸出電壓范圍為0~0.7V,所以確定運算放大電路的放大倍數為7,以獲得最佳的測量結果。運算放大電路的電阻按以下公式確定:   取 。輸出電壓變化范圍大致是0~5V。 由于ADC的轉換精度為10,故當輸入電壓為5V時,其采樣值為1023,根據電橋平衡原理,可得到以下公式: (1)
其中,N——ADC數據寄存器的值, U——電橋電源電壓, ——Pt1000在0°C時的電阻1000 。
Pt1000熱電阻的阻值按以下公式計算::  (2)
Rt——溫度為t時鉑熱電阻的電阻值,Ω; t——溫度,℃; ——Pt1000在0°C時的電阻1000 。
A——分度常數,A=0.0038623139728 B——分度常數,B=-0.00000065314932626 用Visual Basic.Net根據以上公式(1)、(2)生成用N來查找溫度t的程序表格,其代碼如下: Private Sub Pt1000() Me.Cursor = Cursors.WaitCursor txtTab.Clear() Dim U As Integer = 9 '電橋電源電壓 '熱電阻0度時的電阻值 Dim Pt1000_R0 As Integer = 1000 Dim n As Integer Dim sngT As Single Dim sngRt As Single txtTab.AppendText("const float Pt1000Tab[]={" & Chr(13) & Chr(10)) For n = 0 To 1023 sngRt = (10000 * n + 7161000 * U) / (7161 * U - 10 * n) sngT = (-const_A + Sqrt(const_A ^ 2 - 4 * const_B * (1 - sngRt / Pt1000_R0))) / (2 * const_B) If n < 1023 Then txtTab.AppendText(Format(Abs(sngT), "0.0") & ", /* " & n & " */") Else txtTab.AppendText(Format(Abs(sngT), "0.0") & " /* " & n & " */" & Chr(13) & Chr(10) & "};") End If If n Mod 5 = 0 Then txtTab.AppendText(Chr(13) & Chr(10)) End If Next txtTab.SelectAll() txtTab.Copy() Me.Cursor = Cursors.Default End Sub 生成的程序常數表格(1024個值)部分如下: const float Pt1000Tab[]={ 0.0, /* 0 */ 0.1, /* 1 */0.2, /* 2 */0.2, …… 63.4, /* 696 */63.5, /* 697 */ …… 99.3, /* 1022 */99.4 /* 1023 */ }; 2.2 運行狀態顯示 本系統采用一塊16×4的字符型液晶模塊,這種類型的LCD應用很廣泛,其控制驅動主芯片為HD44780及其擴展驅動芯片HD44100(或兼容芯片),少量阻、容元件,結構件等裝配在PCB板上而成。字符型液晶顯示模塊目前在國際上已經規范化,無論顯示屏規格如何變化,其電特性和接口形式都是統一的。因此只要設計出一種型號的接口電路,在指令設置上稍加改動即可使用各種規格的字符型液晶顯示模塊。odeVisionAVR集成開發環境集成這種類型LCD的函數,可方便實現LCD的讀寫,其部分函數及功能簡單介紹如下,更詳細的資料可查閱各種文獻。 函數原型:void lcd_init(unsigned char lcd_columns) 功能:初始化LCD模塊,清屏并把顯示坐標設定在0 列0 行。LCD模塊的列必須指定(例如:16)。這時不顯示光標。在使用其它高級LCD函數前,必須先調用此函數。 函數原型:void lcd_clear(void) 功能:清屏并把顯示坐標設定在0 列0 行。 函數原型:void lcd_gotoxy(unsigned char x, unsigned char y) 功能:設定顯示坐標在x 列y行。列、行。 函數原型:void lcd_putchar(char c) 功能:在當前坐標顯示字符c 。 函數原型:void lcd_puts(char *str) 功能:在當前坐標顯示SRAM 中的字符串str 。 函數原型:void lcd_putsf(char flash *str) 功能:在當前坐標顯示FLASH 中的字符串str 。 在對LCD進行寫入顯示數據之前,需要對它進行初始化,設定顯示參數。 #include <lcd.h> /*使用PORTB連接LCD模塊*/ #asm .equ __lcd_port=0x18 ;PORTB #endasm void main(void){ //定義字符數組 uchar arr[5]; //初始化,指定列數為16 lcd_init(16); //設定顯示坐標為(0,1) lcd_gotoxy(0,1); /*在(0,1)顯示字符串,注意:此字符串存儲在Flash只讀存儲器中*/ lcd_putsf("Run Mode:"); /*調用“浮點數轉換成字符串”函數, 函數原型:void ftoa(float n, unsigned char decimals, char *str) data為浮點數*/ ftoa(data,1,arr); //設定顯示坐標為(0,2) lcd_gotoxy(0,2); //顯示RAM中字符串數組arr的內容 lcd_puts(arr); while(1); } Atmega16輸出緩沖器具有對稱的驅動特性,可以輸出和吸收大電流,直接驅動LED,但是仍然不能直接驅動更大電流的器件,如繼電器,所以必須接入較大功率的驅動器。常用的驅動方法有74系列功率集成電路驅動、MOC系列光耦合過零觸發雙向晶閘管驅動、固態繼電器驅動等。 本系統采用ULN2003芯片來驅動繼電器。其內部結構如圖2所示。 ULN2003是達林頓陣列,是專門用來驅動繼電器的芯片,甚至在芯片內部做了一個消線圈 
圖2 ULN2003內部結構圖 反電動勢的二極管。ULN2003的輸出端允許通過IC 電流200mA,飽和壓降VCE 約1V左右,耐壓BVCEO 約為36V。采用集電極開路輸出,輸出電流大,故可以直接驅動繼電器或固體繼電器(SSR)等外接控制器件,也可直接驅動低壓燈泡,共可以驅動7路,減少了電路板的連線數量,成本較低,廣泛應用于各種工控板,其驅動原理如圖3所示。 
圖3 驅動原理 壓縮機離合器繼電器采用RS觸發器和ULN2003一起控制,這樣做的好處是:當單片機受到外界干擾而不斷復位或看門狗超時復位時,保證壓縮機始終處于開啟或關閉狀態,有助于延長壓縮機的壽命。 2.4鍵盤輸入 本系統采用3×3矩陣式鍵盤。通過鍵盤可以控制系統工作方式(關閉、送風、制冷)、風向步進電機(水平送風、傾斜送風、掃風)、溫度設定等。 鍵盤的行由PD0、PD1、PD2(使能內部上拉電阻)控制,而列則由PC3、PC4、PC5控制,如圖4所示。采用程序掃描的方式識別鍵碼,其工作過程如下: PORTC&=~0x20; if((PIND&0x07)!=0x07) {//……} 首先置PC5為“0”,再判斷PD0、PD1、PD2是否都為“1”。如果全為“1”,則表明第3列無鍵按下,否則有鍵按下,進入消除抖動程序;再置PC4為“0”,再判斷PD0、PD1、PD2是否都為“1”。如果全為“1”,則表明第2列無鍵按下,否則有鍵按下,進入消除抖動程序;再置PC3為“0”,再判斷PD0、PD1、PD2是否都為“1”。如果全為“1”,則表明第1列無鍵按下,否則有鍵按下,進入消除抖動程序。 
圖4 3×3矩陣式鍵盤
- ,消除抖動。當發現有鍵按下時,延時一段時間再判斷鍵盤狀態,若仍有鍵保持按下狀態,則可以確定有鍵按下,否則認為是抖動。通過以下代碼實現:
delay(); if((PIND&0x07)!=0x07) {//……}
- 判斷鍵碼。以下是識別為“Key2-3”( 第2行第3列)的程序代碼,其它按健類似。
if((PIND&0x07)==0x05) { // Key 2-3 // uchar key_num[]="K23"; // 等待按鍵釋放 while((PIND&0x07)==0x05); //判斷換氣風機是否在運行 if(ventilator_state==1) { ventilator_state=0; //關閉換氣風機 stop_ventilator(); //在LCD上的(12,3)顯示“OFF” lcd_gotoxy(12,3); lcd_putsf("OFF"); } else { ventilator_state=1; //開啟換氣風機 start_ventilator(); //在LCD上的(12,3)顯示“Run” lcd_gotoxy(12,3); lcd_putsf("Run"); } return;//識別完畢,返回主程序 } 2.5 風向步進電機控制 Atmega16的定時器能夠輸出PWM,編程簡單,精度高。編程讓定時器2工作于相位可調模式,產生高精度的PWM波形輸出,調節占空比,以達到控制步進電機不同轉角的目的。初始化設置如下: ASSR=0x00; /* 相位可調PWM模式,比較匹配時清零OC2,計數為0xff時置位OC2 */ TCCR2=0x64; TCNT2=0x00; OCR2=0x00; TIMSK=0x80; //使能匹配中斷 
圖5 相位可調PWM 模式的時序圖 
圖6 水平送風模式下的PWM波形 
圖6 傾斜送風模式下的PWM波形 3 仿真 Proteus是目前最好的模擬單片機及外圍器件的仿真軟件,可以仿真51系列、AVR,PIC等常用的MCU及其外圍電路,如LED、LCD、RAM、ROM、鍵盤、馬達、繼電器、AD/DA、部分SPI器件、部分 器件、74系列、 COMS 4000系列芯片等。利用Proteus可以大大提高開發效率、降低投資,在沒有硬件的情況下讓開發人員能像Pspice仿真模擬/數字電路那樣仿真MCU及外圍電路。 Proteus提供的可調電阻是“十級可調”而不是“無級可調”,所以本系統采用三個可調電阻模擬Pt1000熱電阻,以實現“粗調”、“中調”、“細調”,更真實反映熱電阻阻值的細微變化。 
圖7 換氣風機、壓縮機、蒸發器風機處于工作狀態 
圖8 LCD顯示結果
4. 結語 本系統采用AVR單片機實現汽車空調的自動控制(雙位控制),具有電路結構簡單、分立元件少、系統界面友好、操作簡單等優點,能滿足一般精度要求的公交車空調的自動控制。
- /*****************************************************
- Project : 汽車空調控制系統
- Author : Benny
- Company : 509
- Comments:
- Chip type : ATmega16L
- Program type : Application
- Clock frequency : 8.000000 MHz
- Memory model : Small
- External SRAM size : 0
- Data Stack size : 256
- *****************************************************/
- #include <mega16.h>
- #include <stdlib.h>
- #include "Pt1000Tab.h"
- #include "inc.h"
- #asm
- .equ __lcd_port=0x18 ;PORTB
- #endasm
- #include <lcd.h>
- bit boolean;
- uchar ventilator_state;
- uchar fan;
- uchar blow;
- uchar run_mode;
- uchar temp;
- uchar setting_value;
- interrupt [TIM2_COMP] void timer2_comp_isr(void)
- {
- //產生PWM,控制步進電機
- if (fan==1)
- {
- OCR2=64;
- }
- else if(fan==2)
- {
- OCR2=128;
- }
- }
- #define FIRST_ADC_INPUT 0 //第一通道
- #define LAST_ADC_INPUT 1 //最后一通道 ,最大值為7,共8個通道
- unsigned int adc_data[LAST_ADC_INPUT-FIRST_ADC_INPUT+1];
- #define ADC_VREF_TYPE 0x40
- // ADC中斷服務程序
- // 自動掃描模擬量輸入端口,
- interrupt [ADC_INT] void adc_isr(void)
- {
- register static unsigned char input_index=0;
- // 讀取轉換結果
- adc_data[input_index]=ADCW;
- // 選擇轉換通道
- if (++input_index > (LAST_ADC_INPUT-FIRST_ADC_INPUT))
- input_index=0;
- ADMUX=(FIRST_ADC_INPUT|ADC_VREF_TYPE)+input_index;
- //啟動AD轉換
- ADCSRA|=0x40;
- }
- void main(void)
- {
- float current_temp;//保存當前溫度
- // Port A 初始化
- // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
- // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
- PORTA=0x00;
- DDRA=0x00;
- // Port B 初始化
- // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
- // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
- PORTB=0x00;
- DDRB=0x00;
- // Port C 初始化
- // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
- // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
- PORTC=0x38;
- DDRC=0x38;
- // Port D 初始化
- // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
- // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
- PORTD=0x1f;
- DDRD=0xF8;
- //用T2產生PWM,控制風向步進電機
- // Timer/Counter 2 initialization
- // Clock source: System Clock
- // Clock value: Timer 2 Stopped
- // Mode: Normal top=FFh
- // OC2 output: Disconnected
- ASSR=0x00;
- TCCR2=0x64;
- TCNT2=0x00;
- OCR2=0x00;
- // Timer(s)/Counter(s) Interrupt(s) initialization
- TIMSK=0x80;
- // Analog Comparator initialization
- // Analog Comparator: Off
- // Analog Comparator Input Capture by Timer/Counter 1: Off
- ACSR=0x80;
- SFIOR=0x00;
- // ADC initialization
- // ADC Clock frequency: 125.000 kHz
- // ADC Voltage Reference: AVCC pin
- // ADC Auto Trigger Source: Free Running
- ADMUX=FIRST_ADC_INPUT|ADC_VREF_TYPE;
- ADCSRA=0xEE;
- SFIOR&=0x1F;
- // LCD module初始化
- lcd_init(16);
- // 開啟全局中斷
- #asm("sei")
- dis_character();
- setting_value=25;
- run_mode=0;
- ventilator_state=0;
- lcd_gotoxy(12,3);
- lcd_putsf("OFF");
- while (1)
- {
- scan_key();
- blow_mode();
- display();
- if(run_mode==2)
- {
- current_temp=Pt1000Tab[adc_data[0]];
- if (current_temp<setting_value)
- {
- stop_compressor();
- //lcd_gotoxy(10,1);
- //lcd_putsf("Blast");
- }
- else
- {
- start_compressor();
- //lcd_gotoxy(10,1);
- //lcd_putsf("Cool");
- }
-
- }
- }
- }
- void start_compressor(void){
- //Start
- PORTD|=0x18;
-
- PORTD&=~0x10;
-
- PORTD|=0x18;
- }
- void stop_compressor(void){
- //Stop
- PORTD|=0x18;
- PORTD&=~0x08;
- PORTD|=0x18;
- }
- void start_ventilator(void) {
- PORTD|=0x40;//換氣風機運行
- }
- void stop_ventilator(void){
- PORTD&=~0x40;//換氣風機停止
- }
- void start_evaporator_fan(void){
- PORTD|=0x20;//蒸發器風機運行
- }
- void stop_evaporator_fan(void){
- PORTD&=~0x20;//蒸發器風機停止
- }
- /*-----------------------------------------------鍵盤掃描-------------------------------------------
- -----------------------------------------------鍵盤掃描-------------------------------------------*/
- void scan_key(void){
- /*
- K11 K12 K13
- K21 K22 K23
- K31 K32 K33
- */
-
- //K13 K23 K33
- PORTC&=~0x20;
- if((PIND&0x07)!=0x07)
- {
- delay();
- if((PIND&0x07)!=0x07)
- {
- if((PIND&0x07)==0x06)
- { //Key 3-3
- //uchar key_num[]="K33";
- while((PIND&0x07)==0x06);
- switch(blow)
- {
- case 0:
- {
- blow=1;
- lcd_gotoxy(10,2);
- lcd_putsf("Mode0");
- break;
- }
- case 1:
- {
- blow=2;
- lcd_gotoxy(10,2);
- lcd_putsf("Mode1");
- break;
- }
- case 2:
- {
- blow=3;
- lcd_gotoxy(10,2);
- lcd_putsf("Mode2");
- break;
- }
- case 3:
- {
- blow=0;
- lcd_gotoxy(10,2);
- lcd_putsf("Mode3");
- break;
- }
- }
- return;
- }
- if((PIND&0x07)==0x05)
- { //Key 2-3
- //uchar key_num[]="K23";
- while((PIND&0x07)==0x05);
-
- if(ventilator_state==1)
- {
- ventilator_state=0;
- stop_ventilator();
- lcd_gotoxy(12,3);
- lcd_putsf("OFF");
- }
- else
- {
- ventilator_state=1;
- start_ventilator();
- lcd_gotoxy(12,3);
- lcd_putsf("Run");
- }
- return;
- }
- if((PIND&0x07)==0x03)
- { //Key 1-3
- //uchar key_num[]="K13";
- while((PIND&0x07)==0x03);
- switch(run_mode)
- {
- case 2:
- { //關閉模式
- stop_evaporator_fan();
- stop_compressor();
- lcd_gotoxy(10,1);
- lcd_putsf("OFF ");
- run_mode=0;
- break;
- }
- case 0:
- {
- //送風模式
- start_evaporator_fan();
- stop_compressor();
- lcd_gotoxy(10,1);
- lcd_putsf("Blast");
- run_mode=1;
- break;
- }
- case 1:
- {
- //制冷模式
- start_evaporator_fan();
- start_compressor();
- lcd_gotoxy(10,1);
- lcd_putsf("Cool ");
- run_mode=2;
- break;
- }
- }
-
- return;
- }
- }
- }
- PORTC|=0x20;
- //K12 K22 K32
- PORTC&=~0x10;
- if((PIND&0x07)!=0x07)
- {
- if((PIND&0x07)==0x06)
- { //Key 3-2
- //uchar key_num[]="K32";
- while((PIND&0x07)==0x06);
- return;
- }
- if((PIND&0x07)==0x05)
- { //Key 2-2
- //uchar key_num[]="K22";
- while((PIND&0x07)==0x05);
- if (setting_value<=18)
- {
- setting_value=18;
- }
- else
- {
- setting_value--;
- }
-
- return;
- }
- if((PIND&0x07)==0x03)
- { //Key 1-2
- //uchar key_num[]="K12";
- while((PIND&0x07)==0x03);
- if (setting_value>=28)
- {
- setting_value=28;
- }
- else
- {
- setting_value++;
- }
- return;
- }
- }
- PORTC|=0x10;
- //K11 K21 K31
- PORTC&=~0x08;
- if((PIND&0x07)!=0x07)
- {
- delay();
- if((PIND&0x07)!=0x07)
- {
- if((PIND&0x07)==0x06)
- { //Key 3-1
- //uchar key_num[]="K31";
- while((PIND&0x07)==0x06);
- return;
- }
- if((PIND&0x07)==0x05)
- { //Key 2-1
- //uchar key_num[]="K21";
- while((PIND&0x07)==0x05);
- return;
- }
- if((PIND&0x07)==0x03)
- { //Key 1-1
- //uchar key_num[]="K11";
- while((PIND&0x07)==0x03);
- return;
- }
- }
- }
- PORTC|=0x08;
- }
- void blow_mode(void){
- switch(blow)
- {
- case 0:
- {
- fan=0;
- break;
- }
- case 1:
- {
- fan=1;
- break;
- }
- case 2:
- {
- fan=2;
- break;
- }
- case 3:
- {
- temp++;
- if(temp==5)
- {
- boolean=~boolean;
- }
- if (boolean==1)
- {
- fan=1;
- }
- else
- {
- fan=2;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
全部資料51hei下載地址:
基于AVR單片機的汽車空調控制系統資料.rar
(432.45 KB, 下載次數: 98)
2018-9-17 10:26 上傳
點擊文件名下載附件
|