基于CCS20的 DSP28377, 四.高速SPI的配置和使用

「开学季干货」:聚焦知识梳理与经验分享 10w+人浏览 383人参与

SPI一般用于与各种外设的控制 速度自然是越快越好 本章讲解如何使用高速SPI

在ti的官方文档中 这里说有三个高速spi可以达到50MHZ 

 

SPI初始化

首先我们先要初始化普通引脚为spi的控制引脚 在官方提供的pin_map.h头文件中 提供了所有的引脚可以配置的宏定义 我们要使用其中的spi功能 就需要将其配置为spi相关引脚

    GPIO_setPinConfig(GPIO_56_SPICLKA);
	GPIO_setPadConfig(56, GPIO_PIN_TYPE_STD);
	GPIO_setQualificationMode(56, GPIO_QUAL_ASYNC);

	GPIO_setPinConfig(GPIO_55_SPISOMIA);
	GPIO_setPadConfig(55, GPIO_PIN_TYPE_STD);
	GPIO_setQualificationMode(55, GPIO_QUAL_ASYNC);

	GPIO_setPinConfig(GPIO_54_SPISIMOA); 								
	GPIO_setPadConfig(54, GPIO_PIN_TYPE_STD);
	GPIO_setQualificationMode(54, GPIO_QUAL_ASYNC);   

大家照我的配置就行 我这里没有配置SPI片选 因为不同的外设的片选电平不同(虽然大部分都是低电平)这里未来代码易于修改和移植 我就将片选信号io配置为普通io了

    GPIO_setPadConfig(57, GPIO_PIN_TYPE_STD | GPIO_PIN_TYPE_PULLUP);  //CS 拉低为选中
	GPIO_setQualificationMode(57, GPIO_QUAL_SYNC);
	GPIO_setDirectionMode(57, GPIO_DIR_MODE_OUT);
	GPIO_setControllerCore(57, GPIO_CORE_CPU1);        
    GPIO_writePin(57, 1);//先拉高不选

在这里 最后一行代码根据需求修改 拉高或者拉低

接下来就是具体配置spi的代码

    SPI_disableModule(SPIA_BASE);
	SPI_setConfig(SPIA_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA0,
				  SPI_MODE_CONTROLLER, 10000000, 8);
	SPI_setPTESignalPolarity(SPIA_BASE, SPI_PTE_ACTIVE_LOW);
	SPI_disableFIFO(SPIA_BASE);
	SPI_enableLoopback(SPIA_BASE);
	SPI_setEmulationMode(SPIA_BASE, SPI_EMULATION_STOP_AFTER_TRANSMIT);
	SPI_enableModule(SPIA_BASE);

具体详细解释大家可以去看官方文件 这里就只具体讲解配置高速SPI的方式

通过函数

SPI_setConfig(uint32_t base, uint32_t lspclkHz, SPI_TransferProtocol protocol,
              SPI_Mode mode, uint32_t bitRate, uint16_t dataWidth);

我们具体分析每一个参数

参数 base 指定SPI模块的基地址。我使用SPIA_BASE

参数 lspclkHz 提供给SPI模块的时钟速度 。这个速度在官方提供的device.h文件中看到 为50MHZ与开头文档中内容一致

参数 protocol 规定了数据传输的协议。关于spi的协议 想要详细了解的同学可以去网上查找相关资料 具体差别其实就在数据收发的电平是高还是低

参数 mode 指定SPI模式,我这里选择作为主设备。

参数 bitRate 指定时钟频率(以赫兹为单位),这里在官方的解释中有说明 不能超过spi时钟的1/4也就是12500000。

参数 dataWidth 指定每帧传输的位数。可选8或者16

至此spi初始化讲解完毕

注意 函数

SPI_enableLoopback(SPIA_BASE);

这个函数是用来启动回环测试的 在使用spi与外设通信时将它改为

SPI_disableLoopback(SPIA_BASE);

测试函数讲解

void SPI_TEST(uint64_t dat)
{

	uint8_t i = 0;
	uint8_t	buff[8];
    buff[i++] = (dat>>56);
    buff[i++] = (dat>>48);
	buff[i++] = (dat>>40);
	buff[i++] = (dat>>32);
	buff[i++] = (dat>>24);
	buff[i++] = (dat>>16);
	buff[i++] = (dat>>8);
	buff[i++] = (dat>>0);
	ESTOP0;
	GPIO_writePin(57, 0);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[0]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[1]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[2]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[3]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[4]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[5]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
    SPI_writeDataNonBlocking(SPIA_BASE, buff[6]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
    SPI_writeDataNonBlocking(SPIA_BASE, buff[7]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
    GPIO_writePin(57, 0);
	ESTOP0;
}

我们发送一个64位的数据 将他们分开输入到buff中 然后每发送一个八位数据就读取一下 通过这样的方式来测试我们数据是否正确

大家看到这个函数可能有疑问

SPI_writeDataNonBlocking(SPIA_BASE, buff[0]<<8);

为什么数据已经是八位了 发送还要左移8位呢 以下是该函数的原型

SPI_writeDataNonBlocking(uint32_t base, uint16_t data)

这里的data是十六位的 假如我们传入一个8位数据(0xAB) 那么高位自动补零(0x00AB) 而且ti的这个芯片是高位对齐的 相当于我们的数据会被挤掉(0x00    AB被舍去)会使得数据传输出现问题

这里ESTOP0用于调试 现实工程中将它注释掉就行。

GPIO_writePin(57, 0); 这个用于片选 低电平选中 高电平不选

至此测试函数讲解完毕

实验现象

这里我们传入数据

SPI_TEST(0x123456789ABCDEF0);

观察传入buff的数据 正确 前面两位属于软件bug,因为我们的数据为8位 只看后面两位

我们逐过程运行代码 test等于0x12 0x34 0x56 0x78 0x9A 0xBC 0xDE 0xF0 正确

数据测试成功

速度测试

点击这个时钟 里面有个enable 勾选 

右下角会出现一个时钟 后面的数字是经过的时钟周期 双击它变为0 随后运行代码 就会显示在两个软断点之间的时间

观察右下角 花费了2605个时钟周期 

计算时间 我们的主频为200MHZ 具体时间也就是 2605/200_000_000 s 也就是0.000013025 约等于13.03微秒 速度非常快。

至此所有测试完毕 接下来我发出源码

main.c

//
// Included Files
//
#include "F28x_Project.h"
#include "driverlib.h"
#include "device.h"
#include "myLED.h"
#include "myADC.h"
#include "mySPI.h"
uint16_t adca1 = 0;
uint16_t adca2 = 0;
//
// Main
//
void main(void)
{

    //
    // 初始化系统控制、设备时钟和外设
    //
    Device_init();

    //
    // 初始化PIE并清除PIE寄存器。禁用CPU中断。
    // 清除所有CPU中断标志。
    //
    Interrupt_initModule();

    //
    // 初始化带有指向shell中断指针的PIE向量表
    // 服务程序(ISR)
    //
    Interrupt_initVectorTable();
    myLED1_init();
    ADC_A_init();
    init_SPI();
    while(1)
    {
        SPI_TEST(0x123456789ABCDEF0);
        GPIO_writePin(21,1);
        adca1 = get_adc(1);
        adca2 = get_adc(0);
    }
}

//
// End of File
//

mySPI.c

#include "mySPI.h"
uint8_t test = 0;
/*==============================================================================
* Function Name  : init_SPI
* Description    : 初始化spia
* Input          : None
* Output         : None
* Return         : None
==============================================================================*/
void init_SPI(void)
{
    EALLOW;
    GPIO_setPinConfig(GPIO_56_SPICLKA);
	GPIO_setPadConfig(56, GPIO_PIN_TYPE_STD);
	GPIO_setQualificationMode(56, GPIO_QUAL_ASYNC);

	GPIO_setPinConfig(GPIO_55_SPISOMIA);
	GPIO_setPadConfig(55, GPIO_PIN_TYPE_STD);
	GPIO_setQualificationMode(55, GPIO_QUAL_ASYNC);

	GPIO_setPinConfig(GPIO_54_SPISIMOA); 								
	GPIO_setPadConfig(54, GPIO_PIN_TYPE_STD);
	GPIO_setQualificationMode(54, GPIO_QUAL_ASYNC);   

    GPIO_setPadConfig(57, GPIO_PIN_TYPE_STD | GPIO_PIN_TYPE_PULLUP);  //CS 拉低为选中
	GPIO_setQualificationMode(57, GPIO_QUAL_SYNC);
	GPIO_setDirectionMode(57, GPIO_DIR_MODE_OUT);
	GPIO_setControllerCore(57, GPIO_CORE_CPU1);        
    GPIO_writePin(57, 1);//先拉高不选

    SPI_disableModule(SPIA_BASE);
	SPI_setConfig(SPIA_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA0,
				  SPI_MODE_CONTROLLER, 10000000, 8);
	SPI_setPTESignalPolarity(SPIA_BASE, SPI_PTE_ACTIVE_LOW);
	SPI_disableFIFO(SPIA_BASE);
	SPI_enableLoopback(SPIA_BASE);
	SPI_setEmulationMode(SPIA_BASE, SPI_EMULATION_STOP_AFTER_TRANSMIT);
	SPI_enableModule(SPIA_BASE);
    EDIS; 
}
/*==============================================================================
* Function Name  : SPI_TEST
* Description    : 进行SPI回环测试
* Input          : uint64_t dat
* Output         : None
* Return         : None
==============================================================================*/
void SPI_TEST(uint64_t dat)
{

	uint8_t i = 0;
	uint8_t	buff[8];
    buff[i++] = (dat>>56);
    buff[i++] = (dat>>48);
	buff[i++] = (dat>>40);
	buff[i++] = (dat>>32);
	buff[i++] = (dat>>24);
	buff[i++] = (dat>>16);
	buff[i++] = (dat>>8);
	buff[i++] = (dat>>0);
	ESTOP0;
	GPIO_writePin(57, 0);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[0]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[1]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[2]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[3]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[4]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
	SPI_writeDataNonBlocking(SPIA_BASE, buff[5]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
    SPI_writeDataNonBlocking(SPIA_BASE, buff[6]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
    SPI_writeDataNonBlocking(SPIA_BASE, buff[7]<<8);
	test = (uint8_t)SPI_readDataBlockingNonFIFO(SPIA_BASE);
    GPIO_writePin(57, 0);
	ESTOP0;
}

mySPI.h

#ifndef _MYSPI_H
#define _MYSPI_H
#include "F28x_Project.h"
#include "driverlib.h"
#include "device.h"
void init_SPI(void);
void SPI_TEST(uint64_t dat);
#endif

高速spi使用完毕 不得不说 这芯片比stm32快多了 就是贵了点

之后有什么问题评论区见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值