拆分Spi

This commit is contained in:
Stone 2016-06-14 10:19:06 +00:00
parent 09c97ac4ea
commit b2991dfbc7
3 changed files with 173 additions and 142 deletions

View File

@ -1,30 +1,8 @@
#include "Buffer.h"
#include "Sys.h"
#include "Buffer.h"
#include "Spi.h"
#include "Platform\stm32.h"
int GetPre(int index, uint* speedHz)
{
// 自动计算稍低于速度speedHz的分频
ushort pre = SPI_BaudRatePrescaler_2;
uint clock = Sys.Clock >> 1;
while(pre <= SPI_BaudRatePrescaler_256)
{
if(clock <= *speedHz) break;
clock >>= 1;
pre += (SPI_BaudRatePrescaler_4 - SPI_BaudRatePrescaler_2);
}
if(pre > SPI_BaudRatePrescaler_256)
{
debug_printf("Spi%d::Init Error! speedHz=%d mush be dived with %d\r\n", index, *speedHz, Sys.Clock);
return -1;
}
*speedHz = clock;
return pre;
}
Spi::Spi()
{
Init();
@ -53,15 +31,7 @@ void Spi::Init()
void Spi::Init(SPI spi, uint speedHz, bool useNss)
{
SPI_TypeDef* g_Spis[] = SPIS;
_index = spi;
assert_param(_index < ArrayLength(g_Spis));
_SPI = g_Spis[_index];
Pin g_Spi_Pins_Map[][4] = SPI_PINS_FULLREMAP;
auto ps = g_Spi_Pins_Map[_index]; //选定spi引脚
Buffer(Pins, sizeof(Pins)) = ps;
OnInit();
if(!useNss) Pins[0] = P0;
@ -76,7 +46,7 @@ void Spi::Init(SPI spi, uint speedHz, bool useNss)
#endif
// 自动计算稍低于速度speedHz的分频
int pre = GetPre(_index, &speedHz);
int pre = GetPre(_index, speedHz);
if(pre == -1) return;
Speed = speedHz;
@ -114,7 +84,7 @@ void Spi::Open()
// 自动计算稍低于速度speedHz的分频
uint speedHz = Speed;
int pre = GetPre(_index, &speedHz);
int pre = GetPre(_index, speedHz);
if(pre == -1) return;
Pin* ps = Pins;
@ -134,51 +104,7 @@ void Spi::Open()
_nss.Init(ps[0], true).Open();
}
// 使能SPI时钟
switch(_index)
{
case 0: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); break;
#if defined(STM32F1) || defined(STM32F4)
case 1: RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); break;
case 2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); break;
#if defined(STM32F4)
case 3: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI4, ENABLE); break;
case 4: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI5, ENABLE); break;
case 5: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI6, ENABLE); break;
#endif
#endif
}
#if defined(STM32F0)
// SPI都在GPIO_AF_0分组内
_clk.AFConfig(Port::AF_0);
_miso.AFConfig(Port::AF_0);
_mosi.AFConfig(Port::AF_0);
#elif defined(STM32F4)
const byte afs[] = { GPIO_AF_SPI1, GPIO_AF_SPI2, GPIO_AF_SPI3, GPIO_AF_SPI4, GPIO_AF_SPI5, GPIO_AF_SPI6 };
_clk.AFConfig((Port::GPIO_AF)afs[_index]);
_miso.AFConfig((Port::GPIO_AF)afs[_index]);
_mosi.AFConfig((Port::GPIO_AF)afs[_index]);
#endif
Stop();
SPI_I2S_DeInit((SPI_TypeDef*)_SPI);
//SPI_DeInit((SPI_TypeDef*)_SPI); // SPI_I2S_DeInit的宏定义别名
SPI_InitTypeDef sp;
SPI_StructInit(&sp);
sp.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线全双工
sp.SPI_Mode = SPI_Mode_Master; // 主模式
sp.SPI_DataSize = SPI_DataSize_8b; // 数据大小8位 SPI发送接收8位帧结构
sp.SPI_CPOL = SPI_CPOL_Low; // 时钟极性,空闲时为低
sp.SPI_CPHA = SPI_CPHA_1Edge; // 第1个边沿有效上升沿为采样时刻
sp.SPI_NSS = SPI_NSS_Soft; // NSS信号由硬件NSS管脚还是软件使用SSI位管理:内部NSS信号有SSI位控制
sp.SPI_BaudRatePrescaler = pre; // 8分频9MHz 定义波特率预分频的值
sp.SPI_FirstBit = SPI_FirstBit_MSB; // 高位在前。指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
sp.SPI_CRCPolynomial = 7; // CRC值计算的多项式
SPI_Init((SPI_TypeDef*)_SPI, &sp);
SPI_Cmd((SPI_TypeDef*)_SPI, ENABLE);
OnOpen();
Stop();
@ -191,8 +117,7 @@ void Spi::Close()
Stop();
SPI_Cmd((SPI_TypeDef*)_SPI, DISABLE);
SPI_I2S_DeInit((SPI_TypeDef*)_SPI);
OnClose();
debug_printf("\t CLK : ");
_clk.Close();
@ -206,66 +131,6 @@ void Spi::Close()
Opened = false;
}
byte Spi::Write(byte data)
{
if(!Opened) Open();
auto si = (SPI_TypeDef*)_SPI;
int retry = Retry;
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_TXE) == RESET)
{
if(--retry <= 0) return ++Error; // 超时处理
}
#ifndef STM32F0
SPI_I2S_SendData(si, data);
#else
SPI_SendData8(si, data);
#endif
retry = Retry;
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_RXNE) == RESET) //是否发送成功
{
if(--retry <= 0) return ++Error; // 超时处理
}
#ifndef STM32F0
return SPI_I2S_ReceiveData(si);
#else
return SPI_ReceiveData8(si); //返回通过SPIx最近接收的数据
#endif
}
ushort Spi::Write16(ushort data)
{
if(!Opened) Open();
auto si = (SPI_TypeDef*)_SPI;
// 双字节操作,超时次数加倍
int retry = Retry << 1;
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_TXE) == RESET)
{
if(--retry <= 0) return ++Error; // 超时处理
}
#ifndef STM32F0
SPI_I2S_SendData(si, data);
#else
SPI_I2S_SendData16(si, data);
#endif
retry = Retry << 1;
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_RXNE) == RESET)
{
if(--retry <= 0) return ++Error; // 超时处理
}
#ifndef STM32F0
return SPI_I2S_ReceiveData(si);
#else
return SPI_I2S_ReceiveData16(si);
#endif
}
// 批量读写。以字节数组长度为准
void Spi::Write(const Buffer& bs)
{

View File

@ -46,6 +46,12 @@ public:
void Start(); // 拉低NSS开始传输
void Stop(); // 拉高NSS停止传输
private:
static int GetPre(int index, uint& speedHz);
void OnInit();
void OnOpen();
void OnClose();
};
// Spi会话类。初始化时打开Spi超出作用域析构时关闭

160
Platform/STM32F1/Spi.cpp Normal file
View File

@ -0,0 +1,160 @@
#include "Buffer.h"
#include "Sys.h"
#include "Spi.h"
#include "Platform\stm32.h"
int Spi::GetPre(int index, uint& speedHz)
{
// 自动计算稍低于速度speedHz的分频
ushort pre = SPI_BaudRatePrescaler_2;
uint clock = Sys.Clock >> 1;
while(pre <= SPI_BaudRatePrescaler_256)
{
if(clock <= speedHz) break;
clock >>= 1;
pre += (SPI_BaudRatePrescaler_4 - SPI_BaudRatePrescaler_2);
}
if(pre > SPI_BaudRatePrescaler_256)
{
debug_printf("Spi%d::Init Error! speedHz=%d mush be dived with %d\r\n", index, speedHz, Sys.Clock);
return -1;
}
speedHz = clock;
return pre;
}
void Spi::OnInit()
{
SPI_TypeDef* g_Spis[] = SPIS;
assert_param(_index < ArrayLength(g_Spis));
_SPI = g_Spis[_index];
Pin g_Spi_Pins_Map[][4] = SPI_PINS_FULLREMAP;
auto ps = g_Spi_Pins_Map[_index]; //选定spi引脚
Buffer(Pins, sizeof(Pins)) = ps;
}
void Spi::OnOpen()
{
// 自动计算稍低于速度speedHz的分频
uint speedHz = Speed;
int pre = GetPre(_index, speedHz);
if(pre == -1) return;
// 使能SPI时钟
switch(_index)
{
case 0: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); break;
#if defined(STM32F1) || defined(STM32F4)
case 1: RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); break;
case 2: RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); break;
#if defined(STM32F4)
case 3: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI4, ENABLE); break;
case 4: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI5, ENABLE); break;
case 5: RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI6, ENABLE); break;
#endif
#endif
}
#if defined(STM32F0)
// SPI都在GPIO_AF_0分组内
_clk.AFConfig(Port::AF_0);
_miso.AFConfig(Port::AF_0);
_mosi.AFConfig(Port::AF_0);
#elif defined(STM32F4)
const byte afs[] = { GPIO_AF_SPI1, GPIO_AF_SPI2, GPIO_AF_SPI3, GPIO_AF_SPI4, GPIO_AF_SPI5, GPIO_AF_SPI6 };
_clk.AFConfig((Port::GPIO_AF)afs[_index]);
_miso.AFConfig((Port::GPIO_AF)afs[_index]);
_mosi.AFConfig((Port::GPIO_AF)afs[_index]);
#endif
Stop();
SPI_I2S_DeInit((SPI_TypeDef*)_SPI);
//SPI_DeInit((SPI_TypeDef*)_SPI); // SPI_I2S_DeInit的宏定义别名
SPI_InitTypeDef sp;
SPI_StructInit(&sp);
sp.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线全双工
sp.SPI_Mode = SPI_Mode_Master; // 主模式
sp.SPI_DataSize = SPI_DataSize_8b; // 数据大小8位 SPI发送接收8位帧结构
sp.SPI_CPOL = SPI_CPOL_Low; // 时钟极性,空闲时为低
sp.SPI_CPHA = SPI_CPHA_1Edge; // 第1个边沿有效上升沿为采样时刻
sp.SPI_NSS = SPI_NSS_Soft; // NSS信号由硬件NSS管脚还是软件使用SSI位管理:内部NSS信号有SSI位控制
sp.SPI_BaudRatePrescaler = pre; // 8分频9MHz 定义波特率预分频的值
sp.SPI_FirstBit = SPI_FirstBit_MSB; // 高位在前。指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
sp.SPI_CRCPolynomial = 7; // CRC值计算的多项式
SPI_Init((SPI_TypeDef*)_SPI, &sp);
SPI_Cmd((SPI_TypeDef*)_SPI, ENABLE);
}
void Spi::OnClose()
{
SPI_Cmd((SPI_TypeDef*)_SPI, DISABLE);
SPI_I2S_DeInit((SPI_TypeDef*)_SPI);
}
byte Spi::Write(byte data)
{
if(!Opened) Open();
auto si = (SPI_TypeDef*)_SPI;
int retry = Retry;
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_TXE) == RESET)
{
if(--retry <= 0) return ++Error; // 超时处理
}
#ifndef STM32F0
SPI_I2S_SendData(si, data);
#else
SPI_SendData8(si, data);
#endif
retry = Retry;
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_RXNE) == RESET) //是否发送成功
{
if(--retry <= 0) return ++Error; // 超时处理
}
#ifndef STM32F0
return SPI_I2S_ReceiveData(si);
#else
return SPI_ReceiveData8(si); //返回通过SPIx最近接收的数据
#endif
}
ushort Spi::Write16(ushort data)
{
if(!Opened) Open();
auto si = (SPI_TypeDef*)_SPI;
// 双字节操作,超时次数加倍
int retry = Retry << 1;
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_TXE) == RESET)
{
if(--retry <= 0) return ++Error; // 超时处理
}
#ifndef STM32F0
SPI_I2S_SendData(si, data);
#else
SPI_I2S_SendData16(si, data);
#endif
retry = Retry << 1;
while (SPI_I2S_GetFlagStatus(si, SPI_I2S_FLAG_RXNE) == RESET)
{
if(--retry <= 0) return ++Error; // 超时处理
}
#ifndef STM32F0
return SPI_I2S_ReceiveData(si);
#else
return SPI_I2S_ReceiveData16(si);
#endif
}