蓝牙小车_蓝牙小车程序 - CSDN
精华内容
参与话题
  • 51单片机蓝牙小车

    千次阅读 多人点赞 2020-07-30 08:58:28
    51单片机蓝牙小车(是我大二做的一个课程设计,小菜鸟一个,欢迎大家指正和参考。) 摘要 本次设计选择基于蓝牙遥控的多功能智能小车为对象。选用STC98C52RC单片机作为主控芯片,电机驱动采用L293N ,...

     

    51单片机蓝牙小车(是我大二做的一个课程设计,小菜鸟一个,欢迎大家指正和参考。)

     

    摘要   本次设计选择基于蓝牙遥控的多功能智能小车为对象。选用STC98C52RC单片机作为主控芯片,电机驱动采用L293N ,电源部分采用两节3.7V锂电池供电.采用C语言模块化编程,提高开发效率.蓝牙控制功能.用按键或遥控器来控制小车.

     

    关键词  

    51单片机

    L298N_电机驱动

    蓝牙遥控

     


    目 录
    1 前言 1
    11 系统研究背景 1
    12 系统研究的意义和目的 1
    2 系统概述 2
    21 系统的结构 2
    22 系统的功能 2
    23 开发环境 2
    3 系统实现 3
    31 传感器技术 3
    32 其它相关技术 3
    33 硬件实现 3
    34 软件实现 3
    35 系统测试 3
    4 系统使用说明 4
    5 总结 5
    6 参考文献 6


    1. 前言
    1.1.     系统研究背景
     

            蓝牙属于短距离内进行无线控制和收发的通信技术,伴随着科技的飞跃性发展,也让蓝牙找到了发展的空间,它可以代替和取代落后的数字化硬件设备之间繁琐的电缆连接。在蓝牙创造的初期,没有人预料到蓝牙会有如此大的潜力和前景,而现在的发展也是完全超出了我们的预期,因为蓝牙的安全性高,制造成本低廉和所消耗的功率也是同类产品中最低的,所以被很多人使用,越来越受到了广大消费者的欢迎,基于蓝牙技术的产品也在不断的更新和投入市场。

           蓝牙技术是近年来出现的新技术是一种短距离无线通信和信息传输的新型通讯科技,它使数据线的硬件设备接收更方便快捷。它可以广泛应用于世界各地,是一个蓝牙设置一个通用的范围,频率调制技术的使用,以防止外部干扰和多一些。低成本,低功耗和小辐射,和加密设置,让蓝牙的安全性更高;应用范围广,这些特点使得蓝牙技术被广泛的应用在我们日常生活中的蓝牙也支持一对一和一对多传输的通信连接,和多个蓝牙成为微网,也有网络的特点。

         在现在的智能时代,小车智能控制,方便了人们的使用。在51单片机的基础下,通过蓝牙来控制小车的驾驶。



    1.2. 系统研究的意义和目的

     

            因为无线技术的广泛使用,我们在研究无线和有线通信技术的方法中了解到蓝牙系统的小区域性有很大的技术突破,在国际上也得到了广泛的采纳,在市场上也有很大的需求。这也使蓝牙技术的发展成为了趋势之一,蓝牙可以发送和接受语音和数据,满足了大多数人的需求,它也融合了其他相关产品的特点,也是这样技术变得更多样性。然而,蓝牙的安全性不足,而且在小区域范围内的一点对多点的通信受到了很大的限制,这些都是其本身需要改进和完善的

          可以使人们更方便,更简单的控制小车。实现了无线控制小车,摆脱了有线控制的不方便,更智能。


    2. 系统概述2.1.  系统的结构

                                                                                         系统框图

     

     



    2.2.  系统的功能

    51单片机的基础下,通过蓝牙来控制驱动,此驱动能把5~12V的电压,一部分给小车轮子转动,一部分通过降压,稳压,最终降为5V来供给此驱动,单片机和传感器供电。

     

    2.3.  开发环境

    AT89C5RC单片机开发环境。

              AT89C52是一种8位单片机,它是在MCS-51单片机系列上加强了一些功能后升级得到的产物。它的作用基本上就是把外界的数据和命令在中断和时钟的帮助下,在自身内部储存器上把使用者的数据进行处理。AT89C52 由8位的内部处理器,内部数据储存器(RAM,有256个字节)内部储存器有8K的大小,输入和输出双向口有32个,16位的定时器和5个两级中断,全双工串行通信口一个和时钟电路组成。

             AT89C52能够自主地执行给它的指令,也就是你把所需要的指令写在单片机的内部储存器上,它会一步步执行。AT89C52可以在功耗特别低的情况下工作,就是设置成空闲选择和掉电模式两种状态来实现低功耗。

     

                                                                         AT89C52

     

           单片机与外界的通讯是依靠它自身的I/O 口进行的,对单片机I/O 口的控制就是对单片机的控制。I/O 口的存在不仅可以实现数据的传输,还可以改变电平和信号的性质,最重要的一点就是I/O 口可以实现与外部不同电路的连接来使单片机工作。

             AT89C52单片机上我们通常使用的是4个独立的双向通用I/O 口:P0口、P1口、P2和P3口。由于外部设备的工作速率比较慢或者很快的时候,我们可以采用同步传送的方式,而单片机存在的异步传送是为了更加简练的和硬件连接进行传出。也可以通过中断传送和DMA传送来完成。AT89C52单片机还可以实现外部接口单独的编址和外部端口和存储器的统一编制两种方式。AT89C52单片机上一共有32个I/O 口,不同的I/O 口实线的作用和运行的方式都有其自己的方式,我也要通过这次课程设计,更好地了解,更熟练的运用。


    3.  系统实现3.1. 相关技术技术

    蓝牙技术,驱动模块,

    3.2.  硬件实现

    HC-06蓝牙模块

    其TX接单片机的RX,RX接单片机的TX,VCC接5V(或3.3V),GND接单片机的地。HC-06蓝牙模块是通过一款手机APP(蓝牙串口助手)作为中间媒介,在蓝牙串口助手发送相关的数据到串口,串口再把相关信息送到蓝牙模块,蓝牙模块再把相关信号送到单片机中。

                                                                                  HC-06蓝牙模块


                                                          HC-06蓝牙模块和51单片机连接



     

    L298N电机驱动模块,

    该该电机可以驱动2路直流电机,使能端ENA,ENB,为高电频有效,

    通过单片机的输入信号给IN1和IN2来控制左轮,输入信号给IN3和IN4来控制右轮

    IN1和IN2,分别给0,1  :正转

     IN1和IN2,分别给1,0  :反转

    IN1和IN2,分别给1,1 :停止

    IN1和IN2,分别给0,0  :停止

    IN3和IN4,分别给0,1  :正转

    IN3和IN4,分别给1,0  :反转

    IN3和IN4,分别给1,1 :停止

    IN3和IN4,分别给0,0  :停止

     

    L298N的主要引脚功能如下:

    +5V:芯片电压5V;

    VCC:电机电压,最大可接50V;

    GND:共地接法;

    Output1—Output2:输出端,接电机1;

    Output3—Output4:输出端,接电机2;

    EN1、EN2:高电平有效,EN1、EN2分别为 IN1和IN2、IN3和IN4的使能端;

    Input1~ Input4:输入端,输入端电平和输出端电平是对应的;

      

                                                                      L298N




    3.3.  软件实现
                     

                                                                         程序流程图

     

                

     

    51单片机,源程序:

     

    sbit in1 = P1^0;//左电机

    sbit in2 = P1^1;//左电机

    sbit in3 = P1^2;//右电机

    sbit in4 = P1^3;//右电机

    char i;

    /*前进*/

    void forward()

    {

    in1=1;

    in2=0;

    in3=1;

    in4=0;

    }

    /*后退*/

    void back()

    {

    in1=0;

    in2=1;

    in3=0;

    in4=1;

    }

                                                                                                                                                                                                 

    /*左转*/

    void left()

    {

    in1=1;

    in2=1;

    in3=1;

    in4=0;

    }

    /*右转*/

    void right()

    {

    in1=1;

    in2=0;

    in3=1;

    in4=1;

    }

    /*停止*/

    void stop()

    {

    in1=1;

    in2=1;

    in3=1;

    in4=1;

    }

    void main (void)               

    {

    TMOD=0x20;                         //设置T1为工作方式2

          TH1=0xfd;                        //装入初值,比特率为9600bps

          TL1=0xfd;

          TR1=1;                              //开启T1

          REN=1;                             //接收允许

          SM0=0;                             //方式1

          SM1=1;

          EA=1;                               //开全局中断

          ES=1;                                //开串口中断

    while(1)

    {i=SBUF;//SBUF为单片机接收到的数据,单片机接收到的数据都存放在SBUF里;

    RI=0;

    if (i==0x02){forward();}     //如果蓝牙助手发送0x02,小车前进

    if (i==0x08){back();}        //如果蓝牙助手发送0x08,小车后退

    if (i==0x01){left();}         //如果蓝牙助手发送0x01,小车左转

    if (i==0x03){right();}        //如果蓝牙助手发送0x03,小车右转

    if (i==0x05){stop();}        //如果蓝牙助手发送0x05,小车停止

    }

    }

     

     

    3.4.  系统测试

    小车能实现基本功能,成功地用蓝牙控制小车。测试了一段时间,单片机工作稳定,蓝牙稳定的控制,小车较好的按照控制方向行走。

     


    4.  系统使用说明

    1.      为小车装上两节锂电池,来供电。

    2.     打开总开关,在手机端,打开一个蓝牙通讯助手(在手机应用商店可以找到下载),连接上此小车的蓝牙(HC-06),如图:

     

                                        蓝牙 HC-06模块

     

     



     

    3.     然后就可以在手机端按相应的前进,后退,左转,右转,停止等,如图:

     

                                            APP

     

    解析:前进,后退,左转,右转,停止,都对应着程序中相应的信息,如图;

    当手机端发送 0x02 给蓝牙模块,就会执行 forward()函数; 小车会向前走

    当手机端发送 0x08 给蓝牙模块,就会执行 back();函数;,小车会向后走

    当手机端发送 0x01 给蓝牙模块,就会执行 left();函数;,小车会向左走

    当手机端发送 0x03 给蓝牙模块,就会执行 right()函数;,小车会向右走

    当手机端发送 0x05 给蓝牙模块,就会执行stop()函数;,小车会停止

    具体的编辑如图:

                                              APP2

     

    最后这是小车的整体模型;

     

                                                         整体图

     

      注:上面有个RC522读卡器的,哪个是方便后面的课设,在这里,大家可以忽略哈。

    5.  总结

         本设计采用的是STC89C52RC单片机,这主要是因为该单片机的稳定性比较好和执行指令的速度很快。还可以采用其它系列的单片机。电机驱动采用L293N ,稳定电压,充足地向直流电机供电和稳定控制;电源部分采用两节3.7V锂电池供电,电压稳定,电流充足,还可以循环充电,节能环保。采用C语言模块化编程,提高开发效率.蓝牙控制功能.用按键或遥控器来控制小车,简单方便经过自己不断的搜索努力以及老师的耐心指导和热情帮助,本设计已经基本完成。

            过这次课程设计,使我深刻地认识到学好专业知识的重要性,也理解了理论联系实际的含义,并且检验了大学两年的学习成果。虽然在这次设计中对于知识的运用和衔接还不够熟练。但是我将在以后的工作和学习中继续努力、不断完善。这两个月的设计是对过去所学知识的系统提高和扩充的过程,为今后的发展打下了良好的基础。  由于自身水平有限,设计中一定存在很多不足之处,敬请各位批评指正.


    6.  参考文献

    C语言程序设计 :清华大学出版社作者:谭浩强

    51单片机C语言教程:电子工业出版社 ,作者:郭天祥

     

    希望对你有帮助。

     

    为了大家方便,我上传了手机APP在网盘:https://pan.baidu.com/s/1UNjlUhUQa25K2RNW8hjwOQ

      提取码:wn7k 

     

     

     

    展开全文
  • Arduino智能小车——蓝牙小车

    万次阅读 多人点赞 2020-05-19 10:53:50
    Arduino智能小车——蓝牙小车  上一章我们完成了小车的运动控制,虽然小车已经可以运动,但是不能远程遥控,不够高大上。在这一篇,我们将尝试用手机蓝牙遥控小车。蓝牙模块  蓝牙( Bluetooth® ):是一种无线...

    Arduino智能小车——蓝牙小车

      上一章我们完成了小车的运动控制,虽然小车已经可以运动,但是不能远程遥控,不够高大上。在这一篇,我们将尝试用手机蓝牙遥控小车。

    蓝牙模块

      蓝牙( Bluetooth® ):是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换(使用2.4—2.485GHz的ISM波段的UHF无线电波)。

      我们在此使用的蓝牙模块(HC-05)已经在内部实现了蓝牙协议,不用我们再去自己开发调试协议。这类模块一般都是借助于串口协议通信,因此我们只需借助串口将我们需要发送的数据发送给蓝牙模块,蓝牙模块会自动将数据通过蓝牙协议发送给配对好的蓝牙设备。

    串口通信

      由于要借助串口实现蓝牙通信功能,所以我们在此要先了解下Arduino的串口通信。

      Arduino UNO开发板上的串口为0->RX,1->TX,在开发板内部也已经配置好了串口的功能,我们只需调用函数借口即可。以下列出串口通信里面常用的函数,并加以简单解释,详细用法可在用到时自行查询。

    开启串行通信接口并设置通信波特率

    Serial.begin(speed); 
    

    关闭串口通信

    Serial.end();    
    

    判断串口缓冲器是否有数据写入

    Serial.available();
    

    读取串口数据

    Serial.read();    
    

    返回下一字节(字符)输入数据,但不删除它

    Serial.peek();   
    

    清空串口缓存

    Serial.flush();    
    

    写入字符串数据到串口

    Serial.print();    
    

    写入字符串数据+换行到串口

    Serial.println(); 
    

    写入二进制数据到串口

    Serial.write();     
    

    read时触发的事件函数

    Serial.SerialEvent();
    

    读取固定长度的二进制流

    Serial.readBytes(buffer,length);
    

    打印接到数据十进制表示的ascii码

    Serial.println(incomingByte, DEC);
    

    蓝牙模块连接

    TX: 接Arduino UNO开发板"RX"引脚
    RX: 接Arduino UNO开发板"TX"引脚
    GND: 接Arduino UNO开发板"GND"引脚
    VCC: 接Arduino UNO开发板"5V"或"3.3V"引脚

    手机蓝牙助手

      想实现手机蓝牙遥控小车,手机APP是必不可少的,目前网上有很多蓝牙串口助手,省去了我们自己写APP的时间,当然如果朋友你有能力或者想自己DIY的话也可以尝试自己写APP,在这里我推荐大家用这款手机蓝牙助手(百度上搜手机蓝牙串口助手就可以搜到,挺好用的)

      如果不想自己去找的话可以到我的百度网盘下载 [点击这里下载](http://pan.baidu.com/s/1pKClRTL)

      下载并安装后打开APP,在这里可能会提示你有新版本请求更新,建议点击以后再说(暂时不更新),以我的经验,一般点击立即更新都会更新失败。

      进入主界面,左上角会提示"蓝牙未连接",这个时候我们可以先对蓝牙助手的界面进行自定义设置。点击右下角的三个点(在我这里是这样的,其他手机可能不同,如果没有这三个点可以试着点击手机的功能键),选择“更多”。
      然后选择“地面站设置”进入自定义界面,往下拖动,找到“自定义按键[x]”,在此我们对按键[1][2][3][4][6]进行自定义设置。
    **  点击自定义按键[1],将其“显示名称”属性改为“停止”,“点击发送”属性改为“00”,并点击“确定”保存**
    同理更改其他按键:

    点击自定义按键[2],将其“显示名称”属性改为“前进”,“点击发送”属性改为“01”,并点击“确定”保存
    点击自定义按键[4],将其“显示名称”属性改为“左转”,“点击发送”属性改为“03”,并点击“确定”保存
    点击自定义按键[5],将其“显示名称”属性改为“后退”,“点击发送”属性改为“02”,并点击“确定”保存
    点击自定义按键[6],将其“显示名称”属性改为“右转”,“点击发送”属性改为“04”,并点击“确定”保存

      以上修改的属性值即为我们点击对应按键之后,蓝牙串口助手自动通过蓝牙发送的数据,与上一篇所定义的小车的几个状态一致,这样方便在Arduino在接收到蓝牙模块的数据后对小车的状态进行控制。

    #define STOP      0
    #define FORWARD   1
    #define BACKWARD  2
    #define TURNLEFT  3
    #define TURNRIGHT 4
    

    修改后属性如下图

    下面就来看看我们修改的效果吧,点击“模式切换”

    这时候你就可以看到我们自定义的按键咯,看看修改前后的对比吧。
      接下来我们将连接蓝牙,仍然点击右下角的三个点,然后点击“连接”
      一般没有连接过蓝牙模块的时候“已配对的设备”下面没有可选择的设备名称,因此我们要点击“扫描新设备”来检测我们的蓝牙模块,扫描成功后蓝牙模块的名称将显示在“已配对的设备”一栏中
      点击我们的蓝牙模块的名称,输入密码进行配对。配对成功后在蓝牙串口助手的左上角会显示“蓝牙已连接”字样,恭喜你,这时候你已经连接成功。

    小科普:
      蓝牙模块上电(只简单连接"VCC"和"GND"引脚)之后,其他蓝牙设备即可与其连接,一般蓝牙模块默认初始连接密码为"0000"或"1234",如果连接不上蓝牙,请尽快与厂商或者店家联系。蓝牙模块上电后LED指示灯不断闪亮,当有设备连接预期连接之后会隔一段闪两下,蓝牙串口助手也会有相应已连接的提示。

    ##Arduino代码编写
    新建一个工程,将下面代码复制到工程内

    #define STOP      0
    #define FORWARD   1
    #define BACKWARD  2
    #define TURNLEFT  3
    #define TURNRIGHT 4
    
    int leftMotor1 = 4;
    int leftMotor2 = 5;
    int rightMotor1 = 6;
    int rightMotor2 = 7;
    
    void setup() {
      // put your setup code here, to run once:
      Serial.begin(9600);
      pinMode(leftMotor1, OUTPUT);
      pinMode(leftMotor2, OUTPUT);
      pinMode(rightMotor1, OUTPUT);
      pinMode(rightMotor2, OUTPUT);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      //usart read
      if(Serial.available()>0)
      {
        char cmd = Serial.read();//读取蓝牙模块发送到串口的数据
      
        Serial.print(cmd);
        motorRun(cmd);
          
      }  
    }
    void motorRun(int cmd)
    {
      switch(cmd){
        case FORWARD:
          Serial.println("FORWARD"); //输出状态
          digitalWrite(leftMotor1, HIGH);
          digitalWrite(leftMotor2, LOW);
          digitalWrite(rightMotor1, HIGH);
          digitalWrite(rightMotor2, LOW);
          break;
         case BACKWARD:
          Serial.println("BACKWARD"); //输出状态
          digitalWrite(leftMotor1, LOW);
          digitalWrite(leftMotor2, HIGH);
          digitalWrite(rightMotor1, LOW);
          digitalWrite(rightMotor2, HIGH);
          break;
         case TURNLEFT:
          Serial.println("TURN  LEFT"); //输出状态
          digitalWrite(leftMotor1, HIGH);
          digitalWrite(leftMotor2, LOW);
          digitalWrite(rightMotor1, LOW);
          digitalWrite(rightMotor2, HIGH);
          break;
         case TURNRIGHT:
          Serial.println("TURN  RIGHT"); //输出状态
          digitalWrite(leftMotor1, LOW);
          digitalWrite(leftMotor2, HIGH);
          digitalWrite(rightMotor1, HIGH);
          digitalWrite(rightMotor2, LOW);
          break;
         default:
          Serial.println("STOP"); //输出状态
          digitalWrite(leftMotor1, LOW);
          digitalWrite(leftMotor2, LOW);
          digitalWrite(rightMotor1, LOW);
          digitalWrite(rightMotor2, LOW);
      }
    }
    

      朋友们大概也发现了,这个代码和上一篇的代码基本上相同,只不过增加了串口的内容。

    ##代码详解
      串口初始化函数,想要通过串口的库函数对串口进行操作,必须在void set_up()函数中对其进行初始化。

    Serial.begin(9600);
    

      在void loop()函数内,加入了检测串口接收内容的函数,并将接收到的命令输入到 void motorRun(int cmd)函数中控制小车运动。

    if(Serial.available()>0)
      {
        char cmd = Serial.read();
      
        Serial.print(cmd);
        motorRun(cmd);
      }  
    

    蓝牙小车测试

      下载程序之后,重新连接蓝牙模块,切换到我们自定义的按键界面,快试试蓝牙遥控小车吧。

    附件

    安卓手机蓝牙串口点击下载,也可以复制链接 https://download.csdn.net/download/qq_16775293/11165678 到浏览器下载。

    欢迎各位有兴趣的朋友加入Q群1:789127261点评、交流

    展开全文
  • 手把手教你做蓝牙小车(一)

    万次阅读 多人点赞 2016-11-07 17:41:07
    遥控车是不是都玩过? 有没想过自己攒一个?

    第1节 选择Arduino开发板

    1.1 Arduino是什么

    对Arduino,官方有一堆解释。
    作为一个软件程序猿,在我眼里,Arduino是学习“可怕硬件”的一个便捷通道。它把复杂的硬件名称,属性给我们隐藏起来,只需要一些简单的软件知识,就可以学习硬件开发。

    1.2 怎么选择Arduino开发板

    1.2.1 官方版本还是兼容版本

    Arduino是开源项目,硬件结构,软件设计都开源。
    所以不存在盗版的问题。
    官方版质量肯定是杠杠的,但价格也贵。
    两者价格数字差不多,一个卖人民币,一个卖美元。
    不差钱就买官方版,否则兼容版也不错。

    1.2.2 Uno还是Mega

    Arduino有一系列各种用途的开发板,最常见的有两种,Uno和Mega。
    Uno价格便宜一些,功能简单。
    Mega价格比Uno贵二十多块,官方版贵二十多美元,兼容版贵二十多人民币。

    大家买Arduino开发板,主要用途就是学习,要求能方便的了解到更多特性。
    Uno接口太少,比如做个小车,接了四个马达后,基本就不能再添加其他模块了。
    如果你要做个蓝牙小车,调试时噩梦就来了。因为Uno只有一个串口,蓝牙和USB共用。
    你的先拔下蓝牙模块的连接线才能上传程序,上传完成后,然后再插上蓝牙连接线才能开始测试。
    如果你不只是学习,而是要研发产品,要考虑产品的成本价。。。
    选择Mega也任然没有错,你可以现在Mega上完成开发,最后在Uno上做性能测试。

    所以,我的建议是选Mega。

    第2节 从HelloWorld开始

    我记得从学习C语言开始,都是先写个HelloWorld程序。
    Arduino我们也从这里开始吧。

    2.1 搭建开发环境

    官网下载Arduino集成开发环境(以后都简称Arduino IDE)。
    解压后,双击此目录下的arduino.exe,启动Arduino IDE。
    我这里是以Windows平台为例,Mac,Linux界面、操作基本相同,也可以参照本例学习。

    2.2 新建工程

    启动Arduino IDE,点击菜单 文件->新建(快捷键Ctrl+N),生成新的工程。

    点击菜单 文件->保存(快捷键Ctrl+S),保存生成的工程。
    文件名这里我填“HelloWorld”,Arduino IDE会生成一个名称叫“HelloWorld”的文件夹,并在这个文件夹下生成一个同名的HelloWorld.ino文件。

    .ino文件是Arduino工程的主文件,Arduino要求ino文件必须置于一个同名文件夹下

    2.3 Hello World

    新生成的工程自动生成了setup()loop()两个函数。
    我们先改改代码,输出“Hello World”,有点切身感受。稍后再来讲解代码结构。

    在setup函数里设置串口波特率

    void setup() {
    
      // put your setup code here, to run once:
      Serial.begin(9600);
    }

    用串口输出”Hello world!”

    void loop() {
      // put your main code here, to run repeatedly:
      Serial.println("Hello world!");
    }

    点右上角的按钮打开串口监视器(快捷键Ctrl+Shift+m)

    波特率必须和setup里设置的相同,本例是9600.

    可以看到不断输出“Hello world!”

    2.4 代码结构

    HelloWorld.ino文件就两个函数

    void setup()
    
    void loop()

    它们是怎么运行起来的呢?

    看下面这段代码

    void setup(void);
    void loop(void);
    
    int main(void) {
      setup();
    
      while(1) {}
        loop();
      }
    
      return 0;
    }

    是不是很清楚了。

    main和while这些代码去哪了呢?Arduino IDE隐藏了,让我们的代码结构更清晰。
    setup()只执行一次,用来放初始化的函数
    loop()不断循环执行,用来检查各传感器状态,驱动程序运行。

    2.5 Serial

    Arduino IDE通过串口和PC(或其他设备)通讯。
    在Arduino IDE中Serial就是串口的化身。
    注意,Serial是系统对象,不是类,所以使用时直接Serial.begin()。

    2.5.1 官网详述

    详细内容可以参看官网的描述:
    https://www.arduino.cc/en/Reference/Serial
    学习Arduino,官网要随时访问。

    2.5.2 Serial硬件结构

    Uno示例

    USB接口和0、1引脚都是接Serial

    Mega示例

    USB接口和0、1引脚都是接Serial
    18、19引脚是接Serial1
    16、17引脚是接Serial2
    14、15引脚是接Serial3

    第3节 控制LED灯开关

    Arduino自带了很多例子。
    Blink是其中为数不多的只要有Arduino开发板就可以开始学习的例子。

    菜单 文件->示例->01.Basic->Blink打开今天要讲的例子。

    3.1 setup函数

    void setup() {
      // initialize digital pin 13 as an output.
      pinMode(13, OUTPUT);
    }

    学习硬件开发,一个很大的门槛是要记住许多复杂的寄存器地址。
    Arduino的NB之处就在于她简化了这许多地址,定义了几种不同类型的硬件插口,称为引脚。
    编程时只需要对这几类引脚做操作就可以了。
    今天先讲最常用的引脚,DigitalPins。
    官网解释如下:
    https://www.arduino.cc/en/Tutorial/DigitalPins
    简单说就是一种可以输入或输出数字信号0,1的引脚。
    某个引脚是用来输入还是输出信号,就通过pinMode函数来定义。

      pinMode(13, OUTPUT);

    这段代码的意思是编号为D13的引脚,定义为输出模式。

    3.2 为什么是D13引脚?

    因为D13引脚连接着一个焊接在Arduino开发板上的LED灯。
    所以,如果没有可外接的LED模块,就用D13引脚来做演示。

    3.3 loop函数

    void loop() {
      digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
      delay(1000);              // wait for a second
      digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
      delay(1000);              // wait for a second
    }

    loop函数总共4行代码

    digitalWrite(13, HIGH);

    将D13置高,也就是通电。
    切记,只有之前将引脚设置为OUTPUT,digitalWrite才能生效。

    delay(1000);

    延时1秒,在这1秒钟,LED灯状态不变,即点亮状态。

    digitalWrite(13, LOW);

    将D13置低,也就是断电。

    delay(1000);

    延时1秒,在这1秒钟,LED灯状态不变,即熄灭状态。
    之后loop函数被再次执行,我们看到的现象就是LED灯一秒亮、一秒暗的不停闪烁。

    3.4 D13控制的LED灯在哪个位置?

    不同的开发板,D13控制的LED灯位置,颜色都略有不同。
    相信大多数看官我在下一样,都是搞软件出身的。根本分不清LED灯长啥样:P
    开发板连接到上电源(USB线接电脑也算)后,如果只有一个LED灯亮着,这个LED灯旁边肯定有一个“On”标记,这个是表示电源接通的LED灯。
    上传本例到开发板后,闪烁的那个就是我们要找到D13 LED灯了。可以在这个LED灯旁看到个‘L’标记。

    第4节 控制LED灯的亮度

    LED灯是最常见的Arduino模块,上一节我们讲了控制Arduino开发板自带的LED灯。
    这一节还讲LED灯,讲外接、可控亮度的LED灯。

    4.1 PWM

    先介绍个概念,Pulse Width Modulation简称PWM。
    数字接口只能输出0或1两种状态,PWM通过在0、1两种状态间快速切换,生成一个介于0、1之间的值。
    比如1000ms中,平均400ms处于1(高),平均600ms处于0(低),两种状态均匀分布,就输出了一个0.4的值。

    详细内容参加官网:
    https://www.arduino.cc/en/Tutorial/PWM

    4.2 LED模块

    你的LED模块可能是这样子

    也可能是这样子

    不管长什么样,只要单色可调光LED,都是三根线。
    标注字符IN的是控制线、VCC是电源线、GND是地线。

    4.3 连接模块

    Mega开发板,2-13引脚都支持PWM,随便选一个都可以。

    Uno开发板,3,5,6,9,10,11引脚支持PWM,可以在开发板上看到引脚数字边上有个’~’。

    LED灯IN连接到Mega D2引脚;VCC接到Mega 5V引脚;GND接到Mega GND引脚。

    早期的开发板,为了防止电压不稳定击穿电子器件,需要连接个电阻。
    现在的开发板,只在接马达时才需要增加电阻,惯常的做法是增加一块扩展板。

    4.4 修改代码

    4.4.1 修改引脚

    因为这次我们使用了D2引脚,所以需要修改此处的13为2

      pinMode(13, OUTPUT);

    还要修改此处的13为2

    void loop() {
      digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
      delay(1000);              // wait for a second
      digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
      delay(1000);              // wait for a second
    }

    点击菜单 项目->上传,上传代码到开发板。
    可以看到这个外接的LED灯也像内置的LED灯一样闪烁了。

    4.4.2 优化代码

    刚才我们因为更换引脚,修改了3处代码。
    在arduoni开发中,更换引脚是很经常发生的事,常见的做法是在setup函数之前增加宏定义

    define LED_PIN 2
    
    void setup() {
    ...

    将代码中的D2相关代码都用LED_PIN替换,以后再更换引脚就很方便了。

    4.5 调节LED亮度

    4.5.1 调整为固定值

    用analogWrite函数控制PWM引脚,第一个参数是引脚序号,第二个是输出到这个引脚的值,范围0~255.
    analogWrite(LED_PIN, 10)这行代码使LED灯发出微弱的光。

    void loop() {
      analogWrite(LED_PIN, 10);
    }

    4.5.2 动态调整亮度

    我们通过串口输入一个介于0-255的数字来调整LED灯亮度。

    本例我们将演示四个Serial对象函数的使用方法。

    4.5.1.1 初始化

    使用begin()函数在setup函数里设置串口波特率。

    void setup() {
      Serial.begin(9600);
      pinMode(LED_PIN, OUTPUT);
    }

    4.5.1.2 检测串口是否有数据输入

    Serial.available()返回true表示串口有数据待读取

    void loop() {
      while (Serial.available()) {
      ...

    4.5.1.3 从串口读入一个long型数字

    Serial.parseInt()读取串口中输入的字符串。如果输入的是非数字,会被解析为0.

    void loop() {
      while (Serial.available()) {
        Serial.parseInt();

    4.5.1.4 改变LED灯亮度

    analogWrite()函数用来给模拟接口写入数据。
    第一个参数指定引脚序号,第二个参数指定写入引脚的值。

    long ledLevel = 10;
    
    void loop() {
      while (Serial.available()) {
        ledLevel = Serial.parseInt();
      }
    
      analogWrite(LED_PIN, ledLevel);
    }

    因为analogWrite接受的值在0-255之间,所以代码可以做些优化。
    用uint8_t代替long型。

    uint8_t ledLevel = 10;
    
    void loop() {
      while (Serial.available()) {
        ledLevel = Serial.parseInt();
      }
    
      analogWrite(LED_PIN, ledLevel);
    }

    4.5.1.5 输出Debug信息

    print在串口输出参数信息。
    println在串口输出参数信息,并回车。

    uint8_t ledLevel = 10;
    void loop() {
      while (Serial.available()) {
        ledLevel = Serial.parseInt();
        Serial.print("ledLevel=");
        Serial.println(ledLevel);
      }
    
      analogWrite(LED_PIN, ledLevel);
    }

    4.5.1.6 串口模拟器设置修改

    串口模拟器稍作修改,右下角这里改成“没有结束符”。
    否则parseInt会把结束符解析成0,导致LED灯错误熄灭。

    4.6 测试


    /*******************************************************************/
    * 版权声明
    * 本教程只在CSDN安豆网发布,其他网站出现本教程均属侵权。

    *另外,我们还推出了Arduino智能硬件相关的教程,您可以在我们的网店跟我学Arduino编程中购买相关硬件。同时也感谢大家对我们这些码农的支持。

    *最后再次感谢各位读者对安豆的支持,谢谢:)
    /*******************************************************************/

    展开全文
  • 蓝牙小车

    千次阅读 2019-01-26 22:27:05
    建立在51单片机以及stm32f4单片机上的蓝牙小车,它真的只是一台车没有什么别的功能。(主要原因是我太菜了) 硬件 淘宝搜索 1.蓝牙小车底盘。 2. l298n驱动两个。 3. 51单片机最小核心板。 4. STM32F4核心板...

    概要

      建立在51单片机以及stm32f4单片机上的蓝牙小车,它真的只是一台车没有什么别的功能。(主要原因是我太菜了)
    

    硬件

    淘宝搜索
    1.蓝牙小车底盘。
    2. l298n驱动两个。
    3. 51单片机最小核心板。
    4. STM32F4核心板。
    5. 杜邦线一大堆。
    6. 口香糖电池。

    51单片机学习过程

    买了一本郭天祥老师的51单片机教程以及一块学习板,配合着b站上的教程看,主要是为了初步了解入门单片机。怎么说呢,学习起来还是有点感悟的。

    1. 开始我是对照着书本进行学习,然后学了怎么操作自己试了一下之后就直接下一章节了,没有得到充分的练习,以至于真正做车车的时候发现有很多东西稀里糊涂的,得翻书重新查。这里的教训就是,学以致用很重要,理论-实践-理论的三明治原理。(后来发现郭天祥老师的视频里留有充足的课后练习)
    2. 其次就是中间中断了一段时间没有学习,大学生活丰富多彩嘛嘻嘻。。。没人管就很容易滋生堕落的情绪,所以说拥有坚定的信念很重要。

    32单片机学习过程

    这个就更加曲折了。。一开始看这个32的代码,简直是看天书一样,以至于出现什么一周快速学习stm32从入门到放弃再到不行还是得学之类的事情。

    1. 没有充分吸取51单片机的学习教训,也是了解差不多就直接下一章了。因为一个是时间紧迫,一个是因为现阶段没有学习学长学姐们口中的《微机原理》balabala…的书,就只能学会这个单片机怎么用,基本的使用原理大概是怎么个回事,实在没法特别深入地学习。
    2. 发现学习东西啊还是多看看视频,不要闷声看书,有人讲课的效果比自己慢慢慢慢看书的效果更好,书本可以作为对课堂细节的补充,而课堂却可以快速令人掌握一件事物的基本框架。
    3. 总的来说这次是一次有意义的学习体验,入门一件事情首先先了解框架(51单片机),再通过视频巩固框架(stm32的视频),书本补充细节,然后实践实践再实践,过程中的问题及时问前辈,不要闭门造车,有时候学长的一句提醒顶得上自己翻阅两天的资料。

    51的程序

    #include<reg52.h>
    
    sbit IN1=P1^0; 
    sbit IN2=P1^1;
    sbit IN3=P1^2;
    sbit IN4=P1^3;
    sbit IN11=P1^4; 
    sbit IN22=P1^5;
    sbit IN33=P1^6;
    sbit IN44=P1^7;
    
    
    void Left_moto_go()      {IN1=0,IN2=1,IN11=0,IN22=1;}           //小车运动的正反转电平设置
    void Left_moto_back()    {IN1=1,IN2=0,IN11=1,IN22=0;}         
    void Left_moto_Stop()    {IN1=0,IN2=0,IN11=0,IN22=0;}                       
    void Right_moto_go()     {IN3=0,IN4=1,IN33=0,IN44=1;}        
    void Right_moto_back()   {IN3=1,IN4=0,IN33=1,IN44=0;}        
    void Right_moto_Stop()   {IN3=0,IN4=0,IN33=0,IN44=0;}         
    
    unsigned char  mode;  //用字符来作为运行的指令
    unsigned  int  flag;
    
    void delay(unsigned int k)
    {    
      unsigned int x,y;
      for(x=0;x<k;x++) 
      for(y=0;y<2000;y++);
    }
    
    
         void  TIME1()   //        选择使用定时器1;
    {
             TMOD=0x20;                        //并且工作模式2,8位
             TH1=0xfd;                //产生9600波特率,与蓝牙模块同步 ,因为当时购买的蓝牙模块出厂设置就是9600波特率。
             TL1=0xfd;
             SM0=0;                   //设置串口的工作模式为
             SM1=1;                           //传送8位数据
             REN=1;                           //串口通信允许接收
             TR1=1;                           //开定时器1
             EA=1;                           //允许总中断
             ES=1;                           //允许串口中断
    }
    int main()
    {
      TIME1();
      
      while(1)
     {
         if(flag)
         {
    	   ES=0;               //这里一定要清零,不然下一个周期定时器中断就没法判断是否接收到信息了
    	   
            if(mode=='1')        //这里采用数字作为通信          
            {  
    		                     
             Left_moto_go() ;   
             Right_moto_go() ;   
             delay(20); //延时函数一定要有。
            }
            if(mode=='3') 
            {
             Left_moto_back();   
             Right_moto_back();	   //back
             delay(20);
            }
            if(mode=='4')
            {
    	     Right_moto_go(); 
             Left_moto_Stop();     //left
             delay(10);	
            }
            if(mode=='5')
            {
              Left_moto_go();  
             Right_moto_Stop();    //right
             delay(10);
            }
           if(mode=='2')
            {
    		 Right_moto_Stop();  
             Left_moto_Stop();  
             delay(40);			   //stop
    	    }
    	    ES=1;
    	   flag=0;
         }
     }
    }
    
    void ser() interrupt 4
    {
    	RI=0;		    //接收中断标志
    	mode=SBUF;		  //将接收到的手机发送到缓冲区数据SBUF复制给mode
    	flag=1;    			   //说明已经接收数据完毕
    
    }
    

    这里比较简单,没有写pwm功能,将在stm32中使用pwm功能。

    32单片机

    这个花费了比较多的时间,一开始觉得天书,后来慢慢入门发现很多东西前人已经写好了,只要掌握使用的技巧就好了(毕竟我没有足够的专业知识,也不是搞弱电的)所以整个程序是建立在蓝牙模块的程序基础上写的。

    主函数

    #include "sys.h"
    #include "delay.h"  
    #include "usart.h"  
    #include "led.h"
    #include "pwm.h"
    #include "usmart.h"		
    #include "hc05.h" 	 
    #include "usart3.h" 	
    #include "string.h"	 
    
    int main(void)
    { 
        u16 pwmval=1; 
    	u16 speedlost=1; //转弯的时候用
    	u16 dang=1;
    	u8 reclen=0;  //检测获取数据
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
    	delay_init(168);      //初始化延时函数
    	uart_init(115200);		//初始化串口波特率为115200
    	TIM2_PWM_Init(500-1,84-1);	//84M/84=1Mhz的计数频率,重装载值500,所以PWM频率为 1M/500=2Khz.
    	TIM3_PWM_Init(500-1,84-1);
    	TIM9_PWM_Init(500-1,84-1);
    	usmart_dev.init(84); 		//初始化USMART		
    	LED_Init();					//初始化LED
    	delay_ms(1000);			//等待蓝牙模块上电稳定
     	HC05_Init();		//初始化ATK-HC05模块  
    	 										   	   
    	delay_ms(100);
    	USART3_RX_STA=0;
    	
     	while(1) 
    	{		
    
    		LED0=!LED0; 	     
    	 
    		if(USART3_RX_STA&0X8000)			//接收到一次数据了
    		{
     			reclen=USART3_RX_STA&0X7FFF;	//得到数据长度
    		  	USART3_RX_BUF[reclen]=0;	 	//加入结束符
    			if(reclen!=0) 		//控制DS1检测
    			{
    				
    				if(strcmp((const char*)USART3_RX_BUF,"+SPEED1")==0)  
    				 //设置挡位    //必须以+开头才可以啊!
    				{ 
    				 delay_ms(1);
                     LED1=!LED1;					
                     pwmval=1;
    				 dang=1;
    				}
    				if(strcmp((const char*)USART3_RX_BUF,"+SPEED2")==0)
    				{
    				 delay_ms(1);	
                     LED1=!LED1;					
                     pwmval=100;
    				 dang=100;
    				}
    				if(strcmp((const char*)USART3_RX_BUF,"+SPEED3")==0)
    				{ 
    				delay_ms(1);	
                    LED1=!LED1;					
                    pwmval=200;
    				dang=200;
    				}                                                          
    				
    				
    				if(strcmp((const char*)USART3_RX_BUF,"+FORWARD")==0)   
                   { 
    					LED1=!LED1;//测试用的,到时候可以删掉
    					TIM_SetCompare1(TIM9,pwmval);  //右边两个轮子分别接一个PE5,PE6
    					TIM_SetCompare2(TIM9,pwmval);
    					TIM_SetCompare1(TIM2,pwmval);  //左边两个轮子分别接一个PA0,PA1
    					TIM_SetCompare2(TIM2,pwmval); 
    					delay_ms(500);
    				}				
    				
    				if(strcmp((const char*)USART3_RX_BUF,"+BACK")==0)   
                   { 
    					LED1=!LED1;
    					TIM_SetCompare1(TIM3,pwmval);  //右边两个轮子分别接一个PC6789
    					TIM_SetCompare2(TIM3,pwmval);
    					TIM_SetCompare3(TIM3,pwmval);
    					TIM_SetCompare4(TIM3,pwmval);
    					delay_ms(500);
    					
    				}			
    				
    				
    				if(strcmp((const char*)USART3_RX_BUF,"+RIGHT")==0)   
                   { 
    					LED1=!LED1;
    					speedlost=pwmval+100;
    					TIM_SetCompare1(TIM9,speedlost);  //右边两个轮子分别接一个PE5,PE6   //右边轮子变慢
    					TIM_SetCompare2(TIM9,speedlost);
    					TIM_SetCompare1(TIM2,pwmval);  //左边两个轮子分别接一个PA0,PA1
    					TIM_SetCompare2(TIM2,pwmval); 
    					delay_ms(500);
    				}	
    				
    				
    				if(strcmp((const char*)USART3_RX_BUF,"+LEFT")==0)   
                   { 
    					speedlost=pwmval+100;
    					LED1=!LED1;//测试用的,到时候可以删掉
    					TIM_SetCompare1(TIM9,pwmval);  //右边两个轮子分别接一个PE5,PE6
    					TIM_SetCompare2(TIM9,pwmval); 
    					TIM_SetCompare1(TIM2,speedlost);  //左边两个轮子分别接一个PA0,PA1  //左边轮子变慢
    					TIM_SetCompare2(TIM2,speedlost); 
    					delay_ms(500);
    				}
    				
                 	if(strcmp((const char*)USART3_RX_BUF,"+STOP")==0)   
                  { 
    					LED1=!LED1;  //测试用的,到时候可以删掉
    					pwmval=500;
    					TIM_SetCompare1(TIM9,pwmval);  //右边两个轮子分别接一个PE5,PE6
    					TIM_SetCompare2(TIM9,pwmval);
    					TIM_SetCompare1(TIM2,pwmval);  //左边两个轮子分别接一个PA0,PA1
    					TIM_SetCompare2(TIM2,pwmval);
    					TIM_SetCompare1(TIM3,pwmval);  //右边两个轮子分别接一个PC6789
    					TIM_SetCompare2(TIM3,pwmval);
    					TIM_SetCompare3(TIM3,pwmval);
    					TIM_SetCompare4(TIM3,pwmval);                                    //全部停下
    					delay_ms(500);
    					pwmval=dang;
    				}				
    	
    			}
     			
     			USART3_RX_STA=0;	 
    		}	 															     				   
    		
    	}											    
    }
    
    
    
    

    pwm函数

    #include "pwm.h"
    #include "led.h"
    #include "usart.h"
     
    //TIM4 PWM部分初始化 
    //PWM输出初始化
    //arr:自动重装值
    //psc:时钟预分频数
    void TIM3_PWM_Init(u32 arr,u32 psc)
    {		 					 
    	//此部分需手动修改IO口设置
    	
    	GPIO_InitTypeDef GPIO_InitStructure;
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	TIM_OCInitTypeDef  TIM_OCInitStructure;
    	
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  	//TIM3时钟使能    
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); 	//使能PORTC
    	
    	GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM4); //GPIOC6复用为定时器3
    	GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_TIM4);
    	GPIO_PinAFConfig(GPIOC,GPIO_PinSource8,GPIO_AF_TIM4);
    	GPIO_PinAFConfig(GPIOC,GPIO_PinSource9,GPIO_AF_TIM4);
    	
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;           //GPIOC6
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
    	GPIO_Init(GPIOC,&GPIO_InitStructure);              //初始化PC6
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;           //GPIOC7
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
    	GPIO_Init(GPIOC,&GPIO_InitStructure);              //初始化PC7
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;           //GPIOC8
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
    	GPIO_Init(GPIOC,&GPIO_InitStructure);              //初始化PC8
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;           //GPIOC9
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
    	GPIO_Init(GPIOC,&GPIO_InitStructure);              //初始化PC9
    	  
    	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频
    	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
    	TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值
    	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
    	
    	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);//初始化定时器3
    	
    	//初始化TIM3 Channel 6789 PWM模式	 
    	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
     	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
    	TIM_OC1Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 4OC1
    	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR1上的预装载寄存器
    	TIM_OC2Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 4OC1
    	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR1上的预装载寄存器
    	TIM_OC3Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 4OC1
    	TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR1上的预装载寄存器
    	TIM_OC4Init(TIM3, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM3 4OC1
    	TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR1上的预装载寄存器
      
      TIM_ARRPreloadConfig(TIM3,ENABLE);//ARPE使能 
    	
    	TIM_Cmd(TIM3, ENABLE);  //使能TIM3
     
    										  
    }  
    
    void TIM2_PWM_Init(u32 arr,u32 psc)
    {		 					 
    	//此部分需手动修改IO口设置
    	
    	GPIO_InitTypeDef GPIO_InitStructure;
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	TIM_OCInitTypeDef  TIM_OCInitStructure;
    	
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);  	//TIM2时钟使能    
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 	//使能PORTA
    	
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource0,GPIO_AF_TIM2); //GPIOA0复用为定时器2
    	GPIO_PinAFConfig(GPIOA,GPIO_PinSource1,GPIO_AF_TIM2); //GPIOA1复用为定时器2
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
    	GPIO_Init(GPIOA,&GPIO_InitStructure);              //初始化PA0
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;  
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
    	GPIO_Init(GPIOA,&GPIO_InitStructure);              //初始化PA1
    	  
    	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频
    	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
    	TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值
    	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
    	
    	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStructure);//初始化定时器2
    	
    	//初始化TIM2 Channel 12 PWM模式	 
    	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
     	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
    	TIM_OC1Init(TIM2, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM2 4OC1
    	TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);  //使能TIM2在CCR1上的预装载寄存器
    	TIM_OC2Init(TIM2, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM2 4OC2
    	TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);  //使能TIM2在CCR2上的预装载寄存器
    
      
      TIM_ARRPreloadConfig(TIM2,ENABLE);//ARPE使能 
    	
    	TIM_Cmd(TIM2, ENABLE);  //使能TIM2
     
    										  
    }  
    
    
    void TIM9_PWM_Init(u32 arr,u32 psc)
    {		 					 
    	//此部分需手动修改IO口设置
    	
    	GPIO_InitTypeDef GPIO_InitStructure;
    	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    	TIM_OCInitTypeDef  TIM_OCInitStructure;
    	
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9,ENABLE);  	//TIM9时钟使能    
    	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); 	//使能PORTE
    	
    	GPIO_PinAFConfig(GPIOE,GPIO_PinSource5,GPIO_AF_TIM9); //GPIOE5复用为定时器9
    	GPIO_PinAFConfig(GPIOE,GPIO_PinSource6,GPIO_AF_TIM9); //GPIOE6复用为定时器9
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;           //GPIOE5 
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
    	GPIO_Init(GPIOE,&GPIO_InitStructure);              //初始化PE5/6
    	
    	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;           //GPIOE6	 
    	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        //复用功能
    	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
    	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
    	GPIO_Init(GPIOE,&GPIO_InitStructure);              //初始化PE6
    	  
    	TIM_TimeBaseStructure.TIM_Prescaler=psc;  //定时器分频
    	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
    	TIM_TimeBaseStructure.TIM_Period=arr;   //自动重装载值
    	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
    	
    	TIM_TimeBaseInit(TIM9,&TIM_TimeBaseStructure);//初始化定时器9
    	
    	//初始化TIM9 Channel 12 PWM模式	 
    	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式2
     	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
    	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //输出极性:TIM输出比较极性低
    	TIM_OC1Init(TIM9, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM9 4OC1
    	TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable);  //使能TIM9在CCR1上的预装载寄存器
    	TIM_OC2Init(TIM9, &TIM_OCInitStructure);  //根据T指定的参数初始化外设TIM9 4OC2
    	TIM_OC2PreloadConfig(TIM9, TIM_OCPreload_Enable);  //使能TIM9在CCR2上的预装载寄存器
        TIM_ARRPreloadConfig(TIM9,ENABLE);//ARPE使能 	
    	TIM_Cmd(TIM9, ENABLE);  //使能TIM2
     }  
    
    

    这里之所以调用这么多定时器,是因为另外的几个定时器被项目的其他功能占用了。
    这里就只放两个主要的函数吧,蓝牙和其他函数的代码放在总的程序目录里。(懒得拷贝了。。。)

    硬件连接

    原理图(啊别吐槽我灵魂画手了)
    在这里插入图片描述

    这里只上传51的连接
    调用了

    视频截图。。。
    在这里插入图片描述

    在这里插入图片描述

    恭喜你司机同志,秋名山一较高下。

    最后

    再次感谢教我搭建博客,教我做车车,教我开车车的学长学姐。希望自己大学四年能开个好头,继续学习哈。(不说了昨天C语言上机跪了(手动哭泣),得赶紧复习高数把分数捞回来才行。。。)

    展开全文
  • 蓝牙控制小车

    2020-07-22 23:30:46
    蓝牙控制小车源代码。下板可用
  • 手把手教你做蓝牙小车(三)

    千次阅读 2016-11-07 17:15:57
    遥控车是不是都玩过? 有没想过自己攒一个?
  • 手把手教你做蓝牙小车(二)

    万次阅读 2016-11-07 17:20:30
    遥控车是不是都玩过? 有没想过自己攒一个?
  • 蓝牙小车项目APP

    2020-07-21 09:56:50
    这是前面蓝牙小车项目使用的的APP源码,蓝牙小车项目资源链接http://download.csdn.net/download/huangweiqing80/10124241
  • 自己动手做一款蓝牙小车

    千次阅读 2019-07-27 14:21:17
    准备好杜邦线、HC-05蓝牙模块、单片机(我用的是粤嵌的51单片机,自己做一个最小系统也行)、小车底盘、电源、L298N、螺柱(固定零件用的)。如果想做的话请自己买这些零件,做出来的效果图片如下(我加了寻迹模块)...
  • 基于51单片机的蓝牙遥控小车程序【硬软件部分】

    万次阅读 多人点赞 2020-03-07 12:55:20
    ****这是我写的第一篇博客,如果有问题欢迎指正...小车模型一个(直流电机一对) 电池18650一对 HC-08蓝牙模块 蓝牙模块主要要掌握其基本参数以及工作原理即可,附下图。 L298模块 l298内部包含4...
  • 2、打开小车看到蓝牙模块指示灯在闪烁,打开手机搜索蓝牙,看到HC06,连接匹配,密码是1234,具体看提示操作;   若看到 YAHBOOM-L 之类名称的,不需要输入密码;只需打开手机APP,手机靠近小车蓝牙模块,APP就...
  • 基于51单片机的蓝牙智能小车——《入门篇》

    万次阅读 多人点赞 2018-08-29 10:02:38
    我认为在制作小车前需要有心里准备,要充满自信、满怀激情,学会坚持,切忌三分钟热度,半途而废。 在上一篇文章中我已经提到了制作智能小车所需要的材料,如果大家已经准备好材料,或是想进一步了解智能小车的...
  • STM32循迹+蓝牙小车

    千次阅读 多人点赞 2016-11-27 16:51:30
    stm32智能循迹小车+蓝牙控制+代码
  • 硬件课设一直拖到还有几天要毕业了才分享一下,做...3.代码部分是用verilog完成的,项目报告,完成代码,以及小车跑动的视频都在以下链接里,可以下载使用。 https://download.csdn.net/download/sinat_30372583/10...
  • 这个是蓝牙小车的下篇,上篇的地址为:http://blog.csdn.net/lpstudy/article/details/78992038。 源代码: https://github.com/lpstudy/bluetooth-car 此帖子为昨天发的帖子...
  • 安卓手机蓝牙控制智能小车 android程序设计

    万次阅读 热门讨论 2016-06-10 19:20:58
    项目名称: 安卓手机控制智能小车本文主要介绍手机端程序设计源码托管在地址:github.com/cyang812/Bluetooth_Car ...一、Bluetooth_Demo(通过按钮控制)1、这是最早开发的版本,通过连接蓝牙后,可实现通过按钮(B
  • 这是2016年底两周时间做的一个蓝牙小车,它分为上下两篇,本文是上篇。原本是发在了http://bbs.elecfans.com/ 的,不过由于我的博客都在CSDN上,因此我就把它们重新复制到这里来了。 原文地址:...
  • 假期和同伴做了一个android蓝牙控制小车的项目,他负责下位机代码实现,我负责上位机代码实现。但在蓝牙开发上的经验不算熟悉,在网上查找相关资料的时候也发现很多答案参差不齐,并且也不是用于蓝牙上位机连接的,...
  • stm32串口通过蓝牙透传接收到数据,解析,完成相应的函数功能(如小车的前进后退,亮灯、舵机控制); 蓝牙apk发送点击按钮后的数据,发送到单片机蓝牙端;   蓝牙apk界面 蓝牙源码  ...
  • 51超声波避障小车

    千次阅读 多人点赞 2018-12-26 13:24:11
    超声波避障小车 简介 本文小车的功能主要有两个:超声波测距避障,以及蓝牙遥控。主控芯片用的是STC89C52,电机驱动模块用的是L298N,超声波传感器HC-SR04,蓝牙模块使用的是HC-05,电机采用5V的直流电机。 总体设计...
1 2 3 4 5 ... 20
收藏数 1,458
精华内容 583
关键字:

蓝牙小车