Suwmiarka/Soft/Suwmiarka/spi.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;
}