主题中讨论的其他器件: TM4C123、 EK-TM4C1294XL
大家好、
我尝试在 Arduino Mega 2560和 TI 微控制器之间设置 SPI 通信。 我正在尝试将 Arduino Mega 2560设置为主控制器、将 TI 控制器设置为从控制器。 我希望主器件通过一次 SPI 传输连续地将2个字节从 Arduino 发送到 TI 微控制器。
在两个板之间、我有以下连接:
Arduino Mega 2560 EK-TM4C123GXL
引脚50 => PA5
引脚51 => PA4
引脚52 => PA2
引脚53 => PA3
看来、SPI 的中断被调用一次、然后不会再次被调用。 它正确传输发送的第一个字节、但该第一个字节同时出现在存储阵列的0和1索引中。
似乎不会多次调用中断。 有哪些因素阻碍 Arduino 正确重复传输两个字节到 EK-TM4C123GXL?
Arduino 代码:
#include<SPI.h> byte direction_byte = 0b00001110; byte speed_byte = 0b01010101; //SPISettings ti_settings(SPI_CLOCK_DIV4,MSBFIRST,SPI_MODE2); bool flip = 0; void setup (void) { digitalWrite(SS, HIGH); // ensure SS stays high for now SPI.setDataMode(SPI_MODE2); // Put SCK, MOSI, SS pins into output mode // also put SCK, MOSI into LOW state, and SS into HIGH state. // Then put SPI hardware into Master mode and turn SPI on SPI.begin (); // Slow down the master a bit SPI.setClockDivider(SPI_CLOCK_DIV8); SPI.setDataMode(SPI_MODE2); } // end of setup void loop (void) { // enable Slave Select digitalWrite(SS, LOW); // SS is pin 10 // send test string SPI.transfer(direction_byte); SPI.transfer(speed_byte); // disable Slave Select digitalWrite(SS, HIGH); delay (1000); // 1 seconds delay } // end of loop
EK-TM4C123GXL 的代码:
//***************************************************************************** // // spi_slave.c - Example demonstrating how to configure RX timeout interrupt in // SPI slave mode. // // Copyright (c) 2013 Texas Instruments Incorporated. All rights reserved. // TI Information - Selective Disclosure // //***************************************************************************** #include <stdbool.h> #include <stdint.h> #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "driverlib/debug.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/pwm.h" #include "driverlib/rom.h" #include "driverlib/rom_map.h" #include "inc/hw_memmap.h" #include "driverlib/qei.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" #include "driverlib/fpu.h" #include "inc/hw_types.h" #include "inc/hw_memmap.h" // The error routine that is called if the driver library encounters an error. #include "inc/hw_types.h" // Defines common types and macros #include "inc/hw_gpio.h" // Defines Macros for GPIO hardware #include "inc/hw_qei.h" #include "driverlib/ssi.h" #include "utils/uartstdio.h" //***************************************************************************** // //! \addtogroup ssi_examples_list //! <h1>SPI Slave (spi_slave)</h1> //! //! This example configures the SSI0 as SPI Master, SSI2 as SPI Slave on an //! EK-LM4F232 evaluation board. RX timeout interrupt is configured for SSI2. //! Three characters are sent on the master TX, then SSI2 RX timeout interrupt //! is enabled. The code then waits for the interrupt to fire. Once the //! interrupt is fired the data from slave RX FIFO is read and compared to the //! transmitted packet and the appropriate status is displayed. If everything //! goes well you should see a "Test Passed." message on the terminal window. //! The status messages are transmitted over UART0 at 115200 baud and 8-n-1 //! mode. //! //! This example uses the following peripherals and I/O signals on EK-LM4F232. //! You must review these and change as needed for your own board: //! - SSI0 peripheral //! - GPIO Port A peripheral (for SSI0 pins) (available near the SD card slot) //! - SSI0CLK - PA2 //! - SSI0Fss - PA3 //! - SSI0Rx - PA4 //! - SSI0Tx - PA5 //! //! - SSI2 peripheral //! - GPIO Port M peripheral (for SSI2 pins) (available right below the OLED) //! - SSI2CLK - PH4 //! - SSI2Fss - PH5 //! - SSI2Rx - PH6 //! - SSI2Tx - PH7 //! //! For this example to work, the following connections are needed on the //! EK-LM4F232 evaluation board. //! - SSI0CLK(PA2) - SSI2CLK(PH4) //! - SSI0Fss(PA3) - SSI0Fss(PH5) //! - SSI0Rx(PA4) - SSI2Tx(PH7) //! - SSI0Tx(PA5) - SSI2Rx(PH6) //! //! The following UART signals are configured only for displaying console //! messages for this example. These are not required for operation of SSI0. //! - UART0 peripheral //! - GPIO Port A peripheral (for UART0 pins) //! - UART0RX - PA0 //! - UART0TX - PA1 //! //! This example uses the following interrupt handlers. To use this example //! in your own application you must add these interrupt handlers to your //! vector table. //! - SSI2IntHandler. //! // //***************************************************************************** //***************************************************************************** // // Number of bytes to send and receive. // //***************************************************************************** #define NUM_SSI_DATA 2 //***************************************************************************** // // Global variables used in interrupt handler and the main loop. // //***************************************************************************** //volatile unsigned long g_ulSSI2RXTO = 0; //unsigned long g_ulDataRx2[NUM_SSI_DATA]; volatile uint32_t g_ulSSI2RXTO = 0; volatile uint32_t g_ulDataRx2[NUM_SSI_DATA]; //***************************************************************************** // // Interrupt handler for SSI2 peripheral in slave mode. It reads the interrupt // status and if the interrupt is fired by a RX time out interrupt it reads the // SSI2 RX FIFO and increments a counter to tell the main loop that RX timeout // interrupt was fired. // //***************************************************************************** void SSI0IntHandler(void) { unsigned long ulStatus, ulIndex; // // Read interrupt status. // ulStatus = SSIIntStatus(SSI0_BASE, 1); // // Check the reason for the interrupt. // if(ulStatus & SSI_RXTO) { // // Interrupt is because of RX time out. So increment counter to tell // main loop that RX timeout interrupt occurred. // g_ulSSI2RXTO++; // // Read NUM_SSI_DATA bytes of data from SSI2 RX FIFO. // for(ulIndex = 0; ulIndex < NUM_SSI_DATA; ulIndex++) { SSIDataGet(SSI0_BASE, &g_ulDataRx2[ulIndex]); } g_ulSSI2RXTO--; } // // Clear interrupts. // SSIIntClear(SSI2_BASE, ulStatus); } //***************************************************************************** // // This function sets up UART0 to be used for a console to display information // as the example is running. // //***************************************************************************** //***************************************************************************** // // This function sets up SPI0 to be used as Master in freescale mode. // //***************************************************************************** void InitSPI0(void) { // // The SSI0 peripheral must be enabled for use. // SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_SSI0)) { } // // For this example SSI2 is used with PortH[7:4]. GPIO port H needs to be // enabled so these pins can be used. // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)) { } // // Configure the pin muxing for SSI2 functions on port H4, H5, H6 and H7. // This step is not necessary if your part does not support pin muxing. // GPIOPinConfigure(GPIO_PA2_SSI0CLK); GPIOPinConfigure(GPIO_PA3_SSI0FSS); GPIOPinConfigure(GPIO_PA4_SSI0RX); GPIOPinConfigure(GPIO_PA5_SSI0TX); GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2); SSIDisable(SSI0_BASE); // // Configure and enable the SSI0 port for SPI master mode. // SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_2, SSI_MODE_SLAVE, 660000, 8); SSIDisable(SSI0_BASE); // // Enable the SSI2 module. // SSIEnable(SSI0_BASE); IntEnable(INT_SSI0); SSIIntEnable(SSI0_BASE, SSI_RXTO); SSIIntRegister(SSI0_BASE, SSI0IntHandler); } //***************************************************************************** // // This function sets up SPI2 to be used as slave in freescale mode. // //***************************************************************************** //************************************************************************* int main(void) { /* unsigned long ulDataTx0[NUM_SSI_DATA]; unsigned long ulDataRx0[NUM_SSI_DATA]; unsigned long ulindex; */ uint32_t ulDataTx0[NUM_SSI_DATA]; uint32_t ulDataRx0[NUM_SSI_DATA]; uint32_t ulindex; // // Set the clocking to run directly from the external crystal/oscillator. // SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Init SPI0 as master. // InitSPI0(); // // Read any residual data from the SSI port. This makes sure the receive // FIFOs are empty, so we don't read any unwanted junk. This is done here // because the SPI SSI mode is full-duplex, which allows you to send and // receive at the same time. The SSIDataGetNonBlocking function returns // "true" when data was returned, and "false" when no data was returned. // The "non-blocking" function checks if there is any data in the receive // FIFO and does not "hang" if there isn't. This might not be needed here. // while(SSIDataGetNonBlocking(SSI0_BASE, &ulDataRx0[0])) { } // // Clear any pending interrupt // SSIIntClear(SSI0_BASE, SSI_RXTO); while(1) { } }