当前位置:   article > 正文

STM32F4 SPI RX/TX DMA 读写FLASH数据_dma能写flash吗

dma能写flash吗

STM32 使用DMA读写FLASH数据需要注意以下几点:

1.SPI全双工模式下,无论读写FLASH数据均需要同时使能RX/TX DMA。

2.写数据时回读数据应当丢弃,读数据时应当发送0xff来启动SPI读周期。

3.使用DMA时应当使能DMA Stream,然后再使能SPI DMA请求。

 

以下为测试代码,为省事,没启动串口提供打印信息,可在读出FLASH数据后通过断点查看数据。

  1. #include <stdbool.h>
  2. #include <stm32f4xx_dma.h>
  3. #include <stm32f4xx_gpio.h>
  4. #include <stm32f4xx_spi.h>
  5. #define FLASH_PAGE_SIZE 256
  6. static volatile int g_rx_flag = 0;
  7. static volatile int g_tx_flag = 0;
  8. static void spi_wait_rx(void)
  9. {
  10. while(!g_rx_flag);
  11. g_rx_flag = 0;
  12. }
  13. static void spi_post_rx(void)
  14. {
  15. g_rx_flag = 1;
  16. }
  17. static void spi_wait_tx(void)
  18. {
  19. while(!g_tx_flag);
  20. g_tx_flag = 0;
  21. }
  22. static void spi_post_tx(void)
  23. {
  24. g_tx_flag = 1;
  25. }
  26. static void spi_do_delay(uint16_t n)
  27. {
  28. uint16_t t = n;
  29. while (-- t);
  30. }
  31. uint8_t spi_byte_transfer(uint8_t Dat)
  32. {
  33. while ((SPI3->SR & SPI_I2S_FLAG_TXE) == 0);
  34. SPI3->DR = Dat;
  35. while ((SPI3->SR & SPI_I2S_FLAG_RXNE) == 0);
  36. return ((uint8_t)(SPI3->DR));
  37. }
  38. uint8_t spi_readbyte(void)
  39. {
  40. return spi_byte_transfer(0xA5);
  41. }
  42. /* 使用 GPIO6 作为 CS 信号
  43. */
  44. static void spi_chip_select(bool select)
  45. {
  46. spi_do_delay(5);
  47. if (select == true)
  48. {
  49. GPIOB->BSRRH = GPIO_Pin_6;
  50. }
  51. else
  52. {
  53. GPIOB->BSRRL = GPIO_Pin_6;
  54. }
  55. spi_do_delay(5);
  56. }
  57. void flash_wait_write(void)
  58. {
  59. uint8_t status = 0;
  60. spi_chip_select(true);
  61. spi_byte_transfer(0x05);
  62. do
  63. {
  64. status = spi_byte_transfer(0xA5);
  65. } while (status & 0x01);
  66. spi_chip_select(false);
  67. }
  68. void flash_enable_write(void)
  69. {
  70. spi_chip_select(true);
  71. spi_byte_transfer(0x06);
  72. spi_chip_select(false);
  73. }
  74. void flash_write_status(uint8_t value)
  75. {
  76. flash_enable_write();
  77. spi_chip_select(true);
  78. spi_byte_transfer(0x01);
  79. spi_byte_transfer(value);
  80. spi_chip_select(false);
  81. flash_wait_write();
  82. }
  83. void flash_disable_write(void)
  84. {
  85. flash_write_status(0);
  86. }
  87. uint32_t flash_read_identify(void)
  88. {
  89. uint8_t byte0 = 0, byte1 = 0, byte2 = 0;
  90. spi_chip_select(true);
  91. spi_byte_transfer(0x9F);
  92. byte0 = spi_byte_transfer(0xA5);
  93. byte1 = spi_byte_transfer(0xA5);
  94. byte2 = spi_byte_transfer(0xA5);
  95. spi_chip_select(false);
  96. return ((byte0 << 16) | (byte1 << 8) | (byte2 << 0));
  97. }
  98. void flash_erase_sector(uint32_t SectorAddr)
  99. {
  100. flash_enable_write();
  101. spi_chip_select(true);
  102. spi_byte_transfer(0x20);
  103. spi_byte_transfer((SectorAddr >> 16) & 0xFF);
  104. spi_byte_transfer((SectorAddr >> 8) & 0xFF);
  105. spi_byte_transfer((SectorAddr >> 0) & 0xFF);
  106. spi_chip_select(false);
  107. flash_wait_write();
  108. }
  109. /**
  110. * 启动SPI DMA通道
  111. * buffer 缓冲区指针
  112. * length 缓冲区数据长度,
  113. * 如果 isread = true 表示需要从 flash 中读取多少个字节。
  114. * 如果 isread = false 表示需要向 flash 写入多少个字节。
  115. * isread true = 读,false = 写
  116. *
  117. */
  118. void flash_start_dma(uint8_t *buffer, uint32_t length, uint8_t isread)
  119. {
  120. uint32_t temp = 0xffffffff;
  121. DMA_InitTypeDef DMA_InitStructure;
  122. DMA_StructInit(&DMA_InitStructure);
  123. DMA_DeInit(DMA1_Stream0);
  124. DMA_DeInit(DMA1_Stream7);
  125. while(DMA_GetCmdStatus(DMA1_Stream0) != DISABLE);
  126. while(DMA_GetCmdStatus(DMA1_Stream7) != DISABLE);
  127. /* DMA1 channel 0 stream0 --- 配置 SPI3-RX DMA */
  128. DMA_InitStructure.DMA_Channel = DMA_Channel_0;
  129. DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI3->DR;
  130. if (isread == true)
  131. {
  132. /* 读方式下回读数据放到 buffer 中*/
  133. DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer;
  134. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  135. }
  136. else
  137. {
  138. /* 写方式下回读数据丢弃 */
  139. DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&temp;
  140. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  141. }
  142. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  143. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  144. DMA_InitStructure.DMA_BufferSize = length;
  145. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  146. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  147. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  148. DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  149. DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  150. DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  151. DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  152. DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  153. DMA_Init(DMA1_Stream0, &DMA_InitStructure);
  154. /* DMA1 channel 0 stream7 --- 配置 SPI3-TX DMA */
  155. DMA_StructInit(&DMA_InitStructure);
  156. DMA_InitStructure.DMA_Channel = DMA_Channel_0;
  157. DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI3->DR;
  158. if (isread == true)
  159. {
  160. /* 读方式下发送 0xff */
  161. DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&temp;
  162. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  163. }
  164. else
  165. {
  166. /* 写方式下发送 buffer 数据*/
  167. DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer;
  168. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  169. }
  170. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  171. DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  172. DMA_InitStructure.DMA_BufferSize = length;
  173. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  174. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  175. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  176. DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
  177. DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  178. DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  179. DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  180. DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  181. DMA_Init(DMA1_Stream7, &DMA_InitStructure);
  182. /* 1.开启 DMA 数据流传输完成中断 */
  183. DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, ENABLE);
  184. DMA_ITConfig(DMA1_Stream7, DMA_IT_TC, ENABLE);
  185. /* 2.使能 DMA 数据流 */
  186. DMA_Cmd(DMA1_Stream0, ENABLE);
  187. DMA_Cmd(DMA1_Stream7, ENABLE);
  188. /* 3.使能 SPI DMA 请求 */
  189. SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Rx|SPI_I2S_DMAReq_Tx, ENABLE);
  190. /* 5.等待 DMA 传输完成 */
  191. spi_wait_tx();
  192. spi_wait_rx();
  193. }
  194. void DMA1_Stream7_IRQHandler(void)
  195. {
  196. if (DMA_GetFlagStatus(DMA1_Stream7, DMA_FLAG_TCIF7) != RESET)
  197. {
  198. /* 1.清中断标志 */
  199. DMA_ClearFlag(DMA1_Stream7, DMA_FLAG_TCIF7);
  200. /* 2.禁能 DMA 传输完成中断 */
  201. DMA_ITConfig(DMA1_Stream7, DMA_IT_TC, DISABLE);
  202. /* 3.禁能 SPI TX DMA 请求 */
  203. SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, DISABLE);
  204. /* 4.禁能 DMA Stream */
  205. DMA_Cmd(DMA1_Stream7, DISABLE);
  206. /* 5.通知应用程序 TX 传输完成 */
  207. spi_post_tx();
  208. }
  209. }
  210. void DMA1_Stream0_IRQHandler(void)
  211. {
  212. if (DMA_GetFlagStatus(DMA1_Stream0, DMA_FLAG_TCIF0) != RESET)
  213. {
  214. /* 1.清中断标志 */
  215. DMA_ClearFlag(DMA1_Stream0, DMA_FLAG_TCIF0);
  216. /* 2.禁能 DMA 传输完成中断 */
  217. DMA_ITConfig(DMA1_Stream0, DMA_IT_TC, DISABLE);
  218. /* 3.禁能 SPI TX DMA 请求 */
  219. SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Rx, DISABLE);
  220. /* 4.禁能 DMA Stream */
  221. DMA_Cmd(DMA1_Stream0, DISABLE);
  222. /* 6.通知应用程序 RX 传输完成 */
  223. spi_post_rx();
  224. }
  225. }
  226. void flash_write_page(uint8_t* buffer, uint32_t addr)
  227. {
  228. flash_enable_write();
  229. spi_chip_select(true);
  230. spi_byte_transfer(0x02);
  231. spi_byte_transfer((addr >> 16) & 0xFF);
  232. spi_byte_transfer((addr >> 8) & 0xFF);
  233. spi_byte_transfer((addr >> 0) & 0xFF);
  234. flash_start_dma(buffer, FLASH_PAGE_SIZE, false);
  235. spi_chip_select(false);
  236. flash_wait_write();
  237. }
  238. void flash_read_page(uint8_t *buffer, uint32_t addr)
  239. {
  240. spi_chip_select(true);
  241. spi_byte_transfer(0x03);
  242. spi_byte_transfer((addr >> 16) & 0xFF);
  243. spi_byte_transfer((addr >> 8) & 0xFF);
  244. spi_byte_transfer((addr >> 0) & 0xFF);
  245. flash_start_dma(buffer, FLASH_PAGE_SIZE, true);
  246. spi_chip_select(false);
  247. }
  248. void flash_init(void)
  249. {
  250. GPIO_InitTypeDef GPIO_InitStructure;
  251. NVIC_InitTypeDef NVIC_InitStructure;
  252. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
  253. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
  254. SPI_InitTypeDef SPI_InitStructure;
  255. RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
  256. GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI3);
  257. GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI3);
  258. GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI3);
  259. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  260. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  261. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  262. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
  263. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_4;
  264. GPIO_Init(GPIOB, &GPIO_InitStructure);
  265. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  266. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  267. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  268. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  269. GPIO_Init(GPIOB, &GPIO_InitStructure);
  270. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  271. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
  272. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  273. SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  274. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  275. SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
  276. SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
  277. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
  278. SPI_InitStructure.SPI_CRCPolynomial = 7;
  279. SPI_Init(SPI3, &SPI_InitStructure);
  280. SPI_Cmd(SPI3, ENABLE);
  281. NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream7_IRQn;
  282. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  283. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  284. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  285. NVIC_Init(&NVIC_InitStructure);
  286. NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream0_IRQn;
  287. NVIC_Init(&NVIC_InitStructure);
  288. spi_chip_select(false);
  289. }
  290. uint8_t wbuffer[512];
  291. uint8_t rbuffer[512];
  292. int main(void)
  293. {
  294. int i = 0;
  295. flash_init();
  296. /* 初始化测试数据 */
  297. for (i = 0; i < 512; i++)
  298. {
  299. wbuffer[i] = (uint8_t)(i+9);
  300. }
  301. flash_erase_sector(0);
  302. flash_read_page(rbuffer, 0); /* 在此处打断点查看数据 */
  303. flash_write_page(wbuffer, 0);
  304. flash_read_page(rbuffer, 0); /* 在此处打断点查看数据 */
  305. while(1);
  306. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/50699
推荐阅读
相关标签
  

闽ICP备14008679号