• LPC2138微控制器之SPI


    LPC2138微控制器有2个SPI接口,其中SPI 1兼容SSP接口。

    关于SPI协议,可以参考我的上一篇博文《SPI协议详解》。

    SPI总线全双工通信体现在发送数据的同时也在接收数据,主要是在SCLK时钟的控制下,通过两个双向移位寄存器进行数据交换。

    寄存器描述

    S0SPCCR和S0SPCR寄存器在数据传输之前设置,主要是配置SPI工作模式、时钟频率和中断。

    S0SPSR寄存器保存SPI控制器状态,只读。其中SPIF位表示数据传输完成,其他位表示异常状态。

    S0SPDR寄存器负责数据传输

    1)写数据

    SPI控制器内部有一个移位寄存器负责数据发送和接收,往S0SPDR寄存器写数据会马上写入移位寄存器,因此在SPIF没有置位时(即数据传输过程中),不应该往S0SPDR中写入数据。

    另外,往S0SPDR写数据,才会产生SCLK时钟周期,其他情况下,SCLK保持高电平或者低电平。

    2)读数据

    SPI控制器接收数据会缓存到一个单独的数据缓存寄存器中,读S0SPDR寄存器实际上返回该寄存器值。如果在接收到下一个字节数据之前,没有及时读取该寄存器,则下一个字节会直接丢弃,而不是覆写到该寄存器中。

    实例

    本来想用Proteus模拟SPI读写MMC卡,但是折腾了两天,MMC卡初始化都不成功,CMD0切换到idle模式一直不返回0x1。所以直接用MISO和MOSI自环测试了SPI读写。

    #include <lpc213x.h>
    #include "spi.h"
    #include "serial.h"
    
    #define SPI_DEBUG (1)
    
    #if 0
    void spi0_isr(void) __irq
    {
        unsigned char status;
        unsigned char recv_byte;
    
        if ((VICIRQStatus & 0x400) && (S0SPINT & 0x1))
        {
            /* Interrupt Occurs */
            status = S0SPSR;
    
            if (status & 0x78)
            {
                /* ABRT/MODF/ROVR/WCOL exceptions */
                sendstr("spi bus 0 exception, status=");
                sendhex(status);
                sendstr("
    ");
            }
            else if (status == 0x80)
            {
                /* SPIF indicates SPI Transfer Completed,
                ** read or write SPI Data Reg clear SPIF
                */
                recv_byte = S0SPDR;
                sendstr("spi bus 0 recv ");
                sendhex(recv_byte);
                sendstr("
    ");
            }
    
            /* Clear Interrupt */
            S0SPINT = 0x1;
        }
    
    }
    #endif
    
    void spi_init(void)
    {
        /* Configure P0.4~7 as SPI bus 0 */
        PINSEL0 &= ~0x0000FF00;
        PINSEL0 |= 0x00005500;
    
        /* PCLK is 30MHz, SPI Clock Frequency is 5MHz */
        S0SPCCR = 0x6;
    
        /* Master mode, 8 bits per transfer(MSB first),
        ** disable interrupt, CPOL=0, CPHA=0
        */
        S0SPCR = 0x20;
    
    #if 0
        /* SPI Bus 0 ISR */
        VICVectCntl2 = 0x20 | 10;
        VICVectAddr2 = (unsigned int)spi0_isr;
        VICIntEnable = 1 << 10;
    #endif
    
    }
    
    int spi_write_byte(unsigned char byte)
    {
        unsigned char recv_byte;
    
        if (SPI_DEBUG)
        {
            sendstr("spi bus 0 send ");
            sendhex(byte);
            sendstr("
    ");
        }
    
        S0SPDR = byte;
    
        /* Check SPIF bit, Wait for Data Transfer Complete */
        while (!(S0SPSR & 0x80));
        recv_byte = S0SPDR;
        if (SPI_DEBUG)
        {
            sendstr("spi bus 0 recv ");
            sendhex(recv_byte);
            sendstr("
    ");
        }
    
        return recv_byte;
    }
    
    int spi_read_byte(unsigned char *byte)
    {
        if (0 == byte)
        {
            sendstr("spi_read_byte byte is NULL
    ");
            return -1;
        }
    
        /* Only Write S0SPDR generate SPI Clock for receive data */
        *byte = spi_write_byte(0xFF);
    
        return 0;
    }
    
    int spi_write(unsigned char *data, int len)
    {
        int i = 0;
    
        if (0 == data)
        {
            sendstr("spi_write data is NULL
    ");
            return -1;
        }
    
        for (i = 0; i < len; i++)
        {
            spi_write_byte(data[i]);
        }
    
        return 0;
    }
    
    int spi_read(unsigned char *data, int len)
    {
        int i = 0;
    
        if (0 == data)
        {
            sendstr("spi_read data is NULL
    ");
            return -1;
        }
    
        for (i = 0; i < len; i++)
        {
            spi_read_byte(&data[len - 1 -i]);
        }
    
        return 0;
    }
  • 相关阅读:
    Android Studio AVD和SDK Manager灰色不能点击的问题。
    回溯:最佳调度问题
    回溯:八皇后问题(蒟蒻)
    usaco1.4.3等差数列
    单调队列练习题(oj p1157 p1158 p1159)
    OJP1147括号匹配加强版(栈)与P1153乱头发节(单调栈)
    NOIP2017游记......
    火柴棒等式c++
    潜伏者(noip09年t1)解题报告 C++
    2016noipday1t1玩具迷题结题报告
  • 原文地址:https://www.cnblogs.com/justin-y-lin/p/12349235.html
Copyright © 2020-2023  润新知