[求助] 新手求助LM3S9B96 spi问题

zzgezi   2012-2-13 10:35 楼主
我在用LM3S9B96做SPI自发自收的实验,做了两个,第一个是没有加中断,发送一个接收一个(没有问题),第二个是加了中断,在中断里接收发送的数据,问题就出在在中断函数里单步调试运行到匀匀IDataGet(SSI_BASE, &rec[0]);程序就跑飞了,自己能力有限,没弄明白。下面我附上两个程序,请大家帮我看看。

先谢谢了。

[ 本帖最后由 zzgezi 于 2012-2-13 10:43 编辑 ]

    实验一.rar (2012-2-13 10:41 上传)

    1.96 KB, 下载次数: 30

    实验二.rar (2012-2-13 10:41 上传)

    1.76 KB, 下载次数: 27

回复评论 (11)

回复 楼主 zzgezi 的帖子

单步调试程序跑到哪里去了?
点赞  2012-2-13 10:57

停在这了

停在这.jpg
[ 本帖最后由 zzgezi 于 2012-2-13 11:17 编辑 ]
点赞  2012-2-13 11:10

 ,不喜欢检查程序,楼主附件中是3份例程,楼主看一看吧。

 

比对检查debug 本身就是一个学习的过程。

[ 本帖最后由 hlx3012 于 2012-2-13 11:35 编辑 ]
点赞  2012-2-13 11:34

回复 4楼 hlx3012 的帖子

谢谢你!
点赞  2012-2-13 11:38

回复 板凳 zzgezi 的帖子

下一步呢,程序飞到哪里去了?我看你用的是 Keil。可以在 Debug 状态下,看一下 Peripherals 菜单的 core peripherals 下的 fault reports ,看看是否产生了 fault.
点赞  2012-2-13 11:38

 

楼主下面是SSIDataGet的源代码,如果接收FIFO为空就会一直停在那里,这说明程序没有接收到东西。

 

 

SSIDataGet(unsigned long ulBase, unsigned long *pulData)
{
    // 反复确认SSISR[RNE],RNE:为1说明Receive FIFO不为空
    while(!(HWREG(ulBase + SSI_O_SR) & SSI_SR_RNE))
    {
    }

    // 读取数据
    *pulData = HWREG(ulBase + SSI_O_DR);
}

点赞  2012-2-13 11:38

楼主用SSIDataGetNonBlocking试试,如果我猜的没错不会再卡死在那里,但是返回值应该是0.

 

 

//*****************************************************************************
//! 接收数据,把一个数据读出RX FIFO(如无数据直接返回)
//!
//! \param ulBase SSI基础地址
//! \param pulData 接收数据的指针
//!
//! \return 有数据返回1,如无数据返回0
//*****************************************************************************
long
SSIDataGetNonBlocking(unsigned long ulBase, unsigned long *pulData)
{
    // Check the arguments.
    ASSERT(SSIBaseValid(ulBase));

    // 确认SSISR[RNE],RNE:为1说明Receive FIFO不为空
    if(HWREG(ulBase + SSI_O_SR) & SSI_SR_RNE)
    {
        *pulData = HWREG(ulBase + SSI_O_DR);
        return(1);
    }
    else
    {
        return(0);
    }
}

点赞  2012-2-13 11:49

谢谢二位

非常感谢二位,我按hlx3012说的把SSIDataGet 改成SSIDataGetNonBlocking程序没有再死在那里,但是为什么返回值是0呢?为什么没有收到发送的数据呢?还有程序会进入到“FaultISR”死循环里。我按照Study_Stellaris打开了Peripherals 菜单的 core peripherals 下的 fault reports 得到:
Fault Report.jpg
点赞  2012-2-13 15:13
/**--------------File Info---------------------------------------------------------------------------------
** File name:               spi_rec.c
** Latest Version:          1.1
** Descriptions:            通过 SSI 发送接口循环向外输出 ,并通过SSI的接收接口接收回来通过UART在主机上显示。
**
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/

/*  调用库函数的头文件              */
#include "hw_memmap.h"
#include "hw_types.h"
#include "hw_ssi.h"
#include "ssi.h"
#include "gpio.h"
#include "sysctl.h"
#include "systick.h"
#include "driverlib/uart.h"
#include "inc/hw_ints.h"
#include  
  
#define BitRate     115200                                              /*  设定波特率                  */
#define DataWidth   8                                                   /*  设定数据宽度                */
unsigned long rec[16];
/*unsigned char DISP_TAB[16] = {
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E}; */
unsigned char DISP_TAB[] = {0xC0};
/*********************************************************************************************************
** Function name:           delay
**
** Descriptions:            延时函数,输入参数越大,延时时间越长
**
** input parameters:        uld    延时时间值
** output parameters:       NONE
**                          
** Returned value:          NONE
**
**--------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
void delay (unsigned long uld)
{
  for( ;uld ;uld--);
}
/********************************************************************************************************/
void uartPutc(const char c)
{
    UARTCharPut(UART0_BASE, c);
}

//
//  通过UART发送字符串
//
void uartPuts(const char *s)
{
    while (*s != '\0') uartPutc(*(s++));
}

uart_init()
{
        char s[40];
    //
    // Set the device pinout appropriately for this board.
    //
    //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    //
    // Enable the (non-GPIO) peripherals used by this example.  PinoutSet()
    // already enabled GPIO Port A.
    //
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);

    //
    // Enable processor interrupts.
    //
    IntMasterEnable();

    //
    // Set GPIO A0 and A1 as UART pins.
    //
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Configure the UART for 115,200, 8-N-1 operation.
    //
    UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200,
                            (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                             UART_CONFIG_PAR_NONE));

    //
    // Enable the UART interrupt.
    //
    IntEnable(INT_UART0);
    UARTIntEnable(UART0_BASE, UART_INT_RX | UART_INT_RT);

    sprintf(s, "hello, world\r\n");                         //  输出hello, world
        uartPuts(s);
}


int main (void)
{  
    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                       SYSCTL_XTAL_16MHZ);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI);                          /* 为SSI提供时钟              */
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);                        /*  为GPIOA端口提供时钟         */

    /*  设置SPI为主机模式0,8位数据宽度,115200的波特率     */
    SSIConfig(SSI_BASE, SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, BitRate, DataWidth);
                                                   
    /* 设定 GPIO A 2~5 引脚为使用外设功能                     */
    GPIOPinTypeSSI(GPIO_PORTA_BASE, (GPIO_PIN_2 | GPIO_PIN_3 |
                                         GPIO_PIN_4 | GPIO_PIN_5));
           HWREG(SSI_BASE + SSI_O_CR1) |= SSI_CR1_LBM;
        //SSIIntEnable(SSI_BASE ,SSI_RXFF|SSI_RXOR|SSI_RXTO);
        SSIIntEnable(SSI_BASE ,SSI_RXTO|SSI_RXFF);
        //SSIIntEnable(SSI_BASE ,SSI_TXFF);
        SSIEnable(SSI_BASE);                                                              /*  使能SPI            */
        IntEnable(INT_SSI0);
        uart_init();

   // SSIDataPut(SSI_BASE, DISP_TAB[0]);                        
        delay(10);
        /*SSIDataPut(SSI_BASE, DISP_TAB[0]);                                             
        delay(10);
    SSIDataPut(SSI_BASE, DISP_TAB[0]);
        delay(10);
        SSIDataPut(SSI_BASE, DISP_TAB[0]);
        delay(10);
        SSIDataPut(SSI_BASE, DISP_TAB[0]);
        delay(10);
        SSIDataPut(SSI_BASE, DISP_TAB[0]); */
    while (1)
        {
                  SSIDataPut(SSI_BASE, DISP_TAB[0]);                          /*  循环发送数据   */
                 delay(1000);
        }                                                       
}
void SPI_ISR(void)
{
        unsigned long ulStatus;
        char s[40];
    ulStatus = SSIIntStatus(SSI_BASE,true);
    SSIIntClear(SSI_BASE,ulStatus);
     while((HWREG(SSI_BASE + SSI_O_SR) & SSI_SR_RNE))
    {
     
    SSIDataGetNonBlocking(SSI_BASE, &rec[0]);                /* 接收数据 */  
    uartPutc(rec[0]);
    }
}
点赞  2012-2-13 16:04
说不清楚,我改好了,你自己看吧。。。

[ 本帖最后由 hlx3012 于 2012-2-13 16:06 编辑 ]
点赞  2012-2-13 16:04

回复 10楼 hlx3012 的帖子

你好hlx3012 ,加上了“while((HWREG(SSI_BASE + SSI_O_SR) & SSI_SR_RNE))”//SSI的状态为接收FIFO不为空,为什么不加这句就会进“FaultISR”死循环呢?
 还有SSI的发送中断SSI_TXFF  //   发送FIFO 半空或不足半空 ,在发送数据时什么时候会进中断呢?是每发一个数据进一次吗?

[ 本帖最后由 zzgezi 于 2012-2-13 17:38 编辑 ]
点赞  2012-2-13 17:33
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复