اطلاعیه

Collapse
No announcement yet.

ارسال داده به کمک رابط SPI در میکرو کنترلر های ARM سری stm32F030F4

Collapse
X
 
  • فیلتر
  • زمان
  • Show
Clear All
new posts

    ارسال داده به کمک رابط SPI در میکرو کنترلر های ARM سری stm32F030F4

    [pre]با عرض سلام خدمت دوستان.
    من یک پروژه ارسال داده به کمک رابط SPI با میکروکنترلر STM32F030F4 می خوام انجام بدم. هدفم اینه با کلید هایی که به پایه های 9، 10، 13 و 14 پورت A سمت MASTER متصل شده، به ترتیب با فشردن هر کلید، LED های سمت SLAVE متصل شده به پایه های 0، 1، 2، و 3 برای یک فاصله زمانی کوتاه روشن و بعد خاموش بشه. مشکلم اینجاست، زمانی که پین های ورودی master را با کلید فعال میکنم، LED های سمت SLAVE نامرتب روشن میشن، یا دوتایی روشنی میشن. کدی که برای مد های MASTER و SLAVE نوشتم به صورت زیر هست:
    کد مربوط به Master:
    /* MASTER */



    #include "stm32f0xx.h" // Device header // Component selection
    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    /* Private macro -------------------------------------------------------------*/
    /* Private variables ---------------------------------------------------------*/
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    ErrorStatus HSEStartUpStatus;
    int DATA, i;
    /* Private functions ---------------------------------------------------------*/
    void RCC_Configuration(void);
    void GPIO_Configuration(void);
    void NVIC_Configuration(void);

    /************************************************** *****************************
    * Function Name : main
    * Description : Main program
    * Input : None
    * Output : None
    * Return : None
    ************************************************** *****************************/
    int main(void)
    {

    /* System clocks configuration ---------------------------------------------*/
    RCC_Configuration();

    /* GPIO configuration ------------------------------------------------------*/
    GPIO_Configuration();
    /*================================================= ==========================*/
    /* SPI1 configuration */
    // The NSS pulse mode can be managed by the SPI TI mode when enabling
    SPI_TIModeCmd(SPI1, ENABLE);
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1, &SPI_InitStructure);

    /* Enable SPI1 */
    SPI_Cmd(SPI1, ENABLE);
    /*================================================= ==========================*/
    SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_HF);
    /*================================================= ==========================*/
    /*Enables or disables the specified SPI/I2S interrupts.*/
    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, ENABLE);
    NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    while(1){

    //If PinA_9 pressed
    if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_9)==1)
    {
    /* Send SPI1 data */
    //If TX buffer is empty then transmit the next byte.
    while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RES ET);
    DATA=0x0001;
    SPI_I2S_SendData16(SPI1, DATA );
    // All data transmitted/received but SPI may be busy so wait until done.
    while (SPI1->SR & SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));
    }
    /*================================================= ==========================*/
    //If PinA_10 pressed
    else if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)==1)
    {

    //If TX buffer is empty then transmit the next byte.
    while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RES ET);
    /* Send SPI1 data */
    DATA=0x0002;
    SPI_I2S_SendData16(SPI1, DATA );
    // All data transmitted/received but SPI may be busy so wait until done.
    while (SPI1->SR & SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));
    }
    /*================================================= ==========================*/
    //If PinA_13 pressed
    else if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_13)==1)
    {
    //If TX buffer is empty then transmit the next byte.
    while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RES ET);
    /* Send SPI1 data */
    DATA=0x0003;
    SPI_I2S_SendData16(SPI1, DATA );
    // All data transmitted/received but SPI may be busy so wait until done.
    while (SPI1->SR & SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));
    }
    /*================================================= ==========================*/
    //If PinA_14 pressed
    else if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_14)==1)
    {
    //If TX buffer is empty then transmit the next byte.
    while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RES ET);
    /* Send SPI1 data */
    DATA=0x0004;
    SPI_I2S_SendData16(SPI1, DATA );
    // All data transmitted/received but SPI may be busy so wait until done.
    while (SPI1->SR & SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));
    }
    }
    }



    /************************************************** *****************************
    * Function Name : SPI1_IRQ_handler
    * Description : Interrupt code
    * Input : None
    * Output : None
    * Return : None
    ************************************************** *****************************/
    // Process the interrupts for SPI1.
    void SPI1_IRQHandler()
    {
    GPIOA->ODR=0x000F;
    for (i=1; i<800000;i++);
    GPIOA->BRR=0x000F;
    SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_TXE, DISABLE);
    // Clear the interrupt pending bit otherwise this interrupt
    // will be regenerated.
    SPI_I2S_ClearFlag(SPI1, SPI_I2S_FLAG_TXE);
    }
    // If SPI is not busy then we have finished sending data
    // so turn off this interrupt.

    /************************************************** *****************************
    * Function Name : RCC_Configuration
    * Description : Configures the different system clocks.
    * Input : None
    * Output : None
    * Return : None
    ************************************************** *****************************/
    void RCC_Configuration(void)
    {
    /* RCC system reset(for debug purpose) */
    RCC_DeInit();
    /* Enable HSE */
    RCC_HSEConfig(RCC_HSE_ON);

    /* Wait till HSE is ready */
    HSEStartUpStatus = RCC_WaitForHSEStartUp();
    if(HSEStartUpStatus == SUCCESS)
    {
    /* PCLK = HCLK/2 */
    RCC_PCLKConfig (RCC_HCLK_Div2);
    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_0);
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(ENABLE);
    RCC_PLLConfig(RCC_SYSCLKSource_HSE, RCC_PLLMul_6);
    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    {
    }
    /* Enable peripheral clocks --------------------------------------------------*/
    /* GPIOA, GPIOB and SPI1 clock enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOF , ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 , ENABLE);
    }





    /************************************************** *****************************
    * Function Name : GPIO_Configuration
    * Description : Configures the different GPIO ports.
    * Input : None
    * Output : None
    * Return : None
    ************************************************** *****************************/
    void GPIO_Configuration(void)
    {
    /* Configure SPI2 pins: SCK, MISO and MOSI ---------------------------------*/
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_0);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_0);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_0);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    /* SPI SCK pin configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* SPI MOSI pin configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* SPI MISO pin configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // LED Test
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /* User button to send data*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_13 | GPIO_Pin_14;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    }

    کد مربوط به Slave:

    // SLAVE CODE
    /* Includes ------------------------------------------------------------------*/

    #include "stm32f0xx.h" // Device header // Component selection
    #include <string.h>
    #include "stm32f0xx_spi.h"
    #include "stm32f0xx_exti.h"
    #include "stm32f0xx_syscfg.h"
    #include "stm32f0xx_misc.h"
    #include "stm32f0xx_rcc.h"

    /* Private typedef -----------------------------------------------------------*/
    /* Private define ------------------------------------------------------------*/
    /* Private macro -------------------------------------------------------------*/
    /* Private variables ---------------------------------------------------------*/
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef SPI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    ErrorStatus HSEStartUpStatus;

    /* Private functions ---------------------------------------------------------*/
    void RCC_Configuration(void);
    void GPIO_Configuration(void);
    void NVIC_Configuration(void);
    uint16_t DATA;
    int i;
    /************************************************** *****************************
    * Function Name : main
    * Description : Main program
    * Input : None
    * Output : None
    * Return : None
    ************************************************** *****************************/
    int main(void)
    {

    /* System clocks configuration ---------------------------------------------*/
    RCC_Configuration();

    /* GPIO configuration ------------------------------------------------------*/
    GPIO_Configuration();

    /* SPI1 configuration ------------------------------------------------------*/
    /* SPI_TIModeCmd(SPI1, ENABLE);/
    the control bits SSM, SSI, CPOL and CPHA
    * are not taken into consideration and are configured by hardware
    * respectively to the TI mode requirements. */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1, &SPI_InitStructure);

    /* Enable SPI1 CRC calculation */
    //SPI_CalculateCRC(SPI1, ENABLE);

    /* Enable SPI2 */
    SPI_Cmd(SPI1, ENABLE);

    SPI_RxFIFOThresholdConfig(SPI1, SPI_RxFIFOThreshold_HF);
    SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Reset);

    while(1)
    {
    /* Wait for SPI1 last data reception */
    while (SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RE SET);
    /* Data received */
    DATA= SPI_I2S_ReceiveData16(SPI1);

    /*================================================= ==========================*/
    /* if bottom 1 pressed in master, LED 1 turned on */
    if (DATA==0x0001){
    GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
    GPIO_SetBits(GPIOA, GPIO_Pin_0);
    for (i=1;i<100000; i++);

    GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
    while (SPI1->SR & SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));
    }
    /*================================================= ==========================*/
    /* if bottom 2 pressed in master, LED 2 turned on */
    else if (DATA==0x0002){
    GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
    GPIO_SetBits(GPIOA, GPIO_Pin_1);
    for (i=1;i<100000; i++);
    GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
    while (SPI1->SR & SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));
    }
    /*================================================= ==========================*/
    /* if bottom 3 pressed in master, LED 3 turned on */
    else if( DATA==0x0003){
    GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
    GPIO_SetBits(GPIOA, GPIO_Pin_2);
    for (i=1;i<100000; i++);
    GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
    while (SPI1->SR & SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));
    }
    /*================================================= ==========================*/
    /* if bottom 4 pressed in master, LED 4 turned on */
    else if (DATA==0x0004){
    GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
    GPIO_SetBits(GPIOA, GPIO_Pin_3);
    for (i=1;i<100000; i++);
    GPIO_ResetBits(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3);
    while (SPI1->SR & SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY));
    }

    }

    }


    /************************************************** *****************************
    * Function Name : SPI1_IRQ_handler
    * Description : Interrupt code
    * Input : None
    * Output : None
    * Return : None
    ************************************************** *****************************/
    // Process the interrupts for SPI1.

    // If SPI is not busy then we have finished sending data
    // so turn off this interrupt.

    /************************************************** *****************************
    * Function Name : RCC_Configuration
    * Description : Configures the different system clocks.
    * Input : None
    * Output : None
    * Return : None
    ************************************************** *****************************/
    void RCC_Configuration(void)
    {
    /* RCC system reset(for debug purpose) */
    RCC_DeInit();


    /* Enable HSE */
    RCC_HSEConfig(RCC_HSE_ON);

    /* Wait till HSE is ready */
    HSEStartUpStatus = RCC_WaitForHSEStartUp();

    if(HSEStartUpStatus == SUCCESS)
    {

    /* PCLK2 = HCLK/2 */
    RCC_PCLKConfig (RCC_HCLK_Div2);


    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_0);
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(ENABLE);
    /* PLLCLK = 8MHz * 6 = 72 MHz */

    RCC_PLLConfig(RCC_SYSCLKSource_HSE, RCC_PLLMul_6);

    /* Enable PLL */
    RCC_PLLCmd(ENABLE);
    /* COde Information*
    * @brief Enables or disables the PLL.
    * @note After enabling the PLL, the application software should wait on
    * PLLRDY flag to be set indicating that PLL clock is stable and can
    * be used as system clock source.
    * @note The PLL can not be disabled if it is used as system clock source
    * @note The PLL is disabled by hardware when entering STOP and STANDBY modes.
    * @param NewState: new state of the PLL.
    * This parameter can be: ENABLE or DISABLE.
    * @retval None
    */
    /* Wait till PLL is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }
    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
    /* Enable peripheral clocks --------------------------------------------------*/
    /* GPIOA, GPIOB and SPI1 clock enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOF , ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 , ENABLE);
    }
    }

    /************************************************** *****************************
    * Function Name : GPIO_Configuration
    * Description : Configures the different GPIO ports.
    * Input : None
    * Output : None
    * Return : None
    ************************************************** *****************************/
    void GPIO_Configuration(void)
    {
    /* Configure SPI2 pins: SCK, MISO and MOSI ---------------------------------*/
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_0);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_0);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_0);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
    //GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    /* SPI SCK pin configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* SPI MOSI pin configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* SPI MISO pin configuration */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // LED Test
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
    // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    }
    لطف میکنید منو راهنمایی کنید.
    با تشکر
لطفا صبر کنید...
X