#include "stm32f10x.h" //헤더
typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus; //상태 enum
#define SPI2_DR_Address 0x4000380C //spi2 주소
#define BufferSize 32 //버퍼 사이즈
SPI_InitTypeDef SPI_InitStructure; //spi 구조체
DMA_InitTypeDef DMA_InitStructure; //DMA 구조체
GPIO_InitTypeDef GPIO_InitStructure; //GPIO 설정 구조체
uint8_t SPI1_Buffer_Tx[BufferSize] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
0x1C, 0x1D, 0x1E, 0x1F, 0x20}; //spi1 전송 TX 버퍼
uint8_t SPI2_Buffer_Rx[BufferSize]; //수신 버퍼
uint8_t TxIdx = 0; //아이디
volatile TestStatus TransferStatus = FAILED; //상태 (하드웨어 변경 가능)
void RCC_Configuration(void); //클럭 설정
void GPIO_Configuration(void);//gpio 설정
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength); //두개 버퍼 비교후 true false
int main(void)
{
RCC_Configuration();//클럭 설정
GPIO_Configuration();//GPIO설정
/* DMA1 channel4 configuration ---------------------------------------------*/
DMA_DeInit(DMA1_Channel4);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPI2_DR_Address;//실제 SPI 칩의 주소 어떤 정보를 받을지 설정
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)SPI2_Buffer_Rx;// 실제 저장될 메모리 주소
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//?
DMA_InitStructure.DMA_BufferSize = BufferSize;//변수에 저장할 메모리 크기 설정
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//미사용
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//메모리 주소를 증가시키면서 다음메모리 정보 사용
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//바이트
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//변수에 저장할 데이타크기 바이트로 설정
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//보통모드
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//우선순위
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//?
DMA_Init(DMA1_Channel4, &DMA_InitStructure);//저장
/* SPI1 configuration ------------------------------------------------------*/
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; //단방향 양방향 결정가능
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //마스터모드
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //8비트 모드
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;//CPOL 는 리셋 극성 변경 가능
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//CPHA 는 셋 마스터 클럭의 rising,falling edge 할건지 결정 가능
SPI_InitStructure.SPI_NSS = SPI_NSS_Hard; //nss 하드웨어 소프트웨어 셜정가능
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; //18MHZ
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //MSB first
SPI_InitStructure.SPI_CRCPolynomial = 7;//?
SPI_Init(SPI1, &SPI_InitStructure);//설정완료
/* SPI2 configuration ------------------------------------------------------*/
SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Rx; //단방향
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;//슬레이브모드
SPI_Init(SPI2, &SPI_InitStructure);//설정완료
SPI_SSOutputCmd(SPI1, ENABLE);//아웃풋을 받을거라 설정
SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE); //Tx 도 설정 이 가능하지만 spi2의 RX 사용으로 설정함
SPI_Cmd(SPI2, ENABLE);//슬레이브 사용
SPI_Cmd(SPI1, ENABLE);//마스터 사용
DMA_Cmd(DMA1_Channel4, ENABLE);//DMA 채널 14 사용
while (TxIdx < BufferSize) //TX갯수가 버퍼 사이즈보다 작으면 반복
{
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); //마스터의 spi i2s 상태가 리셋이면 계속 spt1 버퍼에 데이터를 저장한다.
SPI_I2S_SendData(SPI1, SPI1_Buffer_Tx[TxIdx++]);
}//데이터를 보내기 위해 spi1의 버퍼 데이터를 DMA에 저장
while (!DMA_GetFlagStatus(DMA1_FLAG_TC4));//데이터가 다 보내질 때 가지 기다림
TransferStatus = Buffercmp(SPI2_Buffer_Rx, SPI1_Buffer_Tx, BufferSize); //송신된 버퍼와 수신된 버퍼를 비교한다.
while (TransferStatus==PASSED)
{
GPIOC->BSRR=GPIO_Pin_9;
}
}
void RCC_Configuration(void)
{
SystemInit();//시스템 이닛
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //DMA1 클럭을 사용한다.
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_SPI1, ENABLE);//72mhz A B SPI1 클럭을 사용
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);//36mhz SPI2 클럭을 사용
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Configure SPI1 pins: NSS, SCK, MISO and MOSI ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50mHZ
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //대체 펑션 모드로 설정
GPIO_Init(GPIOA, &GPIO_InitStructure);//SPI1->A 설정
/* Configure SPI2 pins: NSS, SCK, MISO and MOSI ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure);//SPI2-> B설정 위와 동일
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
TestStatus Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength)//두개 버퍼 비교후 true false
{
while (BufferLength--)
{
if (*pBuffer1 != *pBuffer2)
{
return FAILED;
}
pBuffer1++;
pBuffer2++;
}
return PASSED;
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
while (1)
{}
}
#endif
댓글 없음:
댓글 쓰기