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快多了 就是贵了点
之后有什么问题评论区见