⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 12.c

📁 由P89V51RB2单片机控制小车在翘翘板上寻找平衡点,装载倾角传感器.
💻 C
字号:
/**********************************************
  显示和键盘都已经正常,键盘采用的是中断方式
  
  2008.7.2
  
**************************************/
#include <P89V51.h>
#include <absacc.h>
#include <intrins.h>
#include <stdlib.h>
#include <stdio.h> 
#define   uchar unsigned char 
//SYSTEM ADDRESS ALLOCATION	******************
#define KEYCOLUM XBYTE[0xEFFF]
#define KEYROW XBYTE[0xDFFF]
#define ALARM XBYTE[0xCFFF]
#define HC245C1 XBYTE[0xBFFF]
#define HC245C2 XBYTE[0xAFFF]
#define HC573C1 XBYTE[0x9FFF]
#define HC573C2 XBYTE[0x8FFF]
#define HC573C3 XBYTE[0x7FFF]
#define ADCS XBYTE[0x6FFF]
#define DACS XBYTE[0x5FFF]
#define DACLOAD XBYTE[0x4FFF]
//***************************************	

//static unsigned char keyin=0;


/*-------------LCD1602 definitions and functions--------------*/
#define nops() {_nop_();_nop_();_nop_();}
typedef bit BOOL;

#define FALSE (bit)0
#define TRUE  (bit)1
 
sbit lcd_cs = P2^0;            //控制位
sbit lcd_rw = P2^1; 
sbit lcd_rs = P2^2;
#define DataPort      P0 
#define DataDirPort   P0  
#define StatePort     P0   
      
#define Busy 0x80 // 忙判别位  
uchar keystate,keyin;
unsigned char ucKeyState,flag,c_0,c_1,c_2;
unsigned int n=0,b_out,tick=0,second=0, minute=0;
unsigned char mai[8]={0x11,0x33,0x22,0x66,0x44,0xcc,0x88,0x99};

void delay(long t)
{
    while(t)
     t--;
} 

code unsigned char* WrtieLcdErr =  "Display char outof range."; 

// ------ Private function prototypes --------------------------
static BOOL WaitTillNotBusy();
static BOOL LocateXY(unsigned char posx, unsigned char posy); 
static BOOL LcdWData(unsigned char dataW);
static BOOL LcdWCMD(unsigned char CMD);
BOOL LCDInit() ;
BOOL DisplayOneChar(unsigned char x ,unsigned char y ,unsigned char Wdata) ;
BOOL DisplayString(unsigned char posx, unsigned char posy,  unsigned char*  str);
unsigned char keyscan(void);
unsigned char Gatkey(char keystate);

BOOL WaitTillNotBusy()
{ 
    unsigned int delay = 0xffff;  
 
        DataDirPort = 0xff; 
                            
        lcd_cs = 1;
        lcd_rs = 0;
        lcd_rw = 1;
        while( (StatePort & Busy) && delay)
            delay--;
        lcd_cs = 0;  
        if (!delay)  
            return FALSE ; 
    
    return TRUE; 
}      

BOOL LocateXY( unsigned char posx,unsigned char posy)
{
    posy &= 0x01;
    if (posy == 1)
        posx |= 0x40;
    posx |= 0x80;
   
    return LcdWCMD(posx);   
}


BOOL LcdWCMD(unsigned char CMD) 
{        
        unsigned char i=1;
                            
        if (!WaitTillNotBusy()) // 检测忙信号? 
        return FALSE;    
                                
        DataPort = CMD;
        lcd_rs = 0;
        lcd_rw = 0;
        lcd_cs = 1;
        while(i++);
        lcd_cs = 0;  
    
       return TRUE;
}


BOOL LcdWData( unsigned char dataW )
{    
     
        unsigned char i = 1;
         
        if (!WaitTillNotBusy()) // 检测忙信号? 
            return FALSE; 
      
        
        DataPort = dataW;
        lcd_rs = 1;
        lcd_rw = 0;
        lcd_cs = 1;
        while(i++);
        lcd_cs = 0;   

       return TRUE;
} 

// LCD输出用函数
//LCDInit--LCD初始化
//DisplayOneChar(x,y,char) --在指定x,y显示一个字符
//DisplayString(x,y,str)--在指定位置x,y开始显示一个字符串

BOOL LCDInit() 
{
  
    // 显示模式设置,光标移动设置,显示开及光标设置,显示清屏 
    return (LcdWCMD( 0x38) && LcdWCMD( 0x06) && LcdWCMD( 0x0c) && LcdWCMD( 0x01));       

}

BOOL DisplayOneChar(unsigned char x ,unsigned char y ,unsigned char Wdata) 
{
   
    if( (x >= 0 && x < 16) && (y >= 0 && y < 2) )
        return (LocateXY( x, y ) && LcdWData( Wdata )) ;// 定位显示地址,写字符 
    else
        return ( LCDInit() && DisplayString(0, 0, WrtieLcdErr));    //显示越界消息    
}

BOOL DisplayString(unsigned char posx, unsigned char posy,  unsigned char*  str)
{    
    while ( (*str) != '\0' )
    {
        if (!DisplayOneChar(posx, posy, (*str)))
            return FALSE;
        str++;
        posx++;
        if( posx == 16 )
        {
            posx = 0;
            posy++;

        }
    }
    
    return TRUE;              
}
/*--------------End of LCD1602 macros and functions------------------*/

/*-------------- ----SPI protocols-----------------------------------	*/

void SpiInit(void)
{
   SPCR = 0x51;
   SPSR = 0x00;
}

void SpiClose(void)  {SPCR = 0x00;}

/*----------------End of SPI protocols---------------------------*/

//-----------ADC MCP3208 functions--------------------
// ReadAD(chx)读AD,chx为通道号
//chx=0x00----0x07对应AD0---AD7通道
unsigned int ReadAD(unsigned char chx)
{

    unsigned int lsb,msb;
	char sbuf;
    lsb=0;msb=0;
  	
	ADCS = 0x00;	
	sbuf = 0x06 | (chx>>2);
	SPDAT = sbuf;
    while(!(SPSR&0x80) );
	SPSR = 0x00;
    sbuf = SPDAT;
	
	sbuf = (chx&0x03)<<6;
	SPDAT = sbuf;
    while(!(SPSR&0x80) );
	SPSR = 0x00;
    sbuf = SPDAT;
	msb = sbuf&0x0F;
	
	sbuf = 0x00;
	SPDAT = sbuf;
    while(!(SPSR&0x80) );
	SPSR = 0x00;
    lsb = SPDAT;
	
	XBYTE[0xFFFF] = 0x00;
	
    return msb*256+lsb;

}  
//------------End ADC MCP3208 functions-----------------        

//-----------------DAC MCP4922 functions----------------------
void DACout( unsigned char DACH, unsigned int DAValue)
{
    unsigned char msb,lsb,temp;  

   XBYTE[0xFFFF] = 0;

   DAValue&=0x0FFF;
 
   temp = (DAValue/256)&0x0F;

  DACS = 0x00; 
   
  if(DACH==1)
    {
    msb =0x70|temp;
    lsb = (unsigned char)(DAValue & 0xFF) ; 
    }
  else if(DACH==2)
   {
    msb =0xF0|temp;			  
    lsb = (unsigned char)(DAValue & 0xFF) ; 
    }
  else
    { }
   
 
   SPDAT = msb;
   while(!(SPSR&0x80) );
   SPSR = 0x00;

   SPDAT = lsb;
   while(!(SPSR&0x80) );
   SPSR = 0x00;
  
   XBYTE[0xFFFF] = 0;
   DACLOAD = 0x00;
   nops();
   XBYTE[0xFFFF] = 0;
 
}



//**********************按键中断响应**********************

void Int1_keyscan(  )  interrupt 0	 
{   
    unsigned char ucSKey;
    unsigned int  uiI;
	EA=0;
    for (uiI=0;uiI<100;uiI++);                //延时,去掉抖动 
    if(INT1==1) 
	goto end01;                     
    for (uiI=0;uiI<100;uiI++);                //延时,去掉抖动 
    if(INT1==1) 
	goto end01;                                     //关闭外部中断
    LcdWCMD( 0x01) ;  //显示清屏
    keyscan();   //获取按键状态
    ucSKey=Gatkey(keystate);                        
    ucKeyState=ucSKey;
    //DisplayOneChar(1,1,keyin);   //显示按键对应的字符
    //delay(500);  
	end01:;
	KEYROW=0xE0;
	EA=1;  // 开启中断

}
//********************************平衡************************
void BLB(void)
{
int value_buf[8],temp;
char j,i;

for(i=0;i<8;i++)
{
temp = ReadAD(0x01);
if((temp>10)&&(temp<4500))
{
value_buf[i]=temp;	  //获取采样值
}  
delay(3);
}

for(j=0;j<7;j++)   //采样值由小到大排列,排序采用冒泡法
{
for(i=0;i<8-j;i++)
{
if(value_buf[i]>value_buf[i+1])
{
temp=value_buf[i];
value_buf[i]=value_buf[i+1];
value_buf[i+1]=temp;
}
}
}
 b_out = value_buf[3];
   
}

void deal_BLB(void)
{ 
 if(b_out<1300)
 {
 c_0++;
 if(c_0>15)flag=1;
 }
     
 if(b_out>1350)
  {
   c_1++;
   if(c_1>15)flag = 0;

  }
 if((b_out<1350)&&(b_out>1300))
 { 
   c_2++;
   c_0=0;
   c_1=0;
   flag = 2;
 }
}

void T0INT( )  interrupt 1
{ 
  TH0 = 0x3C;
  TL0 = 0xAF;
  tick ++;
  if(tick>=19)
    { 
      tick =0;
      second++ ; 
	  if(second>=60)
        {
         second=0;
         minute++;
        }
     }
  BLB(); deal_BLB();
} 

//*****************获取按键状态函数******************
unsigned char keyscan(void)      
{
   uchar recode,sccode;
   KEYROW=0xE0;       //将行都设置为低电平
   recode=KEYCOLUM;   //获取列的状态
    if((recode&0x0F)!=0x0F)  //判断是否有键按下和延时去抖动
     {
      // delay(60);        
     if((recode&0x0F)!=0x0F)
       {
        sccode=0xFE;          //设置行扫描的初始值
        while((sccode&0x20)!=0)     //判断并逐行扫描
         {   
             KEYROW=sccode;
             recode=KEYCOLUM;
             if((recode&0x0F)!=0x0F)
              {
                 recode=(recode&0x0F)|0xF0;  //记录列号
                 sccode=~sccode;               //记录行号
		         sccode=sccode<<4;       //把行号方到高四位
		         keystate=(sccode)+(~recode);  //记录行列状态,高四位为行号,低四位为列号
				 return keystate;             
		         break; 
               }
              else
               sccode=(sccode<<1)|0x01;        //行扫描后没找到按键状态则转到下一行
         }
       } 
    }
  return(0); 
} 
//**********************按键对应的显示字符**********************************
unsigned char Gatkey(char keystate)
{

 switch (keystate)
 {
   case 0x11: keyin='a';
              break;
   case 0x12: keyin='b';
              break;
   case 0x14: keyin='c';
              break;
   case 0x18: keyin='d';
              break;
   case 0x21: keyin='e';
              break;
   case 0x22: keyin='f';
              break;
   case 0x24: keyin='g';
              break;
   case 0x28: keyin='h';
              break;
   case 0x41: keyin='i';
              break;
   case 0x42: keyin='j';
              break;
   case 0x44: keyin='k';
              break;
   case 0x48: keyin='l';
              break;
   case 0x81: keyin='m';
              break;
   case 0x82: keyin='n';
              break;
   case 0x84: keyin='0';
              break;
   case 0x88: keyin='p';
              break;
   case 0x01: keyin='q';
              break;
   case 0x02: keyin='r';
              break;
   case 0x04: keyin='s';
              break;
   case 0x08: keyin='t';
              break;
   default: keyin='N' ;
   }
   return keyin;

}

void Setpwm(char channel,  unsigned char pwmval)
{
   switch (channel )
   {
	case 0:
	  CCAP0L = pwmval;
	  CCAP0H = pwmval;
	  break;
	case 1:
	  CCAP1L = pwmval;
	  CCAP1H = pwmval;
  	  break;
	default:
	  CCAP0L = pwmval;
	  CCAP0H = pwmval;

   }
    

}
//*****************************************
void back(long speed, int no)
{
int i;
for(i=0;i<no;i++)
  {
  HC573C1 = mai[i%8];
  delay(speed);
  }
}

void go(long speed, int no)
{
int i;
for(i=no;i>0;i--)
  {
  HC573C1 = mai[i%8];
  delay(speed);
  }
}

void go_left(long speed, int no)		 //750为90度转弯
{
int i;
for(i=no;i>0;i--)
  {
  HC573C1 = mai[i%8]&0x0F+0x10;
  delay(speed);
  }
}

void go_right(long speed, int no)	    //750为90度转弯
{
int i;
for(i=no;i>0;i--)
  {
  HC573C1 = mai[i%8]&0xF0+0x01;
  delay(speed);
  }
}

void deal_go(void)
{
  char mid;
  mid=HC245C1%4;  
  if(mid==2)go_left(250,30);
  if(mid==1)go_right(250,30);
  if(mid==3)go(250,50);
  if(mid==0)go(250,50);
}

void deal_bi(void)
{
  char mid;
  mid=HC245C2%4;  
  if(mid==2)go_left(250,50);
  if(mid==1)go_right(250,30);
  if(mid==3)go(250,50);
  if(mid==0)go(250,30); 
}



//*****************************************
void main()
{
   
  unsigned int ADs,c,i;
  unsigned int b1=0,b2;
  char ADval[10];
  unsigned int BB=3000;

   SpiInit();
   LCDInit();
   DisplayString(0,0,"Hello World");
   // delay(10000);  
   HC573C1 = 0x01;
   HC573C2 = 0x0F;
   KEYROW = 0x00;
   P1 = 0x01;

   TMOD = 0x01;
   TL0 = 0xAF;
   TH0 = 0x3C;
   ET0 = 1;
   TR0 = 1;
   EA = 1;
   EX0 = 1;

   CMOD = 0x02;  
   CCAPM0 = 0x4A; 
   CL =0;
   CCAP0H = 16;
   CCON = 0x40;
  
   LcdWCMD( 0x01) ;  //显示清屏
/*
b1 = (HC245C1/16)%4;
while(b1==3)
{
deal_go();
b1 = (HC245C1/16)%4;
}
delay(50000);
go_right(250,750);
delay(50000); 
b1 = (HC245C1/16)%4;
while(b1==3)
{
deal_bi();
b1 = (HC245C1/16)%4;
}
delay(50000); 
go_left(250,750);

delay(50000);
 
b1 = (HC245C1/16)%4;
while(b1==3)
{
deal_bi();
b1 = (HC245C1/16)%4;
}

delay(50000); 
go_left(250,750);

i=1100;
while(i) 
{
  if(HC245C2%4==3)
  {
  HC573C1 = mai[i%8];
  delay(250);
  i--;
  }
  if(HC245C2%4==2)go_left(250,10);
  if(HC245C2%4==1)go_right(250,10);
}
delay(50000); 

go_right(250,750);

delay(50000);
go(250,800);

LcdWCMD( 0x01) ;
while(1){
   DisplayString(11,0,"m   s ");
  sprintf(ADval,"%d",second);
  DisplayString(13,0,ADval);
  sprintf(ADval,"%d",minute);
  DisplayString(10,0,ADval);
}
*/

HC573C1 = 0x00;
EA = 0;
go(180,1420);
EA = 1;
while(1)
{
LcdWCMD( 0x01);
sprintf(ADval,"%d",b_out);
DisplayString(10,0,ADval);
//delay(100);

if(flag==0)go(250,8);
if(flag==1)back(250,8);
if(flag==2)
{HC573C1 = 0x11;
delay(70000);
}

}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -