欢迎大家关注博主的公众号 大海电子,在大海电子公众号里会和大家分享我的一些看法和知识。
不定期的会发布一些有趣的硬件作品及电路分析、软件源码分享。
需要以下源码工程请扫码关注大海电子,回复“基于STM32F103C8T6的PS2遥控小车源码及接线”,建议直接复制双引号里面的内容。(免费)
整个工程文件:(淘宝购买)
https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.4c651deb7q5Hra&id=582278394068
1、小车底盘
2WD(2驱):
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.12.fff43961B3dZVc&id=567079436225
4WD(4驱):
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.9.fff43961dgCABI&id=567173416961
2、STM32F103C8T6核心板
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.9.fff43961vbraDx&id=567200541464
3、PS2遥控器
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.15.fff43961KPX3S0&id=577723467175
4、L298N电机驱动模块
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.9.fff43961Oz8Sab&id=567173392291
5、18650电池
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.12.fff43961RsCgQd&id=577486077956
(5号充电电池)
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.12.fff43961dqhPEU&id=577324372710
6、18650电池座
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.9.437c3961h9AdcC&id=568450483270
(5号电池座,底盘自带)
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.9.fff43961dqhPEU&id=567280122150
7、杜邦线若干
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-17409464480.9.fff43961ozUBpi&id=567071877141
Main.c
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "pstwo.h"
/*********************************************************
功能:通过PS2控制小车运动
作者:大海电子
时间: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;
}