AnsweredAssumed Answered

Wii Motion Plus (Cant connect)

Question asked by l.phoenix on Oct 17, 2011
Latest reply on Oct 17, 2011 by Clive One

Hello every1, I'm trying to connect my STM32 VL to Wii Motion Plus via I2C, but I get no result. The code I use to do that is given below. Please answer me if anyone had the same issue or who knows how to solve this problem.

#include "stm32f10x.h" 
#include "stm32f10x_rcc.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_usart.h"
#include <string.h>
#include <stdlib.h>

#define RCC_PLLSource_HSE_Div1  ((uint32_t)0x00010000)
#define I2C1_SLAVE_ADDRESS7     0x53

int wmp_data[6];
int yaw0, pitch0, roll0;

void RCC_Configuration(void);
void GPIO_Configuration(void);
void GPIO_I2C(void);
void NVIC_Configuration(void);
void USART2_Configuration(void);
void NVIC_Configuration(void);
void I2CInit(void);
void ZeroSending(void);
void WMon(void);
void ZeroCalibration(void);

int main (void)
{
    RCC_Configuration();
    USART2_Configuration();
    GPIO_I2C();
    I2CInit();
    WMon();
    ZeroSending();
    while (1)
    {
        ZeroCalibration();
    }
}

void RCC_Configuration(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO,ENABLE);
}

void USART2_Configuration(void)
{
    ErrorStatus HSEStartUpStatus;

    RCC_DeInit();

    RCC_HSEConfig(RCC_HSE_ON);
    HSEStartUpStatus = RCC_WaitForHSEStartUp();

    if (HSEStartUpStatus == SUCCESS) 
    {
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
        FLASH_SetLatency(FLASH_Latency_2);

        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        RCC_PCLK2Config(RCC_HCLK_Div1);
        RCC_PCLK1Config(RCC_HCLK_Div2);

        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_2);
        RCC_PLLCmd(ENABLE);
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        while (RCC_GetSYSCLKSource() != 0x08);
    }
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    GPIO_InitTypeDef GPIO_InitStructure;

    /* Configuring USART1_Tx as 'alternate function push-pull' */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configuring USART1_Rx as 'input floating' */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD ;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitTypeDef USART_InitStructure;

    USART_InitStructure.USART_BaudRate = 9600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No ;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART2, &USART_InitStructure);
    USART_Cmd(USART2, ENABLE);
}

void GPIO_I2C()
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void I2CInit()
{
    I2C_InitTypeDef  I2C_InitStructure;

    I2C_Cmd(I2C1, ENABLE);

    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = I2C1_SLAVE_ADDRESS7;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 100000;
    I2C_Init(I2C1, &I2C_InitStructure);
    I2C_Cmd(I2C1, ENABLE);
}

// Start communication with the WM+ and initialize it
void WMon(void)
{
    I2C_GenerateSTART(I2C1, ENABLE);
    I2C_SendData(I2C1, 0xA6);
    I2C_SendData(I2C1, 0xFE);
    I2C_SendData(I2C1, 0x04);
    I2C_GenerateSTOP(I2C1, ENABLE);
    USART_SendString("\nON");
}

// Request the WM+ to send wmp_data
void ZeroSending(void)
{
    I2C_GenerateSTART(I2C1, ENABLE);
    I2C_SendData(I2C1, 0xA4);
    I2C_SendData(I2C1, 0x00);
    I2C_GenerateSTOP(I2C1, ENABLE);
}

// Calibrate Zeroes
void ZeroCalibration(void)
{
    int i;
    for (i=0;i<10;i++)
        {
            ZeroSending();
            I2C_GenerateSTART(I2C1, ENABLE);
            I2C_SendData(I2C1, 0xA5);

            for (i=0;i<5;i++)
                {
                   wmp_data[i]=I2C_ReceiveData(I2C1); // Save readings in array
                }
            wmp_data[5]=I2C_ReceiveData(I2C1);
            I2C_AcknowledgeConfig(I2C1, DISABLE);

            I2C_GenerateSTOP(I2C1, ENABLE);

            yaw0+=(((wmp_data[3]>>2)<<8)+wmp_data[0])/10; //average 10 readings
            pitch0+=(((wmp_data[4]>>2)<<8)+wmp_data[1])/10;
            roll0+=(((wmp_data[5]>>2)<<8)+wmp_data[2])/10;
        }

    char str1[8];      //Make array of 8 chars

    itoa(yaw0, str1, 10);     //Convert value to chars 2=binair 10=decimal 16=hex
    USART_SendString("Yaw0:");
    USART_SendString(str1);

    itoa(pitch0, str1, 10);
    USART_SendString(" Pitch0:");
    USART_SendString(str1);

    itoa(roll0, str1, 10);
    USART_SendString(" Roll0:");
    USART_SendString(str1);
}

void USART_SendString(char *s)
{
    while(*s)
    {
        while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
        USART_SendData(USART2, *s++);
    }
}

Outcomes