我们不仅销售产品,我们还传播知识
商品分类

基于STM32和PS2的遥控无线小车

一、所需材料
整个工程文件:(淘宝购买)

1、小车底盘

 2WD(2驱)

4WD(4驱):

2、STM32F103C8T6核心板

3、PS2遥控器

4、L298N电机驱动模块

5、18650电池

(5号充电电池)

6、18650电池座

(5号电池座,底盘自带)

7、杜邦线若干

二、硬件连接

基于STM32和PS2的遥控无线小车

三、程序源码

Main.c

#include "led.h"

#include "delay.h"

#include "sys.h"

#include "usart.h"  

#include "pstwo.h"

 

/*********************************************************


时间:180531

硬件平台:STM32F103C8T6

时钟:8Mhz

 

硬件引脚分配:

//手柄接口

DI=PB12;

DO=PB13 ;

CS=PB14;

CLK=PB15;

 

//L298N 电机驱动控制引脚

IN1=PA0;    //左侧电机正  

IN2=PA1; //左侧电机负  

IN3=PA2;    //右侧电机正    

IN4=PA3; //右侧电机负

 

**********************************************************/  

#define go {IN1=1;IN2=0;IN3=0;IN4=1;}

#define back {IN1=0;IN2=1;IN3=1;IN4=0;}

#define stop {IN1=1;IN2=1;IN3=1;IN4=1;}

#define turnleft {IN1=1;IN2=1;IN3=0;IN4=1;}

#define turnright {IN1=1;IN2=0;IN3=1;IN4=1;}

 

 

 int main(void)

 {  

 u8 key=0;

delay_init();       //延时函数初始化   

NVIC_Configuration();  //设置NVIC中断分组2:2位抢占优先级,2位响应优先级

uart_init(9600);   //串口初始化为9600

  LED_Init();      //LED端口初始化

PS2_Init();  

     

 

while(1)

{
 

key=PS2_DataKey();

 

 switch(key)

 {
 case 5:go;break;

 case 7:back;break;

 case 8:turnleft;break;

 case 6:turnright;break;

 

 default:stop;break;  

 }

if(key!=0)                   //有按键按下

     {
printf("%d  is  pressed  \r\n",key);

     }

// printf(" %5d %5d %5d %5d\r\n",PS2_AnologData(PSS_LX),PS2_AnologData(PSS_LY),

//                               PS2_AnologData(PSS_RX),PS2_AnologData(PSS_RY) );

       delay_ms(50);

}  

 }

 

 

pstwo.c

#include "pstwo.h"

#include "usart.h"

 

u16 Handkey;

u8 Comd[2]={0x01,0x42}; //开始命令。请求数据

u8 Data[9]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //数据存储数组

u16 MASK[]={
    PSB_SELECT,

    PSB_L3,

    PSB_R3 ,

    PSB_START,

    PSB_PAD_UP,

    PSB_PAD_RIGHT,

    PSB_PAD_DOWN,

    PSB_PAD_LEFT,

    PSB_L2,

    PSB_R2,

    PSB_L1,

    PSB_R1 ,

    PSB_GREEN,

    PSB_RED,

    PSB_BLUE,

    PSB_PINK

}; //按键值与按键明

 

//手柄接口初始化    输入  DI->PB12

//                  输出  DO->PB13    CS->PB14  CLK->PB15

void PS2_Init(void)

{
    //输入  DI->PB12

RCC->APB2ENR|=1<<3;     //使能PORTB时钟

GPIOB->CRH&=0XFFF0FFFF;//PB12设置成输入 默认下拉  

GPIOB->CRH|=0X00080000;   

 

    //  DO->PB13    CS->PB14  CLK->PB15

RCC->APB2ENR|=1<<3;    //使能PORTB时钟           

GPIOB->CRH&=0X000FFFFF;

GPIOB->CRH|=0X33300000;//PB13、PB14、PB15 推挽输出        

}

 

//向手柄发送命令

void PS2_Cmd(u8 CMD)

{
volatile u16 ref=0x01;

Data[1] = 0;

for(ref=0x01;ref<0x0100;ref<<=1)

{
if(ref&CMD)

{
DO_H;                   //输出以为控制位

}

else DO_L;

 

CLK_H;                        //时钟拉高

delay_us(50);

CLK_L;

delay_us(50);

CLK_H;

if(DI)

Data[1] = ref|Data[1];

}

}

//判断是否为红灯模式

//返回值;0,红灯模式

//   其他,其他模式

u8 PS2_RedLight(void)

{
CS_L;

PS2_Cmd(Comd[0]);  //开始命令

PS2_Cmd(Comd[1]);  //请求数据

CS_H;

if( Data[1] == 0X73)   return 0 ;

else return 1;

 

}

//读取手柄数据

void PS2_ReadData(void)

{
volatile u8 byte=0;

volatile u16 ref=0x01;

 

CS_L;

 

PS2_Cmd(Comd[0]);  //开始命令

PS2_Cmd(Comd[1]);  //请求数据

 

for(byte=2;byte<9;byte++)          //开始接受数据

{
for(ref=0x01;ref<0x100;ref<<=1)

{
CLK_H;

CLK_L;

delay_us(50);

CLK_H;

      if(DI)

      Data[byte] = ref|Data[byte];

}

        delay_us(50);

}

CS_H;

}

 

//对读出来的PS2的数据进行处理      只处理了按键部分         默认数据是红灯模式  只有一个按键按下时

//按下为0, 未按下为1

u8 PS2_DataKey()

{
u8 index;

 

PS2_ClearData();

PS2_ReadData();

 

Handkey=(Data[4]<<8)|Data[3];     //这是16个按键  按下为0, 未按下为1

for(index=0;index<16;index++)

{     

if((Handkey&(1<<(MASK[index]-1)))==0)

return index+1;

}

return 0;          //没有任何按键按下

}

 

//得到一个摇杆的模拟量  范围0~256

u8 PS2_AnologData(u8 button)

{
return Data[button];

}

 

//清除数据缓冲区

void PS2_ClearData()

{
u8 a;

for(a=0;a<9;a++)

Data[a]=0x00;

}

 

四、调试

  1. 若转动反向反了则说明电机正负或者左右反了,调整线和程序均可以解决。
  2. 建议使用18650锂电池供电,5号电池电压过低了些,若使用4驱方式,需要增加升压板,并且5号电池耗电很快。

发表评论

登录后才能评论
联系我们

联系我们

微信:13823392571

在线咨询:点击这里给我发消息

工作时间:周一至周五,9:30-18:30,节假日休息

微信客服
微信客服
分享本页
返回顶部