144 lines
3.6 KiB
C
144 lines
3.6 KiB
C
|
|
#include "spi.h"
|
|
#include "hardware.h"
|
|
#include "stm32f10x.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
//------------------------zmienne prywatne-------------------------/
|
|
uint8_t InBuffer[SPI_BSIZE],*dptr;
|
|
uint8_t SPI_State,Counter;
|
|
uint32_t timestamp;
|
|
//------------------------zmienne zewnętrzne-------------------------//
|
|
extern __IO uint32_t Tick;
|
|
//-----------------------------Funkcje------------------------------//
|
|
int8_t SPI_Initialize(void)
|
|
{
|
|
|
|
GPIO_InitTypeDef GPIO_Conf;
|
|
SPI_InitTypeDef SPI_Conf;
|
|
DMA_InitTypeDef DMA_Conf;
|
|
|
|
/* Zegar GPIOA,SPI1 */
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1, ENABLE);
|
|
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
|
|
//MOSI,SCK,CS - wyjście PER
|
|
GPIO_Conf.GPIO_Pin=MOSI1|SCK1;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_AF_PP;
|
|
GPIO_Conf.GPIO_Speed=GPIO_Speed_50MHz;
|
|
GPIO_Init(GPIOA,&GPIO_Conf);
|
|
|
|
//MISO - wejście
|
|
GPIO_Conf.GPIO_Pin=MISO1;
|
|
GPIO_Conf.GPIO_Mode=GPIO_Mode_IN_FLOATING;
|
|
GPIO_Init(GPIOA,&GPIO_Conf);
|
|
|
|
SPI_Cmd(SPI1, DISABLE);
|
|
//Konfuiguracja portu
|
|
SPI_Conf.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
|
SPI_Conf.SPI_Mode = SPI_Mode_Slave;
|
|
SPI_Conf.SPI_DataSize = SPI_DataSize_8b;
|
|
SPI_Conf.SPI_CPOL = 1; //mode 01
|
|
SPI_Conf.SPI_CPHA = 1; //mode 01
|
|
SPI_Conf.SPI_NSS = SPI_NSS_Soft ;
|
|
SPI_Conf.SPI_FirstBit = SPI_FirstBit_MSB;
|
|
SPI_Conf.SPI_CRCPolynomial = 0;
|
|
SPI_Init(SPI1, &SPI_Conf);
|
|
|
|
// sprzętowy CS wyłączony, programowo ustawiony stan niski
|
|
SPI_SSOutputCmd(SPI1,DISABLE);
|
|
SPI_NSSInternalSoftwareConfig(SPI1,SPI_NSSInternalSoft_Reset);
|
|
|
|
//bez CRC
|
|
SPI_CalculateCRC(SPI1,DISABLE);
|
|
|
|
//odbiór przez DMA - kanał 2
|
|
DMA_Cmd(DMA1_Channel2, DISABLE);
|
|
DMA_DeInit(DMA1_Channel2);
|
|
DMA_Conf.DMA_DIR = DMA_DIR_PeripheralSRC;
|
|
DMA_Conf.DMA_M2M = DMA_M2M_Disable;
|
|
DMA_Conf.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
|
DMA_Conf.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
|
DMA_Conf.DMA_MemoryBaseAddr = (uint32_t)InBuffer;
|
|
DMA_Conf.DMA_BufferSize = SPI_BSIZE;
|
|
DMA_Conf.DMA_Mode=DMA_Mode_Circular;
|
|
DMA_Conf.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR);
|
|
DMA_Conf.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
|
DMA_Conf.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
|
DMA_Conf.DMA_Priority = DMA_Priority_VeryHigh;
|
|
DMA_Init(DMA1_Channel2,&DMA_Conf);
|
|
DMA_Cmd(DMA1_Channel2, ENABLE);
|
|
|
|
//inicjalizuj wskaźniki
|
|
dptr=InBuffer;
|
|
|
|
//włącz DMA
|
|
SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,ENABLE);
|
|
|
|
//Włącz SPI
|
|
SPI_Cmd(SPI1, ENABLE);
|
|
}
|
|
|
|
int8_t SPI_GetState(void)
|
|
{
|
|
return SPI_State;
|
|
}
|
|
|
|
uint16_t SPI_Poll(uint8_t *measure,uint16_t length)
|
|
{
|
|
uint16_t count,start,end,remaining,i;
|
|
|
|
//oblicz ile jest danych w buforze
|
|
start = dptr-InBuffer;
|
|
end = SPI_BSIZE - (DMA1_Channel2->CNDTR);
|
|
if(end>=start)
|
|
remaining=end-start;
|
|
else
|
|
remaining=(SPI_BSIZE-(start-end));
|
|
|
|
//oblicz ile danych zwrócić
|
|
if(remaining<length)
|
|
count=remaining;
|
|
else
|
|
count=length;
|
|
|
|
//mamy dane - zwróć
|
|
if(count)
|
|
{
|
|
Counter=0;
|
|
//kopiuj dane do bufora użytkownika
|
|
for(i=0;i<count;i++)
|
|
{
|
|
*measure++ = *dptr++;
|
|
//kraniec bufora. Przestaw wskaźnik na początek.
|
|
if(dptr==InBuffer+SPI_BSIZE)
|
|
dptr=InBuffer;
|
|
}
|
|
SPI_State |= SPI_CONNECTED;
|
|
timestamp=Tick;
|
|
return count;
|
|
}
|
|
else
|
|
{
|
|
//resetuj SPI przy braku komunikacji przez 25ms
|
|
Counter++;
|
|
if(Counter=5)
|
|
{
|
|
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);
|
|
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);
|
|
SPI_Initialize();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//brak danych przez 1 sekundę
|
|
if(Tick-timestamp>1000)
|
|
{
|
|
SPI_State &= ~SPI_CONNECTED;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|