打印
[DSP编程]

arm和dsp芯片采用SPI一对多通信

[复制链接]
5627|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lixiaoqi90129|  楼主 | 2014-11-15 16:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
aresc| | 2014-11-15 20:25 | 只看该作者
直连就可以了,4个单独的片选,共用SCK, MISO和MOSI。

使用特权

评论回复
板凳
airwill| | 2014-11-16 14:37 | 只看该作者
主机出 4 个 IO 口, 分别控制 4 个从机的 SPI 片选信号就是了.

使用特权

评论回复
地板
lixiaoqi90129|  楼主 | 2014-11-17 22:56 | 只看该作者
恩,好的,我试试看,谢谢二楼三楼!

使用特权

评论回复
5
zhangmangui| | 2014-11-18 22:35 | 只看该作者
lixiaoqi90129 发表于 2014-11-17 22:56
恩,好的,我试试看,谢谢二楼三楼!

恩  如果只是片选   那就好办   你完全可以用IO口模拟   在准备发之前就使能
不行你可以用iic啊   这个直接都可以连了   

使用特权

评论回复
6
lixiaoqi90129|  楼主 | 2014-11-24 15:24 | 只看该作者
因为我用的arm开发板是s3c6410芯片的tiny6410,dsp芯片是tms320f2812,该dsp芯片没有iic的接口。所以想用spi一对多通信

使用特权

评论回复
7
lixiaoqi90129|  楼主 | 2014-11-24 15:30 | 只看该作者
airwill 发表于 2014-11-16 14:37
主机出 4 个 IO 口, 分别控制 4 个从机的 SPI 片选信号就是了.

我看您之前做过arm和dsp一对多的spi通信,我用的arm芯片是s3c6410,Linux版本是2.6.38,现在spi的驱动已经加入到内核中,arm板子/dev 下已经有spidev0和spidev1这两个设备,但是arm作为spi主机的程序不知道该怎么写,您能将arm的spi主机程序给我一份吗?或者给点儿建议也可以,菜鸟一枚,谢谢啦!

使用特权

评论回复
8
airwill| | 2014-11-24 16:31 | 只看该作者
    抱歉, 我用的 ARM 不是 是s3c6410, arm 作为spi主机, 其实就是外设的控制, 设置寄存器作为底层驱动而已. 如果不清楚的话, 可以看开发板的例程.
    另外, 控制多个从机, 出来要控制片选, 还需注意互斥控制就是了.

使用特权

评论回复
9
jing43| | 2014-11-29 23:56 | 只看该作者
1 对 4?SPI 比较少这样用啊,我觉得可以考虑一下 SCI,如果转成 485,那是更可以多对多。

使用特权

评论回复
10
lixiaoqi90129|  楼主 | 2014-11-30 20:30 | 只看该作者
airwill 发表于 2014-11-24 16:31
抱歉, 我用的 ARM 不是 是s3c6410, arm 作为spi主机, 其实就是外设的控制, 设置寄存器作为底层驱动而已 ...

s3c6410可以将自己的SPIMOSI和SPIMISO直接连起来,用spidev_test.c程序自测spi功能,那tms320f2812的spi是否也可以将自己的SPIMOSI和SPIMISO直接连起来,实现自发自收呢?期待您的回复!

使用特权

评论回复
11
airwill| | 2014-12-1 07:55 | 只看该作者
如果是外部连接 SPIMOSI和SPIMISO 进行程序自测spi功能, 肯定是没有问题的.
不过没有看到软件的内部连接的设置功能.
tms320f2812的spi 的优势功能是支持一个 16 级的 1~16 位的收发 FIFO.

使用特权

评论回复
12
lixiaoqi90129|  楼主 | 2014-12-1 10:01 | 只看该作者
airwill 发表于 2014-12-1 07:55
如果是外部连接 SPIMOSI和SPIMISO 进行程序自测spi功能, 肯定是没有问题的.
不过没有看到软件的内部连接的 ...

现在arm外部连接 SPIMOSI和SPIMISO 进行程序自测spi成功,dsp的spi内部连接程序自测spi成功。现在有两个问题:1、我看资料理解spi通信clock polarity=0,clock phase=0时,则在主机clk上升沿时,主机SPIDAT发送数据,从机SPIDAT发送数据,在主机clk下降沿时,主机SPIDAT锁存从机发送数据(SPIMISO引脚上电平),从机SPIDAT锁存主机发送数据(SPIMOSI引脚电平),自测时,将SPIMISO和SPIMOSI连接,主机和从机发送内容不同时,而SPIMISO和SPIMOSI又是一根线,不是矛盾吗?
2、我现在的arm和dsp的spi通信,能通上,但是收到的数据不对,不知道是什么原因。程序贴上,您指点一下,谢谢!(arm收到的rx 一直为0,arm的tx为2时,dsp收4)
arm程序:
/*
* SPI testing utility (using spidev driver)
*
* Copyright (c) 2007  MontaVista Software, Inc.
* Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* Cross-compile with cross-gcc -I/path/to/cross-kernel/include
*/

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

static void pabort(const char *s)
{
        perror(s);
        abort();
}

static const char *device = "/dev/spidev1.0";
static uint8_t mode=0;
static uint8_t bits = 8;
static uint32_t speed =500000;
static uint16_t delay=0;


static void transfer(int fd)
{
        int ret;
        uint8_t tx[1]={2};
        uint8_t rx[1]={5};
        struct spi_ioc_transfer tr = {
                .tx_buf = (unsigned long)tx,
                .rx_buf = (unsigned long)rx,
                .len = ARRAY_SIZE(tx),
                .delay_usecs = delay,
                .speed_hz = speed,
                .bits_per_word = bits,
        };

        ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
        if (ret < 1)
                pabort("can't send spi message");

        printf("%.2X ", rx[0]);
        puts("");
}
static void print_usage(const char *prog)
{
        printf("Usage: %s [-DsbdlHOLC3]\n", prog);
        puts("  -D --device   device to use (default /dev/spidev1.0)\n"
             "  -s --speed    max speed (Hz)\n"
             "  -d --delay    delay (usec)\n"
             "  -b --bpw      bits per word \n"
             "  -l --loop     loopback\n"
             "  -H --cpha     clock phase\n"
             "  -O --cpol     clock polarity\n"
             "  -L --lsb      least significant bit first\n"
             "  -C --cs-high  chip select active high\n"
             "  -3 --3wire    SI/SO signals shared\n");
        exit(1);
}

static void parse_opts(int argc, char *argv[])
{
        while (1) {
                static const struct option lopts[] = {
                        { "device",  1, 0, 'D' },
                        { "speed",   1, 0, 's' },
                        { "delay",   1, 0, 'd' },
                        { "bpw",     1, 0, 'b' },
                        { "loop",    0, 0, 'l' },
                        { "cpha",    0, 0, 'H' },
                        { "cpol",    0, 0, 'O' },
                        { "lsb",     0, 0, 'L' },
                        { "cs-high", 0, 0, 'C' },
                        { "3wire",   0, 0, '3' },
                        { "no-cs",   0, 0, 'N' },
                        { "ready",   0, 0, 'R' },
                        { NULL, 0, 0, 0 },
                };
                int c;

                c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);

                if (c == -1)
                        break;

                switch (c) {
                case 'D':
                        device = optarg;
                        break;
                case 's':
                        speed = atoi(optarg);
                        break;
                case 'd':
                        delay = atoi(optarg);
                        break;
                case 'b':
                        bits = atoi(optarg);
                        break;
                case 'l':
                        mode |= SPI_LOOP;
                        break;
                case 'H':
                        mode |= SPI_CPHA;
                        break;
                case 'O':
                        mode |= SPI_CPOL;
                        break;
                case 'L':
                        mode |= SPI_LSB_FIRST;
                        break;
                case 'C':
                        mode |= SPI_CS_HIGH;
                        break;
                case '3':
                        mode |= SPI_3WIRE;
                        break;
                case 'N':
                        mode |= SPI_NO_CS;
                        break;
                case 'R':
                        mode |= SPI_READY;
                        break;
                default:
                        print_usage(argv[0]);
                        break;
                }
        }
}

int main(int argc, char *argv[])
{
        int ret = 0;
        int fd;
       

        parse_opts(argc, argv);

        fd = open(device, O_RDWR);
        if (fd < 0)
                pabort("can't open device");

        /*
         * spi mode
         */
        ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
        if (ret == -1)
                pabort("can't set spi mode");

        ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
        if (ret == -1)
                pabort("can't get spi mode");

        /*
         * bits per word
         */
        ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
        if (ret == -1)
                pabort("can't set bits per word");

        ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
        if (ret == -1)
                pabort("can't get bits per word");

        /*
         * max speed hz
         */
        ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
        if (ret == -1)
                pabort("can't set max speed hz");

        ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
        if (ret == -1)
                pabort("can't get max speed hz");

        printf("spi mode: %d\n", mode);
        printf("bits per word: %d\n", bits);
        printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
       
while(1){
        transfer(fd);
}

        close(fd);

        return ret;
}
dsp程序:
DSP28_sysCtrl.c
#include "DSP28_Device.h"

//---------------------------------------------------------------------------
// InitSysCtrl:
//---------------------------------------------------------------------------
// This function initializes the System Control registers to a known state.
//
void InitSysCtrl(void)
{
   Uint16 i;
   EALLOW;
   
// On TMX samples, to get the best performance of on chip RAM blocks M0/M1/L0/L1/H0 internal
// control registers bit have to be enabled. The bits are in Device emulation registers.
   DevEmuRegs.M0RAMDFT = 0x0300;
   DevEmuRegs.M1RAMDFT = 0x0300;
   DevEmuRegs.L0RAMDFT = 0x0300;
   DevEmuRegs.L1RAMDFT = 0x0300;
   DevEmuRegs.H0RAMDFT = 0x0300;
   
           
// Disable watchdog module
   SysCtrlRegs.WDCR= 0x0068;

// Initalize PLL
   SysCtrlRegs.PLLCR = 0x06;
   // Wait for PLL to lock
   for(i= 0; i< 5000; i++){}
      
// HISPCP/LOSPCP prescale register settings, normally it will be set to default values
   SysCtrlRegs.HISPCP.all = 0x0001;
   SysCtrlRegs.LOSPCP.all = 0x0002;       
// Peripheral clock enables set for the selected peripherals.   
   SysCtrlRegs.PCLKCR.bit.EVAENCLK=1;
   SysCtrlRegs.PCLKCR.bit.EVBENCLK=1;
   SysCtrlRegs.PCLKCR.bit.SCIENCLKA=1;
// SysCtrlRegs.PCLKCR.bit.SCIENCLKB=1;

        SysCtrlRegs.PCLKCR.bit.SPIENCLK=1;//spi模块时钟使能
                                       
   EDIS;
       
}
DSP28_spi.c
void InitSpi(void)
{
        // Initialize SPI-A:
                // Initialize SCI-A:
        EALLOW;
        GpioMuxRegs.GPFMUX.all = 0x000f;
        EDIS;
        /* loopback0x1f   8 bit data */
        SpiaRegs.SPICCR.all = 0x07;
       
        SpiaRegs.SPICTL.all = 0x02;//0x07
       
        //SpiaRegs.SPIBRR = 0x7f;
       
        SpiaRegs.SPICCR.all = 0x87;//0x9f
       

        //PieCtrl.PIEIER6.bit.INTx1 = 1;
//        PieCtrl.PIEIER6.bit.INTx2 = 1;
        //tbd...
        //tbd...
       
}

unsigned int Spi_TxReady(void)
{
        unsigned int i;
        if(SpiaRegs.SPISTS.bit.BUFFULL_FLAG == 1)
        {
                i = 0;
        }
        else
        {
                i = 1;
        }
        return(i);
}

unsigned int Spi_RxReady(void)
{
        unsigned int i;
        if(SpiaRegs.SPISTS.bit.INT_FLAG == 1)
        {
                i = 1;
        }
        else
        {
                i = 0;
        }
        return(i);       
}

interrupt void SPIRXINTA_ISR(void);   // SPI
interrupt void SPITXINTA_ISR(void);    // SPI
主程序:
#include "DSP28_Device.h"
unsigned int Spi_VarRx[100];
unsigned int i,j;
//interrupt void ISRSciaTx(void);
//interrupt void ISRSciaRx(void);

void main(void)
{
        /*初始化系统*/
        InitSysCtrl();
        /* 关中断 */
        DINT;
        IER = 0x0000;
        IFR = 0x0000;
        /* 初始化PIE控制寄存器 */
        InitPieCtrl();
        /* 初始化PIE参数表 */
        InitPieVectTable();       
        /* 初始化外设寄存器 */
        InitPeripherals();
//            init_spi();
            for(i = 0; i < 100; i++)
            {
                    Spi_VarRx = 0;
            }
            i = 0;
            j = 0;
    #if        Spi_Int
        EALLOW;        // This is needed to write to EALLOW protected registers
        PieVectTable.SPITXINTA = &SPITXINTA_ISR;
        PieVectTable.SPIRXINTA = &SPIRXINTA_ISR;
        EDIS;   // This is needed to disable write to EALLOW protected registers
       
        /* 设置IER寄存器 */
        IER |= M_INT6;
        #endif
       
        /* 开中断 */
        EINT;   // Enable Global interrupt INTM
        ERTM;        // Enable Global realtime interrupt DBGM

        for(;;)
        {
                if(Spi_TxReady() == 1)//发送寄存器空
                {
                        SpiaRegs.SPITXBUF = i;
                        i++;
                        if(i == 100)
                        {
                                i = 0;
                        }
                }
               
                #if        !Spi_Int
                if(Spi_RxReady() == 1)//接收寄存器接到了
                {
                        Spi_VarRx[j] = SpiaRegs.SPIRXBUF&0x00FF;
                        j++;
                        if(j == 100)
                        {
                                j = 0;
                        }
                }
                #endif
        }

}

使用特权

评论回复
13
airwill| | 2014-12-1 10:20 | 只看该作者
如果 clock polarity,clock phase 弄错时, 通常的出现的情况是: 收到的数据发生移1位.
比如 tx 为2时,dsp收4,就是左移1位
收到的rx 一直为0 那就不是移1位的问题, 可能是接线或设置问题了.
另外: SPIMISO和SPIMOSI连接, 只用于自测,  对于相互通信的测试, 只能同名端口相连, 否则不仅收不到对方发出的数据了, 而且发生混乱了

使用特权

评论回复
14
lixiaoqi90129|  楼主 | 2014-12-1 23:38 | 只看该作者
airwill 发表于 2014-12-1 10:20
如果 clock polarity,clock phase 弄错时, 通常的出现的情况是: 收到的数据发生移1位.
比如 tx 为2时,dsp ...

现在arm和dsp都能收着数据,但是数据是错误的,我现在感觉可能是收发数据的左对齐右对齐有问题。我在arm和dsp中设置的一个已送序列中,移入或移出的位数为8位。写入SPIRXBUF中数据右对齐,从SPITXBUF中发送的数据要左对齐,对发送和接收的数据怎么处理才符合左对齐右对齐?

使用特权

评论回复
15
xdh1009| | 2014-12-5 15:11 | 只看该作者
看看数据手册吧

使用特权

评论回复
16
七颗咖啡豆| | 2014-12-7 20:04 | 只看该作者
有点晕

使用特权

评论回复
17
zhangmangui| | 2014-12-7 20:17 | 只看该作者
jing43 发表于 2014-11-29 23:56
1 对 4?SPI 比较少这样用啊,我觉得可以考虑一下 SCI,如果转成 485,那是更可以多对多。 ...

SCI可以一对多吗     

使用特权

评论回复
18
zhangmangui| | 2014-12-7 20:19 | 只看该作者
lixiaoqi90129 发表于 2014-12-1 23:38
现在arm和dsp都能收着数据,但是数据是错误的,我现在感觉可能是收发数据的左对齐右对齐有问题。我在arm ...

错误数据你看看有没有规律    不会是一个SPI发同时4个接收吗

使用特权

评论回复
19
cby981541| | 2014-12-7 21:19 | 只看该作者
jing43 发表于 2014-11-29 23:56
1 对 4?SPI 比较少这样用啊,我觉得可以考虑一下 SCI,如果转成 485,那是更可以多对多。 ...

看到SCI,就触动“科研论文”这根神经!

使用特权

评论回复
20
jing43| | 2014-12-8 14:38 | 只看该作者
zhangmangui 发表于 2014-12-7 20:17
SCI可以一对多吗

我是说转成 485,是可以 1 对多的。如果使用非隔离型的 485,速度还是可以的,ADM3485E 可以支持 20Mbps。不过这个是有要求的,1,一个时间只能有一个在发送,其它的都接收。2,因为所有挂在总线上的器件都能收到信息,所以每个器件要有自己的地址。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

10

帖子

0

粉丝