文章目录
一、SPI外设简介
(1)数据传输
SCK的每个时钟周期MOSI和MISO传输一位数据
发送到模块的所有命令都要用0x0A填充到偶数字节
(2)模式
(3)总线分布
APB1总线 : SPI2、SPI3 (最高通信速率为21Mbits/s)
APB2总线 : SPI1、SPI4、SPI5、SPI6 (最高通信速率达42Mbtis/s)
(4)BR位对fpclk的分频
f (pclk) / 2^(BR[0:2])
二、模块引脚功能简介和配置
(1)引脚简介
DATARDY:数据准备引脚。当模块准备好接受命令或者数据的时候,该引脚就会拉高
Wakeup:上升沿触发引脚,触发后会退出停止模式
RST:连接的是内部STM32F205芯片的异步复位脚。输入低电平复位,高电平工作
(2)模块的SPI配置
Clock rate: 20MHz max.
Width: 16-bit
Mode: 0( SPI_MODE_SLAVE 从模式)
Endian: Little
NSS线为低电平表示开始信号,拉高表示结束信号
(3)模块返回SPI的指令格式
成功:\r\nDATA\r\nOK\r\n>sp
失败:\r\nERROR\r\nUSAGE\r\n>sp
(sp是空格的意思,等于’ ')
(4)模块SPI通讯图
三、模块开发
(1)SPI主机配置
引脚配置:
Wakeup:推挽无上下拉低电平输出
Rst:推挽无上下拉低电平输出
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_WritePin( GPIO_PIN_RESET );
DataRdy:无上下拉的上升沿中断触发模式
GPIO_Init.Mode = GPIO_MODE_IT_RISING;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW;
SPI配置:
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_16BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;(这里看自己芯片的AHB频率去定,模块最大支持20MHz)
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 0;
if (HAL_SPI_Init(&hspi3) != HAL_OK)
{
Error_Handler();
}
(2)上电初阶段
通电或复位后,eS-WiFi模块将拉高CMD/DATA READY引脚来表示第一个数据阶段已经开始的信号。
SPI主机需先获取游标,这是主机在不发出命令的情况下从从属设备获取数据的唯一时间。
主机将启动一个SPI周期(低SSN)并时钟输出0x0A(行馈电),直到CMD/DATA READY引脚拉低,表示数据阶段结束的信号。接收到的数据为0x0d (\r) 0x0A (\n) 0x3E (>) 0x20 (SP空格)。
CMD/DATA READY引脚的下一个上升边沿表示命令阶段。
int16_t resetModule()
{
WIFI_Reset_Pin();
WIFI_ENABLE_NSS();
HAL_Delay(1);
//3、等准备引脚
while( HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_1) != GPIO_PIN_SET );
uint8_t reset_cmd[6];
uint8_t count = 0;
while( HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_1) == GPIO_PIN_SET )
{
HAL_SPI_Receive(&hspi3,&reset_cmd[count],1,0xFFFF);
count+=2;
if( count >= 6 ) break;
}
WIFI_DISABLE_NSS();
if( reset_cmd[0] != 0x15 || reset_cmd[1] != 0x15 || reset_cmd[2] != '\r' ||
reset_cmd[3] != '\n' || reset_cmd[4] != '>' || reset_cmd[5] != ' ' )
return -1;
return 0;
}
(3)命令阶段:
命令阶段表示 eS-WiFi 模块已准备好接受 IWIN AT 命令。
命令必须包含该命令的所有分隔符和数据。
命令还必须作为一个连续的 SPI 周期发送,也就是说,对于完整的命令、定界符和数据,SSN 必须保持低电平。
主机将启动一个 SPI 周期(较低的 SSN)并输出命令、定界符和相关数据,并提高 NSS 信号以指示所有数据已发送。
由于 NSS 升高,eS-WiFi 模块将拉低 CMD/DATA READY 引脚以发出结束命令阶段的信号。
回传到主机的数据为 0x15 (NAK)。
int16_t spi_send(uint8_t *send_data,uint16_t len)
{
while( HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_1) != GPIO_PIN_SET );
WIFI_ENABLE_NSS();
rdy_rising_event = 1;
HAL_Delay(1);
if( HAL_SPI_Transmit_IT(&hspi3,send_data,len/2) != HAL_OK )
{
WIFI_DISABLE_NSS();
return -1;
}
while(__HAL_SPI_GET_FLAG(&hspi3,SPI_FLAG_TXE) != 1);
if( len & 1 )
{
uint8_t fill_data[2];
fill_data[0] = send_data[len-1];
fill_data[1] = '\n';
if( HAL_SPI_Transmit_IT(&hspi3,fill_data,1) != HAL_OK )
{
WIFI_DISABLE_NSS();
return -1;
}
while(__HAL_SPI_GET_FLAG(&hspi3,SPI_FLAG_TXE) != 1);
}
return len;
}
(4)数据阶段:
数据阶段表示 eS-WiFi 模块已准备好供主机读取的数据。 eS-WiFi 模块将提高 CMD/DATA READY,主机将启动 SPI 周期(较低的 SSN)并输出 0x0A(换行),直到 CMD/DATA READY 引脚降低,表示数据阶段结束。
int16_t spi_recv(uint8_t *recv_buf,uint16_t len)
{
uint16_t count = 0;
uint8_t tmp[2];
WIFI_DISABLE_NSS();
HAL_Delay(1);
while( rdy_rising_event == 1 );
WIFI_ENABLE_NSS();
HAL_Delay(1);
while( HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_1) == GPIO_PIN_SET )
{
if( len > count )
{
if( HAL_SPI_Receive_IT(&hspi3,tmp,1) != HAL_OK )
{
WIFI_DISABLE_NSS();
return -1;
}
while(__HAL_SPI_GET_FLAG(&hspi3,SPI_FLAG_RXNE) != 0);
recv_buf[count] = tmp[0];
recv_buf[count+1] = tmp[1];
count += 2;
}
else
break;
}
WIFI_DISABLE_NSS();
return count;
}
(5)中断处理程序
void EXTI_rdy_pin(void)
{
if( rdy_rising_event == 1 )
rdy_rising_event = 0;
}
四、AT指令
剩下的根据官网的AT指令进行自己想要的操作即可
官网文档网址:https://www.inventeksys.com/iwin/documentation/