• 【笔记】NIOS II spi详解


    NIOS II spi详解

    1、说明

    本文是依据笔者阅读《Embedded Peripherals (ver 9.0, Mar 2009, 4 MB).pdf》参考文档所作的个人理解,可以看做是笔记吧。

    本文只讲NIOS II嵌入式外设SPI的原理与使用,关于IP-CORE的使用,请读者参考   SPI Slave JTAG to Avalon Master.pdf》。

    在下一篇文章中将用实例说明如何用SPI驱动ADS1256

    2、功能描述

    Spi通讯包括两条数据线(进、出)、一条同步时钟线和一条控制线。

    1Master Out Slave In (mosi)—主设备输入数据到从设备的数据线。

    2Master In Slave Out (miso)—从设备输出数据到主设备的数据线。

    3Serial Clock (sclk)—主设备驱动从设备的同步时钟。

    4Slave Select (ss_n)—主设备驱动,用于选择从设备。置低时有效。最多可以设置32个从设备。

                     
                SclkAvalonMM是同步的。当配置为主设备,spi-coreAvalonMM的时钟分频得到sclk。若配置为从设备,接收逻辑是与sclk的输入同步的。

    3、发送逻辑

    发送逻辑包含发送保持寄存器(txdata)和发送移位寄存器,各有n位宽度,可配置1~32位。当某主外设写txdata,值会自动被复制到移位寄存器,并在下个操作开始时传输。

    Txdata和移位寄存器提供两个存储空间。当有数据在移位寄存器传输时,可以往txdata中写入数据,并且在移位寄存器处理完当前数据时会自动加载txdata中数据,并发送。

    在主设备模式传输移位寄存器直接驱动mosi,在从设备模式,传输移位寄存器直接驱动miso

    数据传输时,LSB或者MSB在前,由配置时用户指定。指定之后,不可软件更改。

    4、接收逻辑

    接收逻辑包含接收保持寄存器(rxdata)和接收移位寄存器,各有n位宽度,可配置1~16位。在接收移位寄存器捕获满n位数据后,主外设可以从rxdata中读取接收到的数据。

    同发送逻辑类似,接收逻辑同样具有提供两个存储空间的功能。Rxdata可以保持前一个接收到的数据,同时接收移位寄存器亦在接收数据。当一个传输完毕时,接收逻辑自动将接收移位寄存器的数据更新至rxdata

    在主设备模数时,接收移位寄存器直接受miso驱动。在从设备模式 ,受mosi驱动。同样,数据传输时,LSB或者MSB在前,由配置时用户指定。指定之后,不可软件更改。

    5、在SOPC中安装SPI-CORE

    5.1 主从设置

    用户可以选择主设备模式或者从设备模式。当选择主设备模式时,下面的选择是有效的:Number of select (SS_n) signalsSPI clock rate Specify delay.

    1Number of Select (SS_n) Signals

    设置从设备的个数。取值范围是1~32。该选择会在生成NIOS II时产生nSS_n引脚,用于片选。

     

    2SPI Clock (sclk) Rate

    该时钟是有Avalon-MM分频产生,其数学关系是:

    <Avalon-MM system clock frequency> / [2, 4, 6, 8, ...]

    SOPC设置时,可以输入所需要的时钟,软件会自动选择一个低于或者等于所输入时钟的最近符合值。

    时钟的设置注意结合从设备的要求。

    3Specify Delay

    该延时是指片选信号有效(置低)之后,需要多长的时间才能对从设备发起操作。

          

    5.2 数据寄存器设置

    该设置影响数据寄存器的大小和行为特性。

    1Width—设置txdatarxdata、发送移位寄存器、接收移位寄存器的大小,可设置为1~32位。

    2Shift direction指定数据传输时LSB或者MSB在前。用户需了解从设备所需的模式。

    5.3 时序设定

    该设定涉及ss_n, sclk, mosi miso 信号的设置。共有两处设定,可设定4种模式。

    1Clock polarity设置为0时,sclk空闲时为低;设置为1时,sclk空闲时为高。

    2Clock phase设置为0时,数据在sclk的上升沿锁存;设置为1时,数据在sclk的下降沿锁存。

    具体见如下时序图:

           1. Clock Polarity = 0, Clock Phase = 0



          2. Clock Polarity = 0, Clock Phase = 1

     
                            

                3. Clock Polarity = 1, Clock Phase = 0

                     
          
                 4. Clock Polarity = 1, Clock Phase = 1

            

    6NIOS II软件驱动模块

    有两种方式:

    1.              使用有Altera提供的alt_avalon_spi_command()函数,使用非常简单。具体可见笔者下一篇驱动实例。

    2.              读者自己编写。

    这里先将读者自己DIY的驱动编写方法。

    6.1 驱动方式一

    必须包含:

    #include "altera_avalon_spi.h"

    #include "altera_avalon_pio_regs.h"

    这两个头文件。

    文件中包含有寄存器地址与API函数。

    IOWR_ALTERA_AVALON_SPI_SLAVE_SEL();    //从设备选择

    IOWR_ALTERA_AVALON_SPI_CONTROL(base, data); //控制寄存器

    IORD_ALTERA_AVALON_SPI_RXDATA(base);                  //读接收寄存器

    IOWR_ALTERA_AVALON_SPI_TXDATA(base, data);       //写发送寄存器

    IORD_ALTERA_AVALON_SPI_STATUS(base);          //读状态寄存器

    为了准确实现方式,首先列出SPI寄存器映射图 

     

     (1)若rxdatatxdata少于16位,则[31:16]位无效;

    2)写status会清除ROETOEE位;

    3ss0只在作为主设备时有效;用来启动发送或者接受数据。例如:

    // Force SS_n active:
    na_spi_0-> np_spicontrol |= np_spicontrol_sso_mask;
    for (i = 0; i < 3++i)
    {
    // Transmit a byte:
    while (!(na_spi_0->np_spistatus & np_spistatus_trdy_mask));
    na_spi_0
    ->np_spitxdata = data[i];
    // Read and throw away the received data:
    while (!(na_spi_0->np_spistatus & np_spistatus_rrdy_mask));
    na_spi_0
    ->np_spirxdata;
    }
    // Wait until the last byte is transmitted:
    while (!(na_spi_0->np_spistatus & np_spistatus_tmt_mask));
    // Release SS_n:
    na_spi_0-> np_spicontrol &=~np_spicontrol_sso_mask;


        (4rxdata

             a)当接收寄存器接收到所设置的n位且将数据移入rxdata后,status中的RRDY设为1;软件可设查询此位来判断是否有新数据接收。如:

    while(IORD_ALTERA_AVALON_SPI_STATUS(base) & ALTERA_AVALON_SPI_STATUS_RRDY_MSK == 1);

                       b)读rxdata会自动清除RRDY位;

                       c)新数据总是不断读入rxdata,若RRDY=1; rxdata的数据未读出时,有新的数据传入rxdata,则ROE=1;此时,rxdata存储的数据未定义。

             5txdata

                       a)当TRDY=1时,表示发送寄存器准备好接受下一个发送数据。如:

    while(IORD_ALTERA_AVALON_SPI_STATUS(base) & ALTERA_AVALON_SPI_STATUS_TRDY_MSK == 1);

                       b)写入rxdata使TRDY=0;

                       c)当txdata中的数据传入发送寄存器时,TRDY=1;

                       d)若TRDY=0时写入数据至txdata会导致TOE=1;此时新数据被忽略。

    6.2驱动方式二

    该方式使用官方的函数:(下篇文章使用的是该方式。)

    int alt_avalon_spi_command(alt_u32 base, alt_u32 slave,

    alt_u32 write_length,

    const alt_u8* wdata,

    alt_u32 read_length,

    alt_u8* read_data,

    alt_u32 flags)

    该函数不支持8位或者8位以上的传输。但是,可以调用多次实现高于8位的传输。该函数源码位于“<安装路径>/altera/81/ip/altera/sopc_builder_ip/altera_avalon_spi/HAL/src”

    alt_u32 base, alt_u32 slave,   //选择从设备

    alt_u32 write_length, //设置写入长度。8位为一个长度。

    const alt_u8* wdata,                //将要写入数据的数组地址。该函数自动将数组中的数据依次发出直到发出所设定的write_length长度。

    alt_u32 read_length,                //设置读出长度。8位为一个长度

    alt_u8* read_data,                  //将读出的数据存储到数组中,直到存满所设定的read_length长度

    alt_u32 flags                        //如果flag=ALT_AVALON_SPI_COMMAND_MERGE,则访问完从设备之后不会释放从设备,一般用于需多次访问的情况。如果flag=0,则每次访问完从设备都会释放从设备,即当读取read_length个字节数,或者写完write_length个字节数,会释放从设备。

    7、总结

    笔者测试使用环境均为8.1版本。

    使用器件为CYCLONE II EP2C8Q208C8N

     

  • 相关阅读:
    POJ1521 最优哈夫曼编码树 贪心算法的有效应用
    hdu4911逆序对+mergesort
    hdu1735 字数统计 贪心算法
    最大不相交区间数+最少区间数覆盖问题 贪心思想
    洛谷1010 幂次方 分治算法+掩码的应用
    POJ 2082 三种解法(暴力+树状数组+线段树)
    POJ3134 Power Calculus IDA*搜索的一个应用
    hdu2648 STL map的简单应用
    Delphi 数据类型与Windows 数据类型 对照
    Delphi Window Messages 消息
  • 原文地址:https://www.cnblogs.com/oneseven/p/1543909.html
Copyright © 2020-2023  润新知