久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2000|回復: 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++);
}



回復

使用道具 舉報

ID:1 發表于 2019-4-1 18:12 | 顯示全部樓層
本帖需要重新編輯補全電路原理圖,源碼,詳細說明與圖片即可獲得100+黑幣(帖子下方有編輯按鈕)
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日本一区二区高清视频 | 999久久久久久久 | 国产在线aa | 一区二区三区在线电影 | 国产精品一区二区久久 | 欧美激情精品久久久久久免费 | 日韩久久网 | 国产在线网址 | 国内自拍偷拍一区 | 影音先锋中文字幕在线观看 | 欧美精品在线播放 | 免费的日批视频 | 国产精品免费一区二区三区 | 色综合av | 在线观看视频亚洲 | 日本精品在线播放 | 欧美无乱码久久久免费午夜一区 | 1000部精品久久久久久久久 | 色999日韩| 久久伊人精品一区二区三区 | av入口| 一区二区三区精品 | 欧美一区二区免费视频 | 97av视频在线 | 国产综合精品一区二区三区 | 国产精品色综合 | 一级黄色夫妻生活 | 欧美在线一区二区三区 | 午夜免费精品视频 | 国产精品视频免费看 | 精品国产乱码久久久久久影片 | 亚洲欧美成人影院 | 成人字幕网zmw| 国产羞羞视频在线观看 | 日韩精品免费在线观看 | 国产成人精品一区二区三区四区 | 紧缚调教一区二区三区视频 | 国产精品久久久久久吹潮 | 国产精品视频一区二区三区 | 国产一区二区三区精品久久久 | 亚洲一区二区三区福利 |