#include<math.h>
#include<absacc.h>
#include<intrins.h>
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define BUSY 0x80 //常量定义
#define DATAPORT P0
#define ADCDELAY 5
sbit LCM_RS=P2^0;
sbit LCM_RW=P2^1;
sbit LCM_EN=P2^2;
sbit CS =P1^2; //ADC0832 chip seclect
sbit CLK =P1^3; //ADC0832 clock signal
sbit SDI =P1^1; //ADC0832 k in
sbit SDO =P1^0; //ADC0832 k out
uchar ad_data; //采样值存储
unsigned char press_bai=0; //显示值百位
unsigned char press_shi=0; //显示值十位
unsigned char press_ge=0; //显示值个位
unsigned char press_dot=0; //显示值十分位
uchar code str0[]={"Weight: . kg. "};
uchar HighRH = 0;
uchar HighRL = 0;
uchar LowRH = 0;
uchar LowRL = 0;
unsigned int a;
uchar rate;
sbit PWMOUT = P1^0;
uchar step, rec_data,flag;
void ADCInit(void); //初始化TLC2543
uint StartConversion(uchar channl); //开始转换,同时选择通道,同时返回上一次采样值
void delay(uint);
void lcd_wait(void); //检测忙子程序
void delay_LCM(uint); //延时子程序
void initLCM(void); //初始化子程序
void WriteCommandLCM(uchar WCLCM,uchar BusyC); //写指令到LCM子程序
void WriteDataLCM(uchar WDLCM); //写数据到LCM子程序
void DisplayOneChar(uchar X,uchar Y,uchar DData); //显示指定坐标的一个字符子函数
void DisplayListChar(uchar X,uchar Y,uchar code *DData); //显示指定坐标的一串字符子函数
void display(void); //系统显示子函数
void ConfigPWM(uchar rate);
void alarm(void);
void data_pro(void);
void ConfigPWM(uchar dc);
void key_setPWM(void);
uchar duty_cycle(uchar ad_data);
void chuankou_init();
/**********main funcation************/
void main(void)
{
delay(50);
initLCM( );
chuankou_init();
WriteCommandLCM(0x01,1); //清屏显示
DisplayListChar(0,0,str0);
delay(10);
EA = 1;
ConfigPWM(rate);
while(1)
{
ad_data =StartConversion(0); //采样值存储单元初始化为0
alarm();
data_pro();
display();
a=duty_cycle(ad_data);
ConfigPWM(a);
key_setPWM();
if(a!=rate)
{
ConfigPWM(rate);
}
if(RI==1)//串口
{
RI=0;
rec_data=SBUF;
step=rec_data*2;
SBUF=rec_data;
}
}
}
void TIME_INIT()
{
TMOD|=0X02;
IT0=1;
IT1=1;
TR1=1;
EX1=1;
EX0=1;
ET0=1;
TR0=1;
EA=1;
}
void chuankou_init()
{
SCON|=0X50;
TMOD|=0X20;
PCON|=0X80;
TH1=0XFA;
TL1=0XFA;
TR1=1;
SM0=0;
SM1=1;
REN=1;
EA=1;
ES=1;
}
/********延时K*1ms,12.000mhz**********/
void delay(uint x)
{
uchar i;
while(x--)
{
for(i = 0;i < 120;i++)
{;}
}
}
/**********写数据到ICM子函数************/
void WriteCommandLCM(uchar WCLCM,uchar BusyC)
{
if(BusyC)
lcd_wait(); //检测忙信号
DATAPORT=WCLCM;
LCM_RS=0;
LCM_RW=0;
LCM_EN=1;
_nop_();
_nop_();
_nop_();
LCM_EN=0;
}
/**********????LCM???************/
void WriteDataLCM(uchar WDLCM)
{
lcd_wait( );
DATAPORT=WDLCM;
LCM_RS=1; //选中数据寄存器
LCM_RW=0; //写模式
LCM_EN=1;
_nop_();
_nop_();
_nop_();
LCM_EN=0;
}
/***********lcm内部等待程序*************/
void lcd_wait(void)
{
DATAPORT=0xff; //读LCD前若单片机输出低电平,而读出LCD为高电平,则冲突,Proteus仿真会有显示逻辑黄色
LCM_EN=1;
LCM_RS=0;
LCM_RW=1;
_nop_();
_nop_();
_nop_();
while(DATAPORT&BUSY)
{
LCM_EN=0;
_nop_();
_nop_();
LCM_EN=1;
_nop_();
_nop_();
}
LCM_EN=0;
}
/**********LCM??????***********/
void initLCM( )
{
DATAPORT=0;
delay(15);
WriteCommandLCM(0x38,0); //三次显示模式,不检测忙信号
delay(5);
WriteCommandLCM(0x38,0);
delay(5);
WriteCommandLCM(0x38,0);
delay(5);
WriteCommandLCM(0x38,1); //8bit数据传送,两行显示,5*7字型,检测忙信号
WriteCommandLCM(0x08,1); //关闭显示,检测忙信号
WriteCommandLCM(0x01,1); //清屏,检测忙信号
WriteCommandLCM(0x06,1); //显示光标右移设置
WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
}
/****??????????????****/
void DisplayOneChar(uchar X,uchar Y,uchar DData)
{
Y&=1;
X&=15;
if(Y)X|=0x40; //若Y为1(显示第二行)地址译码+0x40
X|=0x80; //指令码为地址码+0x80
WriteCommandLCM(X,0);
WriteDataLCM(DData);
}
/*******??????????????*****/
void DisplayListChar(uchar X,uchar Y,uchar code *DData)
{
uchar ListLength=0;
Y&=0x01;
X&=0x0f;
while(X<16)
{
DisplayOneChar(X,Y,DData[ListLength]);
ListLength++;
X++;
}
}
/*****************???????*****************/
void display(void)
{
WriteCommandLCM(0x0c,1); //显示屏打开,光标不显示,不闪烁,检测忙信号
DisplayListChar(0,0,str0);
DisplayOneChar(7,0,press_bai+0x30);
DisplayOneChar(8,0,press_shi+0x30);
DisplayOneChar(9,0,press_ge +0x30);
DisplayOneChar(10,0,056);
DisplayOneChar(11,0,press_dot+0x30);
}
void Delay_ADC(uchar ms)
{
uchar i;
for(; ms > 0; ms--)
for(i = 5; i > 0; i--);
}
void ADCInit(void) //初始化TLC2543
{
CS = 1;
CLK = 0;
SDI = 0;
SDO = 1;
}
uint StartConversion(uchar channl) //开始转换,同时选择通道,同时返回上一次采样值
{
uint dat = 0;
uchar i;
CS = 0;
SDI = 0;
for(i = 0; i < 12; i++) //通道选择
{
dat <<= 1; //左移一位
if(channl & 0x80)
SDI = 1;
else
SDI = 0;
channl <<= 1; //左移一位
CLK = 1;
if(SDO)
dat += 1;
Delay_ADC(ADCDELAY);
CLK = 0;
}
CS = 1;
return dat;
}
void data_pro(void)
{
unsigned int temp;
float press;
int vary=ad_data; //y=(115-15)/(243-13)*X+15kpa
//press=24+ad_data/2.67;
press=((10.0/28.1)*vary)+9.3; //测试时补偿值为9.3
temp=(int)(press*10); //放大10倍,便于后面计算
press_bai=temp/1000;
press_shi=(temp%1000)/100;
press_ge=((temp%1000)%100)/10;
press_dot=((temp%1000)%100)%10;
}
uchar duty_cycle(uchar ad_data)
{
uchar rate;
rate= 100*ad_data/256;
return(rate);
}
/*??????dc,??20Hz????*/
void ConfigPWM(uchar dc)
{
unsigned long tmp; //临时变量
uint high, low;
tmp = 11059200/12/20; //计算一个周期所需的计数值
high = (tmp*dc)/100; //计算高电平所需计数值
low = tmp - high; //计算低电平所需计数值
high = 65536 - high + 12; //计算高电平的定时器重载值并补偿中断延时
low = 65536 - low + 12; //计算低电平的定时器重载值并补偿中断延时
HighRH = (uchar)(high >>8); //高电平重载值拆分为高低字节
HighRL = (uchar)high;
LowRH = (uchar)(low >> 8); //低电平重载值拆分为高低字节
LowRL = (uchar)low;
TMOD &= 0xF0; //清0 T0的控制位
TMOD |= 0x01; //配置T0的模式为 1
TH0 = HighRH; //加载T0重载值
TL0 = HighRL;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
}
void init0() interrupt 0
{
step++;
if(step==200)
{
step=0;
}
}
/*???0????*/
void init1() interrupt 2
{
step--;
if(step==0)
{
step=0;
}
}
void chuankou() interrupt 4
{
RI=0;
rec_data=SBUF;
step=rec_data*2;
flag=1;
}
|