2017-10-29 9 views
1

SPIを使用してGPIOレジスタに書き込むことで、MCP23S09のLEDを有効にしようとしています。STM32 SPIが期待通りに動作しない

ボードには2つのチップがあり、入力用と出力用の2つのLEDがあります。

私は、私がCH2をローにして、MOSIとSCKピンをマイコンに接続しました。

私はNucleo STM32F411をCubeMXソフトウェアと組み合わせて使用​​していますので、機能を有効にするためにレジスタにデータを送信しようとしています。

残念ながら、LEDのどれもIO Expanderで点灯しません。

私が試した次のことは、STM32duinoだったので、私のボードにArduinoコードを書くことができます。しかし、私が知る限り、これはHALライブラリの一番上にある別のレイヤーです。

私の驚きにはうまくいった!それは同じコードですが、Arduinoのために少し変更しました。

しかし、CubeMXで生成されたHALライブラリを使用すると、なぜそれが動作しないのかまだ分かりません。

Arduinoのコード:

#include <SPI.h> 

#define IODIR 0x00 
#define IPOL 0x01 
#define GPINTEN 0x02 
#define DEFVAL 0x03 
#define INTCON 0x04 
#define IOCON 0x05 
#define GPPU 0x06 
#define INTF 0x07 
#define INTCAP 0x08 
#define GPIO 0x09 
#define OLAT 0x0A 

#define OPCODEW 0x40 
#define OPCODER 0x41 

// CS0 -> D2 
const int slaveAPin = 2; 

// CS1 -> D3 
const int slaveBPin = 3; 

// LED VAL 
const uint8_t value = ~0x3F; 


void setup() { 
    // put your setup code here, to run once: 
    // initialize SPI: 
    SPI.begin(); //Initialize the SPI_1 port. 
    SPI.setBitOrder(MSBFIRST); // Set the SPI_1 bit order 

    SPI.setDataMode(SPI_MODE0); //Set the SPI_1 data mode 0 
    SPI.setClockDivider(SPI_CLOCK_DIV64);  

    pinMode (slaveAPin, OUTPUT); // First chip for inputs 
    pinMode (slaveBPin, OUTPUT); // Second chip for outputs 

    digitalWrite (slaveAPin, HIGH); 
    digitalWrite (slaveBPin, HIGH); 

} 

void loop() { 
    // configuration led-io-expander 
    sendDataSPI(IOCON, 0x20); 

    // all pins = output 
    sendDataSPI(IODIR, 0x00); 

    // Enable LEDS 
    sendDataSPI(GPIO, value); 
} 


void sendDataSPI(uint8_t reg, uint8_t value){ 
    digitalWrite (slaveBPin, LOW); // Take slave-select low 
    SPI.transfer(OPCODEW); // Send the MCP23S09 opcode, and write byte 
    SPI.transfer(reg); // Send the register we want to write 
    SPI.transfer(value); // Send the byte 
    digitalWrite (slaveBPin, HIGH); // Take slave-select high 
} 

STM32 HAL:

/** 
    ****************************************************************************** 
    * File Name   : main.c 
    * Description  : Main program body 
    ****************************************************************************** 
    ** This notice applies to any and all portions of this file 
    * that are not between comment pairs USER CODE BEGIN and 
    * USER CODE END. Other portions of this file, whether 
    * inserted by the user or by software development tools 
    * are owned by their respective copyright owners. 
    * 
    * COPYRIGHT(c) 2017 STMicroelectronics 
    * 
    * Redistribution and use in source and binary forms, with or without modification, 
    * are permitted provided that the following conditions are met: 
    * 1. Redistributions of source code must retain the above copyright notice, 
    *  this list of conditions and the following disclaimer. 
    * 2. Redistributions in binary form must reproduce the above copyright notice, 
    *  this list of conditions and the following disclaimer in the documentation 
    *  and/or other materials provided with the distribution. 
    * 3. Neither the name of STMicroelectronics nor the names of its contributors 
    *  may be used to endorse or promote products derived from this software 
    *  without specific prior written permission. 
    * 
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
    * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 
    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
    * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
    * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    * 
    ****************************************************************************** 
    */ 
/* Includes ------------------------------------------------------------------*/ 
#include "main.h" 
#include "stm32f4xx_hal.h" 

/* USER CODE BEGIN Includes */ 

/* USER CODE END Includes */ 

/* USER CODE BEGIN Defines */ 
#define IODIR 0x00 
#define IPOL 0x01 
#define GPINTEN 0x02 
#define DEFVAL 0x03 
#define INTCON 0x04 
#define IOCON 0x05 
#define GPPU 0x06 
#define INTF 0x07 
#define INTCAP 0x08 
#define GPIO 0x09 
#define OLAT 0x0A 

#define OPCODEW  0x40 
#define OPCODER 0x41 

#define SPI_TRANSFER_TIMEOUT 1000 
/* USER CODE END Defines */ 

/* Private variables ---------------------------------------------------------*/ 
SPI_HandleTypeDef hspi1; 

UART_HandleTypeDef huart2; 

/* USER CODE BEGIN PV */ 
/* Private variables ---------------------------------------------------------*/ 

/* USER CODE END PV */ 

/* Private function prototypes -----------------------------------------------*/ 
void SystemClock_Config(void); 
static void MX_GPIO_Init(void); 
static void MX_SPI1_Init(void); 
static void MX_USART2_UART_Init(void); 
void sendDataSPI(uint8_t reg, uint8_t value); 
int fgetc(FILE *f); 
int fputc(int c, FILE *f); 
/* USER CODE BEGIN PFP */ 
/* Private function prototypes -----------------------------------------------*/ 

/* USER CODE END PFP */ 

/* USER CODE BEGIN 0 */ 

/* USER CODE END 0 */ 

int main(void) 
{  
    // LED VAL 
    uint8_t value = 0x3F; 

    /* 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(); 
    MX_SPI1_Init(); 
    MX_USART2_UART_Init(); 


    /* USER CODE BEGIN 2 */ 

    /* USER CODE END 2 */ 

    /* Infinite loop */ 
    /* USER CODE BEGIN WHILE */ 
    while (1) 
    { 
    /* USER CODE END WHILE */ 

    /* USER CODE BEGIN 3 */ 
     // configuration led-io-expander 

     sendDataSPI(IOCON, 0x20); 

     // all pins = output 
     sendDataSPI(IODIR, 0x00); 

     // Enable LEDS 
     sendDataSPI(GPIO, value); 

    } 
    /* USER CODE END 3 */ 

} 

// REGISTER, VALUE 
void sendDataSPI(uint8_t reg, uint8_t value){ 
     HAL_GPIO_WritePin(CS1_GPIO_Port, CS1_Pin, GPIO_PIN_RESET); // Take slave-select low 
     HAL_SPI_Transmit(&hspi1,(uint8_t *)OPCODEW,sizeof(uint8_t),SPI_TRANSFER_TIMEOUT); // Send the MCP23S09 opcode, and write bit 
     HAL_SPI_Transmit(&hspi1,(uint8_t *)&reg,sizeof(uint8_t),SPI_TRANSFER_TIMEOUT); // Send the register we want to write 
     HAL_SPI_Transmit(&hspi1,(uint8_t *)&value,sizeof(uint8_t),SPI_TRANSFER_TIMEOUT); // Send the byte 
     HAL_GPIO_WritePin(CS1_GPIO_Port, CS1_Pin, GPIO_PIN_SET); // Take slave-select high 
} 

int fputc(int c, FILE *f) { 
    return (HAL_UART_Transmit(&huart2, (uint8_t *)&c,1,HAL_MAX_DELAY)); 
} 

int fgetc(FILE *f) { 
    char ch; 
    HAL_UART_Receive(&huart2,(uint8_t*)&ch,1,HAL_MAX_DELAY); 
    return (ch); 
} 

/** System Clock Configuration 
*/ 
void SystemClock_Config(void) 
{ 

    RCC_OscInitTypeDef RCC_OscInitStruct; 
    RCC_ClkInitTypeDef RCC_ClkInitStruct; 

    /**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_HSI; 
    RCC_OscInitStruct.HSIState = RCC_HSI_ON; 
    RCC_OscInitStruct.HSICalibrationValue = 16; 
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; 
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; 
    RCC_OscInitStruct.PLL.PLLM = 16; 
    RCC_OscInitStruct.PLL.PLLN = 336; 
    RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4; 
    RCC_OscInitStruct.PLL.PLLQ = 4; 
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) 
    { 
    _Error_Handler(__FILE__, __LINE__); 
    } 

    /**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_DIV2; 
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 

    if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) 
    { 
    _Error_Handler(__FILE__, __LINE__); 
    } 

    /**Configure the Systick interrupt time 
    */ 
    HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); 

    /**Configure the Systick 
    */ 
    HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); 

    /* SysTick_IRQn interrupt configuration */ 
    HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); 
} 

/* SPI1 init function */ 
static void MX_SPI1_Init(void) 
{ 
    /* SPI1 parameter configuration*/ 
    hspi1.Instance = SPI1; 
    hspi1.Init.Mode = SPI_MODE_MASTER; 
    hspi1.Init.Direction = SPI_DIRECTION_2LINES; 
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT; 
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; 
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; 
    hspi1.Init.NSS = SPI_NSS_SOFT; 
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64; 
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; 
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE; 
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; 
    hspi1.Init.CRCPolynomial = 10; 
    if (HAL_SPI_Init(&hspi1) != HAL_OK) 
    { 
    _Error_Handler(__FILE__, __LINE__); 
    } 

} 

/* USART2 init function */ 
static void MX_USART2_UART_Init(void) 
{ 

    huart2.Instance = USART2; 
    huart2.Init.BaudRate = 115200; 
    huart2.Init.WordLength = UART_WORDLENGTH_8B; 
    huart2.Init.StopBits = UART_STOPBITS_1; 
    huart2.Init.Parity = UART_PARITY_NONE; 
    huart2.Init.Mode = UART_MODE_TX_RX; 
    huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE; 
    huart2.Init.OverSampling = UART_OVERSAMPLING_16; 
    if (HAL_UART_Init(&huart2) != HAL_OK) 
    { 
    _Error_Handler(__FILE__, __LINE__); 
    } 

} 

/** Configure pins as 
     * Analog 
     * Input 
     * Output 
     * EVENT_OUT 
     * EXTI 
*/ 
static void MX_GPIO_Init(void) 
{ 

    GPIO_InitTypeDef GPIO_InitStruct; 

    /* GPIO Ports Clock Enable */ 
    __HAL_RCC_GPIOC_CLK_ENABLE(); 
    __HAL_RCC_GPIOH_CLK_ENABLE(); 
    __HAL_RCC_GPIOA_CLK_ENABLE(); 
    __HAL_RCC_GPIOB_CLK_ENABLE(); 

    /*Configure GPIO pin Output Level */ 
    HAL_GPIO_WritePin(CS0_GPIO_Port, CS0_Pin, GPIO_PIN_RESET); 

    /*Configure GPIO pin Output Level */ 
    HAL_GPIO_WritePin(CS1_GPIO_Port, CS1_Pin, GPIO_PIN_RESET); 

    /*Configure GPIO pin : B1_Pin */ 
    GPIO_InitStruct.Pin = B1_Pin; 
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; 
    GPIO_InitStruct.Pull = GPIO_NOPULL; 
    HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct); 

    /*Configure GPIO pin : CS0_Pin */ 
    GPIO_InitStruct.Pin = CS0_Pin; 
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 
    GPIO_InitStruct.Pull = GPIO_NOPULL; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 
    HAL_GPIO_Init(CS0_GPIO_Port, &GPIO_InitStruct); 

    /*Configure GPIO pin : CS1_Pin */ 
    GPIO_InitStruct.Pin = CS1_Pin; 
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 
    GPIO_InitStruct.Pull = GPIO_NOPULL; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 
    HAL_GPIO_Init(CS1_GPIO_Port, &GPIO_InitStruct); 

} 

/* USER CODE END 4 */ 

答えて

3

あなたはSPI転送があなたのsendDataSPI機能の次の送信を開始する前に完了するのを待つしないでください。それは次のように変更する必要があります。

void sendDataSPI(uint8_t reg, uint8_t value){ 
     HAL_GPIO_WritePin(CS1_GPIO_Port, CS1_Pin, GPIO_PIN_RESET); // Take slave-select low 

     HAL_SPI_Transmit(&hspi1,(uint8_t *)OPCODEW,sizeof(uint8_t),SPI_TRANSFER_TIMEOUT); // Send the MCP23S09 opcode, and write bit 
     while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY); 

     HAL_SPI_Transmit(&hspi1,(uint8_t *)&reg,sizeof(uint8_t),SPI_TRANSFER_TIMEOUT); // Send the register we want to write 
     while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY); 

     HAL_SPI_Transmit(&hspi1,(uint8_t *)&value,sizeof(uint8_t),SPI_TRANSFER_TIMEOUT); // Send the byte 
     while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY); 

     HAL_GPIO_WritePin(CS1_GPIO_Port, CS1_Pin, GPIO_PIN_SET); // Take slave-select high 
} 

また、この行は単なるゴミではなく0x40を送信します。

HAL_SPI_Transmit(&hspi1,(uint8_t *)OPCODEW,sizeof(uint8_t),SPI_TRANSFER_TIMEOUT); // Send the MCP23S09 opcode, and write bit 

あなたがそう実際にあなたが(いくつかのランダムなメモリを指す)ポインタとしてではなくデータとして0x40を渡しますuint8_t*OPCODEWをキャストしていることに注意してください。

+1

あなたの助けてくれてありがとう、それは間違ったアドレスを指してOPCODEWによって実際に引き起こされました。プログラムはしばらくの間うまく動作しているようです(HAL_SPI_GetState(&hspi1)!= HAL_SPI_STATE_READY);しかし、私は送信が完了するのを待つことが本当に重要であることがわかります。 – stickfigure4

+0

@ stickfigure4うれしいことを聞いてうれしいです。これ( 'while(HAL_SPI_GetState(&hspi1)!= HAL_SPI_STATE_READY);)はライブラリの初期のバグだったはずです。 –

関連する問題