创建基于RTThread的项目工程,根据自己的情况创建,理论上stm32F(x)系列的单片机都是通用的代码;
然后打开spi驱动并通过cubemx配置初始化spi的代码
这里的代码是我用STM32CubeMx生成的,你们可以直接使用下面这段代码修改成自己的SPI端口和SPIx就省去配置了。
void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(spiHandle->Instance==SPI2) { /* USER CODE BEGIN SPI2_MspInit 0 */ /* USER CODE END SPI2_MspInit 0 */ /* SPI2 clock enable */ __HAL_RCC_SPI2_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**SPI2 GPIO Configuration PB12 ------> SPI2_NSS PB13 ------> SPI2_SCK PB14 ------> SPI2_MISO PB15 ------> SPI2_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USER CODE BEGIN SPI2_MspInit 1 */ /* USER CODE END SPI2_MspInit 1 */ } }
创建app文件
#include <rtthread.h> #include <board.h> #include "rtdevice.h" #include "./sfud/inc/sfud.h" #include <dfs_posix.h> /* 当需要使用文件操作时,需要包含这个头文件 */ #define W25Q_SPI_DEVICE_NAME "spi20" /** * 总线上挂载设备 spi20 * @return */ static int bsp_spi_attach_init(void) { __HAL_RCC_GPIOB_CLK_ENABLE(); // spi10 表示挂载在 spi1 总线上的 0 号设备,PC0是片选,这一步就可以将从设备挂在到总线中。 rt_err_t ret = rt_hw_spi_device_attach("spi2", "spi20", GPIOB, GPIO_PIN_12); if(ret < 0) { rt_kprintf("flash attach spi2 failed"); return -RT_ERROR; } return RT_EOK; } static void bsp_spi_w25q_sample(int argc, char *argv[]) { struct rt_spi_device *spi_dev_w25q; char name[RT_NAME_MAX]; rt_uint8_t w25x_read_id = 0x90; rt_uint8_t id[5] = {0}; if (argc == 2) { rt_strncpy(name, argv[1], RT_NAME_MAX); } else { rt_strncpy(name, W25Q_SPI_DEVICE_NAME, RT_NAME_MAX); } /* 查找 spi 设备获取设备句柄 */ spi_dev_w25q = (struct rt_spi_device *)rt_device_find(name);//根据 SPI 设备名称查找设备获取设备句柄 if (!spi_dev_w25q) { rt_kprintf("spi sample run failed! can't find %s device!\n", name); } else { /* 方式1:使用 rt_spi_send_then_recv()发送命令读取ID */ rt_spi_send_then_recv(spi_dev_w25q, &w25x_read_id, 1, id, 5);//先发送后接收数据id rt_kprintf("use rt_qspi_send_then_recv() read w25q ID is:%x%x\n", id[3], id[4]); } } /** * 注册为块设备 * @return */ static int bsp_spi_block_device_init(void) { if (RT_NULL == rt_sfud_flash_probe("W25Q128", "spi20")) //注册块设备,这一步可以将外部flash抽象为系统的块设备 { LOG_E("flash sfud failed\n"); return -RT_ERROR; }; return RT_EOK; } /** * 挂载文件系统 * @return */ static int bsp_spi_flash_mnt_init(void) { // dfs_mkfs("elm", "W25Q128");//格式化设备 if(dfs_mount("W25Q128", "/", "elm", 0, 0)==0)//挂载文件 { LOG_I("dfs mount success\r\n"); return RT_EOK; }else { LOG_E("dfs mount failed\r\n"); return -RT_ERROR; } } static void readwrite_sample(void) { int fd, size; char s[] = "write file text!", buffer[80]; /* 以创建和读写模式打开 /text.txt 文件,如果该文件不存在则创建该文件*/ fd = open("/updata.bin", O_WRONLY | O_CREAT); if (fd >= 0) { write(fd, s, sizeof(s)); close(fd); rt_kprintf("Write done.\n"); } /* 以只读模式打开 /text.txt 文件 */ fd = open("/updata.bin", O_RDONLY); if (fd >= 0) { size = read(fd, buffer, sizeof(buffer)); close(fd); rt_kprintf("read: %s \n", buffer); if (size < 0) return ; } } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(readwrite_sample, readwrite sample); ///* 组件自动初始化 */ INIT_COMPONENT_EXPORT(bsp_spi_flash_mnt_init); ///* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(bsp_spi_w25q_sample, spi w25q sample); INIT_DEVICE_EXPORT(bsp_spi_attach_init); /* 导出到自动初始化 */ INIT_DEVICE_EXPORT(bsp_spi_block_device_init);
然后开始编译
打开控制台调试测试
挂载文件系统失败了,检查DFS配置
最后的测试