www.pudn.com > Tem_main.rar > Tem_main.c


#include 
////////////////////////////////////////////// 
////////////////////////////////////////////// 
#define NOP() asm(" nop") 
 
#define lcd_data_port P4OUT 
#define lcd_data_ddr P4DIR 
#define lcd_busy_pin P4IN 
#define lcd_busy_ddr P4DIR  
#define lcd_control_port P3OUT  
#define lcd_control_ddr P3DIR 
 
#define lcd_RS 0x20     
//PORTD^0  
#define lcd_RW 0x40     
//PORTD^1  
#define lcd_EN 0x80    
//PORTD^2  
#define busy 0x80     
//LCD_DB7-PORTB^2  
 
 
//88888888888888888888888888888888888888888888888888888888888888888 
 
//8888888888888888888888888888888888888888888888888888888888888888888 
/*----------------------------------函数声明------------------------------------------*/  
void lcd_init_portCD(void);  
void lcd_init(void);  
void lcd_write_command(unsigned char command,unsigned char wait_en);  
void lcd_write_data(unsigned char char_data);  
void wait_enable(void);  
void lcd_set_xy( unsigned char x, unsigned char y );  
void display_a_char(unsigned char x,unsigned char y,unsigned char char_data);  
void display_a_string(unsigned char x,unsigned char y,unsigned char *ptr);  
void delay_1ms(void );  
void delay_nms(unsigned int n) ;  
 
//显示的两行字符  
 
 
/*------------------------------------主函数------------------------------------- 
 
void main(void)  
{  
   lcd_init_portCD();  
   lcd_init();  
   
   //display_a_char(8,0,'s'); 
    
//   display_a_string(1,str2);  
    
}  
 
*/ 
/**********************************************************  
光标命令  
lcd_write_command(0x0e,0);//光标开  
lcd_write_command(0x0d,0);//光标所在字符闪烁    
lcd_write_command(0x0c,0); //光标关   
**********************************************************/  
 
/*------------------------------------液晶驱动函数-------------------------------------*/  
void lcd_init_portCD(void)  
{  
    lcd_data_port=0xFF;  
   lcd_data_ddr=0xff;  
   lcd_control_port=0xE0;  
   lcd_control_ddr=0xE0;  
}  
 
//液晶初始化  
void lcd_init(void)  
{  
   delay_nms(15);  
   lcd_write_command(0x38,0);//显示模式设置三次(此时不管lcd空闲与否)  
   delay_nms(5);  
   lcd_write_command(0x38,0);  
   delay_nms(5);  
   lcd_write_command(0x38,0);  
   delay_nms(5);  
     
   lcd_write_command(0x38,1);//显示模式设置(从此之后均需lcd空闲)  
   lcd_write_command(0x08,1);//显示关闭  
   lcd_write_command(0x01,1);//显示清屏  
   lcd_write_command(0x06,1);//显示光标移动设置  
   lcd_write_command(0x0C,1);//显示开及光标设置  
}  
 
//写指令函数: E=高脉冲 RS=0 RW=0  
void lcd_write_command(unsigned char command,unsigned char wait_en)//command为指令,wait_en指定是否要检测LCD忙信号  
{  
   if(wait_en)wait_enable();//若wait_en为1,则要检测LCD忙信号,等待其空闲  
   lcd_control_port&=~lcd_RS;//RS=0  
   lcd_control_port&=~lcd_RW;//RW=0  
   lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲  
   NOP();  
   lcd_control_port|=lcd_EN;//E=1  
   lcd_data_port=command;  
   lcd_control_port&=~lcd_EN;//重设E=0  
}  
 
//写数据函数: E =高脉冲 RS=1 RW=0  
void lcd_write_data(unsigned char char_data)  
{  
   wait_enable();//等待LCD空闲  
   lcd_control_port|=lcd_RS;//RS=1  
   lcd_control_port&=~lcd_RW;//RW=0  
   lcd_control_port&=~lcd_EN;//E=0,下面给LCD一个高脉冲  
   NOP();  
   lcd_control_port|=lcd_EN;//E=1  
   lcd_data_port=char_data;  
   lcd_control_port&=~lcd_EN;//重设E=0  
}  
 
//正常读写操作之前必须检测LCD控制器状态:E=1 RS=0 RW=1;DB7: 0 LCD控制器空闲,1 LCD控制器忙。  
//检测忙信号,等待LCD空闲函数  
void wait_enable(void)  
{  
   lcd_busy_ddr&=~busy;//设置busy口为输入  
   lcd_control_port&=~lcd_RS;//RS=0  
   lcd_control_port|=lcd_RW;//RW=1  
   NOP();  
   lcd_control_port|=lcd_EN;//E=1  
   while(lcd_busy_pin&busy);//等待LCD_DB7为0  
   lcd_control_port&=~lcd_EN;//重设E=0  
   lcd_busy_ddr|=busy;//设置busy口为输出  
}  
/**LCD_set_xy:设置LCD显示的起始位置输入参数:x、y :   
                    显示字符串的位置,X:0-15,Y:0-1  
                    LCD第一行显示寄存器地址:0X80-0X8F  
                    LCD第一行显示寄存器地址:0XC0-0XCF   ***/  
void lcd_set_xy( unsigned char x, unsigned char y )  
{  
    unsigned char address;  
    if (y == 0)   
       address = 0x80 + x;  
    else   
        address = 0xc0 + x;  
    lcd_write_command(address,1);//一定需要检查忙信号,所以为1  
}  
//显示一个字符函数  
void display_a_char(unsigned char x,unsigned char y,unsigned char char_data)//char_data为要显示的字符  
{  
    lcd_set_xy(x,y);  
    lcd_write_data(char_data);  
}  
 
//指定一行显示连续字符串:0显示在第一行,1显示在第二行,注字符串不能长于16个字符  
//显示一行连续字符串函数  
 
void display_a_string(unsigned char x,unsigned char y,unsigned char *ptr)  
{  
//ptr:指向无符号字符型变量的指针变量,指针也就是地址,指字符串数组的首指针  
    lcd_set_xy(x,y);  
   while(*ptr)//当ptr='\0'(空指针null)跳出循环  
    {  
     lcd_write_data(*ptr);//*ptr,指向该地址的内容  
     ptr++;  
    }  
}  
 
/*---------------------------------------延时函数-------------------------------------*/  
void delay_1ms(void )  //延时1ms  
{  
   unsigned int i ;  
  
   for (i=1;i<570;i++); 
    
     
}  
 
void delay_nms(unsigned int n)  //延时nms  
{  
   unsigned int i=0 ;   
   for(i=0;i0;iq0--);                  //延时,等待XT2起振 
   } 
   while((IFG1&OFIFG)!=0); 
    
   BCSCTL2|=SELS+DIVS_3;//选择XT2CLK作为SMCLK的时钟源,8分频                  
   //_EINT();                             //打开全局中断控制 
  } 
  ///////////////////////////////////////////// 
  //////////定时中断初始化//////////////// 
  ///////////////////////////////////////////// 
  void Timer_A_init(void) 
  { 
   TACTL|=TASSEL_2+TACLR;// 
   //TACCTL0=CCIE;//允许定时中断 
   //CCR0=10000;  //定时1 微秒 
   TACTL|=MC_1; //增计数模式 
   _EINT();                                   
  } 
  ////////////////////////////////////////////////// 
  /////////////////////////////////////////////// 
  //////////////  外部中断初始化//////////////////// 
  ///////////////////////////////////////////////// 
  void Init_IE() 
{ 
  P2SEL=0; 
  P2IES|=BIT0; 
  P2DIR&=~BIT0; 
  P2IE|=BIT0; 
  P2IFG=0; 
   
  } 
  ////////////////////////////////////////////////////// 
  ///////////////////AD转换初始化////////////////////////// 
///////////////////////////////////////////////////////// 
void AD_change_init(void) 
{ 
     ADC12CTL0 &=~ 0X0002; //ENC=0; 
      
     ADC12CTL0 |=  0X00f0;  //开4 5 6 7  位  
      
     ADC12CTL0 |=  0x3300; //设置采样时间 
      
     ADC12CTL1 |=  0x0204; //单通道重复模式 
      
     ADC12CTL1 |=  0x0010; //mclk 1 分频  
                
     ADC12MCTL0 |=  0X05;//选择通道5 
      
     ADC12MCTL0 |=  0X90; 
          
     ADC12CTL0 |= 0X0001; 
      
     ADC12CTL0 |= 0X0002; //ENC=1; 
      
     ADC12CTL0 |= 0X0001; 
     
} 
////////////////////////////////////////////////////////////////// 
////////////////////////////////////////////////////////////////// 
////////////////////////////////////////////////////////////////// 
void IO_init() 
{ 
    P3DIR|=BIT3; 
} 
/////////////////////////////// 
//////////////////////////////// 
unsigned int dii=0; 
unsigned char chuan,number[]={'0','1','2','3','4','5','6','7','8','9'}; 
unsigned int data_200[200]={0},data_i=0,data_j=0;  
unsigned char a,b,c,d,e,l,o,v; 
unsigned int up_l,key3,key4,key5,j=0,i=0,k=0,down_r,key1,key2,ad_x=0; 
unsigned int timer_ccr0=0; 
long AD_X=0; 
unsigned int p2int_x=0,pid_en=0; 
unsigned int tmp_number=0; 
//===================================================================== 
int Error;//Error为当前误差值 
int Pre_Error;//Error为当前一次误差值 
int Set_Value;//SetValue 为设定值 
int Real_Value;//RealValue 为测量值 
int Int_Value;//为积分值 
int Der_Value;//为微分值 
int ControlValue;//PID输出控制值 
int Int_Value_SPL=0;//积分上限 
int Int_Value_SPH=5000;//积分下限 
//==================================================================== 
 
///////////////////////////////////////////////////////////////////////// 
//////////////////////////////////////////////////////////////////////// 
void key(void) 
{ 
    if((P1IN&BIT3)==0x00) 
    { 
       for(i=0;i<=10000;i++); 
       if((P1IN&BIT3)==0x00) 
       { 
         key3=key3+1; 
         while(key3>9) 
         key3=0; 
       } 
    } 
     
    if((P1IN&BIT4)==0x00) 
    { 
       for(i=0;i<=10000;i++); 
       if((P1IN&BIT4)==0x00) 
       { 
         key4=key4+1; 
         if(key4>9) 
         { 
         key4=0; 
         } 
       } 
    } 
     
    if((P1IN&BIT1)==0x00) 
    { 
      for(i=0;i<=10000;i++); 
       
      if((P1IN&BIT1)==0x00) 
      { 
        data_j++; 
        //key1=key1+1; 
        //while(key1>200) 
        //key1=0; 
      } 
    } 
     
    if((P1IN&BIT2)==0x00) 
    { 
      for(i=0;i<=10000;i++); 
       
      if((P1IN&BIT2)==0x00) 
      { 
        //P6OUT^=BIT7; 
        key2=key2+1; 
        if(key2>9) 
         { 
         key2=0; 
         } 
      } 
    } 
     
   if((P1IN&BIT5)==0x00) 
    { 
      for(i=0;i<=10000;i++); 
       
      if((P1IN&BIT5)==0x00) 
      { 
        //P6OUT^=BIT7; 
        key5=key5+1; 
        if(key5>2) 
         { 
         key5=0; 
         } 
      } 
    }  
} 
////////////////////////////////////////////////////// 
/////////////    PID控制    //////////////////// 
////////////////////////////////////////////////////// 
void PID(int Kp,int Ki,int Kd)//Ki为积分增益   Kd为微分增益    Kp比例增益 
{ 
 Error=Set_Value-Real_Value;//比例项调幅度 
 Der_Value=Error-Pre_Error;//微分调节的速度 
 Int_Value=Int_Value+Error;//积分消除温态误差 
  
 if(Int_Value>=Int_Value_SPH)//积分上限保护 
 { 
   Int_Value=Int_Value_SPH; 
 } 
 if(Int_Value<=Int_Value_SPL)//积分下限保护 
 { 
   Int_Value=Int_Value_SPL; 
 } 
  
 ControlValue=Kp*Error+Ki*Int_Value+Kd*Der_Value;//PID输出控制值 
 Pre_Error=Error;//下一次抽样用 
  
 if(ControlValue>=9200)//最大输出保护 
 { 
  ControlValue=9200; 
 } 
 
 if(ControlValue<=0)//最小限制 
 { 
 ControlValue=0; 
 } 
  
 
} 
/////////////////////////////////////////////////////////////////////////// 
/////////////////////////////////////////////////////////////////////////// 
/****************************************************************************/ 
//****************************主函数****************************************** 
//×××××××××××××××××××××××××××××××××××××× 
////////////////////////////////////////////////////////////////////////////// 
main() 
{ 
    
   WDTCTL= WDTPW + WDTHOLD;//记得加 
   InitSys(); 
   Init_IE(); 
   Timer_A_init();  
   lcd_init_portCD();  
   lcd_init();  
   lcd_init();   
   AD_change_init(); 
   IO_init(); 
   for(;;) 
   {  
    
 
       key(); 
       AD_X+= ADC12MEM0; 
       ad_x++; 
       if(ad_x==100) 
       { 
         ad_x=0; 
         tmp_number = AD_X/100; 
          
          
         AD_X=0; 
       } 
    
         
          up_l =tmp_number*6; 
	  a = up_l/10000; 
          b = up_l%10000/1000; 
          c = up_l%1000/100; 
          d = up_l%100/10; 
          e = up_l%10; 
          display_a_char(8,0,number[a]);  
          display_a_char(9,0,number[b]);  
          display_a_char(10,0,number[c]);  
          display_a_char(11,0,'.'); 
          display_a_char(12,0,number[d]); 
          display_a_char(13,0,number[e]); 
          //display_a_string(0,0,"Now Tem:"); 
          display_a_string(0,1,"SetTem:"); 
           
           
          a = data_200[data_j]/10000; 
          b = data_200[data_j]%10000/1000; 
          c = data_200[data_j]%1000/100; 
          d = data_200[data_j]%100/10; 
          e = data_200[data_j]%10; 
          display_a_char(0,0,number[a]);  
          display_a_char(1,0,number[b]);  
          display_a_char(2,0,number[c]);  
          display_a_char(4,0,number[d]); 
          display_a_char(5,0,number[e]); 
          display_a_char(3,0,'.'); 
           
           
           
          a = key5; 
          b = key4; 
          c = key3; 
          d = key2; 
          e = key1; 
          display_a_char(8,1,number[a]);  
          display_a_char(9,1,number[b]);  
          display_a_char(10,1,number[c]);  
          display_a_char(12,1,number[d]); 
          display_a_char(13,1,number[e]); 
          display_a_char(11,1,'.'); 
           
          if(pid_en==1) 
          { 
            Set_Value=(key5*10000+key4*1000+key3*100+key2*10)/6; 
            Real_Value=tmp_number; 
            PID(5,1,30); 
            pid_en=0; 
            if(Set_Value<=Real_Value) 
            {ControlValue=0;} 
          } 
          timer_ccr0=9210-ControlValue; 
           
   } 
   _EINT(); 
} 
 
///////////////////////////////////////////////////////////////// 
//////////////定时中断/////////////////// 
///////////////////////////////////////////////////////////////// 
#pragma vector=TIMERA0_VECTOR  
__interrupt void Timer_A(void) 
  {    
      P3OUT|=BIT3; 
      TACCTL0&=~CCIE;//禁止定时中断 
      _EINT();  
      return; 
  } 
  ////////////////////////////////////////////////////////// 
  ////////////////////////////////////////////////////////// 
  ///////////////////////外部中断、、、、、、、、、、、、、、 
  #pragma vector=PORT2_VECTOR 
__interrupt void Port2(void) 
{ 
    
     if((P2IFG&BIT0)==BIT0) 
     {   
        P3OUT&=~BIT3; 
        TACTL|=TACLR;//定时器清零 
        if(ControlValue==0) 
        { timer_ccr0=0;} 
        CCR0=timer_ccr0;///定时中断值100