基於stm32f103zet6的DMA學習

來源:互聯網
上載者:User

stm32內部整合的ADC介紹
一、參考電壓的範圍為 
/*2.4V≦ V
≦3.6V
所以它的輸入類比電壓範圍0 <= V <=V*/
二、需要測量負電壓或測量的電壓訊號超出範圍時,要先經過運算電路進行平移或利用電阻分壓。
三、我採用的是51單片機上面的10k的電阻來類比輸入
四、規則通道和注入通道
/*所謂規則,那麼就是按常理出牌的,我們可以稱之為正常的通道,那麼與之對應的是注入通道,就是
在規則通道正在轉換的時候是可以被注入通道打斷,轉而去執行注入通道轉換的,當注入通道轉換完
成之後,才繼續去進行規則通道裡面的轉換,TM32ADC的規則通道組最多包含16 個轉換,而注入通道
組最多包含 4 個通道*/
五、初始化ADC這是必須的,比東有一個結構體來初始化這個ADC
1、首先確定從哪裡輸入我們的類比量呢?
這裡涉及到ADC通道的知識,每個ADC通道都對應著一個GPIO引腳連接埠
PC0對應的預設複用功能是ADC1、ADC2、ADC3的通道10
所以最開始應該配置GPIO,現在可以來做個猜測
2、配置GPIO

GPIO_Mode = GPIO_Mode_AIN 
GPIO_Pin = GPIO_Pin_10
GPIO_Speed = GPIO_Speed_50MHz   
以上就是類比輸入
六、然後是配置ADC,也就是初始化ADC了,
找到這樣一個結構體
ADC_InitTypeDef 
結構體成員有{
FunctionalState  ADC_ContinuousConvMode 
uint32_t  ADC_DataAlign 
uint32_t  ADC_ExternalTrigConv 
uint32_t  ADC_Mode 
uint8_t  ADC_NbrOfChannel 
FunctionalState  ADC_ScanConvMode 
}
1、ADC_ContinuousConvMode的取值有
Specifies whether the conversion is performed in Continuous or Single mode.
This parameter can be set to ENABLE or DISABLE
此參數用來配置是否開啟迴圈採集ENABLE or DISABLE
2、ADC_DataAlign明顯意思是資料對齊,它的取值有
#define  ADC_DataAlign_Left   ((uint32_t)0x00000800) 
#define  ADC_DataAlign_Right   ((uint32_t)0x00000000) 
#define  IS_ADC_DATA_ALIGN(ALIGN) 
靠左對齊,靠右對齊。。
3、ADC_ExternalTrigConv外部中斷觸發方式?它的取值有
#define  ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO   ((uint32_t)0x000C0000) 
#define  ADC_ExternalTrigConv_None   ((uint32_t)0x000E0000) 
#define  ADC_ExternalTrigConv_T1_CC1   ((uint32_t)0x00000000) 
#define  ADC_ExternalTrigConv_T1_CC2   ((uint32_t)0x00020000) 
#define  ADC_ExternalTrigConv_T1_CC3   ((uint32_t)0x00040000) 
#define  ADC_ExternalTrigConv_T2_CC2   ((uint32_t)0x00060000) 
#define  ADC_ExternalTrigConv_T2_CC3   ((uint32_t)0x00020000) 
#define  ADC_ExternalTrigConv_T3_CC1   ((uint32_t)0x00000000) 
#define  ADC_ExternalTrigConv_T3_TRGO   ((uint32_t)0x00080000) 
#define  ADC_ExternalTrigConv_T4_CC4   ((uint32_t)0x000A0000) 
#define  ADC_ExternalTrigConv_T5_CC1   ((uint32_t)0x000A0000) 
#define  ADC_ExternalTrigConv_T5_CC3   ((uint32_t)0x000C0000) 
#define  ADC_ExternalTrigConv_T8_CC1   ((uint32_t)0x00060000) 
#define  ADC_ExternalTrigConv_T8_TRGO   ((uint32_t)0x00080000) 
觸發方式很豐富,當然 ADC_ExternalTrigConv_None這就表示不採用外部中斷方式觸發(那麼軟體觸發)
4、ADC_Mode ADC的模式?
Configures the ADC to operate in independent or dual mode. 
This parameter can be a value of ADC_mode
它的取值有
#define  ADC_Mode_AlterTrig   ((uint32_t)0x00090000) 
#define  ADC_Mode_FastInterl   ((uint32_t)0x00070000) 
#define  ADC_Mode_Independent   ((uint32_t)0x00000000) 
#define  ADC_Mode_InjecSimult   ((uint32_t)0x00050000) 
#define  ADC_Mode_InjecSimult_FastInterl   ((uint32_t)0x00030000) 
#define  ADC_Mode_InjecSimult_SlowInterl   ((uint32_t)0x00040000) 
#define  ADC_Mode_RegInjecSimult   ((uint32_t)0x00010000) 
#define  ADC_Mode_RegSimult   ((uint32_t)0x00060000) 
#define  ADC_Mode_RegSimult_AlterTrig   ((uint32_t)0x00020000) 
#define  ADC_Mode_SlowInterl   ((uint32_t)0x00080000) 
貌似是有注入組、和規則群組的概念,有些單詞不是很熟悉,沒關係那就先這樣吧!用到了再來
5、ADC_NbrOfChannel採樣通道?
明顯一般採用的是是16個規則通道,那取值就是1--16
Specifies the number of ADC channels that will be converted using the sequencer for regular
channel group.This parameter must range from 1 to 16
6、ADC_ScanConvMode,字面意思不是很懂,看手冊
Specifies whether the conversion is performed in Scan (multichannels) or Single (one channel)
mode. This parameter can be set to ENABLE or DISABLE 
意思是當有多個通道的時候,使用掃描的方式,反之只有單個通道的是那麼就是選擇單通道了
那麼取值就是ENABLE or DISABLE 
至此結構成員分析完畢,下面來猜測一下,應該怎樣賦值,聲明:單通道採集,靠右對齊(方便存資料)
軟體觸發,通道採用10(使用PC0)
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None
ADC_InitStructure.ADC_Mode= ADC_Mode_Independent
ADC_InitStructure.ADC_NbrOfChannel = 11
ADC_InitStructure.ADC_ScanConvMode = DISABLE
下面來對照下,原始代碼看看:
  /* ADC1 configuration */
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);
顯然錯誤還是比較多的,沒關係,慢慢分析
1、因為是一個通道沒必要掃描,所以第2個錯了
2、通道數目理解錯誤。我以為那是指定的哪個通道,原來是number of channel
3、好的最後就是少了一個庫函數的調用,這確實是缺乏這種意識呀!
七、既然是使用DMA來傳送資料,那麼下一步就開始初始化DMA吧!DMA的知識暫時不分析,那個得單獨出來
我還是先來瞭解下DMA的變成思想吧!
1、STM32就是這樣完美,每個模組都能有個結構體來組織它的一些參數配置,我甚至覺得它和uboot一樣討人喜歡
這隻是我的愚見,也是這樣一個結構體 DMA_InitTypeDef DMA_InitStructure;
跟著手冊來吧
2、DMA_InitTypeDef{
uint32_t  DMA_BufferSize 
uint32_t  DMA_DIR 
uint32_t  DMA_M2M 
uint32_t  DMA_MemoryBaseAddr 
uint32_t  DMA_MemoryDataSize 
uint32_t  DMA_MemoryInc 
uint32_t  DMA_Mode 
uint32_t  DMA_PeripheralBaseAddr 
uint32_t  DMA_PeripheralDataSize 
uint32_t  DMA_PeripheralInc 
uint32_t  DMA_Priority
}
3、DMA_BufferSize,明顯就是資料的大小,看她是怎麼描述的
Specifies the buffer size, in data unit, of the specified Channel. The data unit is equal to 
the configuration set in DMA_PeripheralDataSize or DMA_MemoryDataSize members depending in 
the transfer direction 
可以得出DMA_PeripheralDataSize = DMA_MemoryDataSize = DMA_BufferSize
取值可以是
#define  DMA_MemoryDataSize_Byte   ((uint32_t)0x00000000) 
#define  DMA_MemoryDataSize_HalfWord   ((uint32_t)0x00000400) 
#define  DMA_MemoryDataSize_Word   ((uint32_t)0x00000800) 
4、DMA_DIR字面意思不怎麼明朗方向?看解釋
Specifies if the peripheral is the source or destination. This parameter can be a value of 
DMA_data_transfer_direction
資料來源和目的源
取值
#define  DMA_DIR_PeripheralDST   ((uint32_t)0x00000010) 
#define  DMA_DIR_PeripheralSRC   ((uint32_t)0x00000000 
從儲存空間到外設或者從外設到儲存空間
5、DMA_M2M 這個可以猜測到,DMA的作用出了上面一個還有M to M的沒有提及那麼
#define  DMA_M2M_Disable   ((uint32_t)0x00000000) 
#define  DMA_M2M_Enable   ((uint32_t)0x00004000) 
可以這樣設定了
6、DMA_MemoryBaseAddr、DMA_PeripheralBaseAddr
這兩個可以一起看了,字面意思很清楚了,外設地址和儲存空間(變數)地址,這個得看你的地址了
7、DMA_MemoryInc、DMA_PeripheralInc看變數名不是很瞭解,中斷觸發嗎?看解釋
Specifies whether the memory address register is incremented(adj.增加的) or not. 
This parameter can be a value of DMA_memory_incremented_mode
地址增加?理解嚴重錯誤,那麼就是地址遞增的意思吧,那就是可以連續採集多個通道咯?繼續分析
8、DMA_Mode:DMA的模式,他有什麼模式呢?看解釋
Specifies the operation mode of the DMAy Channelx. 
This parameter can be a value of DMA_circular_normal_mode
還有一句:The circular buffer mode cannot be used if the memory-to-memory 
data transfer is configured on the selected Channel 
取值有
#define  DMA_Mode_Circular   ((uint32_t)0x00000020) 
#define  DMA_Mode_Normal   ((uint32_t)0x00000000) 
正常和迴圈模式,難道是輪采?先這樣繼續
9、DMA_Priority優先順序這個就好理解了,不就是控制優先權麼看解釋以及取值
Specifies the software priority for the DMAy Channelx. This parameter can be 
a value of DMA_priority_level 
取值
#define  DMA_Priority_High   ((uint32_t)0x00002000) 
#define  DMA_Priority_Low   ((uint32_t)0x00000000) 
#define  DMA_Priority_Medium   ((uint32_t)0x00001000) 
#define  DMA_Priority_VeryHigh   ((uint32_t)0x00003000 
很明朗4個優先順序
至此,分析完畢,嘗試性猜測
1、DMA_InitStructure.DMA_BufferSize = 1
2、DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST
3、DMA_InitStructure.DMA_M2M = DMA_M2M_Disable 
4、DMA_InitStructure.DMA_MemoryBaseAddr = 一個地址單元的變數單位元組 可以使char型的
5、DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte
6、DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable 不需要地址增量
7、DMA_InitStructure.DMA_Mode = DMA_Mode_Circular 不停的采
8、DMA_InitStructure.DMA_PeripheralBaseAddr = 串口的地址?
9、DMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_Byte
10、DMA_InitStructure.MA_PeripheralInc = DMA_PeripheralInc_Disable 同樣的
11、DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh 給最高的
查看原始碼
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = 1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
貌似有點不妙的感覺
1、MA_InitStructure.DMA_DIR這個明顯是作為資料來源
2、DMA_MemoryDataSize_Byte和DMA_PeripheralDataSize_HalfWord有什麼區別
百度裡面我沒有找到,先這樣,等做完實驗再驗證
八、結構體成員初始化完畢之後,還有很多工作要做
1、  /* ADC1 regular channel11 configuration */ 
  ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_55Cycles5);
  配置規則通道11
2、  /* Enable DMA channel1 */
  DMA_Cmd(DMA1_Channe10, ENABLE);
  使能DMA通道
3、  /* Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);
  使能ADC1的DMA控制器
4、  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);
  使能ADC1
5、  /* Enable ADC1 reset calibaration register */   
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));//複位校準

  /* Start ADC1 calibaration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));//校準
     
  /* Start ADC1 Software Conversion */ 
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);//軟體觸發,這時候真正開始轉換  
  硬體測試後,結果正確的!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.