微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 新手发帖求救

新手发帖求救

时间:10-02 整理:3721RD 点击:
     用51单片机控制舵机转动超声波测距,然后用1602显示。结果是角度显示了,距离也显示了,就是舵机SG90不转动,没办法定位障碍位置,想了好几天,都还搞不好,求大神帮助  PS:我不是伸手党,已经查了好多资料,我是确实做不了,以下是我的程序,新手上路,不喜勿喷
*时间:
*备注:
**************************************************
==============================================================
LCD1602模拟口线接线方式
连接线图:       
       ---------------------------------------------------
       |LCM-----51   |        LCM-----51   |        LCM------51      |
       --------------------------------------------------|
       |DB0-----P0.0 |        DB4-----P0.4 |        RW-------P3.4    |
       |DB1-----P0.1 |        DB5-----P0.5 |        RS-------P3.3    |
       |DB2-----P0.2 |        DB6-----P0.6 |        E--------P3.5    |
       |DB3-----P0.3 |        DB7-----P0.7 |        VLCD接1K电阻到GND|
       ---------------------------------------------------
接线:模块TRIG接 P1.1  ECH0 接P1.2                 蜂鸣器报警 P2.2
=============================================================*/
#include <reg52.H>                //器件配置文件
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar anglecount ,jd =1 ;
sbit TX = P1^1;                               //#define  TX  P1_1   超声波引脚配置
sbit RX = P1^2;                               //#define  RX  P1_2
sbit pwm = P1^3;
sbit beep = P2^1;
sbit LCM_RS = P2^4 ; //定义LCD引脚
sbit LCM_RW = P2^5 ;
sbit LCM_E  = P2^6 ;
#define LCM_Data  P0
sbit jia = P3^6 ;//定义Keyboard引脚
sbit jian  = P3^7 ;

#define Busy    0x80 //用于检测LCM状态字中的Busy标识
void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void Delay5Ms(void);
void Delay400Ms(void);
void Decode(unsigned char ScanCode);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
//void T1_time0_init(void);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
unsigned char code   system[] ={"Warning systems "};
unsigned char code designer[] = {"Designed by  Li "};
unsigned char code Cls[] =      {"                "};
unsigned char code ASCII[15] ={'0','1','2','3','4','5','6','7','8','9','.','-','M','*'};
static unsigned char DisNum = 0; //显示用指针                                  
       unsigned int  time=0;
           unsigned long S=0;
           bit      flag =0;
           unsigned char disbuff[4]           ={ 0,0,0,0,};
           unsigned char angbuff[4]           ={ 0,0,0,0,};
/***********************************************************************************************/
/*****************************************LCD1602设置程序***************************************/
/***********************************************************************************************/
//写数据
void WriteDataLCM(unsigned char WDLCM)
{
        ReadStatusLCM(); //检测忙
        LCM_Data = WDLCM;
        LCM_RS = 1;
        LCM_RW = 0;
        LCM_E = 0; //若晶振速度太高可以在这后加小的延时
        LCM_E = 0; //延时
        LCM_E = 1;
}
//写指令
void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
{
        if (BuysC) ReadStatusLCM(); //根据需要检测忙
        LCM_Data = WCLCM;
        LCM_RS = 0;
        LCM_RW = 0;       
        LCM_E = 0;
        LCM_E = 0;
        LCM_E = 1;       
}
//读数据
unsigned char ReadDataLCM(void)
{
        LCM_RS = 1;
        LCM_RW = 1;
        LCM_E = 0;
        LCM_E = 0;
        LCM_E = 1;
        return(LCM_Data);
}
//读状态
unsigned char ReadStatusLCM(void)
{
        LCM_Data = 0xFF;
        LCM_RS = 0;
        LCM_RW = 1;
        LCM_E = 0;
        LCM_E = 0;
        LCM_E = 1;
        while (LCM_Data & Busy); //检测忙信号
        return(LCM_Data);
}
void LCMInit(void) //LCM初始化
{
        LCM_Data = 0;
        WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
        Delay5Ms();
        WriteCommandLCM(0x38,0);
        Delay5Ms();
        WriteCommandLCM(0x38,0);
        Delay5Ms();
        WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
        WriteCommandLCM(0x08,1); //关闭显示
        WriteCommandLCM(0x01,1); //显示清屏
        WriteCommandLCM(0x06,1); // 显示光标移动设置
        WriteCommandLCM(0x0F,1); // 显示开及光标设置
}
//按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
        Y &= 0x1;
        X &= 0xF; //限制X不能大于15,Y不能大于1
        if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
        X |= 0x80; //算出指令码
        WriteCommandLCM(X, 1); //发命令字
        WriteDataLCM(DData); //发数据
}
//按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
        unsigned char ListLength;
  ListLength = 0;
        Y &= 0x1;
        X &= 0xF; //限制X不能大于15,Y不能大于1
        while (DData[ListLength]>0x19) //若到达字串尾则退出
                {
                        if (X <= 0xF) //X坐标应小于0xF
                                {
                                        DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
                                        ListLength++;
                                        X++;
                                }
                }
}
/****************************************************************************************/
/**************************************延时程序***************************************/
/******************************************************************************************/
//5ms延时
void Delay5Ms(void)
{
        unsigned int TempCyc = 5552;
        while(TempCyc--);
}
//400ms延时
void Delay400Ms(void)

{
        unsigned char TempCycA = 5;
        unsigned int TempCycB;
        while(TempCycA--)
                {
                        TempCycB=7269;
                        while(TempCycB--);
                };
}
void delay(uchar x)
{
uchar i,j;
for(i=x;i>0;i--)
  for(j=125;j>0;j--);
}
void delayms(unsigned int ms)
{
        unsigned char i=100,j;
        for(;ms;ms--)
        {
                while(--i)
                {
                        j=10;
                        while(--j);
                }
        }
}
/******************************************************************************************/
/********************************超声波距离显示*******************************************/
/*********************************************************************************************/
    void Conut(void)
        {
         time=TH0*256+TL0;
         TH0=0;
         TL0=0;
       
         S=(time*17)/1000;          //算出来是M
         if((S>=700)||flag==1)      //超出测量范围显示“-”
         {         
          flag=0;
         
          DisplayOneChar(0, 1, ASCII[11]);
          DisplayOneChar(1, 1, ASCII[10]);                //显示点
          DisplayOneChar(2, 1, ASCII[11]);
          DisplayOneChar(3, 1, ASCII[11]);
          DisplayOneChar(4, 1, ASCII[12]);               //显示M
         }
         else
         {
          disbuff[0]=S%1000/100;
          disbuff[1]=S%1000%100/10;
          disbuff[2]=S%1000%10 %10;
          DisplayOneChar(0, 1, ASCII[disbuff[0]]);
          DisplayOneChar(1, 1, ASCII[10]);               //显示点
          DisplayOneChar(2, 1, ASCII[disbuff[1]]);
          DisplayOneChar(3, 1, ASCII[disbuff[2]]);
          DisplayOneChar( 4, 1, ASCII[12]);                //显示M
          DisplayOneChar(11, 1, ASCII[13]);                        //显示角度*
          
         }
        }
/***********************************************************************************************************/
/***********************************************角度按键控制扫描*********************************/
/************************************************************************************************************/
void keyscan()
{
  if(jia==0)
  {
   delay(15);                                //消抖
   if(jia==0)
   {
            jd++;                                  //角度增加 1
         anglecount=0;                          //按键按下则20ms周期重新开始计时
         if(jd==6)
           jd=5;                          //已经是180度,保持
          while(jia==0);
   }
  }
    if(jian==0)
   {
            delay(15);                            //消抖
         if(jian==0)
         {
           jd--;
           anglecount=0;
           if(jd==0)
             jd=1;                        //已经0度,保持
          while(jian==0);
         }
   }
}
/*******************************************************************************************************/
/***********************************************角度显示函数************************************************/
/*********************************************************************************************************/
void display()
{
uchar bai ,shi,ge ;
switch(jd)
{
  case 1:
     bai=0;
     shi=0;
         ge=0;
     break;
  case 2:
     bai=0;
     shi=4;
         ge=5;
     break;
  case 3:
     bai=0;
     shi=9;
         ge=0;
     break;
  case 4:
     bai=1;
     shi=3;
         ge=5;
     break;
  case 5:
     bai=1;
     shi=8;
         ge=0;
     break;
}
angbuff[0] = bai;
angbuff[1] = shi;
angbuff[2] = ge;
delay(5);
      DisplayOneChar(8, 1, ASCII[angbuff[0]]);                        //bai
          DisplayOneChar(9, 1, ASCII[angbuff[1]]);                        //shi
          DisplayOneChar(10,1, ASCII[angbuff[2]]);                        //ge
}
/********************************************************/
     void T0_time() interrupt 1                      //T0中断用来计数器溢出,超过测距范围
  {
    flag=1;                                                             //中断溢出标志
  }
/********************************************************/
/*void T1_time0_init()
{
  TMOD=0x11;                  //定时器1工作方式1
  IE=0x82;
  TH0=0xfe;
  TL0=0x33;                                 //11.0592MHZ晶振,0.5ms
  TR0=1;
}
*/
/*******************************************定时器1中断程序(角度控制)*************************/
void T1_time() interrupt 3
{ uchar anglecount ;
  TH1=0xfe;
  TL1=0x33;
  if(anglecount<jd)           //判断0.5ms次数是否小于角度标识
     pwm=1;                                      //是,pwm输出高电平
  else
         pwm=0;                                      //否,输出低电平
         anglecount=anglecount+1;
         anglecount=anglecount%40;         //次数始终保持为40,即保持周期为20ms
}
/*****************************************************************************************/
/*******************************超声波发射函数*************************/
/*********************************************************************************************/
     void  StartModule()                          //启动模块函数
  {
          TX=1;                                             //启动一次模块
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          _nop_();
          TX=0;
  }
/*******************************报警函数****************************
     void warning()
  {
     beep = 0 ;
        if(S<=20)
        {
         beep = 1 ;
        }
        else
        {
         beep = 0 ;
        }
  }
/**********************************************************************************************/
/**********************************************************************************************/
/******************************************主函数***************************************************/
void main(void)
{          
    unsigned char TempCyc;
        Delay400Ms();                             //启动等待,等LCM讲入工作状态
        LCMInit();                                //LCM初始化
//        beep = 0 ;
        Delay5Ms();                               //延时片刻(可不要)
        DisplayListChar(0, 0, system);
        DisplayListChar(0, 1, designer);
        ReadDataLCM();                            //测试用句无意义
        for (TempCyc=0; TempCyc<10; TempCyc++)
        Delay400Ms();                             //延时
        DisplayListChar(0, 1, Cls);       
         TMOD=0x11;                           //设T0,T1为方式1,GATE=1;
         TH0=0;
         TL0=0;         
         TH1=0xfe;
     TL1=0x33;                                 //11.0592MHZ晶振,0.5ms
         IE = 0x09;                    //允许T0,T1中断
         EA=1 ;                                   //开启总中断       
         TR1=1;
         anglecount=0;
        while(1)
          {
             
                 StartModule();                                    //启动模块
                 DisplayOneChar(4, 1, ASCII[12]);                //距离显示
             while(!RX);                                    //当RX为零时等待
             TR0=1;                                                //开启计数
             while(RX);                                            //当RX为1计数并等待
             TR0=0;                                                    //关闭计数
         Conut();                                            //距离计算
                 delayms(20);                                    //80MS延时
                 TR1=1;
                 keyscan();
//                 TR1=0;
//                 delayms(80);
                 display();
          }
                           
}

好长的代码!

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top