c - STM32 F411RE Nucleo SPI 支持和编程 PlayStation 2 Controller

标签 c stm32 stm32f4

几天来,我一直试图从 PS2 中获得正确答案STM32F411RE 上的游戏 handle (DualShock 2)Nucleo .

我使用 SPIUSART接收消息。 时钟频率设置为 8 MHz,SPI 预分频器设置为 64 配置,这为我提供了 125 kHz (kbit/s)。

第一位取自LSB ,CPOL 参数为 1,CPHA 为 2。它由 NSS 软件控制,设置为 GPIO 输出(PA4-CS 引脚)。我使用 PA5 引脚作为 SCK(时钟)PA6-MISO、PA7-MOSI。 SPI 设置为全双工主机模式。 (USART 异步和 9600 位/秒,但它仅用于在 PC 上接收消息)。

微 Controller 运行一个 HAL图书馆。

在main.c文件中:

#define CS_LOW HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET)
#define CS_HIGH HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET)

CS LOW - 将线路“注意”设置为状态 0,将 CS_HIGH 设置为状态 1。

发送命令和返回数据的函数(MISO-MOSI):

uint8_t PS2_RWByte(uint8_t komenda, uint8_t tablica, int wielkosc)
{
    HAL_SPI_Transmit(&hspi1, &komenda, sizeof(komenda), 1);
    HAL_SPI_Receive(&hspi1, &tablica, sizeof(tablica), 1);
    return(tablica);
}

函数发送一个字节串:

uint8_t Get_PS2Dat(uint8_t buf[])
{
    CS_LOW;
    HAL_Delay(15/1000);
    buf[0] = PS2_RWByte(0x01, buf[0], 8);HAL_Delay(15/1000);
    buf[1] = PS2_RWByte(0x42, buf[1], 8);HAL_Delay(15/1000);
    buf[2] = PS2_RWByte(0x00, buf[2], 8);HAL_Delay(15/1000);
    buf[3] = PS2_RWByte(0x00, buf[3], 8);HAL_Delay(15/1000);
    buf[4] = PS2_RWByte(0x00, buf[4], 8);HAL_Delay(15/1000);
    buf[5] = PS2_RWByte(0x00, buf[5], 8);HAL_Delay(15/1000);
    buf[6] = PS2_RWByte(0x00, buf[6], 8);HAL_Delay(15/1000);
    buf[7] = PS2_RWByte(0x00, buf[7], 8);HAL_Delay(15/1000);
    buf[8] = PS2_RWByte(0x00, buf[8], 8);HAL_Delay(15/1000);
    CS_HIGH;
    if((buf[0] == 0xFF) && (buf[1] == 0x41) && (buf[2] == 0x5A))
        return 1;
    if((buf[0] == 0xFF) && (buf[1] == 0x73) && (buf[2] == 0x5A))
        return 2;
    return 0;
}

main 函数中:

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_USART2_UART_Init();
    MX_SPI1_Init();
    HAL_SPI_MspInit(&hspi1);
    uint8_t PS2buf[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    uint8_t wyswietl[30] = {0};
    while (1)
    {
        Get_PS2Dat(PS2buf);
        for(int i=0; i<9; i++)
        {
            sprintf(wyswietl, "%u ,", PS2buf[i]);
            HAL_UART_Transmit(&huart2, wyswietl, 30, 250);
        }
        sprintf(wyswietl, "\n\r");
        HAL_UART_Transmit(&huart2, wyswietl, 30, 250);
        HAL_Delay(300);
    }
 }

发送信息后:0x01 0x42 0x00 0x00 0x00 如果没有按下任何按钮,我应该得到 0xFF 0x41 0x5A 0xFF 0xFF。

当我得到这样的值时,在 3 和 4 字节处应该出现有关按下的键的信息: 65、255、255、255、255 即 0xFF 0xFF 0xFF 0xFF 0xFF。

奇怪的是,第二个发送的字节如何对应于第一个收到的字节。补充一点是,如果按“模式”键,值65变为115(0x73),而其他值保持不变。

最佳答案

您应该使用 HAL_SPI_TransmitReceive 而不是 HAL_SPI_Transmit 和 HAL_SPI_Receive 的组合。

  • 函数 HAL_SPI_Transmit 仅发送数据并忽略传入字节。
  • 函数 HAL_SPI_Receive 发送虚拟数据并获取传入字节。

基本上,您每隔一个字符就会收到一次。 65 = 0x42 是第二个字符。因为您在接收数据时发送了一个虚拟字节,所以剩余的消息不被 PS2 Controller 理解,所以您得到 0xFF。

像那样更改您的 PS2_RWByte 函数,它应该可以工作:

uint8_t PS2_RWByte(uint8_t komenda, uint8_t tablica, int wielkosc)
{
  HAL_SPI_TransmitReceive(&hspi1, &komenda, &tablica, sizeof(uint8_t), 1);
  return(tablica);
}

关于c - STM32 F411RE Nucleo SPI 支持和编程 PlayStation 2 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44078941/

相关文章:

c - 我的代码在CLion中可以正常运行,但是在repl.it中出现错误

c - 有效地交换半字

c - 使用 "EXTI_IRQHandler"和 "EXTI_Callback"有什么区别?

assembly - ARM 汇编中的 STR 指令不起作用(使用 KEIL)

arm - 为什么需要内存别名?

c - 函数 HMAC_MD5 : Return succes but no value

python - 在 f2py 中设置 fortran 编译器

c - printf/scanf 的输入/输出选项

c - 有时会绕过 gcc 内存 Hook 吗?

c - 窗口看门狗定时器STM32F4