|
msp430单片机adc+12864液晶显示菜单程序
[复制链接]
#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 |
|