找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1885|回复: 1
打印 上一主题 下一主题
收起左侧

51单片机小车蓝牙遥控+lcd1602+超声波测距程序

[复制链接]
跳转到指定楼层
楼主
ID:450825 发表于 2019-4-1 10:48 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include<reg52.h>
#include <intrins.h>
typedef unsigned char uchar;
typedef unsigned int uint;
#define L_go      IN1=0;IN2=1 //左轮前进
#define L_back    IN1=1;IN2=0 //左轮后退   
#define L_stop    IN1=0;IN2=0 //左轮停止
#define R_go      IN3=0;IN4=1 //右轮前进
#define R_back    IN3=1;IN4=0 //右轮后退
#define R_stop    IN3=0;IN4=0 //右轮停止
sbit Echo=P3^2;//超声波模块的回响信号输出,P3^2也是51单片机外部中断0的输入端,利用下降沿来触发中断
sbit Trig=P3^3;//触发信号脚
sbit IN1 =P3^4;               
sbit IN2 =P3^5;
sbit IN3 =P3^6;
sbit IN4 =P3^7;
sbit lcdrs=P1^0;//数据命令选择端,为0时写指令,为1时写数据
sbit lcdrw=P1^1;//读、写命令选择端,为0时写数据,为1时读数据,读状态时置1,其他时间都是0;
sbit lcden=P2^5;//使能端
sbit dula=P2^6;//在这段程序里没有用处
sbit wela=P2^7;
sbit STA7=P0^7;//D0~D7数据口对应P0^0~P0^7,当读液晶的数据时,STA7对应P0^7,STA7为1时表示液晶忙,无法接收数据
float dis;//距离的缓存
uchar flag;//中断标志位

char code table[]="distance:";//在规定位置显示字符
char code table1[]="cm";
void delayms(uchar x)
{
        uint i,j;
        for(i=0;i<x;i++)
        {
                for(j=0;j<110;j++);
        }
}
void nops()//延时10.9us,每个机器周期约1.09us,在晶振为11.0592MHz时
{
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        _nop_();
}
void distance()//计算距离的函数
{
        Trig=0;//首先将触发拉低
        nops();
        Trig=1;//给至少10us的高电平,启动模块
        nops();
        nops();
        Trig=0;//此时已经触发了模块,接下来立刻开启定时器计数
        TR0=1;//打开定时器0
        EX0=1;//打开外部中断,外部中断输入为P3^2,下降沿有效,触发中断
        delayms(1);//等待一下,一个机器周期约为1.09us,如果不等待,可能就错过计算dis,陷入死循环,永远无法得出值
        if(flag==1)//如果标志位置1,表示Echo输出下降沿,即接收结束
        {
                flag=0;
        }
}
void wait()//等待液晶空闲
{
        P0=0xff;
        do
        {
                lcdrs=0;//循环里的这些语句是读状态时的操作时序
                lcdrw=1;
                lcden=0;
                lcden=1;
        }while(STA7==1);//等液晶空闲的时候再出循环
        lcden=0;//使使能为0
}
void write_com(uchar com)//写命令程序
{
        wait();
        lcdrs=0;//使RS为0,发出的数据会被液晶当做命令而不是现实数据,这也是与写数据程序的唯一不同
        P0=com;
        lcdrw=0;//总是写的,故为0
        delayms(5);//使数据平稳,让液晶有时间读取
        lcden=1;//根据操作时序,使能要输出高脉冲,这句与后面那句共同构成一个高脉冲
        delayms(5);
        lcden=0;
}
void write_date(uchar date)//写数据程序
{
        wait();
        lcdrs=1;//注意这是写数据
        P0=date;
        lcdrw=0;
        delayms(5);
        lcden=1;
        delayms(5);
        lcden=0;
}
/*初始化函数*/
void init()
{
        wait();
        dula=0;//没用
        wela=0;
        lcden=0;
        write_com(0x38);//设置16*2显示,5*7点阵,8位数据口。这句是不变的
        write_com(0x0c);//根据操作时序设置的状态字。下面一样
        write_com(0x06);
        TMOD=0x21;//16位计数器,这里不用开启定时器中断,因为定时器中断无事可做,只要定时器里的值就行,因此无需将TF0置1
        TH0=0;//全部设为0
        TL0=0;
        IT0=1;//设置外部中断下降沿有效
        EA=1;//开总中断
}
/*显示函数*/
void display(float dis)
{
        uint bai,shi,ge,p1,p2;//分别是百位一次向下,到小数点后两位
        bai=dis/100;
        shi=(dis-bai*100)/10;
        ge=dis-bai*100-shi*10;
        p1=(dis*10)-bai*1000-shi*100-ge*10;
        p2=(dis*100)-bai*10000-shi*1000-ge*100-p1*10;
        write_date(0x30+bai);//将数字转换为字符,必须+0x30,另外,1602液晶只能接收字符型的数据
        write_date(0x30+shi);
        write_date(0x30+ge);
        write_date('.');
        write_date(0x30+p1);
        write_date(0x30+p2);
}
void csbbz()
{
        uchar i=0;
        init();
        write_com(0x80);//设置地址,在第一行第一列显示distance:,0x80是第一行的起始地址
        while(table[ i]!='\0')[ i]
        {
                write_date(table[ i]);[ i]
                i++;
                delayms(5);
        }
        i=0;
        write_com(0x80+0x40+6);//设置地址,在第二行第7位显示cm,0x80+0x40是第二行的起始地址
        while(table1[ i]!='\0')[ i]
        {
                write_date(table1[ i]);[ i]
                i++;
                delayms(5);
        }
        while(1)
        {
                distance();
                write_com(0x80+0x40);//设置数据的显示地址,为第二行的起始位,之后在进行循环时不断刷新在这个地方显示
                display(dis);
                delayms(60);
        }
}
void ex() interrupt 0//外部中断的中断函数
{
        TR0=0;//一旦受到下降沿,立马停止定时器计数
        dis=(TH0*256+TL0)*1.09/58;//先取出定时器里的时间值,之后再将定时器置0
        flag=1;//将标志位置0
        TH0=0;
        TL0=0;
}
void UsartConfiguration();
void Delay_1ms(uint i);
/********************************************************************
* 名称 : Com_Int()
* 功能 : 串口中断子函数
* 输入 : 无 * 输出 : 无
***********************************************************************/
void Com_Int(void) interrupt 4
{
  uchar i;
  uchar receive_data;        
  EA = 0;

  if(RI == 1) //当硬件接收到一个数据时,RI会置位
        {                 
                RI = 0;
                receive_data = SBUF;//接收到的数据
                if(receive_data == 'A')         
                {
                        L_go;
                        R_go;
                }
                if(receive_data == 'B')         
                {
                        R_back;
                        L_back;
                }
                if(receive_data == 'C')         
                {
                        L_stop;
                        R_stop;
                }
                if(receive_data == 'D')         
                {
                        L_back;
                        R_go;
                }
                if(receive_data == 'E')         
                {
                         L_go;
                         R_back;
                }

        }

                for(i=0; i<36; i++)
                {
                        SBUF = '1';   //将要发送的数据放入到发送寄存器
                        while(!TI);          //等待发送数据完成
                        TI=0;                  //清除发送完成标志位
                        Delay_1ms(1);
                }
                EA = 1;
}

/*******************************************************************************
* 函 数 名       : main
* 函数功能                   : 主函数
* 输    入       : 无
* 输    出       : 无
*******************************************************************************/

void main()
{
        PS=1;
        PX0=0;
        UsartConfiguration();
        csbbz();
        while(1);        
}


void UsartConfiguration()
{        
        SCON=0X50;                        //设置为工作方式1,8位数据,可变波特率
        TMOD=0X21;                        //设置计数器工作方式2
        PCON=0X00;                        //波特率不加倍
        TH1=0XFd;                    //计数器初始值设置,9600@11.0592MHz
        TL1=0XFd;
        TR1=1;                                        //打开计数器
        ES = 1;         //开串口中断
  EA = 1;         //开总中断
}

void Delay_1ms(uint i)//1ms延时
{
  uchar x,j;
  for(j=0;j<i;j++)
    for(x=0;x<=148;x++);
}



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏3 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2019-4-1 18:12 | 只看该作者
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表