在做AM335D板子与STM32F103使用SPI通信时,需要用到STM32的从机模式,所以特别对于ST的从机模式进行了研究,由于硬件上使用的是STM32F103的SPI3,所以过程中遇到了一点麻烦,这里记录一下过程,以备查阅:
使用SPI3通信时,从机时钟产生不了中断,经过查阅资料,是因为spi3的nss口与JTAG有共用引脚,所以配置错误会导致SPI3无法使用。需要注意以下两点就可以了:
1.开启GPIO时钟的同时,开启AFIO时钟,如下:
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE );
2.关闭JTAG功能,使能SWD 如下:
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE) ;
其他的SPI口正常配置,因为板子重启后默认为JTAG模式,所以注意千万不要使用GPIO_Remap_SWJ_Disable ,一旦这样就不能下载程序了,要使用ST的那个工具专门烧录。
以下是具体的代码:
extern u8 SPI3_Buffer_Rx[];
extern u8 RxIdx ;
u16 net_spi_Write(void);
void SPI3_Slave_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE);
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE );
//RCC_APB2Periph_AFIO很重要
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI3, ENABLE );
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE) ; //disable掉JTAG复用,很重要
/* MISO设置为推挽输出 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* SCK和MOSI设置为下拉输入 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
SPI3_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI3_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI3_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI3_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI3_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI3_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI3_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //
SPI3_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI3_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI3, &SPI3_InitStructure); //
SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_RXNE, ENABLE);
SPI_Cmd(SPI3, ENABLE);
//SPI1_ReadWriteByte(0xff);
}
void SPI3_SetSpeed(u8 SpeedSet)
{
SPI3_InitStructure.SPI_BaudRatePrescaler = SpeedSet ;
SPI_Init(SPI3, &SPI3_InitStructure);
SPI_Cmd(SPI3,ENABLE);
}
u8 SPI3_ReadWriteByte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET) //发送缓存标志位
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI3, TxData); //发送数据
retry=0;
while (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET)//接收缓存标志位
{
retry++;
if(retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI3); //返回接收到的数据
}
void SPI_net_Init(void)
{
SPI3_Slave_Init();
}
void NVIC_config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = SPI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void SPI3_IRQHandler(void)
{
volatile uint8_t data;
if(SPI_I2S_GetITStatus(SPI3, SPI_I2S_IT_RXNE) == SET)
{
while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_RXNE) == RESET)
{
}
SPI3_Buffer_Rx[RxIdx++] = SPI_I2S_ReceiveData(SPI3);
while(SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) == RESET)
{
}
SPI_I2S_ClearITPendingBit(SPI3, SPI_I2S_IT_RXNE);
}
}
void net_spi_read_loop(void)
{
u8 i;
while (1)
{
if(RxIdx>=10)
{
SPI_Cmd(SPI3, DISABLE);
RxIdx=0;
printf("rcv full:\n");
for(i=0;i<10;i++)
printf("0x%02X ",SPI3_Buffer_Rx[i]);
printf("\r\n ");
memset(SPI3_Buffer_Rx,0,10);
SPI_Cmd(SPI3, ENABLE);
}
}
}