#include<reg52.h> //包含单片机寄存器的头文件
#include <I2C.H>
#define PCF8591 0x90 //PCF8591 地址
#define uint unsigned int
#define uchar unsigned char
unsigned char AD_CHANNEL;
unsigned long xdata LedOut[8];
unsigned int D[32];
uchar code table1[4]={0x04,0x08,0x10,0x20}; //步进电机正转表格,(P0.2-P0.5)各位分别取1,二进制码即:00000100,00001000,00010000,00100000
uchar code table2[4]={0x20,0x10,0x08,0x04}; //步进电机反转表格
/********************数码管模块程序********************************/
sbit MOSIO=P2^2;
sbit R_CLKa=P2^3;
sbit S_CLKa=P2^4;
unsigned char code duan[]={~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F};//此表为LED数码管段选字模
unsigned char code wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //此表为LED数码管位选字模
sbit key1=P3^2; // 独立按键K1
sbit key2=P3^3; // 独立按键K2
sbit key3=P3^4; // 独立按键K3
sbit key4=P3^5; // 独立按键K4
/*******************************************************************
延时子程序
*******************************************************************/
void delay(unsigned int z)
{
unsigned int i;
for(i=z;i>0;i--);
}
/*******************************************************************
数码管部分程序
*******************************************************************/
void send595(unsigned char dat) //数据输入
{
unsigned char i;
for(i=0;i<8;i++)
{
if((dat<<i)&0x80)
MOSIO=1;
else MOSIO=0;
S_CLKa=0;
S_CLKa=1;
}
}
void out595(void) // 数据输出
{
R_CLKa=0;
//delay(1);
R_CLKa=1; //上升沿
}
void disp(unsigned char w,unsigned char d) //数码管显示函数:w-位码,d-段码
{
send595(wei[w]);
send595(duan[d]);
out595();
}
/*******************************************************************
DAC 变换, 转化函数
*******************************************************************/
bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val)
{
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(c); //发送控制字节
if(ack==0)return(0);
SendByte(Val); //发送DAC的数值
if(ack==0)return(0);
Stop_I2c(); //结束总线
return(1);
}
/*******************************************************************
ADC发送字节[命令]数据函数
*******************************************************************/
bit ISendByte(unsigned char sla,unsigned char c)
{
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(c); //发送数据
if(ack==0)return(0);
Stop_I2c(); //结束总线
return(1);
}
/*******************************************************************
ADC读字节数据函数
*******************************************************************/
unsigned char IRcvByte(unsigned char sla)
{ unsigned char c;
Start_I2c(); //启动总线
SendByte(sla+1); //发送器件地址
if(ack==0)return(0);
c=RcvByte(); //读取数据0
Ack_I2c(1); //发送非就答位
Stop_I2c(); //结束总线
return(c);
}
/*******************************************************************
Led显示数据子程序
dj1表示光强最值时电机一转动的次数
dj2表示光强最值时电机二运行的次数
gm表示光敏元件在光强最值时的模拟量
*******************************************************************/
void xianshi(uint dj1,uint dj2,uint gm)
{
uint i;
LedOut[0]=dj1;
LedOut[1]=dj2%1000/100;
LedOut[2]=dj2%100/10;
LedOut[3]=dj2%10;
LedOut[4]=gm%10000/1000;
LedOut[5]=gm%1000/100;
LedOut[6]=gm%100/10;
LedOut[7]=gm%10;
for(i=0;i<8;i++)
{
disp(i,LedOut[i]);
delay(1);
}
}
/*******************************************************************
电机1转动子程序
调用一次转动约为18度
*******************************************************************/
void dianji1()
{
uint i,j;
for(i=0;i<25;i++)
{
for(j=0;j<4;j++)
{
P1=table1[j];
delay(250);
}
}
}
void dianji12()
{
uint i,j;
for(i=0;i<25;i++)
{
for(j=0;j<4;j++)
{
P1=table2[j];
delay(250);
}
}
}
/****************************************************************/
/****************************************************************
主程序
*******************************************************************/
void main()
{
uint a,b,c,d,e,f,i,j,k,l,m,n;
d=0;
while(1)
{
if(key1==0)
{
delay(1);
if(key1==0)
{
for(i=0;i<4;i++)
{
P0=table1[i];
delay(250);
}
}
}
else if(key2==0)
{
delay(1);
if(key2==0)
{
for(j=0;j<4;j++)
{
P1=table1[j];
delay(250);
}
}
}
else if(key3==0)
{
delay(1);
if(key3==0)
{
for(k=0;k<4;k++)
{
P1=table2[k];
delay(250);
}
}
}
else if(key4==0)
{
delay(1);
if(key4==0)
{
for(a=0;a<5;a++) //运行五次,实现竖直90度扫描
{
dianji1();
delay(100000); //电机一转动
for(b=0;b<512;b++) //电机二转动程序,每次转动一圈
{
for(c=0;c<4;c++)
{
if(a%2==0) //正反转,防止绕线
{
P0=table1[c];
delay(250); //电机二转动速度控制
}
else if(a%2==1)
{
P0=table2[c];
delay(250); //电机二转动速度控制
}
}
switch(AD_CHANNEL)
{
case 1: ISendByte(PCF8591,0x42);
D[1]=IRcvByte(PCF8591)*2; //ADC1 模数转换2
break;
case 2: ISendByte(PCF8591,0x43);
D[2]=1000-IRcvByte(PCF8591)*2; //ADC2 模数转换3
break;
}
D[4]=D[0]; //把模拟输入采样的信号 通过数模转换输出
if(++AD_CHANNEL>4) AD_CHANNEL=0;
if(D[2]>d) //取最值时坐标
{
d=D[2];
e=a;
f=b;
}
xianshi(e,f,d) ;
}
delay(100000);
}
while(1) //电机停止转动
{break;}
//返回极值程序
for(m=0;m<4-e;m++)
{
dianji12();
}
delay(100000);
for(n=0;n<512-f;n++)
{
for(i=0;i<4;i++)
{
P0=table2[i];
delay(250);
}
}
while(1)
{break;}
//关于各数据的清零程序
e=0;
f=0;
d=0;
}
}
}
}