我在用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
回复 楼主 zzgezi 的帖子
单步调试程序跑到哪里去了?
,不喜欢检查程序,楼主附件中是3份例程,楼主看一看吧。
比对检查debug 本身就是一个学习的过程。
[
本帖最后由 hlx3012 于 2012-2-13 11:35 编辑 ]
回复 板凳 zzgezi 的帖子
下一步呢,程序飞到哪里去了?我看你用的是 Keil。可以在 Debug 状态下,看一下 Peripherals 菜单的 core peripherals 下的 fault reports ,看看是否产生了 fault.
楼主下面是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);
}
楼主用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);
}
}
谢谢二位
非常感谢二位,我按hlx3012说的把SSIDataGet 改成SSIDataGetNonBlocking程序没有再死在那里,但是为什么返回值是0呢?为什么没有收到发送的数据呢?还有程序会进入到“FaultISR”死循环里。我按照Study_Stellaris打开了Peripherals 菜单的 core peripherals 下的 fault reports 得到:
/**--------------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]);
}
}
回复 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 编辑 ]