本帖最后由 sujingliang 于 2025-6-6 10:33 编辑
很荣幸在《@开发者们!100+开发板免费领,上海慕尼黑 电子展见》活动中获得一个块APM32E030R开发板。
此次,我首次通过回帖的方式收获幸运,这究竟是幸运之神偶然的恩赐,还是我本就是幸运之子,此刻不过是命运轨迹中一次恰到好处的回归?
不管怎样,感谢极海半导体,感谢21IC。
下面是APM32E030R开发板:

原理图:
可以看到原理图上留有FLASH的扩展(开发板上这部分没有焊接)。
所以我在开发板上补上了一个W25Q80并进行了驱动
1、SPI初始化
对时钟、引脚、SPI等进行初始化
- void SPI_InitForFlash(void)
- {
- SPI_Config_T spiConfig;
- GPIO_Config_T gpioConfig;
-
- // 使能时钟
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SPI1);
- RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);
-
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
-
-
- /* Config alter function*/
- GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_5, GPIO_AF_PIN0);
- GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_6, GPIO_AF_PIN0);
- GPIO_ConfigPinAF(GPIOA, GPIO_PIN_SOURCE_7, GPIO_AF_PIN0);
-
- // 配置SPI引脚
- // PA5 - SCK, PA6 - MISO, PA7 - MOSI
- gpioConfig.pin = GPIO_PIN_5 | GPIO_PIN_7;
- gpioConfig.mode = GPIO_MODE_AF;
- gpioConfig.speed = GPIO_SPEED_50MHz;
- gpioConfig.outtype = GPIO_OUT_TYPE_PP;
- gpioConfig.pupd = GPIO_PUPD_PU;
- GPIO_Config(GPIOA, &gpioConfig);
-
- // 配置CS引脚(假设使用PA4)
- gpioConfig.pin = GPIO_PIN_4;
- gpioConfig.outtype = GPIO_OUT_TYPE_PP;
- gpioConfig.speed = GPIO_SPEED_50MHz;
- gpioConfig.pupd = GPIO_PUPD_PU;
- gpioConfig.mode = GPIO_MODE_OUT;
- GPIO_Config(GPIOA, &gpioConfig);
- GPIO_SetBit(GPIOA, GPIO_PIN_4); // 初始高电平(不选中)
-
- /* config PIN_6 MISO*/
- gpioConfig.pin = GPIO_PIN_6;
- gpioConfig.mode = GPIO_MODE_AF;
- gpioConfig.pupd = GPIO_PUPD_PU;
- gpioConfig.speed = GPIO_SPEED_50MHz;
- GPIO_Config(GPIOA, &gpioConfig);
-
-
- /* SPI RESET*/
- SPI_Reset(SPI1);
- SPI_ConfigStructInit(&spiConfig);
- /* SPI configuration*/
- /* Set Clock polarity is Low, but Slave is High*/
- spiConfig.polarity = SPI_CLKPOL_LOW;
- /* select master mode*/
- spiConfig.mode = SPI_MODE_MASTER;
- /* SPI Clock Phase is 1EDGE, but Slave is 1EDGE*/
- spiConfig.phase = SPI_CLKPHA_1EDGE;
- /* Enable Software slave control */
- spiConfig.slaveSelect = SPI_SSC_ENABLE;
- /* Set SPI BaudRate divider*/
- spiConfig.baudrateDiv = SPI_BAUDRATE_DIV_256;
- /* SPI data length*/
- spiConfig.length = SPI_DATA_LENGTH_8B;
- /* Set internal slave*/
- SPI_EnableInternalSlave(SPI1);
- SPI_Config(SPI1, &spiConfig);
- SPI_ConfigFIFOThreshold(SPI1, SPI_RXFIFO_QUARTER);
- SPI_Enable(SPI1);
- }
2、片选控制
- // 片选控制
- static void FLASH_CS_Low(void) {
- GPIO_ClearBit(GPIOA, GPIO_PIN_4);
- }
- static void FLASH_CS_High(void) {
- GPIO_SetBit(GPIOA, GPIO_PIN_4);
- }
3、发送单字节
- // SPI发送接收单字节
- static uint8_t SPI_TransmitReceiveByte(uint8_t data)
- {
- while(SPI_ReadStatusFlag(SPI1, SPI_FLAG_TXBE) == RESET);
- SPI_TxData8(SPI1, data);
-
- while(SPI_ReadStatusFlag(SPI1, SPI_FLAG_RXBNE) == RESET);
- return SPI_RxData8(SPI1);
- }
4、写使能
- static void FLASH_WriteEnable(void)
- {
- FLASH_CS_Low();
- SPI_TransmitReceiveByte(0x06); // 写使能命令
- FLASH_CS_High();
- }
5、读取数据
- void FLASH_ReadData(uint32_t addr, uint8_t *pData, uint32_t size)
- {
- FLASH_CS_Low();
- SPI_TransmitReceiveByte(0x03); // 读数据命令
-
- // 发送地址(24位)
- SPI_TransmitReceiveByte((addr >> 16) & 0xFF);
- SPI_TransmitReceiveByte((addr >> 8) & 0xFF);
- SPI_TransmitReceiveByte(addr & 0xFF);
-
- // 读取数据
- while(size--) {
- *pData++ = SPI_TransmitReceiveByte(0xFF);
- }
-
- FLASH_CS_High();
- }
6、页编程(写入数据,通常256字节一页)
|