歡迎大家關注部落客的公衆号 大海電子,在大海電子公衆号裡會和大家分享我的一些看法和知識。
不定期的會釋出一些有趣的硬體作品及電路分析、軟體源碼分享。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmLxQTNxQjNwETMwITOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
基于STM32和PS2的遙控無線小車一、所需材料二、硬體連接配接三、程式源碼四、調試
需要以下源碼工程請掃碼關注大海電子,回複“基于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"
#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;
}
四、調試
- 若轉動反向反了則說明電機正負或者左右反了,調整線和程式均可以解決。
- 建議使用18650锂電池供電,5号電池電壓過低了些,若使用4驅方式,需要增加升壓闆,并且5号電池耗電很快。
- 上面的源碼并非全部源碼,簡單的頭檔案等,LED及IO初始化等都為寫入,如果需要完整的打開連結通過旺旺與我索要。