天嵌 ARM开发社区

 找回密码
 注册
查看: 3521|回复: 8

有没有TQ2440的SPI的裸机程序啊??

[复制链接]
ghoulich 发表于 2011-12-21 15:53:45 | 显示全部楼层 |阅读模式
这几天在做这方面的裸机程序,死活不能传输,急死了。。。忘大家帮帮忙啊!!:dizzy:
dainter 发表于 2011-12-21 19:27:23 | 显示全部楼层
~~~~~~同求~~~~~
超级忍者龟 发表于 2011-12-22 09:14:35 | 显示全部楼层
这个要根据你们芯片支持的SPI模式来写时序代码,SPI有4个模式的,都不同,要看芯片手册!
 楼主| ghoulich 发表于 2011-12-26 10:19:59 | 显示全部楼层
超级忍者龟 发表于 2011-12-22 09:14
这个要根据你们芯片支持的SPI模式来写时序代码,SPI有4个模式的,都不同,要看芯片手册!

我现在先想在同一块板子上SPI0做主设备,SPI1做从设备,写个示例程序,但是不行啊。。。失败啊。。。
 楼主| ghoulich 发表于 2011-12-26 10:20:36 | 显示全部楼层
我把程序贴上来吧
 楼主| ghoulich 发表于 2011-12-26 10:21:34 | 显示全部楼层
本帖最后由 ghoulich 于 2011-12-26 10:22 编辑

#include "2440addr.h"
#include "2440lib.h"

/* SPI_0 */
#define MISO0 11 /* GPE11:SPI输入  */
#define GET_MISO0() ((rGPEDAT & (1<<MISO0)) >> MISO0)
#define MOSI0 12 /* GPE12:SPI输出  */
#define SET_MOSI0(value) (rGPEDAT = (rGPEDAT & ~(1<<MOSI0)) | (value<<MOSI0))
#define SCK0  13 /* GPE13:SPI输出  */
#define SET_SCK0(value) (rGPEDAT = (rGPEDAT & ~(1<<SCK0)) | (value<<SCK0))
#define CE0   14 /* GPG14:数字输出 */
#define SET_CE0(value) (rGPGDAT = (rGPGDAT & ~(1<<CE0)) | (value<<CE0))
#define GET_CE0() ((rGPGDAT & (1<<CE0)) >> CE0)
#define CSN0  2  /* GPG2: SPI输出  */
#define SET_CSN0(value) (rGPGDAT = (rGPGDAT & ~(1<<CSN0)) | (value<<CSN0))
#define IRQ0  13 /* GPG13: 中断输入 */
#define GET_IRQ0() ((rGPFDAT & (1<<IRQ0)) >> IRQ0)

/* SPI_1 */
#define MISO1 5  /* GPG5:SPI输入  */
#define GET_MISO1() ((rGPGDAT & (1<<MISO1)) >> MISO1)
#define MOSI1 6  /* GPG6:SPI输出  */
#define SET_MOSI1(value) (rGPGDAT = (rGPGDAT & ~(1<<MOSI1)) | (value<<MOSI1))
#define SCK1  7  /* GPG7:SPI输出  */
#define SET_SCK1(value) (rGPGDAT = (rGPGDAT & ~(1<<SCK1)) | (value<<SCK1))
#define CE1   0  /* GPG0:数字输出 */
#define SET_CE1(value) (rGPGDAT = (rGPGDAT & ~(1<<CE1)) | (value<<CE1))
#define GET_CE1() ((rGPGDAT & (1<<CE1)) >> CE1)
#define CSN1  3  /* GPG3: SPI输出  */
#define SET_CSN1(value) (rGPGDAT = (rGPGDAT & ~(1<<CSN1)) | (value<<CSN1))
#define IRQ1  11 /* GPG11: 中断输入 */
#define GET_IRQ1() ((rGPGDAT & (1<<IRQ1)) >> IRQ1)

static void usDelay(U32 uSeconds, void __irq (*PwmIsr)(void)) {
    // set ISR for PWM Timer 4
    if (PwmIsr != NULL) {
        ClearPending(BIT_TIMER4);
        pISR_TIMER4 = (U32) PwmIsr;
        EnableIrq(BIT_TIMER4);
    }

    // timer input clock frequency = PCLK / (24 + 1) / 2 = 1 MHz
        rTCFG0 &= ~(0xff << 8);   // clear TCFG0[15:8](Prescaler 1) to 0
        rTCFG0 |= 24 << 8;                  // Prescaler 1 = 24
        rTCFG1 &= ~(0xf << 16);   // clear TCFG1[19:16](MUX 4) to 0
        rTCFG1 |= 0 << 16;                  // MUX 4 = 0000 = 1/2

        rTCNTB4 = uSeconds;       // use PWM Timer 4, the initial count value is uSeconds
        rTCON &= ~(0x7 << 20);    // clear TCON[22:20] to 0
        rTCON |= 0x0 << 22;                  // one-shot
        rTCON |= 0x1 << 21;       // manula update TCNTB4
        rTCON |= 0x1 << 20;       // start for Timer 4
        rTCON &= ~(0x1 << 21);          // clear TCON[21](Timer 4 Manual Update) to zero
        
        while(rTCNTO4)
            ;
}

static void InitSpi(void) {
    int i;
   
    // 设置时钟控制寄存器(CLKCON),使能SPI时钟
    rCLKCON = (rCLKCON & ~(1 << 18)) | (1 << 18);
   
    // SPI0为主设备
    // 初始化GPE GPE11:MISO0(MISO);GPE12:MOSI0(MOSI);GPE13:SPICLK0(SCK)
    rGPECON = (rGPECON & ~(3 << MISO0 * 2 | 3 << MOSI0 * 2 | 3 << SCK0 * 2)) |
        (2 << MISO0 * 2 | 2 << MOSI0 * 2 | 2 << SCK0 * 2);
    // 初始化GPG GPG13:GPG2: nSS_SPI0(CSN)
    rGPGCON = (rGPGCON & ~(3 << CSN0 * 2)) | (1 << CSN0 * 2);
    // 设置波特率预定标器寄存器(SPPREn),波特率 = PCLK / 2 / (预定标器值 + 1) = 1MHz
    rSPPRE0 = 0x18;
    // 设置SPCONn寄存器以正确配置SPI模块
    // normal; format A; active high; master; enable; polling mode
    rSPCON0 = (rSPCON0 & ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 3 << 5)) |
        (0 << 0 | 0 << 1 | 0 << 2 | 1 << 3 | 1 << 4 | 0 << 5);
    // 设置SPI引脚控制寄存器(SPPINn)
    // Release; Disable (general purpose)
    rSPPIN0 = (rSPPIN0 & ~(1 << 0 | 1 << 2)) | (0 << 0 | 0 << 2);
   
    // SPI1为从设备
    // 初始化GPG GPG5:MISO1(MISO);GPG6:MOSI1(MOSI);GPG7:SPICLK1(SCK)
    //           GPG3: nSS_SPI1(CSN)
    rGPGCON = (rGPGCON & ~(3 << MISO1 * 2 | 3 << CSN1 * 2 | 3 << MOSI1 * 2 | 3 << SCK1 * 2)) |
        (3 << MISO1 * 2 | 3 << CSN1 * 2 | 3 << MOSI1 * 2 | 3 << SCK1 * 2);
    // 设置波特率预定标器寄存器(SPPREn),波特率 = PCLK / 2 / (预定标器值 + 1) = 1MHz
    rSPPRE1 = 0x18;
    // 设置SPCONn寄存器以正确配置SPI模块
    // normal; format A; active high; master; enable; polling mode
    rSPCON1 = (rSPCON1 & ~(1 << 0 | 1 << 1 | 1 << 2 | 1 << 3 | 1 << 4 | 3 << 5)) |
        (0 << 0 | 0 << 1 | 0 << 2 | 0 << 3 | 0 << 4 | 0 << 5);
    // 设置SPI引脚控制寄存器(SPPINn)
    // Release; Disable (general purpose)
    rSPPIN1 = (rSPPIN1 & ~(1 << 0 | 1 << 2)) | (0 << 0 | 0 << 2);
   
    // 初始化SPI模块,向SPTDATn写入10次0xFF哑数据
    for(i = 0; i < 10; i++) {
        rSPTDAT0 = 0xFF;
        rSPTDAT1 = 0xFF;
    }
}

static char Spi0Send(char uch) {
    char temp;

        // 将nSS(CSN)引脚设为低电平,激活SPI模块
    SET_CSN0(0);
    usDelay(1, NULL);
               
    // 发送流程,若uch不为NULL,则开始发送;若uch为NULL,则自动发送哑数据
    if (uch != NULL)
        rSPTDAT0 = uch;
    else
        rSPTDAT0 = 0xFF;
    // 判定SPSTAn寄存器的REDY标志
    while (!(rSPSTA0 & 0x01))
        ;
    // 接收流程,初始化时已经配置为TAGD位,没有数据发送时自动发送哑数据
    temp = rSPRDAT0;
               
        // 将nSS(CSN)引脚设为高电平,关闭SPI模块
        SET_CSN0(1);
        usDelay(1, NULL);
        
        Uart_Printf("\nSPTDAT0 = 0x%x\n", rSPTDAT0);
        Uart_Printf("Send Complete!");
        
        return temp;
}

static char Spi1Receive(char uch) {
    char temp;
               
    // 发送流程,若uch不为NULL,则开始发送;若uch为NULL,则自动发送哑数据
    if (uch != NULL)
        rSPTDAT1 = uch;
    else
        rSPTDAT1 = 0xFF;
    // 判定SPSTAn寄存器的REDY标志
    while (!(rSPSTA1 & 0x01))
        ;
    // 接收流程,初始化时已经配置为TAGD位,没有数据发送时自动发送哑数据
    temp = rSPRDAT1;
        
        Uart_Printf("\nSPRDAT1 = 0x%x\n", rSPRDAT1);
        Uart_Printf("Receive Complete!");
        
        return temp;
}

void SpiTest(void) {
    InitSpi();
    Spi0Send(0xDE);
    Spi1Receive(NULL);
}

 楼主| ghoulich 发表于 2011-12-26 10:23:47 | 显示全部楼层
上面程序中,把SPI_0配置为主设备,SPI_1配置为从设备,在SpiTest函数中进行发送和接收测试,但从设备总是接收不到数据,总是卡在状态寄存器那儿的无线循环。。。
超级忍者龟 发表于 2011-12-26 15:38:08 | 显示全部楼层
ghoulich 发表于 2011-12-26 10:23
上面程序中,把SPI_0配置为主设备,SPI_1配置为从设备,在SpiTest函数中进行发送和接收测试,但从设备总是接 ...

给你提供一份SPI的代码:
static void init_spi (void)
{
        volatile immap_t *immap = (immap_t *) CFG_IMMR;

        /* Force output pins to begin at logic 0 */
        immap->im_cpm.cp_pbdat &= ~(PB_SPI_CE | PB_SPIMOSI | PB_SPISCK);

        /* 设置发送脚,使能脚,时钟脚为输出 */
        immap->im_cpm.cp_pbdir |= (PB_SPIMOSI | PB_SPI_CE | PB_SPISCK);
                /* 设置接收脚为输入 */
        immap->im_cpm.cp_pbdir &= ~PB_SPIMISO;        /* Make MISO pin an input */
        udelay (10);
}

/* NOTE: soft_spi_read() assumes that the I/O lines are configured already */
static unsigned char soft_spi_read (void)
{
        volatile immap_t *immap = (immap_t *) CFG_IMMR;

        unsigned char spi_byte = 0;        /* Return value, assume success */
        unsigned char bitpos;        /* bit position to receive */
        unsigned char i;        /* Loop Control */

        /* bit position to receive, start with most significant bit */
        bitpos = 0x80;

        /* Read 8 bits here */
        for (i = 0; i < 8; i++) {        /* Do 8 bits in loop */
                immap->im_cpm.cp_pbdat |= PB_SPISCK;        /* Raise SCK */
                udelay (10);
                if (immap->im_cpm.cp_pbdat & PB_SPIMISO)        /* Get a bit of data */
                        spi_byte |= bitpos;        /* Set data accordingly */
                immap->im_cpm.cp_pbdat &= ~PB_SPISCK;        /* Lower SCK */
                udelay (10);
                bitpos >>= 1;        /* Shift for next bit position */
        }

        return spi_byte;        /* Return the byte read */
}

/* NOTE: soft_spi_send() assumes that the I/O lines are configured already */
static void soft_spi_send (unsigned char n)
{
        volatile immap_t *immap = (immap_t *) CFG_IMMR;
        unsigned char bitpos;        /* bit position to receive */
        unsigned char i;        /* Loop Control */

        /* bit position to send, start with most significant bit */
        bitpos = 0x80;

        /* Send 8 bits to software SPI */
        for (i = 0; i < 8; i++) {        /* Loop for 8 bits */
                immap->im_cpm.cp_pbdat |= PB_SPISCK;        /* Raise SCK */

                if (n & bitpos)
                        immap->im_cpm.cp_pbdat |= PB_SPIMOSI;        /* Set MOSI to 1 */
                else
                        immap->im_cpm.cp_pbdat &= ~PB_SPIMOSI;        /* Set MOSI to 0 */
                udelay (10);

                immap->im_cpm.cp_pbdat &= ~PB_SPISCK;        /* Lower SCK */
                udelay (10);

                bitpos >>= 1;        /* Shift for next bit position */
        }
}
你参考下,对照着改改!
jjkwz 发表于 2012-5-14 16:17:26 | 显示全部楼层
哇,我正需要这个东西呢,呵呵,两个都看看,都借鉴下,谢谢拉
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

i.MX8系列ARM cortex A53 M4 工控板上一条 /1 下一条

Archiver|手机版|小黑屋|天嵌 嵌入式开发社区 ( 粤ICP备11094220号 )

GMT+8, 2024-5-27 09:00 , Processed in 1.078132 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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