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;i 0;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