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

📄 pc temperature control .c

📁 gps.c:GPS主代码 constant.h:GPS的头文件 PC temperature control .c:电脑温度控制 code.c:数字血压计的代码 Computer side.c
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// Cornell 2005
// Edward Lo and Sihan Goi
// ECE476 final project
// Temperature sensor and fan controller
//
#include <mega32.h> 
#include <stdio.h>
#include <string.h>       
#include <delay.h>

//number of supported fans
#define MAXFAN 2

//wireless packet definitions (maintain DC balance)
#define start_packet 0b10100110
#define stop_packet  0b11010010

//timeout values for each task
#define t1 20000   //Update LCD
#define t2 20000   //Hyperterminal display
#define t3 1000    //Hyperterminal input
#define t4 500     //Read temperature
#define t5 100     //Adjust fan speed
#define t6 5000    //PWM pulse stretching

//values for temperature calibration
#define inittemp  0.76
#define roomtemp  72.0
#define opampGain 4.00
#define Arefvolt  5.09

//other thresholds
#define t_lockedrotor 5  //when a fault occurs for this many cycles, the user is notified

//conversion macros
#define getTemp(input) ((float)(roomtemp +( ((float)((float)input-fproomtemp)/255.0)*Arefvolt/(0.01 * opampGain) )))
#define getRpm(input)  ((unsigned int)(60000.0 / (((float)input/10.0) * tachdivider)))

//I like these definitions
#define begin {
#define end   }
#define LCDwidth 16 //characters

//lcd definitions
#asm
    .equ __lcd_port=0x15
#endasm
#include <lcd.h> // LCD driver routines

enum { pwm, dac, off };        //fan mode
enum { user, auto };           //opmode
enum { wireless, computer };   //inputmode
enum { start, data, stop };    //wireless data packets

//variables
unsigned char i;                                                    //local counter
unsigned char j;                                                    //counter in ISR
unsigned char opmode, inputmode, fanmode[MAXFAN];                   //operation modes
unsigned int  counttime, time1, time2, time3, time4, time5, time6;  //task scheduling timeout counters

//wireless stuff
unsigned char rstate;  //receive state
unsigned char datain;  //data from serial in

//lcd stuff
unsigned char lcddispnum;     //remembers which fan we are displaying status for
char          lcd_buffer[17]; //LCD display buffer

//alarm stuff
unsigned char f_alarm, f_alarmsound;  //flags to determine if an alarm should light and sound

//temperature sensing stuff
unsigned char sensornum;            //remembers which temperature sensor we are currently reading from
unsigned char tempsensor[MAXFAN];   //temperature reading from ADC register
unsigned char t_mintemp[MAXFAN];    //minimum temperature threshold when fan turns on
unsigned char t_alarmtemp[MAXFAN];  //maximum temperature threshold when alarm sounds
float fpcurrtemp[MAXFAN];           //current temperature
float t_fpmintemp[MAXFAN];          //min threshold temperature
float t_fpalarmtemp[MAXFAN];        //max threshold temperature
float fproomtemp;                   //room temperature (for calibration)
float fpmaxtemp;                    //temporary variable for calculating fan speed

//fan tachometer detection stuff
int           tachhi[MAXFAN];        //counts time spent in high phase of tach pulse
int           tachlo[MAXFAN];        //counts time spent in low phase of tach pulse
unsigned char rpmsensor[MAXFAN];     //holds current tach pulse value
unsigned char f_readrpm[MAXFAN];     //flag to read rpm
unsigned char f_tachphase[MAXFAN];   //flag to remember which phase of the tach pulse we are in
unsigned char f_lockedrotor[MAXFAN]; //flag to detect a locked rotor
unsigned int  rpm[MAXFAN];           //holds the calculated rpm of a fan
float         tachdivider;           //adjust for each fan - pulses per revolution

//pwm and dac stuff
unsigned char dacout;    //holds dac value (0-15)
unsigned char pwmspeed;  //holds pwm duty cycle (0-255)
unsigned char pwmcnt;    //specifically for fan 2 rpm detection
float         fanspeed;  //speed to drive fan at: 1.0 = 100% power, 0.0 = 0% power

//keyboard input stuff
char         cmd;
unsigned int val1;

//RXC ISR variables
unsigned char r_index;          //current string index
unsigned char r_buffer[90];     //input string 
unsigned char r_ready;          //flag for receive done
unsigned char r_char;           //current character  

//TX empth ISR variables
unsigned char t_index;          //current string index
unsigned char t_buffer[90];     //output string 
unsigned char t_ready;          //flag for transmit done
unsigned char t_char;           //current character

//the subroutines
void gets_int(void);            //starts getting a string from serial line
void puts_int(void);            //starts a send to serial line
void initialize(void);          //all the usual mcu stuff 

//scheduled tasks
void DispScreen(void);
void DispLCD(void);
void ReadTemp(void);
void Sysadmin(void);
void AdjustFanSpeed(void);
void PWMPulseStretch(void);


//**********************************************************
//timer 2 comparison ISR
//  This ISR ticks down the timers used to run scheduled tasks.
//  It generates the square wave for the piezo buzzer when an alarm should sound.
//  It reads the tachometer pulses from the fans and detects rpm.
//  It detects locked fan rotors based on the behaviour of the tach pulses
interrupt [TIM2_COMP] void timer2_compare(void)
begin
  //Decrement the scheduler times if they are not already zero
  if (time1>0)  --time1;
  if (time2>0)  --time2;
  if (time3>0)  --time3;
  if (time4>0)  --time4;
  if (time5>0)  --time5;
  if (time6>0)  --time6;
  
  //generates square wave for the alarm
  if( counttime-- == 0 ) {
    if( f_alarmsound ) PORTD.5 ^= 1;
    counttime = 10;
  }

  //turn off pwm mode pulse stretching after getting tachometer reading
  if( (fanmode[1] == pwm) && (pwmcnt == 3) ) {
    TCCR0 = 0b01101011;  //resume normal pwm mode
    f_readrpm[1] = 0;    //don't read rpm anymore
  }

  //cycle through each fan and get rpm data
  for( j = 0; j < MAXFAN; j++ ) {
    //get rpm sensor reading
    rpmsensor[j] = (PINA >> (j+4)) & 0x1;

    //sample tachometer pulses
    if( f_readrpm[j] == 1 ) {
      //tachometer pulse is HIGH
      if (rpmsensor[j] == 1) {
        f_tachphase[j] = 1;
        if (tachhi[j] > 600) f_lockedrotor[j] = t_lockedrotor;  //rotor is locked in place
        tachhi[j]++;                                            //counts in 0.1ms intervals
      }
      //tachnometer pulse is LOW
      else {
        //check for falling edge
        if (f_tachphase[j] == 1) {
          //check for locked rotor here! (check if time difference between phases is > factor of 3)
          if( ((tachhi[j]-tachlo[j]) > (3*tachlo[j])) && (f_lockedrotor[j] < t_lockedrotor) ||
              ((tachlo[j]-tachhi[j]) > (3*tachhi[j])) && (f_lockedrotor[j] < t_lockedrotor) ) {
            f_lockedrotor[j]++;
          }
          else {
            //rotor operating normally
            f_lockedrotor[j] = 0;
          
            //pwm fan 2
            if( fanmode[j] == pwm ) pwmcnt++;  //for pwm pulse stretching, count number of cycles
          }
      
          if( fanmode[j] == pwm ) {
            if( pwmcnt == 3 ) rpm[j] = getRpm(tachlo[j]);  //converts ms to rpm
          }
          else {
            rpm[j] = getRpm(tachlo[j]);  //converts ms to rpm
          }
          tachhi[j] = 0;               //reset for counting next cycle
          tachlo[j] = 0;               //reset for counting next cycle
        }
        f_tachphase[j] = 0;
        if (tachlo[j] > 600) f_lockedrotor[j] = t_lockedrotor;  //rotor is locked in place
        tachlo[j]++;                                            //counts in 0.1ms intervals
      }
    }
    
  }  //for loop
  
end  


//**********************************************************
//UART character-ready ISR
interrupt [USART_RXC] void uart_rec(void)
begin
    r_char=UDR;    //get a char

    //computer input mode
    if( inputmode == computer ) {
      UDR=r_char;    //then print it
      //build the input string
      if (r_char != '\r') r_buffer[r_index++]=r_char;
      else
      begin
        putchar('\n');          //use putchar to avoid overwrite
        r_buffer[r_index]=0x00; //zero terminate
        r_ready=1;              //signal cmd processor
        UCSRB.7=0;              //stop rec ISR
      end
    }

    //wireless input mode
    else {
      if( (rstate == start) && (r_char == start_packet) ) {
        rstate = data;
      }
      else if( rstate == data ) {
        datain = r_char;
        rstate = stop;
      }
      else if( (rstate == stop) && (r_char == stop_packet) ) {
        rstate = start;  
      }
      else {
        rstate = start;
      }
   }
end

/**********************************************************/
//UART xmit-empty ISR
interrupt [USART_DRE] void uart_send(void)
begin
    t_char = t_buffer[++t_index];
    if (t_char == 0) 	
    begin
      UCSRB.5 = 0;     //kill isr 
      t_ready = 1;     //transmit done 
    end
    else UDR = t_char; //send the char 
end


//********************************************************** 
//  -- non-blocking keyboard check initializes ISR-driven
// receive. This routine merely sets up the ISR, which then
// does all the work of getting a command.
void gets_int(void) 
begin
  memset(r_buffer,0x00,90);
  r_ready = 0;
  r_index = 0;
  UCSRB.7 = 1;
end


//********************************************************** 
//  -- nonblocking print: initializes ISR-driven
// transmit. This routine merely sets up the ISR, then
// send one character. The ISR does all the work.   
void puts_int(void) 
begin
  t_ready = 0;
  t_index = 0;
  if (t_buffer[0]>0) 
  begin
    putchar(t_buffer[0]);
    UCSRB.5=1;
  end 
end


//**********************************************************       
//Entry point and task scheduler loop
//  Handles mux selection, alarm and lights, and operation modes.
//  Calls various task timers based on the timeout counters.
void main(void)
begin  
  initialize();

  //main task scheduler loop -- never exits!
  while(1)
  begin     
    if (time1==0)	DispLCD();         //display system status on LCD
    if (time2==0)	DispScreen();      //display information on terminal
    if (time3==0)	Sysadmin();        //gets input from keyboard
    if (time4==0)	ReadTemp();        //reads temperature sensors
    if (time5==0)	AdjustFanSpeed();  //adjusts fan speeds
    if (time6==0)	PWMPulseStretch(); //sets PWM to max for rpm detection

    //wireless or computer mode?
    inputmode = PINB.1;

    //mux output
    PORTB.0 = opmode;
    PORTB.2 = inputmode;

    //alarm system
    f_alarm = 0;
    for( i = 0; i < MAXFAN; i++ ) {
      if( (fanmode[i] != off) &&
          ((fpcurrtemp[i] > t_fpalarmtemp[i]) ||
          ((fpcurrtemp[i] > t_fpmintemp[i]) && (f_lockedrotor[i] == t_lockedrotor))) ) {
        f_alarm = 1;
        break;
      }
    }
    f_alarmsound = f_alarm;
    PORTD.4      = f_alarm;  //alarm status light

    //status lights
    PORTD.2 = (opmode == auto);
    PORTD.3 = (inputmode == wireless);

    //manual mode
    if( opmode == user ) {
      TCCR0   = 0;
      PORTB.3 = 1;       //drive PWM at full power to maintain rpm detection
      PORTA.2 = 1;       //enable fan 2 so it will spin
      f_readrpm[0] = 1;  //continue rpm detection
      f_readrpm[1] = 1;  //continue rpm detection
      pwmcnt  = 0;       //so interrupt will always read rpm
    }

    //auto mode
    if( opmode == auto ) {
      //fan 2 (pwm fan)
      if( (fanmode[1] != off) && (fpcurrtemp[1] > t_fpmintemp[1]) ) {
        // turn on fan
        if( f_readrpm[1] == 0 ) {
          OCR0 = pwmspeed;   //only set PWM speed if rpm is not being detected
        }
        TCCR0 = 0b01101011;  //clear OC0 on upcount
      }
      else {
        // turn off fan
        OCR0    = 0;
        TCCR0   = 0;
        PORTB.3 = 0;         //don't drive PWM  
        rpm[1]  = 0;
        f_lockedrotor[1] = 0;
      }

      //fan1 (dac fan)
      if( (fanmode[0] != off) && (fpcurrtemp[0] > t_fpmintemp[0]) ) {
        PORTA.2 = 1;         //enable fan
      }
      else {
        PORTA.2 = 0;         //disable fan
        rpm[0]  = 0;
        f_lockedrotor[0] = 0;
      }

      //output dac value to port B
      PORTB = PINB & 0x0f | (dacout << 4);
    }

    //wireless input
    if( inputmode == wireless ) {
      switch( datain ) {
        case 0b11000010: t_fpmintemp[0] += 1.0; break;
        case 0b10100010: t_fpmintemp[0] -= 1.0; break;
        case 0b10010010: t_fpmintemp[1] += 1.0; break;
        case 0b10001010: t_fpmintemp[1] -= 1.0; break;
        case 0b10000110: opmode ^= 1;
                           if( opmode == auto ) f_readrpm[1] = 0;
                           break;
      }
      datain = 0;  //clears received data
    }
  end   
end  


//**********************************************************          
//Adjusts fan speeds
//  This function uses the temperature detected from the sensors
//  and adjusts the fan speed accordingly. It assumes linear ramping.
//  The percentage of power to use is stored in 'fanspeed'.
void AdjustFanSpeed(void) 
begin
  time5=t5;

  for( i = 0; i < MAXFAN; i++ ) {
    //get percentage of max speed to use
    fpmaxtemp = (t_fpalarmtemp[i] - t_fpmintemp[i]) * 0.75;
    fanspeed = (fpcurrtemp[i] - t_fpmintemp[i]) / fpmaxtemp;

    //pwm adjustment (fan 2)
    if( i == 1 ) {
      if( fanspeed >= 1.0 ) {
        pwmspeed = 255;
      } else if( fanspeed <= 0 ) {
        pwmspeed = 0;
      } else {
        pwmspeed = (unsigned char)( fanspeed * 255.0 );
      }
    }

    //4 bit DAC adjustment (fan 1)
    if( i != 1 ) {
      if( fanspeed >= 1.0 ) {
        dacout = 15;
      } else if( fanspeed <= 0 ) {
        dacout = 0;
      } else {
        dacout = (unsigned char)( fanspeed * 15.0 );
      }
    }
  }

⌨️ 快捷键说明

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