#include "msp430g2553.h"
typedef unsigned char u8; //數據類型定義
typedef unsigned int u16;
typedef unsigned long u32;
float T_diff1 = 0 ; //定義積分環節參數
float T_diff2[10] ; //定義微分環節參數
float T_diff3 = 0;
#define SID_1 P1OUT |=BIT0 //串行數據傳輸P1.0
#define SID_0 P1OUT &=~BIT0
#define SID_IN_1 P1IN
#define CLK_1 P1OUT |=BIT3 //串行時鐘P1.2
#define CLK_0 P1OUT &=~BIT3
#define KM_S (P2IN&BIT4) //主菜單鍵 P2.4
#define KM_SSDOWN (P2IN&BIT5) //功能下選鍵 P2.5
#define KM_SSUP (P2IN&BIT3) //功能上選鍵 P2.3
#define KM_SURE (P2IN&BIT2) //確認鍵 P2.2
#define KM_RETURN (P2IN&BIT0) //返回鍵 P2.0
#define SCLK_UP P2OUT |= BIT0
#define SCLK_DOWN P2OUT &= ~BIT0
#define SYNC_UP P1OUT |= BIT4
#define SYNC_DOWN P1OUT &= ~BIT4
#define SDIN_UP P1OUT |= BIT5
#define SDIN_DOWN P1OUT &= ~BIT5
u8 M_S ; //全局變量M_S功能選擇函數入口
u8 MM_S ; //功能選定結果
u16 ADC_Result; //AD轉換的結果
u8 Number[10] ={"0123456789"};
u32 time1 = 0,time2 = 0; //計時變量
float T_real = 0; //當前值
float T_target = 0; //目標值
float T_diff = 0; //誤差
float f;
float T ;
float c;
float last = 0;
u8 DA_ON[4]={0,0,0,1};
u8 time11 = 0;
u8 flag =0;
u8 CHANGE = 0; //子菜單功能切換變量
u8 M_S1; //全局變量子菜單入口
u8 MM_S1; //子菜單功能選擇結果
u8 MM_S2; //子菜單2功能選擇結果
u16 ADC_RESULT1; //ADC轉換結果
u8 GO = 0;
u8 GO1 = 0;
u8 FANHUI; //記錄上級菜單最后選定結果
u8 FANHUI1; //記錄二級菜單中最后選定結果
u8 FANHUI2; //溫度二級菜單中的最后選定結果
float TEMPE ; //溫度變量
u16 _ADC;
signed int TARGET; //目標溫度
float TEMPE1; //溫度轉換變量
u8 HOW_A; //程控增益基礎篇增益選擇變量
u8 HOW_A1; //程控增益提高篇增益選擇變量
void delay(u16 t); //延時函數
void Send_Byte(u8 data); //串行發送8位數據
void Write_CMD(u8 CMD); //寫命令函數
void Write_DATA(u8 DATA); //寫數據函數
void LCD12864_Init(void); //LCD初始化函數
void print_string(u8 *s); //顯示字符串函數
void Init_port(void) ; //msp430管腳初始化函數
void LCD_write_char(u8 X,u8 Y,u8 data); //在屏幕任意位置寫字符函數
void Menu_LCDshow(u8 HOW); //LCD12864顯示菜單函數
void Menu_Init(void); //菜單初始化函數
void ADC_Init(void); //ADC初始化函數
void ADC_Run(void); //ADC運行函數
void LCD_set_xy( u8 x, u8 y ); //設置LCD12864上顯示的位置
void Time_Init(void); //LCD12864上顯示時鐘函數
void RES_show(void);
void Time_change(void);
void Miaobiao(void);
void Daojishi(void);
void Time_choose(u8 HOW);
u16 ADC_LVBO(void);
void game_play(void);
void delay_(u32 time);
u16 PID_Run(float Target); //PID運算函數
void Temper_run(void); //溫度操控
void Tempe_show(u8 HOW); //顯示溫度
void Tempe_relook(void); //查看當前溫度
void Tempe_change(void); //溫度調整函數
void Tempe_PID(void); //溫度PID
void write_da7811(u16 data); //模擬SPI串行發送數據
/*************************************************************
*函數名稱:void write_da7811(u16 da)
*函數功能:實現普通I/O模擬SPI通信
*輸入參數:void
*返回值:u16 data
**************************************************************/
void write_da7811(u16 data)
{
char i;
SYNC_DOWN;
for(i=0;i<4;i++)
{
SCLK_UP;
if(DA_ON[i])
{
SDIN_UP;
}
else
{
SDIN_DOWN;
}
SCLK_DOWN;
}
for (i=0;i<12;i++)
{
SCLK_UP;
if(data&0x800)
{
SDIN_UP;
}
else
{
SDIN_DOWN;
}
SCLK_DOWN;
data<<=1;
}
SDIN_UP;
SYNC_UP;
SCLK_DOWN;
}
/****************************************************************
*函數名稱:void Zeng_yi(void)
*函數功能:輸出相應的增益
*輸入參數:void
*返回值: void
*****************************************************************/
void Zeng_yi(void)
{
signed long i,j,i_1,j_1,b = 0,c=0;
u16 Control_Val[3] = {0} ; //存儲數據的地址
u16 a = 0;
u16 SHUZI=0 ,SHUZI_1=0 ;
ADC10CTL1|= CONSEQ_3 + INCH_2 + INCH_0 + INCH_1; //序列通道多次轉換+最大通道為A2
ADC10CTL0|= ADC10SHT_2 + MSC + ADC10ON + SREF_0 ;
ADC10DTC1|= 0x08; //一共采樣8次
ADC10AE0 |= BIT1 + BIT2; //打開A1和A2的模擬輸入通道
Write_CMD(0x01); //清屏
P1DIR |= BIT4 + BIT5; //讓P1.4和P1.5工作在輸出狀態
Write_CMD(0x80); //第一行顯示
print_string("當前增益:"); //選擇倒計時功能
i = HOW_A/10;
LCD_write_char(5,0,Number[i]);
LCD_write_char(6,0,'.');
i = HOW_A%10;
LCD_write_char(7,0,Number[i]);
Write_CMD(0x90); //第一行顯示
print_string("Vin:"); //選擇倒計時功能
Write_CMD(0x88); //第一行顯示
print_string("Vout:"); //選擇倒計時功能
Write_CMD(0x98); //第一行顯示
print_string("返回"); //選擇倒計時功能
Write_CMD(0x9c); //第一行顯示
print_string("單位:V"); //選擇倒計時功能
while(M_S ==12)
{
do{
SHUZI=0 ;
SHUZI_1=0 ;
ADC10CTL0 &= ~ENC; //關閉采樣使能
while(ADC10CTL1 & BUSY);
ADC10CTL0 |= ENC + ADC10SC; //Enable conversion,Start conversion
ADC10SA = (unsigned int)Control_Val;
SHUZI = Control_Val[2] ;
SHUZI_1 = Control_Val[1] ;
b = b + SHUZI;
c = c + SHUZI_1;
if(a==400)
{
b = b/400;
i = (b*35)/10*2-50 ;
j = i/1000;
LCD_write_char(3,1,Number[j]);
LCD_write_char(4,1,'.');
j = i/100%10;
LCD_write_char(5,1,Number[j]);
j = i/10%10;
LCD_write_char(6,1,Number[j]);
if(i*50<=21000)
{
HOW_A = 50;
}
else if(i*20<=21000)
{
HOW_A = 20;
}
else if(i*5<=21000)
{
HOW_A = 5;
}
else if(i*2<=21000)
{
HOW_A = 2;
}
c = c/400;
if((HOW_A==50)||(HOW_A==20))
{
i_1 = (c*35)/10 ;
}
else if(HOW_A==5)
{
i_1 = ((c*35)/10)*100/88 -280;
}
else if(HOW_A==2)
{
i_1 = ((c*35)/10)*100/85-210;
}
if(i_1>2000)
{
i_1=2000;
}
j_1 = i_1/1000;
LCD_write_char(3,2,Number[j_1]);
LCD_write_char(4,2,'.');
j_1 = i_1/100%10;
LCD_write_char(5,2,Number[j_1]);
j_1 = i_1/10%10;
LCD_write_char(6,2,Number[j_1]);
a=0;
b=0;
}
else
{
a++;
}
i = HOW_A/10;
LCD_write_char(5,0,Number[i]);
LCD_write_char(6,0,'.');
i = HOW_A%10;
LCD_write_char(7,0,Number[i]);
switch(HOW_A)
{
case 2:
P1OUT &= ~BIT4 ;
P1OUT &= ~BIT5;
break;
case 5:
P1OUT &= ~BIT4 ;
P1OUT |= BIT5;
break;
case 20:
P1OUT |= BIT4 ;
P1OUT &= ~BIT5;
break;
case 50:
P1OUT |= BIT4 ;
P1OUT |= BIT5;
break;
}
}while(KM_RETURN&&KM_S);
if(!KM_RETURN)
{
while(!KM_RETURN);
P1DIR &= ~BIT5 ; //讓P1.4和P1.5工作在輸出狀態
P1DIR &= ~BIT4 ; //讓P1.4和P1.5工作在輸出狀態
M_S = 5;
}
else if(!KM_S)
{
while(!KM_S);
P1DIR &= ~BIT4 ; //讓P1.4和P1.5工作在輸出狀態
P1DIR &= ~BIT5 ; //讓P1.4和P1.5工作在輸出狀態
M_S = 0;
}
}
}
/****************************************************************
*函數名稱:void PID_PWM(void)
*函數功能:進行PID運行
*輸入參數:void
*返回值:void
****************************************************************/
void Tempe_PID(void)
{
u8 a = 1,b,c,d ;
u16 e;
Write_CMD(0x01); //第一行顯示
while(M_S == 11)
{
do{
if(a==1)
{
P2SEL |= BIT1 ;
TA1CCTL1 = OUTMOD_7;
TA1CCR0 =10000;
Write_CMD(0x80);
b = (u8)(TARGET*10/100);
c = (u8)(TARGET*10/10%10);
d = (u8)(TARGET*10%10);
print_string("當前溫度:"); //當前溫度顯示
Write_CMD(0x88);
print_string("目標溫度:"); //目標溫度顯示
LCD_write_char(2,3,Number[b]);
LCD_write_char(3,3,Number[c]);
LCD_write_char(4,3,'.');
LCD_write_char(5,3,Number[d]);
Write_CMD(0x9e);
print_string("°C"); //目標溫度設置
Write_CMD(0x96); //第二行
print_string("°C"); //目標溫度設置
a = 2;
}
TA1CCR1 = PID_Run(TARGET);
TEMPE = TEMPE*10;
e = (u16)TEMPE;
b = (u8)(e/100);
c = (u8)(e/10%10);
d = (u8)(e%10);
LCD_write_char(2,1,Number[b]);
LCD_write_char(3,1,Number[c]);
LCD_write_char(4,1,'.');
LCD_write_char(5,1,Number[d]);
delay_(3);
}while(KM_S&&KM_RETURN );
if(!KM_S)
{
M_S = 0;
TA1CCTL1 = OUTMOD_0;
T_real = 0; //當前值
T_target = 0; //目標值
T_diff = 0; //誤差
}
else if(!KM_RETURN)
{
M_S = 10;
TA1CCTL1 = OUTMOD_0;
T_real = 0; //當前值
T_target = 0; //目標值
T_diff = 0; //誤差
T_diff3 = 0;
T_diff1 = 0 ;
}
}
}
/***************************************************************
*函數名稱:void Tempe_show(u8 HOW)
*函數功能:顯示溫度
*輸入參數:void
*輸出參數:void
****************************************************************/
void Tempe_show(u8 HOW)
{
switch(HOW)
{
case 0:
Write_CMD(0x80); //第一行顯示
print_string("1.當前溫度"); //顯示當前溫度值
Write_CMD(0x90); //第二行顯示
print_string("2.目標溫度"); //目標溫度設置
break;
case 1:
Write_CMD(0x96); //第二行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x86); //第一行顯示
Write_DATA(0x03); //選定電壓測量
break;
case 2:
Write_CMD(0x86); //第二行顯示
Write_DATA(0x20); //選定電壓測量
Write_CMD(0x96); //第二行顯示
Write_DATA(0x03); //清除其他功能
break;
}
}
/**************************************************************
*函數名稱:void Tempe_change(void)
*函數功能:選擇目標溫度
*輸入參數:void
*返回值:void
****************************************************************/
void Tempe_change(void)
{
u8 a = 1,b,c;
signed int Target = 30;
Write_CMD(0x01); //清屏
while(M_S == 10 )
{
while(!KM_SURE)
{}
do{
b = Target/10%10;
c = Target%10;
if(a)
{
Write_CMD(0x80); //第一行
print_string("目標溫度:"); //目標溫度設置
Write_CMD(0x95); //第四行
print_string("°C"); //目標溫度設置
Write_CMD(0x98); //第四行
print_string("返回"); //目標溫度設置
Write_CMD(0x9e);
print_string("確定"); //目標溫度設置
a = 0;
}
LCD_write_char(3,1,Number[b]);
LCD_write_char(4,1,Number[c]);
if(!KM_SSUP)
{
while(!KM_SSUP);
Target++;
if(Target>80)
{
Target=80;
}
}
else if(!KM_SSDOWN)
{
while(!KM_SSDOWN);
Target--;
if(Target<30)
{
Target=30;
}
}
}while(KM_S&&KM_RETURN&&KM_SURE);
if(!KM_S)
{
M_S = 0;
FANHUI=1;
}
else if(!KM_RETURN)
{
M_S = 3;
}
else if(!KM_SURE)
{
M_S = 11;
TARGET = Target; //將目標溫度值傳遞給pid1結構體
}
}
}
/***************************************************************
*函數名稱:void Tempe_relook(void)
*函數功能:查看當前溫度值
*輸入參數:void
*返回值:void
****************************************************************/
void Tempe_relook(void)
{
u8 i;
Write_CMD(0x01); //清屏
while(M_S == 9 )
{
do{
_ADC = ADC_LVBO(); //經過濾波算法后取值
TEMPE = ((float)(_ADC-24)/30) ; //計算當前溫度值
i=((u8)TEMPE)/100;
Write_CMD(0x80);
print_string("當前溫度值:");
if(i!=0)
{
LCD_write_char(2,1,Number[i]);
}
else
{
LCD_write_char(2,1,0x20);
}
i=((u8)TEMPE)/10%10;
LCD_write_char(3,1,Number[i]);
i=((u8)TEMPE)%10;
LCD_write_char(4,1,Number[i]);
Write_CMD(0x95);
print_string("°C");
}while(KM_S&&KM_RETURN);
if(!KM_S)
{
M_S = 0;
FANHUI=1;
}
else if(!KM_RETURN)
{
M_S = 3;
}
}
}
/***************************************************************
*函數名稱:void Temper_run(void)
*函數功能:溫度操作
*輸入參數:void
*輸出參數:void
****************************************************************/
void Temper_run(void)
{
Write_CMD(0x01); //清屏
MM_S2 = 0;
Tempe_show(MM_S2); //調用溫度顯示函數
while(M_S==3)
{
while((!KM_SURE)||(!KM_RETURN))
{
Tempe_show(MM_S2); //調用溫度顯示函數
}
MM_S2 =FANHUI2;
do{
_ADC = ADC_LVBO();
TEMPE = (((float)(_ADC-24))/30) ; //計算當前溫度值
Tempe_show(MM_S2); //調用溫度顯示函數
if(!KM_SSDOWN) //下選鍵按下
{
while(!KM_SSDOWN ) //按鍵消抖操作
{
Tempe_show(MM_S2); //顯示當前MM_S(即所選功能)
}
MM_S2++;
if(MM_S2 == 3)
{
MM_S2 = 1; //當MM_S加到3就恢復到1
}
}
else if(!KM_SSUP)
{
while(!KM_SSUP ) //按鍵消抖操作
{
Menu_LCDshow(MM_S2); //顯示當前MM_S(即所選功能)
}
MM_S2--; //選擇下一功能
if(MM_S2 == 0)
{
MM_S2 = 2; //當MM_S減到0就恢復到2
}
}
}while(KM_S&&KM_RETURN&&KM_SURE);
if(!KM_S)
{
M_S = 0;
FANHUI=1;
}
else if(!KM_RETURN)
{
while(!KM_RETURN);
M_S = 0;
}
else if(!KM_SURE)
{
M_S = MM_S2 + 8;
}
}
}
/****************************************************************
*函數名稱:u16 PID_Run(signed Target)
*函數功能:進行PID計算
*輸入參數:PID_INT *pid
*輸出參數:void
******************************************************************/
u16 PID_Run(float Target)
{
signed long PWM = 0 ;
float Kp; //比例系數
float Ki; //積分系數
float Kd; //微分系數
float P_OUT; //比例
float D_OUT; //微分
float I_OUT; //積分
Kp = 250; //PID參數
Ki = 1.0;
Kd = 0;
TEMPE = (((float)(ADC_LVBO()-24))/30) ; //讀取當前溫度
T_real = (((float)(ADC_LVBO()-24))/30) ; //讀取當前溫度
T_target = Target; //設置目標溫度
T_diff = (float)((T_target - T_real)*10); //計算誤差
if(T_diff<=30&&T_diff>0)
{
P_OUT = Kp* T_diff ; //計算比例環節
I_OUT = Ki* T_diff1 ; //計算積分環節
D_OUT = Kd* T_real;
PWM = (signed int)(P_OUT + I_OUT + D_OUT ) ;
}
else
{
return 10000;
}
if(PWM<0)
{
return 0;
}
else if(PWM >=10000)
{
return 10000;
}
return (u16) PWM;
}
/************************************************************
*函數名稱:void delay_(u32)
*函數功能:可被打斷延時
*輸入參數:u32
*返回值:void
************************************************************/
void delay_(u32 time)
{
u32 b = 0,a;
do{
for(a=0;a<990;a++)
{
_NOP();
}
b++;
}while((b<time)&&KM_S&&KM_RETURN);
}
/*****************************************
*函數名稱:void LCD_write_char(u8 X,u8 Y,u8 data)
*函數功能:在屏幕上隨意顯示字符
*輸入參數:u8 x,u8 y,u8 data
*返回值:void
*****************************************/
void LCD_write_char(u8 X,u8 Y,u8 data)
{
LCD_set_xy( X, Y ); //寫地址
Write_DATA( data);
}
/*****************************************
*函數名稱:void LCD_set_xy( u8 x, u8 y )
*函數功能:設置LCD12864上要顯示的位置(字母或是符號)
*輸入參數:u8 x,u8 y
*返回值:void
****************************************/
void LCD_set_xy( u8 x, u8 y )
{
u8 address;
switch(y)
{
case 0:
address=x+0x80;
break;
case 1:
address=x+0x90;
break;
case 2:
address=x+0x88;
break;
case 3:
address=x+0x98;
break;
}
Write_CMD( address);
}
/******************************************************************
*函數名稱:void int_port(void)
*函數功能:初始化LCD的管腳
*輸入參數:void
*輸出參數:void
*******************************************************************/
void Init_port(void) //管腳初始化
{
P1DIR |= BIT3;
P1OUT &= ~BIT3;
//P1DIR |= BIT0;
//P1OUT &= ~BIT0;
P2DIR &= ~BIT4 ; //P2.4(KM_S菜單)設置為輸入
P2DIR &= ~BIT5 ; //P2.5(KM_SS功能向下選擇)設置為輸入
P2DIR &= ~BIT3; //P2.3(KM_SS功能向上選擇)設置為輸入
P2DIR &= ~BIT2; //P2.2(KM_SURE確定鍵)設置為輸入
P2DIR &= ~BIT0; //P2.1(KM_RETURN返回鍵)設置為輸入
}
/*****************************************************
*函數名稱:void delay(u8 t)
*函數功能:實現簡單的軟件延時
*輸入參數:u8 t
*輸出參數:void
********************************************************/
void delay(u16 t)
{
u16 i,j;
for(i=0; i<t; i++)
for(j=0; j<10; j++);
}
/********************************************************
*函數名稱:void Send_Byte(u8 data)
*函數功能:串行發送8位數據
*輸入參數:u8 data
*輸出參數:void
**********************************************************/
void Send_Byte(u8 data)
{
P1DIR |= BIT0;
P1OUT &= ~BIT0;
u8 a;
for(a=0;a<8;a++)
{
if(data&(0x80>>a))
{
SID_1;
}
else
{
SID_0;
}
CLK_0;
delay(2);
CLK_1;
}
}
/********************************************************************
*函數名稱:void Send_CMD(u8)
*函數功能:向LCD發送指令
*輸入參數:u8 CMD
*返回值:void
*********************************************************************/
void Write_CMD(u8 CMD)
{
Send_Byte(0xf8); //5個1,RS(0),RW(0),0
Send_Byte(0xf0&CMD); //高四位
Send_Byte(0xf0&(CMD<<4)); //低四位
delay(2);
}
/********************************************************************
*函數名稱:void Send_DATA(u8 DATA)
*函數功能:向LCD發送數據
*輸入參數:u8 CMD
*返回值:void
*********************************************************************/
void Write_DATA(u8 DATA)
{
Send_Byte(0xfa); //5個1,RS(0),RW(0),0
Send_Byte(0xf0&DATA); //高四位
Send_Byte(0xf0&(DATA<<4)); //低四位
delay(2);
}
/********************************************************************
*函數名稱:void LCD12864_Init(void)
*函數功能:LCD初始化函數
*輸入參數:void
*返回值:void
*********************************************************************/
void LCD12864_Init(void)
{
delay(200); //復位等待(內部自帶上電復位電路),時間較長
Write_CMD(0x30);
delay(50); //延時等待
Write_CMD(0x0c); //整體顯示,關游標
delay(50);
}
/******************************************************************
*函數名稱:void print_string(u8 *s)
*函數功能:顯示一個字符串
*輸入參數:u8 *s
*返回值:void
********************************************************************/
void print_string(u8 *s)
{
while(*s>0) //C語言里字符串末尾自動加“\0”(ASCII碼值為0)
{
Write_DATA(*s); //發送字符對應的ASCII碼,12864指針可設置自動指向下一個顯示地址
s++;
delay(50);
}
}
/********************************************************************
*函數名稱:void Menu_LCDshow(U8 HOW)
*函數功能:顯示菜單
*輸入參數:void
*返回值:void
*********************************************************************/
void Menu_LCDshow(u8 HOW)
{
switch(HOW)
{
case 0 :
Write_CMD(0x80); //第一行顯示
print_string("1.測量電壓"); //選擇電壓顯示功能
Write_CMD(0x90); //第二行顯示
print_string("2.功能合集"); //選擇時鐘功能
Write_CMD(0x88); //第三行顯示
print_string("3.溫度PID"); //選擇游戲功能
Write_CMD(0x98); //第三行顯示
print_string("4.串口調試"); //選擇游戲功能
break;
case 1:
Write_CMD(0x96); //第二行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x9E); //第四行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x8E); //第三行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x86); //第一行顯示
Write_DATA(0x03); //選定電壓測量
break;
case 2:
Write_CMD(0x9E); //第四行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x8E); //第三行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x86); //第一行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x96); //第二行顯示
Write_DATA(0x03); //選定電壓測量
break;
case 3:
Write_CMD(0x9E); //第四行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x96); //第二行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x86); //第一行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x8E); //第三行顯示
Write_DATA(0x03); //選定電壓測量
break;
case 4:
Write_CMD(0x8E); //第三行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x96); //第二行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x86); //第一行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x9E); //第四行顯示
Write_DATA(0x03); //選定電壓測量
break;
}
}
/*********************************************************************
*函數名稱:void menu(void)
*函數功能:進入菜單
*輸入參數:void
*返回值: void
*********************************************************************/
void Menu_Init(void)
{
Write_CMD(0x01); //清屏
MM_S = 0;
Menu_LCDshow(MM_S);
while(M_S==0)
{
MM_S = FANHUI;
do{
Menu_LCDshow(MM_S); //MM_S為菜單中功能選擇變量
if(!KM_SSDOWN) //下選鍵按下
{
while(!KM_SSDOWN ) //按鍵消抖操作
{
Menu_LCDshow(MM_S); //顯示當前MM_S(即所選功能)
}
MM_S++; //選擇下一功能
if(MM_S == 5)
{
MM_S = 1; //當MM_S加到3就恢復到1
}
}
else if(!KM_SSUP)
{
while(!KM_SSUP ) //按鍵消抖操作
{
Menu_LCDshow(MM_S); //顯示當前MM_S(即所選功能)
}
MM_S--; //選擇下一功能
if(MM_S == 0)
{
MM_S = 4; //當MM_S減到0就恢復到2
}
}
}while(KM_SURE&&KM_S); //當菜單鍵再次按下的時候即可退出循環
if(!KM_SURE)
{
if(MM_S==4)
{
MM_S = 13;
}
M_S = MM_S;
FANHUI = M_S; //把M_S的值賦給FANHUI
}
else if(!KM_S)
{
M_S = 0;
FANHUI =1;
}
}
}
/********************************************************************
*函數名稱:void ADC_Run(void)
*函數功能:運行ADC檢測電壓(管腳P1.1)
*輸入參數:void
*輸出參數:void
*********************************************************************/
void ADC_Run(void)
{
ADC10CTL1 |= INCH_1; // input A1模擬信號輸入選擇通道A1即p1.1
ADC10AE0 |= 0x02; // PA.1 ADC option select使p1.1允許AD模擬輸入信號
u8 i;
Write_CMD(0x01);
while(M_S)
{
while(!KM_S )
{
Menu_LCDshow(MM_S); //MM_S為菜單中功能選擇變量
}
do
{
ADC_RESULT1 = ADC_LVBO() ;
Write_CMD(0x86); //第一行顯示
Write_DATA(0x20); //選定電壓測量
Write_CMD(0x90);
print_string("U");
LCD_write_char(1,1,':');
i = ADC_RESULT1/1000;
LCD_write_char(2,1,Number[i]);
LCD_write_char(3,1,'.');
i = (ADC_RESULT1/100)%10;
LCD_write_char(4,1,Number[i]);
i = (ADC_RESULT1/10)%10;
LCD_write_char(5,1,Number[i]);
i = ADC_RESULT1%10;
LCD_write_char(6,1,Number[i]);
LCD_write_char(7,1,'V');
}while(KM_S&&KM_RETURN);
if(!KM_S)
{
while(!KM_S);
M_S = 0;
}
else if(!KM_RETURN)
{
while(!KM_RETURN);
M_S = 0;
ADC10CTL0 &= ~ADC10ON ; // ADC10ON, interrupt enabled
}
}
}
/********************************************************************
*函數名稱:u16 ADC_LVBO(void)
*函數功能:濾波算法(中位值)
*輸入參數:void
*返回值:u32
*********************************************************************/
u16 ADC_LVBO(void)
{
u8 a,b,c ;
u16 SHUZI[9] ,SHUZHI,d;
for(a=0;a<9;a++)
{
ADC10CTL0 |= ENC + ADC10SC; //開始轉換
while(ADC10CTL1&ADC10BUSY);
ADC_Result = ADC10MEM; //采集轉換結果
SHUZHI = ADC_Result*35/10; //轉換結果運算
SHUZI[a] = SHUZHI; //取轉換結果接下來進行濾波計算
}
for(c=0;c<9;c++)
{
for(b=c;b<9;b++)
{
if(b+1<9)
{
if(SHUZI[c]<SHUZI[b+1])
{
d = SHUZI[c];
SHUZI[c] = SHUZI[b+1];
SHUZI[b+1] = d;
}
}
}
}
return SHUZI[4];
}
/*********************************************************************
*函數名稱:void ADC_Init(void)
*函數功能:初始化ADC
*輸入參數:void
*返回值:void
**********************************************************************/
void ADC_Init(void)
{
ADC10CTL0 |= ADC10SHT_2 + ADC10ON ; // ADC10ON, interrupt enabled
}
/*********************************************************************
*函數名稱:void Time_choose(u8 HOW)
*函數功能:時鐘第二功能設置
*輸入參數:u8 HOW
*返回值:void
**********************************************************************/
void Time_choose(u8 HOW)
{
switch(HOW)
{
case 0:
Write_CMD(0x80); //第一行顯示
print_string("1.測電阻(H)"); //選擇電壓顯示功能
Write_CMD(0x90); //第二行顯示
print_string("2.程控放大"); //選擇時鐘功能
Write_CMD(0x88); //第三行顯示
print_string("3.測電容"); //選擇秒表功能
Write_CMD(0x98); //第四行顯示
print_string("4.程控提高"); //選擇倒計時功能
break;
case 1:
Write_CMD(0x96); //第二行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x9E); //第四行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x8E); //第三行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x86); //第一行顯示
Write_DATA(0x03); //選定電壓測量
break;
case 2:
Write_CMD(0x9E); //第四行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x8E); //第三行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x86); //第一行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x96); //第二行顯示
Write_DATA(0x03); //選定電壓測量
break;
case 3:
Write_CMD(0x9E); //第四行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x96); //第二行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x86); //第一行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x8E); //第三行顯示
Write_DATA(0x03); //選定電壓測量
break;
case 4:
Write_CMD(0x8E); //第三行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x96); //第二行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x86); //第一行顯示
Write_DATA(0x20); //清除其他功能
Write_CMD(0x9E); //第四行顯示
Write_DATA(0x03); //選定電壓測量
break;
case 5:
if(GO==0)
{
Write_CMD(0x01); //清屏
GO = 1;
}
Write_CMD(0x80); //第一行顯示
print_string("5.呼吸燈"); //選擇PWM呼吸燈功能
Write_CMD(0x86); //第一行顯示
Write_DATA(0x03); //選定呼吸燈
break;
}
}
/*********************************************************************
*函數名稱:void Time_Init(void)
*函數功能:進入時鐘選擇
*輸入參數:void
*返回值:void
**********************************************************************/
void Time_Init(void)
{
Write_CMD(0x01); //清屏
if(FANHUI1!=5)
{
MM_S1 = 0;
Time_choose(MM_S1);
}
MM_S1 = FANHUI1;
Time_choose(MM_S1); //MM_S為菜單中功能選擇變量
if(MM_S1==5)
{
GO=0;
}
while(M_S==2)
{
while(!KM_SURE)
{
Time_choose(MM_S1);
}
do{
Time_choose(MM_S1); //MM_S為菜單中功能選擇變量
if(!KM_SSDOWN) //下選鍵按下
{
while(!KM_SSDOWN ) //按鍵消抖操作
{
Time_choose(MM_S1); //顯示當前MM_S(即所選功能)
}
if(MM_S1==5)
{
Write_CMD(0x01);//清屏
Write_CMD(0x80); //第一行顯示
print_string("1.測電阻(H)"); //選擇電壓顯示功能
Write_CMD(0x90); //第二行顯示
print_string("2.程控放大"); //選擇時鐘功能
Write_CMD(0x88); //第三行顯示
print_string("3.側電容"); //選擇秒表功能
Write_CMD(0x98); //第四行顯示
print_string("4.程控提高"); //選擇倒計時功能
}
MM_S1++; //選擇下一功能
if(MM_S1==5)
{
GO=0;
}
if(MM_S1 == 6)
{
MM_S1 = 1; //當MM_S加到5就恢復到1
}
}
else if(!KM_SSUP)
{
while(!KM_SSUP ) //按鍵消抖操作
{
Time_choose(MM_S1); //顯示當前MM_S(即所選功能)
}
if(MM_S1==5)
{
Write_CMD(0x01);//清屏
Write_CMD(0x80); //第一行顯示
print_string("1.測電阻(H)"); //選擇電壓顯示功能
Write_CMD(0x90); //第二行顯示
print_string("2.程控放大"); //選擇時鐘功能
Write_CMD(0x88); //第三行顯示
print_string("3.測電容"); //選擇秒表功能
Write_CMD(0x98); //第四行顯示
print_string("4.程控提高"); //選擇倒計時功能
}
MM_S1--; //選擇下一功能
if(MM_S1==5)
{
GO=0;
}
if(MM_S1 == 0)
{
MM_S1 = 5; //當MM_S減到0就恢復到5
GO=0;
}
}
}while(KM_SURE&&KM_S&&KM_RETURN);
if(!KM_SURE)
{
M_S = MM_S1 + 3; //把選定結果賦給M_S
FANHUI1 = MM_S1; //將選定結果賦給FANHUI
}
else if(!KM_S)
{
M_S = 0;
FANHUI = 1;
}
else if(!KM_RETURN)
{
M_S = 0;
FANHUI1 = 1;
}
}
}
/************************************************************
*函數名稱:void Time_Look(void)
*函數功能:測量電阻
*輸入參數:void
*返回值:void
*************************************************************/
void RES_show(void)
{
Write_CMD(0x01); //第一行顯示
CHANGE = 1; //功能切換變量為1(選擇測電阻)
TACTL = TASSEL_2 + MC_2 + ID_3 ; //SMCLK,up?mode
TACCTL1 |= CM_1 + CCIS_0 + CAP + CCIE; //cap設置
P1SEL |= BIT2 ; //select P1.1,P1.2 function
P1DIR &= ~BIT2;
P1DIR |= BIT4;
P1OUT |=BIT2;
TAR = 0;
_BIS_SR( GIE);
P2SEL &= ~BIT1 ;
while(M_S==4)
{
do{
}while(KM_S&&KM_RETURN);
if(!KM_S)
{
M_S = 0;
_DINT();
TACCTL1 &= (~CM_1) + (~CCIS_0) + (~CAP) + (~CCIE); //cap設置
TACTL &= (~TASSEL_1) + (~MC_2) ;
TAR = 0;
time11 = 0;
CHANGE = 0;
}
else if(!KM_RETURN)
{
while(!KM_RETURN);
M_S = 2;
_DINT();
TACCTL1 &= (~CM_1) + (~CCIS_0) + (~CAP) + (~CCIE); //cap設置
TACTL &= (~TASSEL_1) + (~MC_2) ;
P1OUT &= ~BIT4;
TAR = 0;
time11=0;
CHANGE = 0;
}
}
}
/***********************************************************************
*函數名稱:void Time_change(void)
*函數功能:程控增益基礎篇一級菜單
*輸入參數:void
*返回值:void
************************************************************************/
void Time_change(void)
{
signed char a = 0,b = 0 ;
u8 i[4]={ 2,5,20,50};
Write_CMD(0x01); //第一行顯示
while(M_S==5)
{
while(!KM_RETURN);
while(!KM_SURE)
{
b = i[a]/10;
Write_CMD(0x80);
print_string("選擇增益:"); //選擇電壓顯示功能
LCD_write_char(3,1,Number[b]);
b = i[a]%10;
LCD_write_char(4,1,'.');
LCD_write_char(5,1,Number[b]);
}
do{
b = i[a]/10;
Write_CMD(0x80);
print_string("選擇增益:"); //選擇電壓顯示功能
LCD_write_char(3,1,Number[b]);
b = i[a]%10;
LCD_write_char(4,1,'.');
LCD_write_char(5,1,Number[b]);
Write_CMD(0x98);
print_string("返回"); //選擇電壓顯示功能
Write_CMD(0x9e);
print_string("確定"); //選擇電壓顯示功能
if(!KM_SSDOWN)
{
while(!KM_SSDOWN);
a--;
if(a<0)
{
a = 3;
}
}
else if(!KM_SSUP)
{
while(!KM_SSUP);
a++;
if(a>3)
{
a = 0;
}
}
}while(KM_S&&KM_RETURN&&KM_SURE);
if(!KM_S)
{
while(!KM_S); //延時
M_S = 0;
}
else if(!KM_RETURN)
{
while(!KM_RETURN); //延時
M_S = 2;
}
else if(!KM_SURE)
{
while(!KM_SURE); //延時
HOW_A = i[a];
M_S = 12;
}
}
}
/*************************************************************
*函數名稱:void Miaobiao(void)
*函數功能:測量電容
*輸入參數:void
*返回值:void
**************************************************************/
void Miaobiao(void)
{
Write_CMD(0x01);
CHANGE = 2; //功能切換變量為1(選擇測電容)
TACTL = TASSEL_2 + MC_2 + ID_3 ; //SMCLK,up?mode
TACCTL1 |= CM_1 + CCIS_0 + CAP + CCIE; //cap設置
P1SEL |= BIT2 ; //select P1.1,P1.2 function
P1DIR &= ~BIT2;
P1DIR |= BIT4;
P1OUT |=BIT2;
TAR = 0;
_BIS_SR( GIE);
while(M_S==6)
{
do{
}while(KM_S&&KM_RETURN);
if(!KM_S)
{
M_S = 0;
_DINT();
TACCTL1 &= (~CM_1) + (~CCIS_0) + (~CAP) + (~CCIE); //cap設置
TACTL &= (~TASSEL_1) + (~MC_2) ;
TAR = 0;
time11 = 0;
CHANGE = 0;
}
else if(!KM_RETURN)
{
while(!KM_RETURN);
M_S = 2;
_DINT();
TACCTL1 &= (~CM_1) + (~CCIS_0) + (~CAP) + (~CCIE); //cap設置
TACTL &= (~TASSEL_1) + (~MC_2) ;
P1OUT &= ~BIT4;
TAR = 0;
time11=0;
CHANGE = 0;
}
}
}
/**********************************************************************************
*函數名稱:void Daojishi(void)
*函數功能:實現程控增益提高篇
*輸入參數:void
*返回值:void
***********************************************************************************/
void Daojishi(void)
{
signed long i,j,i_1,j_1,b = 0,c=0;
u16 Control_Val[3] = {0} ; //存儲數據的地址
u16 a = 0;
u16 SHUZI=0 ,SHUZI_1=0 ;
P1DIR |= BIT1; //設置為輸入狀態
P1DIR |= BIT2;
ADC10CTL1|= CONSEQ_3 + INCH_2 + INCH_0 + INCH_1; //序列通道多次轉換+最大通道為A2
ADC10CTL0|= ADC10SHT_2 + MSC + ADC10ON + SREF_0 ;
ADC10DTC1|= 0x08; //一共采樣8次
ADC10AE0 |= BIT1 + BIT2; //打開A1和A2的模擬輸入通道
Write_CMD(0x01); //清屏
Write_CMD(0x80); //第一行顯示
print_string("當前增益:"); //選擇倒計時功能
i = HOW_A/10;
LCD_write_char(5,0,Number[i]);
LCD_write_char(6,0,'.');
i = HOW_A%10;
LCD_write_char(7,0,Number[i]);
Write_CMD(0x90); //第一行顯示
print_string("Vin:"); //選擇倒計時功能
Write_CMD(0x88); //第一行顯示
print_string("Vout:"); //選擇倒計時功能
while(M_S==7)
{
do{
SHUZI=0 ;
SHUZI_1=0 ;
ADC10CTL0 &= ~ENC; //關閉采樣使能
while(ADC10CTL1 & BUSY);
ADC10CTL0 |= ENC + ADC10SC; //Enable conversion,Start conversion
ADC10SA = (unsigned int)Control_Val;
SHUZI = Control_Val[2] ;
SHUZI_1 = Control_Val[1] ;
b = b + SHUZI;
c = c + SHUZI_1;
}while(KM_S&&KM_RETURN);
if(!KM_S)
{
M_S = 0;
}
else if(!KM_RETURN)
{
while(!KM_RETURN);
M_S = 2;
}
}
}
void Pwm_run(void)
{
u16 a = 20000;
u16 b;
P2SEL |= BIT1 ;
Write_CMD(0x01); //第一行顯示
TA1CCTL1 = OUTMOD_7;
TA1CCR0 =20000;
TA1CCR1 = a;
while(M_S == 8)
{
do{
Write_CMD(0x80); //第一行顯示
print_string("呼吸燈"); //選擇倒計時功能
if(a==20000)
{
do{
delay(1);
b++;
}while((b<10000)&&KM_S&&KM_RETURN);
b=0;
do{
a--;
TA1CCR1 = a;
delay(3);
}while((a>0)&&KM_S&&KM_RETURN);
if(a==0)
{
do{
delay(1);
b++;
}while((b<10000)&&KM_S&&KM_RETURN);
b=0;
do{
a++;
TA1CCR1 = a;
delay(3);
}while((a<20000)&&KM_S&&KM_RETURN);
}
}
}while(KM_S&&KM_RETURN );
if(!KM_S)
{
M_S = 0;
TA1CCTL1 = OUTMOD_0;
}
else if(!KM_RETURN)
{
while(!KM_RETURN);
M_S = 2;
TA1CCTL1 = OUTMOD_0;
}
}
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; //關閉看門狗
P2DIR |= BIT1 ;
P2OUT &= ~BIT1;
BCSCTL1 = CALBC1_8MHZ; //MCLK=8MHz
DCOCTL = CALDCO_8MHZ;
TA1CTL = MC_1 + TASSEL_2;
Init_port(); //管腳初始化
LCD12864_Init(); //LCD12864初始化
ADC_Init(); //AD轉換初始化
// Write_CMD(0x01);
M_S = 0; //直接進入主菜單
MM_S = 0;
FANHUI = 1; //將上級菜單最后結果設置為1
FANHUI1 = 1; //將二級菜單中最后結果設置為1
FANHUI2 = 1; //將溫度二級菜單中最后結果設置為1
MM_S1 = 1;
MM_S2 = 0;
while(1)
{
switch(M_S)
{
case 0:
Menu_Init(); //菜單顯示
break;
case 1:
ADC_Run(); //ADC運行
break;
case 2:
Time_Init();
break;
case 3:
Temper_run(); //溫度
break;
case 4:
RES_show (); //檢測電阻
break;
case 5:
Time_change(); //選擇放大器增益
break;
case 6:
Miaobiao();
break;
case 7:
Daojishi();
break;
case 8:
Pwm_run();
break;
case 9:
Tempe_relook();
break;
case 10:
Tempe_change();
break;
case 11:
Tempe_PID();
break;
case 12:
Zeng_yi();
break;
}
}
}
#pragma vector = TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
{
long a = 0 ;
if(TACCTL1&CCIFG)
{
TACCTL1 &= ~CCIFG;
time11++;
if(time11==1)
{
TA0CTL |= TACLR;
}
if(time11==2)
{
T = TACCR1;
f = 1000000/T;
switch (CHANGE)
{
case 2:
f = 1000000000000/(709632*f);
Write_CMD(0x80); //第一行顯示
print_string("電容值"); //選擇電壓顯示功能
Write_CMD(0x98); //第一行顯示
print_string("單位,pF"); //選擇電壓顯示功能
a = (u16)(((long)f)/1000%10);
LCD_write_char(3,1,Number[a]);
a = (u16)(((long)f)/100%10);
LCD_write_char(4,1,Number[a]);
a = (u16)(((long)f)/10%10);
LCD_write_char(5,1,Number[a]);
a = (u16)(((long)f)%10);
LCD_write_char(6,1,Number[a]);
P1OUT ^= BIT4;
break;
case 1:
LCD_write_char(0,1,0x20);
LCD_write_char(1,1,0x20);
LCD_write_char(2,1,0x20);
LCD_write_char(3,1,0x20);
LCD_write_char(4,1,0x20);
LCD_write_char(5,1,0x20);
LCD_write_char(6,1,0x20);
LCD_write_char(7,1,0x20);
f = (3333333/f-165);
Write_CMD(0x80); //第一行顯示
print_string("電阻值"); //選擇電壓顯示功能
Write_CMD(0x98); //第一行顯示
print_string("單位,R"); //選擇電壓顯示功能
if((f>=1)&&(f<10))
{
LCD_write_char(0,1,0x20);
LCD_write_char(1,1,0x20);
LCD_write_char(2,1,0x20);
LCD_write_char(3,1,0x20);
LCD_write_char(4,1,0x20);
LCD_write_char(5,1,0x20);
LCD_write_char(6,1,0x20);
f = f-f*0.04;
a = (u16)f;
LCD_write_char(7,1,Number[a]);
last = f;
}
else if((f>=10)&&(f<100))
{
LCD_write_char(0,1,0x20);
LCD_write_char(1,1,0x20);
LCD_write_char(2,1,0x20);
LCD_write_char(3,1,0x20);
LCD_write_char(4,1,0x20);
LCD_write_char(5,1,0x20);
f = f-f*0.04;
a = ((u16)f)/10;
LCD_write_char(6,1,Number[a]);
a = ((u16)f)%10;
LCD_write_char(7,1,Number[a]);
}
else if((f>=100)&&(f<1000))
{
LCD_write_char(0,1,0x20);
LCD_write_char(1,1,0x20);
LCD_write_char(2,1,0x20);
LCD_write_char(3,1,0x20);
LCD_write_char(4,1,0x20);
f = f-f*0.04;
a = ((u16)f)/100;
LCD_write_char(5,1,Number[a]);
a = ((u16)f)/10%10;
LCD_write_char(6,1,Number[a]);
a = ((u16)f)%10;
LCD_write_char(7,1,Number[a]);
}
else if((f>=1000)&&(f<10000))
{
LCD_write_char(0,1,0x20);
LCD_write_char(1,1,0x20);
LCD_write_char(2,1,0x20);
LCD_write_char(3,1,0x20);
f = f-f*0.04;
a = ((u16)f)/1000;
LCD_write_char(4,1,Number[a]);
a = ((u16)f)/100%10;
LCD_write_char(5,1,Number[a]);
a = ((u16)f)/10%10;
LCD_write_char(6,1,Number[a]);
a = ((u16)f)%10;
LCD_write_char(7,1,Number[a]);
}
else if((f>=10000)&&(f<100000))
{
LCD_write_char(0,1,0x20);
LCD_write_char(1,1,0x20);
LCD_write_char(2,1,0x20);
f = f-f*0.04;
a = ((u16)f)/10000;
LCD_write_char(3,1,Number[a]);
a = ((u16)f)/1000%10;
LCD_write_char(4,1,Number[a]);
a = ((u16)f)/100%10;
LCD_write_char(5,1,Number[a]);
a = ((u16)f)/10%10;
LCD_write_char(6,1,Number[a]);
a = ((u16)f)%10;
LCD_write_char(7,1,Number[a]);
}
else if((f>=100000)&&(f<1000000))
{
LCD_write_char(1,1,0x20);
f = f-f*0.04;
a = ((long)f)/100000;
LCD_write_char(2,1,Number[a]);
a = ((long)f)/10000%10;
LCD_write_char(3,1,Number[a]);
a = ((long)f)/1000%10;
LCD_write_char(4,1,Number[a]);
a = ((long)f)/100%10;
LCD_write_char(5,1,Number[a]);
a = ((long)f)/10%10;
LCD_write_char(6,1,Number[a]);
a = ((long)f)%10;
LCD_write_char(7,1,Number[a]);
}
P1OUT ^= BIT4;
break;
}
}
}
}
|