用cube移植PS2手柄–HAL库

STM32F4 PS2手柄移植HAL库,利用Cube进行设置

请按以下步骤进行





配置GPIO

D0 input
D1 output
D2 output
D3 output

详见下图

然后配置工程文件生成格式


生成MDK文件并用keil打开
下载下面链接的文件并开始移植

将文件内的delay.c sys.c ps2.c misc.c 进行移植
移植过程如下:

1.将delay.c sys.c ps2.c misc.c 四个文件放置在cube生成的MDK-ARM文件夹内; 2…将delay.h sys.h ps2.h misc.h 四个文件放置在cube生成的Inc文件夹
3. 在keil里面填入这几个.c文件

4.编译即可通过

code:

// ps2.c
#include "stm32f4xx_hal.h"
#include "misc.h"
#include "ps2.h"
#include "gpio.h"#define DELAY_TIME  delay_us(5); volatile int PS2_LX,PS2_LY,PS2_RX,PS2_RY,PS2_KEY;     //
uint16_t Handkey;
uint8_t Comd[2]={0x01,0x42};   //开始命令。请求数据
uint8_t Data[9]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//数据存储数组
uint16_t 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}; //按键值与按键明//向手柄发送命令
void PS2_Cmd(uint8_t CMD)
{volatile uint16_t ref=0x01;Data[1] = 0;for(ref=0x01;ref<0x0100;ref<<=1){if(ref&CMD){DO_H;                   //输出一位控制位}else DO_L;CLK_H;                        //时钟拉高DELAY_TIME;CLK_L;DELAY_TIME;CLK_H;if(DI)Data[1] = ref|Data[1];}delay_us(16);
}//判断是否为红灯模式  0x41=模拟绿灯  0x73=模拟红灯
//返回值;0,红灯模式
//        其他,其他模式
uint8_t 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 uint8_t byte=0;volatile uint16_t 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;DELAY_TIME;CLK_L;DELAY_TIME;CLK_H;if(DI)Data[byte] = ref|Data[byte];}delay_us(16);}CS_H;
}//对读出来的PS2的数据进行处理      只处理了按键部分         默认数据是红灯模式  只有一个按键按下时
//按下为0, 未按下为1
uint8_t PS2_DataKey()
{uint8_t index;PS2_ClearData();PS2_ReadData();Handkey=(Data[4]<<8)|Data[3];     //这是16个按键  按下为0, 未按下为1for(index=0;index<16;index++){        if((Handkey&(1<<(MASK[index]-1)))==0)return index+1;}return 0;          //没有任何按键按下
}//得到一个摇杆的模拟量    范围0~256
uint8_t PS2_AnologData(uint8_t button)
{return Data[button];
}//清除数据缓冲区
void PS2_ClearData()
{uint8_t a;for(a=0;a<9;a++)Data[a]=0x00;
}//void delay_init(uint8_t SYSCLK)
//{//  SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟  HCLK/8
//  fac_us=SYSCLK/8;
//}//void delay_us(uint32_t nus)
//{
//  uint32_t temp;
//  SysTick->LOAD=nus*fac_us; //时间加载
//  SysTick->VAL=0x00;        //清空计数器
//  SysTick->CTRL=0x01 ;      //开始倒数
//  do
//  {//      temp=SysTick->CTRL;
//  }
//  while(temp&0x01&&!(temp&(1<<16)));//等待时间到达
//  SysTick->CTRL=0x00;       //关闭计数器
//  SysTick->VAL =0X00;       //清空计数器
//}//short poll
void PS2_ShortPoll(void)
{CS_L;delay_us(16);PS2_Cmd(0x01);  PS2_Cmd(0x42);  PS2_Cmd(0X00);PS2_Cmd(0x00);PS2_Cmd(0x00);CS_H;delay_us(16);
}//进入设置
void PS2_EnterConfing(void)
{CS_L;delay_us(16);PS2_Cmd(0x01);  PS2_Cmd(0x43);  PS2_Cmd(0X00);PS2_Cmd(0x01);PS2_Cmd(0x00);PS2_Cmd(0X00);PS2_Cmd(0X00);PS2_Cmd(0X00);PS2_Cmd(0X00);CS_H;delay_us(16);
}//发送模式设置
void PS2_TurnOnAnalogMode(void)
{CS_L;PS2_Cmd(0x01);  PS2_Cmd(0x44);  PS2_Cmd(0X00);PS2_Cmd(0x01); //analog=0x01;digital=0x00  软件设置发送模式PS2_Cmd(0x03); //Ox03锁存设置,即不可通过按键“MODE”设置模式。//0xEE不锁存软件设置,可通过按键“MODE”设置模式。PS2_Cmd(0X00);PS2_Cmd(0X00);PS2_Cmd(0X00);PS2_Cmd(0X00);CS_H;delay_us(16);
}//振动设置
void PS2_VibrationMode(void)
{CS_L;delay_us(16);PS2_Cmd(0x01);  PS2_Cmd(0x4D);  PS2_Cmd(0X00);PS2_Cmd(0x00);PS2_Cmd(0X01);CS_H;delay_us(16);
}//完成并保存配置
void PS2_ExitConfing(void)
{CS_L;delay_us(16);PS2_Cmd(0x01);  PS2_Cmd(0x43);  PS2_Cmd(0X00);PS2_Cmd(0x00);PS2_Cmd(0x5A);PS2_Cmd(0x5A);PS2_Cmd(0x5A);PS2_Cmd(0x5A);PS2_Cmd(0x5A);CS_H;delay_us(16);
}//手柄配置初始化
void PS2_SetInit(void)
{PS2_ShortPoll();PS2_ShortPoll();PS2_ShortPoll();PS2_EnterConfing();        //进入配置模式PS2_TurnOnAnalogMode(); //“红绿灯”配置模式,并选择是否保存//PS2_VibrationMode();    //开启震动模式PS2_ExitConfing();      //完成并保存配置
}/******************************************************
Function:    void PS2_Vibration(u8 motor1, u8 motor2)
Description: 手柄震动函数,
Calls:       void PS2_Cmd(u8 CMD);
Input: motor1:右侧小震动电机 0x00关,其他开motor2:左侧大震动电机 0x40~0xFF 电机开,值越大 震动越大
******************************************************/
void PS2_Vibration(uint8_t motor1, uint8_t motor2)
{CS_L;delay_us(16);PS2_Cmd(0x01);  //开始命令PS2_Cmd(0x42);  //请求数据PS2_Cmd(0X00);PS2_Cmd(motor1);PS2_Cmd(motor2);PS2_Cmd(0X00);PS2_Cmd(0X00);PS2_Cmd(0X00);PS2_Cmd(0X00);CS_H;delay_us(16);
}//读取手柄信息
void PS2_Receive (void)
{PS2_LX=PS2_AnologData(PSS_LX);PS2_LY=PS2_AnologData(PSS_LY);PS2_RX=PS2_AnologData(PSS_RX);PS2_RY=PS2_AnologData(PSS_RY);PS2_KEY=PS2_DataKey();
}
// ps2.h
#ifndef __PS2_H__
#define __PS2_H__#include "stm32f4xx_hal.h"
#include "sys.h"#define DI PDin(0)#define DO_H PDout(1)=1
#define DO_L PDout(1)=0#define CS_H PDout(2)=1
#define CS_L PDout(2)=0#define CLK_H PDout(3)=1
#define CLK_L PDout(3)=0 //These are our button constants
#define PSB_SELECT      1
#define PSB_L3          2
#define PSB_R3          3
#define PSB_START       4
#define PSB_PAD_UP      5
#define PSB_PAD_RIGHT   6
#define PSB_PAD_DOWN    7
#define PSB_PAD_LEFT    8
#define PSB_L2         9
#define PSB_R2          10
#define PSB_L1          11
#define PSB_R1          12
#define PSB_GREEN       13
#define PSB_RED         14
#define PSB_BLUE        15
#define PSB_PINK        16
#define PSB_TRIANGLE    13
#define PSB_CIRCLE      14
#define PSB_CROSS       15
#define PSB_SQUARE      26//These are stick values
#define PSS_RX 5                //右摇杆X轴数据
#define PSS_RY 6
#define PSS_LX 7
#define PSS_LY 8extern uint8_t Data[9];
extern uint16_t MASK[16];
extern uint16_t Handkey;void PS2_Init(void);
uint8_t PS2_RedLight(void);//判断是否为红灯模式
void PS2_ReadData(void);
void PS2_Cmd(uint8_t CMD);        //
uint8_t PS2_DataKey(void);        //键值读取
uint8_t PS2_AnologData(uint8_t button); //得到一个摇杆的模拟量
void PS2_ClearData(void);     //清除数据缓冲区
void delay_init(uint8_t SYSCLK);
void delay_us(uint32_t nus);void PS2_ShortPoll(void);//short poll
void PS2_EnterConfing(void);//进入设置
void PS2_TurnOnAnalogMode(void);//保存并完成设置
void PS2_VibrationMode(void);
void PS2_ExitConfing(void);//保存并完成设置
void PS2_SetInit(void);//手柄设置初始化
void PS2_Vibration(uint8_t motor1 ,uint8_t motor2);#endif
;
// sys.c
#include "sys.h"
//   //********************************************************************************
//修改说明
//无
//  //THUMB指令不支持汇编内联
//采用如下方法实现执行汇编指令WFI
__asm void WFI_SET(void)
{WFI;
}
//关闭所有中断(但是不包括fault和NMI中断)
__asm void INTX_DISABLE(void)
{CPSID   IBX      LR
}
//开启所有中断
__asm void INTX_ENABLE(void)
{CPSIE   IBX      LR
}
//设置栈顶地址
//addr:栈顶地址
__asm void MSR_MSP(uint32_t addr)
{MSR MSP, r0            //set Main Stack valueBX r14
}
// ps2.h
#ifndef __SYS_H
#define __SYS_H
#include "stm32f4xx.h"
#include "delay.h"
#include "ps2.h"
#define SYSTEM_SUPPORT_OS       0       //定义系统文件夹是否支持UCOS
extern volatile int PS2_LX,PS2_LY,PS2_RX,PS2_RY,PS2_KEY;//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).M4同M3类似,只是寄存器地址变了.
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814
#define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14
#define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014     #define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x40020010
#define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x40020410
#define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x40020810
#define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x40020C10
#define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x40021010
#define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x40021410
#define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x40021810
#define GPIOH_IDR_Addr    (GPIOH_BASE+16) //0x40021C10
#define GPIOI_IDR_Addr    (GPIOI_BASE+16) //0x40022010
//
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 #define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 #define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 #define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 #define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入#define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出
#define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入#define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  //输出
#define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  //输入//以下为汇编函数
void WFI_SET(void);     //执行WFI指令
void INTX_DISABLE(void);//关闭所有中断
void INTX_ENABLE(void); //开启所有中断
void MSR_MSP(uint32_t addr);    //设置堆栈地址
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>#endif
// misc.c
#include "stm32f4xx_hal.h"
#include "misc.h"/* Cortex M3 Delay functions */static __IO uint32_t TimingDelay = 0;void Delay(__IO uint32_t nTime)
{TimingDelay = nTime;while(TimingDelay != 0);
}void TimingDelay_Decrement(void)
{if (TimingDelay != 0x00) {TimingDelay--;}
}/* STM32F10x TIM helper functions */TIM_Direction TIM_ReadDirection(TIM_TypeDef* TIMx)
{return (TIMx->CR1 & TIM_CR1_DIR);
}void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{/* Check the parameters */assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));if (SysTick_CLKSource == SysTick_CLKSource_HCLK){SysTick->CTRL |= SysTick_CLKSource_HCLK;}else{SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;}}
// misc.h
#ifndef __STM32F10X_MISC_H__
#define __STM32F10X_MISC_H__#include "stm32f4xx_hal.h"/* Cortex M3 bit banding macros */#define BITBAND_SRAM_REF   0x20000000
#define BITBAND_SRAM_BASE  0x22000000
#define BITBAND_SRAM(ptr,n) ((volatile uint32_t*)((BITBAND_SRAM_BASE + \(((uint32_t)ptr)-BITBAND_SRAM_REF)*32 + (n*4))))
#define BITBAND_PERI_REF   0x40000000
#define BITBAND_PERI_BASE  0x42000000
#define BITBAND_PERI(ptr,n) ((volatile uint32_t*)((BITBAND_PERI_BASE + \(((uint32_t)ptr)-BITBAND_PERI_REF)*32 + (n*4))))#define SysTick_CLKSource_HCLK_Div8    ((uint32_t)0xFFFFFFFB)
#define SysTick_CLKSource_HCLK         ((uint32_t)0x00000004)/* Cortex M3 Delay functions */
void TimingDelay_Decrement(void);
void Delay(__IO uint32_t nTime);
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);/* STM32F10x GPIO helper functions */#define GPIO_ToggleBit(port, pin) GPIO_WriteBit(port, pin, \(BitAction) (1-GPIO_ReadOutputDataBit(port, pin)))/* STM32F10x TIM helper functions */typedef enum {UP = 0, DOWN = 1} TIM_Direction;TIM_Direction TIM_ReadDirection(TIM_TypeDef* TIMx);#endif
// delay.c
#include "delay.h"
#include "misc.h"
#include "sys.h"
//
//如果使用OS,则包括下面的头文件(以ucos为例)即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"                 //支持OS时,使用
#endif// static uint8_t  fac_us=0;                         //us延时倍乘数
static uint16_t fac_ms=0;                          //ms延时倍乘数,在os下,代表每个节拍的ms数#if SYSTEM_SUPPORT_OS                          //如果SYSTEM_SUPPORT_OS定义了,说明要支持OS了(不限于UCOS).#ifdef   OS_CRITICAL_METHOD                      //OS_CRITICAL_METHOD定义了,说明要支持UCOSII
#define delay_osrunning     OSRunning           //OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec OS_TICKS_PER_SEC    //OS时钟节拍,即每秒调度次数
#define delay_osintnesting  OSIntNesting        //中断嵌套级别,即中断嵌套次数
#endif//支持UCOSIII
#ifdef  CPU_CFG_CRITICAL_METHOD                 //CPU_CFG_CRITICAL_METHOD定义了,说明要支持UCOSIII
#define delay_osrunning     OSRunning           //OS是否运行标记,0,不运行;1,在运行
#define delay_ostickspersec OSCfg_TickRate_Hz   //OS时钟节拍,即每秒调度次数
#define delay_osintnesting  OSIntNestingCtr     //中断嵌套级别,即中断嵌套次数
#endif//us级延时时,关闭任务调度(防止打断us级延迟)
void delay_osschedlock(void)
{#ifdef CPU_CFG_CRITICAL_METHOD              //使用UCOSIIIOS_ERR err; OSSchedLock(&err);                       //UCOSIII的方式,禁止调度,防止打断us延时
#else                                       //否则UCOSIIOSSchedLock();                            //UCOSII的方式,禁止调度,防止打断us延时
#endif
}//us级延时时,恢复任务调度
void delay_osschedunlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD              //使用UCOSIIIOS_ERR err; OSSchedUnlock(&err);                 //UCOSIII的方式,恢复调度
#else                                       //否则UCOSIIOSSchedUnlock();                      //UCOSII的方式,恢复调度
#endif
}//调用OS自带的延时函数延时
//ticks:延时的节拍数
void delay_ostimedly(u32 ticks)
{#ifdef CPU_CFG_CRITICAL_METHODOS_ERR err; OSTimeDly(ticks,OS_OPT_TIME_PERIODIC,&err);//UCOSIII延时采用周期模式
#elseOSTimeDly(ticks);                      //UCOSII延时
#endif
}//systick中断服务函数,使用OS时用到
void SysTick_Handler(void)
{   if(delay_osrunning==1)                    //OS开始跑了,才执行正常的调度处理{OSIntEnter();                       //进入中断OSTimeTick();                     //调用ucos的时钟服务程序               OSIntExit();                          //触发任务切换软中断}
}
#endif//初始化延迟函数
//当使用OS的时候,此函数会初始化OS的时钟节拍
//SYSTICK的时钟固定为AHB时钟的1/8
//SYSCLK:系统时钟频率
void delay_init(uint8_t SYSCLK)
{#if SYSTEM_SUPPORT_OS                       //如果需要支持OS.u32 reload;
#endifSysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); fac_us=SYSCLK/8;                       //不论是否使用OS,fac_us都需要使用
#if SYSTEM_SUPPORT_OS                       //如果需要支持OS.reload=SYSCLK/8;                        //每秒钟的计数次数 单位为M    reload*=1000000/delay_ostickspersec;    //根据delay_ostickspersec设定溢出时间//reload为24位寄存器,最大值:16777216,在168M下,约合0.7989s左右    fac_ms=1000/delay_ostickspersec;       //代表OS可以延时的最少单位    SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;     //开启SYSTICK中断SysTick->LOAD=reload;                  //每1/delay_ostickspersec秒中断一次   SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;     //开启SYSTICK
#elsefac_ms=(uint16_t)fac_us*1000;             //非OS下,代表每个ms需要的systick时钟数
#endif
}                                   #if SYSTEM_SUPPORT_OS                       //如果需要支持OS.
//延时nus
//nus:要延时的us数.
//nus:0~204522252(最大值即2^32/fac_us@fac_us=21)
void delay_us(u32 nus)
{       u32 ticks;u32 told,tnow,tcnt=0;u32 reload=SysTick->LOAD;               //LOAD的值             ticks=nus*fac_us;                         //需要的节拍数 delay_osschedlock();                   //阻止OS调度,防止打断us延时told=SysTick->VAL;                      //刚进入时的计数器值while(1){tnow=SysTick->VAL;  if(tnow!=told){        if(tnow<told)tcnt+=told-tnow;  //这里注意一下SYSTICK是一个递减的计数器就可以了.else tcnt+=reload-tnow+told;        told=tnow;if(tcnt>=ticks)break;            //时间超过/等于要延迟的时间,则退出.}  };delay_osschedunlock();                 //恢复OS调度
}
//延时nms
//nms:要延时的ms数
//nms:0~65535
void delay_ms(u16 nms)
{   if(delay_osrunning&&delay_osintnesting==0)//如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)       {        if(nms>=fac_ms)                        //延时的时间大于OS的最少时间周期 { delay_ostimedly(nms/fac_ms);   //OS延时}nms%=fac_ms;                        //OS已经无法提供这么小的延时了,采用普通方式延时    }delay_us((u32)(nms*1000));               //普通方式延时
}
#else  //不用ucos时
//延时nus
//nus为要延时的us数.
//注意:nus的值,不要大于798915us(最大值即2^24/fac_us@fac_us=21)
void delay_us(uint32_t nus)
{       uint32_t temp;           SysTick->LOAD=nus*fac_us;              //时间加载           SysTick->VAL=0x00;                     //清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数   do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));  //等待时间到达   SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器SysTick->VAL =0X00;                      //清空计数器
}
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对168M条件下,nms<=798ms
void delay_xms(uint16_t nms)
{                 uint32_t temp;           SysTick->LOAD=(uint32_t)nms*fac_ms;          //时间加载(SysTick->LOAD为24bit)SysTick->VAL =0x00;                       //清空计数器SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;          //开始倒数 do{temp=SysTick->CTRL;}while((temp&0x01)&&!(temp&(1<<16)));   //等待时间到达   SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;       //关闭计数器SysTick->VAL =0X00;                    //清空计数器
}
//延时nms
//nms:0~65535
void delay_ms(uint16_t nms)
{        uint8_t repeat=nms/540;                       //这里用540,是考虑到某些客户可能超频使用,//比如超频到248M的时候,delay_xms最大只能延时541ms左右了uint16_t remain=nms%540;while(repeat){delay_xms(540);repeat--;}if(remain)delay_xms(remain);
}
#endif
// delay.h
#ifndef __DELAY_H
#define __DELAY_H
#include "misc.h"
//
void delay_init(uint8_t SYSCLK);
void delay_ms(uint16_t nms);
void delay_us(uint32_t nus);#endif
// main.c
/* USER CODE BEGIN Header */
/********************************************************************************* @file           : main.c* @brief          : Main program body******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2019 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under BSD 3-Clause license,* the "License"; You may not use this file except in compliance with the* License. You may obtain a copy of the License at:*                        opensource.org/licenses/BSD-3-Clause********************************************************************************/
/* USER CODE END Header *//* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h"
#include "ps2.h"
#include "sys.h"
#include "delay.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();/* USER CODE BEGIN 2 */delay_init(168);PS2_SetInit();delay_ms(500);/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE */PS2_LX=PS2_AnologData(PSS_LX);    PS2_LY=PS2_AnologData(PSS_LY);PS2_RX=PS2_AnologData(PSS_RX);PS2_RY=PS2_AnologData(PSS_RY);PS2_KEY=PS2_DataKey(); printf("PS2_LX:%d     ",PS2_LX);printf("PS2_LY:%d     ",PS2_LY);printf("PS2_RX:%d     ",PS2_RX);printf("PS2_RY:%d     ",PS2_RY);printf("PS2_KEY:%d \r\n",PS2_KEY);delay_ms(100);/* USER CODE BEGIN 3 */   }/* USER CODE END 3 */
}/*** @brief System Clock Configuration* @retval None*/
void SystemClock_Config(void)
{RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};/** Configure the main internal regulator output voltage */__HAL_RCC_PWR_CLK_ENABLE();__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);/** Initializes the CPU, AHB and APB busses clocks */RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 4;RCC_OscInitStruct.PLL.PLLN = 168;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 4;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB busses clocks */RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK){Error_Handler();}
}/* USER CODE BEGIN 4 */
/* USER CODE END 4 *//*** @brief  This function is executed in case of error occurrence.* @retval None*/
void Error_Handler(void)
{/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state *//* USER CODE END Error_Handler_Debug */
}#ifdef  USE_FULL_ASSERT
/*** @brief  Reports the name of the source file and the source line number*         where the assert_param error has occurred.* @param  file: pointer to the source file name* @param  line: assert_param error line source number* @retval None*/
void assert_failed(uint8_t *file, uint32_t line)
{ /* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number,tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) *//* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

如何使用摇杆和按键就需要读者自己去探索了
博主所使用的摇杆是控制麦克拉姆轮底片运动
下次会更新ps2手柄控制麦克拉姆轮的底盘代码

用cube移植PS2手柄--HAL库相关推荐

  1. STM32F103C8移植uCOSIII(HAL库)

    少年 一.随笔 二.uCOSIII源码 三.项目导入文件整理 四.导入文件和增加头函数路径 五.代码改动 六.参考资料 一.随笔 移植一个嵌入式系统用了一天时间,只能说不愧是我,在不了解的情况下还是少 ...

  2. 四针脚0.96寸OLED屏幕标准库代码转Cube Max创建的HAL库工程代码

    stm32学了一个多月了. 刚开始是跟着江科大学的,讲的很好,里面是用标准库. 后来因为Hal库用着简单,就开始学习Hal库,跟的是b站的[小蜜蜂笔记]基于STM32CubeMX的嵌入式开发基础教程. ...

  3. stm32移植freemodbusRTU(HAL库+Freertos)主机

    modbus主机源码下载 freemodbus主机源码下载地址 注:感谢armink提供的开源主机代码. 一.移植准备 1.cubemx配置基础工程,包括串口,freertos等. 在这里主要用到串口 ...

  4. STM32移植freemodbusRTU(hal库)从机

    MODBUS源码下载 freemodbus源码 github地址 一.移植准备 1.cubemx创建基础工程,配置串口和定时器以及时钟. 2.拷贝freertos源码到工程目录,新建一个freemod ...

  5. STM32F103C8T6移植uCOS基于HAL库

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.使用CubeMX建立STM32F103C8T6HAL库 二.效果展示 1.串口输出结果 2.设备效果展示 总结 一.使用 ...

  6. 移植TFT-LCD到HAL库

    1.找到你的开发板的原理图 特别注意 1和2管脚,根据你的原理图配置 这里设置好后,还要配置屏幕的背光设置 所以配置LCD_BL管脚 生成代码后, 计算写命令和地址的初始地址 最后是计算命令地址拉,命 ...

  7. STM32F407 DP83848驱动调试过程总结(标准库到HAL库移植避坑指南)

    文章目录 移植到正点原子例程 下载ST最新F4平台例程适配 使用CubeMX从头开始 移植标准库上层函数到CubeMX初始化的HAL库 项目要从之前的STM32F107平台移植到STM32F407平台 ...

  8. STM32用HAL库移植LORA(SX1276)的2.1版本驱动教程

    网上多数是STM32标准库LORA驱动2.0.0的例程,在此小编移植STM32的HAL库2.1.0版本LORA驱动,,但是有丢包现象需要调节参数,用的模块是安信可Ra-01 SX1278 LoRa,如 ...

  9. STM32中HAL库与标准库的区别

    这是扒的某网站上大佬们的见解. 1.HAL库就是封装的比较猛,移植性比较强,标准库就是将寄存器封装好,移植性没有HAL好. 2.HAL库可以用ST的软件CUBE生成初始化工程.3.HAL库最方便的就是 ...

  10. 【08】STM32·HAL库开发-HAL库介绍 | STM32Cube固件库介绍 | HAL库框架结构 | 如何使用HAL库及使用注意事项

    目录 1.初识HAL库(了解) 1.1CMSIS简介 1.2HAL库简介 2.STM32Cube固件包浅析(了解) 2.1如何获取STM32Cube固件包? 2.2STM32Cube固件包文件夹简介 ...

最新文章

  1. 打印session cookie
  2. jenkins 手动执行_Jenkins环境配置篇-增加节点
  3. 大数据技术是“地球的神经系统”
  4. 自学python编程笔记本推荐-这件神器,每个 Python入门学习者都值得一试
  5. CentOS 7 service systemnctl
  6. InnoDB的RR隔离级别能否防止“幻读”
  7. 局域网共享工具_win10一键局域网共享工具使用教程
  8. 自动阅读专业版第七次更新---原薅羊毛专业版
  9. 【UnityShader】使用Cubemap/Matcap制作玻璃
  10. python海龟库命令_turtle库常用命令
  11. IT博客大赛,快来围观!【人艰不拆】
  12. ML-Agent——使用可执行.exe文件
  13. 改变base64加密图片的大小
  14. 使用BIND9+MySql搭建一个智能解析DNS
  15. 基于人工智能的软件测试
  16. 惊闻Google Reader将被关闭
  17. python入门 数据类型(七种数据类型,序列,元素)
  18. 3D点云论文相关论文资料总结
  19. PAT 1070 结绳
  20. springboot zipkin调用链

热门文章

  1. python确定样本量(总体比例)
  2. 5.4、聚类之EM聚类实例
  3. ABAQUS二次开发手册【随书代码使用说明】
  4. 如何减小电压跟随器输出电阻_运算放大器和比较器还傻傻分不清楚?一篇图文教你轻松辨认...
  5. 联想小新i1000拆机图解_联想小新Air拆解:死磕小米笔记本 谁才是良心精品?
  6. 加壳、脱壳以及如何病毒免杀技术与原理
  7. 实验一 单片机 绘制原理图
  8. Word转换PDF技巧之通过虚拟打印机生成pdf格式文件
  9. 服务器系统2008网络发现,Windows Server 2008中解决局域网共享发现问题
  10. C++ SHFileOperation实现文件、文件夹拷贝、删除、重命名