ep1c3 发表于 2010-3-12 09:07:15

nios自带spi核如何编程

想用魏坤的第二版示波器做一个SPI读写SD卡用MICROCHIP GUI显示(MICROCHIP GUI已经好了),但是NIOS的SPI核,一直用不上,找了很多的资料(包括NIOS的软件文档)一直用不上,哪位朋友有写过SPI的程序吗?发出来参考一下

wuyongqing1960 发表于 2010-3-12 09:55:47

同问,我也想知道答案

avic 发表于 2010-3-12 22:44:21

先定义一个结构体
typedef struct{

    volatile unsigned long int RXDATA;

    volatile unsigned long int TXDATA;

    union{
      struct{
            volatile unsigned long int NC       :3;
            volatile unsigned long int ROE      :1;
            volatile unsigned long int TOE      :1;
            volatile unsigned long int TMT      :1;
            volatile unsigned long int TRDY   :1;
            volatile unsigned long int RRDY   :1;
            volatile unsigned long int E      :1;
            volatile unsigned long int NC1      :23;      
      }BITS;
      volatile unsigned long int WORD;
    }STATUS;

    union{
      struct{
            volatile unsigned long int NC       :3;
            volatile unsigned long int IROE   :1;
            volatile unsigned long int ITOE   :1;
            volatile unsigned long int NC1      :1;
            volatile unsigned long int ITRDY    :1;
            volatile unsigned long int IRRDY    :1;
            volatile unsigned long int IE       :1;
            volatile unsigned long int NC2      :1;
            volatile unsigned long int SSO      :21;
      }BITS;
      volatile unsigned long int CONTROL;
    }CONTROL;

    unsigned long int RESERVED0;
    unsigned long int SLAVE_SELECT;

}SPI_ADC_T;

#define SPI_ADC          ((SPI_ADC_T *) SPI_ADC_BASE)//SPI_ADC_BASE是在system.h里产生的地址

这个就是利用nios的spi接口的adc,下面是例程
unsigned int read_adc(void)
{
       SPI_ADC->TXDATA=0;
      
       while(!(SPI_LAN->STATUS.BITS.TMT));
      
       return SPI_ADC->RXDATA;
}
很简单吧

tear086 发表于 2010-3-13 08:00:48

回复【2楼】avic
-----------------------------------------------------------------------

楼上的位域用的出神入化。学习了。

个人感觉,有时候需要多看看手册。手册上讲得很清楚。
点击此处下载 ourdev_538101.pdf(文件大小:1.01M) (原文件名:SPI CORE.pdf)

avic 发表于 2010-3-13 09:24:46

回复【3楼】tear086 .COM缺氧
-----------------------------------------------------------------------

说的有道理,更重要的是能够利用手册来实现程序的编写,好像是废话啊,呵呵

1181zjf 发表于 2010-3-13 09:45:45

mark

ep1c3 发表于 2010-3-13 23:12:10

回复【3楼】tear086.COM缺氧
-----------------------------------------------------------------------

不是没看过手册,看了之后没感觉,而且到网找了很多的资料, 就是出不来。可能是NIOS的操作还不太会吧

tear086 发表于 2010-3-14 07:11:43

回复【6楼】ep1c3
-----------------------------------------------------------------------

借ZLG的代码花献佛。

/********************************************************************
* 文 件 名:spi_test.c
* 功    能:用alt_avalon_spi_command()函数来发送数据。
* 说    明:用LA1032逻辑分析仪测试数据。
********************************************************************/

#include "system.h"                     //system.h文件中提供了基本的硬件信息
#include "altera_avalon_spi_regs.h"//定义了SPI寄存器的基本信息
#include "altera_avalon_spi.h"      //提供了访问SPI的函数声明
#include "alt_types.h"               //Altera自定义的一些数据类型

#define BUFFER_SIZE255
int main()
{
   alt_u8 Writebuf;
   alt_u8 ReadBuf;
   int i;
   int cnt = 500;
   for (i=0; i<BUFFER_SIZE; i++)
   {
       Writebuf = (alt_u8)i+1;//初始化准备发送的数据
   }
   while(1)
   {
      alt_avalon_spi_command(SPI_BASE, 0,   
                           100, Writebuf,
                           0, ReadBuf,
                           0);
      while(cnt--);
      cnt = 500;
   }
return 0;
}

点击此处下载 ourdev_538229.pdf(文件大小:442K) (原文件名:SPI操作及逻辑分析仪实验.pdf)

avic 发表于 2010-3-14 08:23:13

回复【6楼】ep1c3
-----------------------------------------------------------------------

其实NIOS的操作跟单片机,arm是一样的,都是对地址进行操作,不同之处就是,单片机,arm的地址寄存器都在头文件给出了 ,而NIOS的地址是通过system.h给出的,并且只给出了没个功能的首地址,这样就需要我们自己写一个结构体,将所有的寄存器地址展示出来,例如SPI的寄存器结构体就是下面这样的
typedef struct{

    volatile unsigned long int RXDATA;

    volatile unsigned long int TXDATA;

    union{
      struct{
            volatile unsigned long int NC       :3;
            volatile unsigned long int ROE      :1;
            volatile unsigned long int TOE      :1;
            volatile unsigned long int TMT      :1;
            volatile unsigned long int TRDY   :1;
            volatile unsigned long int RRDY   :1;
            volatile unsigned long int E      :1;
            volatile unsigned long int NC1      :23;         
      }BITS;
      volatile unsigned long int WORD;
    }STATUS;

    union{
      struct{
            volatile unsigned long int NC       :3;
            volatile unsigned long int IROE   :1;
            volatile unsigned long int ITOE   :1;
            volatile unsigned long int NC1      :1;
            volatile unsigned long int ITRDY    :1;
            volatile unsigned long int IRRDY    :1;
            volatile unsigned long int IE       :1;
            volatile unsigned long int NC2      :1;
            volatile unsigned long int SSO      :21;
      }BITS;
      volatile unsigned long int CONTROL;
    }CONTROL;

    unsigned long int RESERVED0;
    unsigned long int SLAVE_SELECT;

}SPI;
而这个结构体的写法就是根据手册上的寄存器地址顺序写的。
不建议大家用Nios自己带的库函数,那样的效率不但不高,也找不到像单片机那样的编程方式,简洁明了。
更重要一点就是不灵活,不能按照自己的想法来处理函数。

avic 发表于 2010-3-14 08:27:46

回复【2楼】avic
先定义一个结构体
typedef struct{
    volatile unsigned long int RXDATA;
    volatile unsigned long int TXDATA;
    union{
      struct{
            volatile unsigned long int NC       :3;
            volatile unsigned long int ROE      :1;
            volatile unsigned long int TOE      :1;
            volatile unsigned long int TMT      :1;
            volatile unsigned long int TRDY   :1; ......
-----------------------------------------------------------------------

这是很常用的寄存器分配方式,一般在头文件中很常见

tear086 发表于 2010-3-14 08:32:34

回复【10楼】avic
-----------------------------------------------------------------------

学习了。我对NIOS里面的地址对齐方式还没有深入研究,不敢不用Altera给的api呀。

avic 发表于 2010-3-14 08:39:26

回复【11楼】tear086 .COM缺氧
回复【10楼】avic
-----------------------------------------------------------------------
学习了。我对NIOS里面的地址对齐方式还没有深入研究,不敢不用Altera给的api呀。
-----------------------------------------------------------------------

大家可以一起交流,共同进步啊,在论坛里面就是这个目的,真的非常感谢阿莫给我们提供这么好的一个平台,谢谢ourdev,呵呵

tangfree 发表于 2010-3-14 15:14:08

MARK

wolfboy8913 发表于 2010-3-14 19:17:45

mark, thanks everyone

ep1c3 发表于 2010-3-14 20:25:01

谢谢 tear086 .COM缺氧avic,弄一下SD卡+显示

ep1c3 发表于 2010-3-16 15:29:46

回复【2楼】avic
-----------------------------------------------------------------------
这个程序可以用吗?
用你提供的结构体,写了个测试程序,在MODELSIM里,MOSI和CLK变换一直为低
测试程序如下:
int alt_main()
{
    int i;
    ALTERA_AVALON_SPI_INIT(SPI_BASE, 0);
    while (1)
    {
      SPI_SD->TXDATA = i;      
      while(!(SPI_SD->STATUS.BITS.TMT));
      i++;

    }   
}
http://cache.amobbs.com/bbs_upload782111/files_27/ourdev_538675.JPG
(原文件名:未命名.JPG)

tear086 发表于 2010-3-17 09:09:08

回复【2楼】avic
-----------------------------------------------------------------------

一看了不起,再看很佩服。

avic 发表于 2010-3-17 23:35:30

回复【16楼】ep1c3
-----------------------------------------------------------------------

程序一定好用的,我在板子上测试过的。我没有仿真过这个程序,我也不知道是怎么回事啊

qw1234900 发表于 2010-5-5 13:00:06

回复【楼主位】ep1c3
-----------------------------------------------------------------------

请问 能吧NIOS读SD卡的 程序发出来参考一下么
///////////////////////////////////////////////////
// SPI 测试
///////////////////////////////////////////////////

#include "system.h"
#include "altera_avalon_spi_regs.h"
#include "altera_avalon_pio_regs.h"
#include "alt_types.h"

int main(void) __attribute__ ((weak, alias("alt_main")));

int alt_main(void)
{
    alt_u16 data=0x1234;
    alt_u16 i;
   
    // ss_1 为片选
    IOWR_ALTERA_AVALON_SPI_SLAVE_SEL(spi_BASE, 1);
    // spi 主模式
    IOWR_ALTERA_AVALON_SPI_CONTROL(spi_BASE, 0x0400); //控制寄存器
   
    while (1)
    {
      IOWR_ALTERA_AVALON_SPI_TXDATA(spi_base , data);
      while (!(IORD_ALTERA_AVALON_SPI_STATUS(spi_BASE) & ALTERA_AVALON_SPI_STATUS_TRDY_MSK));
      for (i=0;i<60000;i++);
    }
}
这是 一位师兄 编的SPI

lgcHR 发表于 2010-8-5 11:39:22

二楼的做法很值得大家借鉴啊,其实使用一个指针完成地址映射(从软件指针一一映射到硬件寄存器),这样可以通过SPI_ADC          ((SPI_ADC_T *) SPI_ADC_BASE操作每一位硬件寄存器,。不过这样有一个问题,当真正使用的寄存器不多时,所有的寄存器都得写上,因为寄存器是顺序排列的,只要少一个,就会出大麻烦,所以在小型工程中不建议这样使用。使用系统提供的API有助于减小代码的规模,所以在小工程中API是不错的选择。当然大工程中为了排查的需要映射寄存器的做法是非常值得借鉴的。就是这样

yu_wen 发表于 2011-4-8 16:32:03

mark

scofiled 发表于 2011-4-14 10:30:12

其实在一定规模的项目上 按顺序多排几个 寄存器映射也没什么,还可以防止出错

lazyduck 发表于 2011-6-28 11:23:13

回复【2楼】avic
-----------------------------------------------------------------------



#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "altera_avalon_spi_regs.h"//定义了SPI寄存器的基本信息
#include "altera_avalon_spi.h"      //提供了访问SPI的函数声明
#include "alt_types.h"               //Altera自定义的一些数据类型
#include "stdio.h"
//#include "altera_avalon_pio_regs.h"
#include "unistd.h"

typedef struct{

    volatile unsigned long int RXDATA;

    volatile unsigned long int TXDATA;

    union{
      struct{
            volatile unsigned long int NC       :3;
            volatile unsigned long int ROE      :1;
            volatile unsigned long int TOE      :1;
            volatile unsigned long int TMT      :1;
            volatile unsigned long int TRDY   :1;
            volatile unsigned long int RRDY   :1;
            volatile unsigned long int E      :1;
            volatile unsigned long int NC1      :23;         
      }BITS;
      volatile unsigned long int WORD;
    }STATUS;

    union{
      struct{
            volatile unsigned long int NC       :3;
            volatile unsigned long int IROE   :1;
            volatile unsigned long int ITOE   :1;
            volatile unsigned long int NC1      :1;
            volatile unsigned long int ITRDY    :1;
            volatile unsigned long int IRRDY    :1;
            volatile unsigned long int IE       :1;
            volatile unsigned long int NC2      :1;
            volatile unsigned long int SSO      :21;
      }BITS;
      volatile unsigned long int CONTROL;
    }CONTROL;

    unsigned long int RESERVED0;
    unsigned long int SLAVE_SELECT;

}SPI_ADC_T;

#define SPI_ADC          ((SPI_ADC_T *) SPI_0_BASE)//SPI_ADC_BASE是在system.h里产生的地址

int main (void)
{
//alt_u8 led = 0x2;
//alt_u8 dir = 0;


unsigned int i=0;
/*
   * Infinitly shift a variable with one bit set back and forth, and write
   * it to the LED PIO.Software loop provides delay element.
   */
while (1)
{
       SPI_ADC->TXDATA=i;
      
       while(!(SPI_ADC->STATUS.BITS.TMT));
       i=i+1;
       if(i>0xfff) i=0;
}

return 0;
}


我也试了下,跟16楼一样,没结果啊!这是为什么?

amote 发表于 2011-10-10 16:18:16

mark

frankmeng 发表于 2011-10-12 11:38:09

回复【1楼】wuyongqing1960
-----------------------------------------------------------------------

支持顶

john2liu 发表于 2011-10-21 12:22:30

自带的不是很好用,但很完整,如果要求高速的话,就要自己写一个。

lov9210 发表于 2012-6-5 22:22:35

tear086 发表于 2010-3-14 07:11 static/image/common/back.gif
回复【6楼】ep1c3
-----------------------------------------------------------------------



太好了我也在写SPI 的程序 求交流QQ:1520168691

wuliaoswz 发表于 2013-3-12 18:17:27

lov9210 发表于 2012-6-5 22:22 static/image/common/back.gif
太好了我也在写SPI 的程序 求交流QQ:1520168691

想问下您有关SPI的事,可加不成你的QQ。。

wuliaoswz 发表于 2013-3-12 18:23:44

麻烦问下你成功了吗?

wuliaoswz 发表于 2013-3-12 18:26:49

avic 发表于 2010-3-12 22:44 static/image/common/back.gif
先定义一个结构体
typedef struct{



我也是那样子弄得不行啊

lov9210 发表于 2013-3-23 18:02:49

wuliaoswz 发表于 2013-3-12 18:17 static/image/common/back.gif
想问下您有关SPI的事,可加不成你的QQ。。

不好意思啊!你的QQ是多少呢?

qswsjs 发表于 2013-3-23 21:09:28

我是用xilinx的Microblaze控制做的,是用的IO模拟spi的时序。现在我想把flash挂在总线上,但是也只是给了一个首地址。那flash的信号线(地址线,数据线,信号线)要用结构体自己定义么?

siriux 发表于 2013-3-24 12:30:13

水印。。。
页: [1]
查看完整版本: nios自带spi核如何编程