搜索
bottom↓
回复: 33

nios自带spi核如何编程

[复制链接]

出0入0汤圆

发表于 2010-3-12 09:07:15 | 显示全部楼层 |阅读模式
想用魏坤的第二版示波器做一个SPI读写SD卡用MICROCHIP GUI显示(MICROCHIP GUI已经好了),但是NIOS的SPI核,一直用不上,找了很多的资料(包括NIOS的软件文档)一直用不上,哪位朋友有写过SPI的程序吗?发出来参考一下

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2010-3-12 09:55:47 | 显示全部楼层
同问,我也想知道答案

出0入0汤圆

发表于 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;
}
很简单吧

出0入0汤圆

发表于 2010-3-13 08:00:48 | 显示全部楼层
回复【2楼】avic
-----------------------------------------------------------------------

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

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

出0入0汤圆

发表于 2010-3-13 09:24:46 | 显示全部楼层
回复【3楼】tear086 .COM缺氧
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 2010-3-13 09:45:45 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2010-3-13 23:12:10 | 显示全部楼层
回复【3楼】tear086  .COM缺氧
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 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_SIZE  255
int main()
{  
   alt_u8 Writebuf[BUFFER_SIZE];
   alt_u8 ReadBuf[BUFFER_SIZE];
   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)

出0入0汤圆

发表于 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自己带的库函数,那样的效率不但不高,也找不到像单片机那样的编程方式,简洁明了。
更重要一点就是不灵活,不能按照自己的想法来处理函数。

出0入0汤圆

发表于 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; ......
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 2010-3-14 08:32:34 | 显示全部楼层
回复【10楼】avic
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 2010-3-14 08:39:26 | 显示全部楼层
回复【11楼】tear086 .COM缺氧
回复【10楼】avic  
-----------------------------------------------------------------------
学习了。我对NIOS里面的地址对齐方式还没有深入研究,不敢不用Altera给的api呀。
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 2010-3-14 15:14:08 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-3-14 19:17:45 | 显示全部楼层
mark, thanks everyone

出0入0汤圆

 楼主| 发表于 2010-3-14 20:25:01 | 显示全部楼层
谢谢 tear086 .COM缺氧  avic,弄一下SD卡+显示

出0入0汤圆

 楼主| 发表于 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++;

    }   
}

(原文件名:未命名.JPG)

出0入0汤圆

发表于 2010-3-17 09:09:08 | 显示全部楼层
回复【2楼】avic
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 2010-3-17 23:35:30 | 显示全部楼层
回复【16楼】ep1c3
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 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

出0入0汤圆

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

出100入0汤圆

发表于 2011-4-8 16:32:03 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-14 10:30:12 | 显示全部楼层
其实在一定规模的项目上 按顺序多排几个 寄存器映射也没什么,还可以防止出错

出0入0汤圆

发表于 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楼一样,没结果啊!这是为什么?

出0入0汤圆

发表于 2011-10-10 16:18:16 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-10-12 11:38:09 | 显示全部楼层
回复【1楼】wuyongqing1960
-----------------------------------------------------------------------

支持顶

出0入0汤圆

发表于 2011-10-21 12:22:30 | 显示全部楼层
自带的不是很好用,但很完整,如果要求高速的话,就要自己写一个。

出0入0汤圆

发表于 2012-6-5 22:22:35 | 显示全部楼层
tear086 发表于 2010-3-14 07:11
回复【6楼】ep1c3
-----------------------------------------------------------------------

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

出0入0汤圆

发表于 2013-3-12 18:17:27 | 显示全部楼层
lov9210 发表于 2012-6-5 22:22
太好了  我也在写SPI 的程序 求交流QQ:1520168691

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

出0入0汤圆

发表于 2013-3-12 18:23:44 | 显示全部楼层
麻烦问下你成功了吗?

出0入0汤圆

发表于 2013-3-12 18:26:49 | 显示全部楼层
avic 发表于 2010-3-12 22:44
先定义一个结构体
typedef struct{

我也是那样子弄得不行啊

出0入0汤圆

发表于 2013-3-23 18:02:49 | 显示全部楼层
wuliaoswz 发表于 2013-3-12 18:17
想问下您有关SPI的事,可加不成你的QQ。。

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

出0入0汤圆

发表于 2013-3-23 21:09:28 | 显示全部楼层
我是用xilinx的Microblaze控制做的,是用的IO模拟spi的时序。现在我想把flash挂在总线上,但是也只是给了一个首地址。那flash的信号线(地址线,数据线,信号线)要用结构体自己定义么?

出0入0汤圆

发表于 2013-3-24 12:30:13 | 显示全部楼层
水印。。。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-17 22:18

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表