1. 程式人生 > >STM32f103的數電采集電路的DMA設計和使用優化程序

STM32f103的數電采集電路的DMA設計和使用優化程序

mod time alt art 輸出 次數 中文 技術分享 技術

DMA,全稱為:Direct Memory Access,即直接存儲器訪問。DMA傳輸方式無需CPU直接控制傳輸,也沒有中斷處理方式那樣保留現場和恢復現場的過程,通過硬件為RAMI/O設備開辟一條直接傳送數據的通路,能使CPU的效率大為提高。

DMA設置的一般步驟可以總結為如下幾個步驟:

1.DMA時鐘使能

2.DMA設置復位

3.設置DMA基地址,內存地址,輸出方向參數

4.設置DMA數據大小,優先級,使用通道參數

5.DMA工作方式初始化

6.使能DMA

7.編寫中斷處理函數

技術分享

前端采集模塊的DMA使用主要用於ADC采集結果的傳輸和USART串口的數據發送傳輸。根據《stm32中文參考手冊》的DMA請求一覽表,選用了DMA1的通道1作為ADC1的數據傳輸通道,以及DMA1通道4作為和USART串口的數據發送傳輸通道。此處采用了單個DMA復用多通道的設計,是因為DMA速度足以完成這些任務,而且留下其他DMA資源以便項目以後可以擴展,達到節省資源的目的。

技術分享

USART使用DMA發送數據配置和使能代碼

[cpp] view plain copy
  1. //DMA1的各通道配置
  2. //這裏的傳輸形式是固定的,這點要根據不同的情況來修改
  3. //從存儲器->外設模式/8位數據寬度/存儲器增量模式
  4. //DMA_CHx:DMA通道CHx
  5. //cpar:外設地址
  6. //cmar:存儲器地址
  7. //cndtr:數據傳輸量
  8. void DMA_USART_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
  9. {
  10. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA傳輸
  11. DMA_DeInit(DMA_CHx); //將DMA的通道1寄存器重設為缺省值
  12. DMA1_MEM_LEN=cndtr;
  13. DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外設ADC基地址
  14. DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA內存基地址
  15. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; //數據傳輸方向,從內存讀取發送到外設
  16. DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA緩存的大小
  17. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址寄存器不變
  18. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內存地址寄存器遞增
  19. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; //數據寬度為8位
  20. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; //數據寬度為8位
  21. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; //工作在正常緩存模式
  22. DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; //DMA通道 x擁有中優先級
  23. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x沒有設置為內存到內存傳輸
  24. DMA_Init(DMA_CHx, &DMA_InitStructure); //根據DMA_InitStruct中指定的參數初始化DMA的通道USART1_Tx_DMA_Channel所標識的寄存器
  25. }
  26. //開啟一次DMA傳輸
  27. void DMA_USART_Enable(DMA_Channel_TypeDef*DMA_CHx)
  28. {
  29. DMA_Cmd(DMA_CHx, DISABLE ); //關閉USART1 TX DMA1 所指示的通道
  30. DMA_SetCurrDataCounter(DMA_CHx, DMA1_MEM_LEN);//DMA通道的DMA緩存的大小
  31. DMA_Cmd(DMA_CHx, ENABLE); //使能USART1 TX DMA1 所指示的通道
  32. }


ADC使用DMA傳送多通道數據配置和使能代碼

[cpp] view plain copy
  1. //DMA1的各通道配置
  2. //這裏的傳輸形式是固定的,這點要根據不同的情況來修改
  3. //從存儲器->外設模式/8位數據寬度/存儲器增量模式
  4. //DMA_CHx:DMA通道CHx
  5. //cpar:外設地址
  6. //cmar:存儲器地址
  7. //cndtr:數據傳輸量
  8. void DMA_ADC_Config(DMA_Channel_TypeDef* DMA_CHx,u32 cpar,u32 cmar,u16 cndtr)
  9. {
  10. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //使能DMA傳輸
  11. DMA_DeInit(DMA_CHx); //將DMA的通道1寄存器重設為缺省值
  12. DMA_InitStructure.DMA_PeripheralBaseAddr = cpar; //DMA外設ADC基地址
  13. DMA_InitStructure.DMA_MemoryBaseAddr = cmar; //DMA內存基地址
  14. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; //內存作為數據傳輸的目的地
  15. DMA_InitStructure.DMA_BufferSize = cndtr; //DMA通道的DMA緩存的大小
  16. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外設地址寄存器不變
  17. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //內存地址寄存器遞增
  18. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //數據寬度為16位
  19. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //數據寬度為16位
  20. DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //工作在循環緩存模式
  21. DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA通道 x擁有高優先級
  22. DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; //DMA通道x沒有設置為內存到內存傳輸
  23. DMA_Init(DMA_CHx, &DMA_InitStructure); //根據DMA_InitStruct中指定的參數初始化DMA的通道
  24. }
  25. //開啟一次DMA傳輸
  26. void DMA_ADC_Enable(DMA_Channel_TypeDef*DMA_CHx)
  27. {
  28. DMA_Cmd(DMA_CHx, DISABLE ); //關閉USART1 TX DMA1 所指示的通道
  29. DMA_Cmd(DMA_CHx, ENABLE); //使能USART1 TX DMA1 所指示的通道
  30. }


這裏需要註意的是USART使用DMA發送數據需要每一次都重新使能,即每發送一次數據使能一下。

ADC使用DMA傳送多通道數據則只需要使能一次就可以自動循環工作,只需從數組空間讀取ADC數據。

STM32f103的數電采集電路的DMA設計和使用優化程序