Arduinowilliam hill官网
直播中

fullmous

12年用户 32经验值
擅长:控制/MCU
私信 关注
[经验]

蓝牙遥控小车帖子的补充:源代码




//蓝牙遥控小车

//Arduino 源程序

//定稿日期:2016-3-16

//程序功能简介:

//程序采用软件PWM方式,控制两支直流电机的运行行为,实现直行、后退、左转和右转动作。

//操作者使用Android手机的蓝牙功能发出指令,操控小车动作。

//操作者还通过蓝牙对小车的动作参数进行调试。

//使用自定义串口收发数据

//使用软件PWM,输出引脚可任意制定

//使用Atmega48芯片

//Arduio 版本1.0.5

#include   

#include   

#include

#include "usart.h"


unsigned int counter;   //PWM计数器

unsigned char wCnt = 0; //接收字计数

unsigned int pwm_LH;    //左电机高电平计数

unsigned int pwm_RH;    //右电机高电平计数

unsigned char lDirect;  //左电机运转方向

unsigned char rDirect;  //右电机运转方向

unsigned int LP = 0;

unsigned int RP = 0;

unsigned int LD = 0;

unsigned int RD = 0;


unsigned int PWM[6];    //存放当前PWM参数的整数型数组,全局变量


unsigned char inputString[8];         // 存输入数据字符串变量

boolean stringComplete = false;  // 数据串结束标志


//定时器2初始化函数

void timer2_init()  

{  

cli();

TCCR2B = 0x00; //

TCNT2 = 0xF6; //

TCCR2A = 0x00;

TCCR2B = 0x02; //

TIMSK2 = 0x01; //定时器2中断允许

sei();

}  



//定时器2中断服务函数

//PWM波形产生器

ISR(TIMER2_OVF_vect)

{  

TCNT2 = 0xF6; //

counter++;

  if(counter == 0x3ff)

  {

   if (rDirect == 1)

     bitSet(PORTD,5);

   else

     bitSet(PORTD,4);


   if (lDirect == 1)

     bitSet(PORTD,7);

   else

     bitSet(PORTD,6);

   counter = 0;

  }

  if(counter == pwm_RH)

  {

   bitClear(PORTD,4);

   bitClear(PORTD,5);

  }

  if(counter == pwm_LH)

  {

   bitClear(PORTD,6);

   bitClear(PORTD,7);

  }


}

//电机运行函数

void Move(unsigned int LS,unsigned charLD,unsigned int RS,unsigned char RD)

{            

asm("BCLR 7");  //关中断

pwm_LH = LS;

pwm_RH = RS;

lDirect = LD;

rDirect = RD;

asm("BSET 7");  //开中断        

}


//获取EEPROM数据函数

//功能:从EEPROM里顺序读出六个PWM参数,存入PWM数组

void GetData()

{

unsigned char bytes[2];      //暂时存放PWM参数的字节数组,全局变量

unsigned char i;

unsigned char j;

unsigned char k;

  for(i = 0;i < 6;i++)                         //for循环,读六个参数

  {

   for (j = 0;j < 2;j++)           //内循环,每次读两个字节

    {

     k = i * 2 + 1 - j;             //地址计算

      bytes[j] = EEPROM.read(k);       //EEPROM读操作

    }

   PWM = word(bytes[0], bytes[1]);      //将读出的两个字节合成一个PWM整数数据

  }

}


//数据发送函数

//功能:将一个整数拆分成四个ASCII代码,通过蓝牙串口发出的函数。

//例如:整数784,将拆分成;' ','7','8','4'四个字符

void Number(int val)

{

  inttmp;                //中间变量

unsigned char i;           //循环计数变量

unsigned char buf[4];         //存字符数组


  tmp= val / 1000;

buf[0] = tmp + 0x30;  //获得千位


  val= val % 1000;

  tmp= val / 100;

buf[1] = tmp + 0x30;  //获得百位


  val= val % 100;

  tmp= val / 10;

buf[2] = tmp + 0x30;  //获得十位


  val= val % 10;

  buf[3] = val + 0x30;    //获得个位


  for(i = 0;i < 4;i++)

  {

   if (buf == 0x30)    //从高位整理,如果是0,则转换成空格。

     buf = 0x20;

   else

     break;

  }

Usart_Transmit(buf[0]);      //通过蓝牙串口连续发出四个字符。

Usart_Transmit(buf[1]);

Usart_Transmit(buf[2]);

  Usart_Transmit(buf[3]);

}



void setup() {

timer2_init();

Usart_Init(9600);

sei();

PORTD = 0x00;

DDRD  = 0xF0;

GetData();    //初始化PWM参数

}




void loop() {


unsigned char buf[6];         //存连续字符的数组

unsigned char index = 0;    //存索引值变量

unsigned char i;

unsigned char k;

unsigned int para;                //PWM数据变量

delay(500);

  if(stringComplete == true)   //分解手机传过来的参数

{                              //格式是:#n%dddd

    k= 0;                      //其中:n 为索引(地址);dddd 为数据

   index = 0;

   for (i = 0;i <= wCnt ;i++)

    {

     if (inputString == '%')

     {

       index = inputString[i-1] - 0x30; //获得索引

       k = 0;

     }

     else

     {

       buf[k] = inputString - 0x30; //获得数据

       k++;

     }

    }

   para = 0;

   for (i = 0;i < k-1;i++)

     para = para * 10 + buf;


   PWM[index] = para;       //将得到的整数参数立即存入对应的PWM数组单元,修改当前运行参数

   buf[1] = lowByte(para);   //将整数转换成两个字节。

   buf[0] = highByte(para);

   index = index * 2;            //计算EEPROM地址

   EEPROM.write(index, buf[1]);  //写入EEPROM低位在前

    index++;

   EEPROM.write(index, buf[0]);  //高位在后


   stringComplete = false;

   wCnt = 0;

  }

}



ISR(USART_RX_vect)

{

unsigned char command=0;

  inti;

command = UDR0;             //接收数据

inputString[wCnt] = command;

wCnt++;

  if(command == 13) {

   stringComplete = true;

   wCnt--;

  }

else if (command == 10)

  {

   stringComplete = false;

   wCnt = 0;

  }

switch (command) {

case '@':

   GetData();       //EEPROM中读出数据

   for (i = 0;i < 6;i++)

    {

     Number(PWM);       //通过蓝牙回传,Android手机上会有显示

    }

   wCnt = 0;

   break;

case '#':            //得到手机发回的修改参数数据

   break;

case  'w' :     // 接收到 'w',前进

   LP = PWM[0];

   RP = PWM[1];

   LD = 1;

   RD = 1;

   wCnt = 0;

   break;

case  'x' :     // 接收到 'x',后退

   LP = PWM[0];

    RP = PWM[1];

   LD = 0;

   RD = 0;

   wCnt = 0;

   break;

case  'a' :     // 接收到 'a',左转

   LP = PWM[2];

   RP = PWM[3];

   LD = 0;

   RD = 1;

   wCnt = 0;

   break;

case  'd' :     // 接收到 'd',右转

   LP = PWM[4];

   RP = PWM[5];

   LD = 1;

   RD = 0;

   wCnt = 0;

   break;

case  's' :     // 接收到 's',停止电机

   LP = 0;

   RP = 0;

   LD = 1;

   RD = 1;

   wCnt = 0;

   break;

default:

   LP = 0;

   RP = 0;

   LD = 1;

   RD = 1;

  }

Move(LP,LD,RP,RD);

}


感兴趣的朋友可以跟帖,我将又问必答。



回帖(10)

tigerrocy

2016-3-21 16:38:31
好好好好好好好好好好
举报

bluest1234

2016-3-22 10:12:53
谢谢 分享   准备动手也做一个 ~~~~~~~~~~~~~~~~~
举报

张电子

2016-3-22 22:13:43
#include "usart.h"  

usart哪里下载啊?
举报

h1654155947.7788

2016-3-22 22:18:58
TB2Qd8olFXXXXa2XpXXXXXXXXXX_!!862076816.jpg
举报

更多回帖

×
20
完善资料,
赚取积分