久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    STM32學習:ADC/DMA/USART

     昵稱25698214 2015-06-02

    學習STM32的ADC轉換,在開發板上寫程序調試。

    四個任務:

    1.AD以中斷方式(單次)采集一路

    2.AD以中斷方式連續采集四路

    3.AD以DMA方式采集一路,DMA深度為一級

    4.AD以DMA方式采集四路,每路DMA深度為28級,并濾波,說明濾波原理。

    總結:

    第一個任務:ADC以中斷方式采集一路ADC,通過配置ADC_InitStructure結構體中的ADC_ScanConvMode,它規定模數轉換工作在掃描模式(多通道)還是單次模式(單通道),

    ADC_InitStructure.ADC_ScanConvMode=DISABLE,為單通道單次模式。

    ADC_ContinuousConvMode,定轉換是連續還是單次,ADC_ContinuousConvMode=DISABLE
    為單次,ADC_NbrOfChangnel規定ADC規則轉換的通道數。ADC_NbrOfChannel=1;//開啟1個通道數。

    ADC_RegularChannelConfig(ADC1,ADC_Channel_13, 1,ADC_SampleTime_55Cycles5);設置指定規則組的通道的采樣順序和轉換時間。這里以為只有一路通道,采用的是PC3引腳,對應的通道數是13通道,采樣順序也就是1,。

    ADC_Cmd(ADC1,ENABLE);使能ADC

    ADC_ITConfig(ADC1, ADC_IT_EOC,ENABLE);開啟ADC轉換結束中斷。

    ADC_ResetCalibration(ADC1);//重置校驗寄存器

    while(ADC_GetResetCalibrationStatus(ADC1)); //等待重置校驗成功

    ADC_StartCalibration(ADC1);//開始ADC校驗

    while(ADC_GetCalibrationStatus(ADC1));//等待ADC校驗好

    ADC_SoftwareStartConvCmd(ADC1, ENABLE);//軟件觸發開始轉換

    因為ADC有一個16位的規則組數據寄存器(ADC_DR),采用一路轉換時可以不用通過DMA傳輸。這里就沒有配置DMA。

    void ADC_IRQHandler(void)

    {

    ADCConvertedValue=ADC_GetConversionValue(ADC1);

    ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);

    }

    當一次轉換結束,DAC產生中斷,在中斷函數里,讀取ADC_DR寄存器中的值,一定清除中斷標志位。

    采集出來的數據是16進制數,要經過處理,變成10進制數,具體如下:

    (value*100/4096)*33,value是從寄存器讀出來的十六進制的數據,經過此變換后就變成10進制數,是個整數,我們通過串口顯示的時候要把小樹部分也要顯示出來則有:((value*100/4096)*33)/1000,整數部分。

    ((value*100/4096)*33)%1000/100,((value*100/4096)*33)%100/10),小數部分,

    串口配置,我是通過STM32上的串口1與PC機通訊的,具體配置如下:

    void USART_Configuration(void)

    {

    USART_InitTypeDef USART_InitStructure;

    USART_InitStructure.USART_BaudRate=9600;波特率9600

    USART_InitStructure.USART_WordLength=USART_WordLength_8b;//8位數據位

    USART_InitStructure.USART_StopBits=USART_StopBits_1;1個停止位

    USART_InitStructure.USART_Parity=USART_Parity_No;無奇偶校驗

    USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;

    USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;

    USART_Init(USART1,&USART_InitStructure);初始化串口配置

    USART_Cmd(USART1,ENABLE);使能串口

    }

    int fputc(int ch,FILE *f)

    {

    USART_SendData(USART1, (u8)ch);

    while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)//檢查發送是否完成

    {

    }

    return ch;

    }此函數,是把printf輸出函數定向到USART。

    第一個任務大概就是這個過程,在后面的任務有相同之處,就不重復敘述了。

    第二個任務:ADC以中斷方式連續采集四路。

    首先配置4路模擬輸入,我配置的是PC0、PC1、PC2、PC3四個IO口,輸入方式為模擬輸入,速度采用2M,它們對應的ADC通道分別是10、11、12、13通道。

    在第一個任務說了,ADC規則轉換多路采樣時,ADC的數據寄存器只有一個16位寄存器,所以必須采用DMA來傳輸數據,DMA配置如下:

    DMA_InitStructure.DMA_PeripheralBaseAddr=DR_ADDRESS; //DMA對應的外設基地址

    DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&Buf; //內存存儲基地址,定義的一個數組

    DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC; //DMA轉換模式為SRC模式,由外設搬移到內存

    DMA_InitStructure.DMA_BufferSize=4; // DMA緩存大小,4個(設置DMA在傳輸時緩沖區的長度)

    DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable; //接收一次數據后,設備地址禁止后移(設置DMA的外設遞增模式)

    DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable; //關閉接收一次數據后,目標內存地址后移(設置DMA的內存遞增模式)

    DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//定義外設數據長度

    DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;

    DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;

    //循環模式開啟,Buf寫滿后,自動回到初始地址開始傳輸

    DMA_InitStructure.DMA_Priority=DMA_Priority_High;//優先級高

    DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;

    ADC配置:

    //ADC配置

    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外部開關,關閉狀態

    ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;//對齊方式,右對齊方式

    ADC_InitStructure.ADC_NbrOfChannel=4;//開啟通道數,4個

    ADC_Init(ADC1,&ADC_InitStructure);//初始化ADC

    ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_55Cycles5);

    ADC_RegularChannelConfig(ADC1,ADC_Channel_11,2,ADC_SampleTime_55Cycles5);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_12,3,ADC_SampleTime_55Cycles5);

    ADC_RegularChannelConfig(ADC1,ADC_Channel_13,4,ADC_SampleTime_55Cycles5);;

    //ADC通道組,第10、11、12、13個通道,采樣順序分別是1,2,3,4轉換時間55.5個周期

    ADC_DMACmd(ADC1, ENABLE);//使能ADC1模塊DMA

    ADC_Cmd(ADC1, ENABLE);//打開ADC1

    ADC_ResetCalibration(ADC1);//重置ADC1校準寄存器

    while(ADC_GetResetCalibrationStatus(ADC1));//等待ADC1校準重置完成

    ADC_StartCalibration(ADC1);//開始ADC1校準

    while(ADC_GetCalibrationStatus(ADC1));//等待ADC1校準完成

    ADC_SoftwareStartConvCmd(ADC1,ENABLE);//使能ADC1軟件開始轉換

    中斷是采用DMA中斷,當DMA第一輪傳輸結束時,設一個標志位,當標志位為1時,表明第一輪轉化和傳輸完成,此時就可以讀取數組中的數據,經過處理就可以通過串口顯示出來。

    void DMAChannel1_IRQHandler(void)

    {

    ADC_DMA_OK=1;

    DMA_ClearITPendingBit(DMA1_IT_TC1);

    }中斷函數。

    第二個任務大概就這樣子

    第三個任務:AD以DMA方式采集一路,DMA深度為一級。

    這個任務不難,關鍵要理解到DMA深度,用自己的語言來理解哈DMA深度吧,當ADC以一路采集時,ADC轉換完成就自動把轉換結果通過DMA傳給目的地址,如果傳輸一次結束DMA就產生中斷的話,DMA的深度就為一級,如果連續傳輸N次,DMA的深度就位N級,當然這個N是又范圍的,因為受目的地址的內存大小控制和數據寬度,這個大家應該豆明白的。

    這個任務在第一個任務的基礎上我通過DMA傳輸,意思是AD配置沒什么區別。DMA配置和第二個任務的區別就是DMA_BufferSize的寬度不同。

    #define DR_ADDRESS (u32)0x4001244c ADC的地址

    #define DMA_Count 1 DMA深度,也就是連續傳輸的次數

    #define ADC_Channle 1 ADC通道

    數據處理和串口通訊這里不重復敘述。DMA中斷和任務二的類似。

    第四個任務:AD以DMA方式采集四路,每路DMA深度為128級,并濾波,說明濾波原理。

    這個任務和是個綜合性任務,只要弄懂前面三個任務,難點是再如何濾波,開始的時候我也不知道怎么濾波,同事提醒我才知道怎么濾波的,我大概說哈我的理解,把四路通道采集的數據分別放到四個數組中,然后給他來個排序,降序,升序都行,把首位兩個數丟掉,然后加起來求平均值。但是我這里因為DMA的深度為128級,也就是四個通道分別采樣了128次,大家都知道,數據越多,求平均值就越準確,所以我就沒有采用什么排序法了,直接給他們分別求平均值,具體如下:

    #define DR_ADDRESS (u32)0x4001244c ADC的地址

    #define DMA_Count 128 DMA深度,也就是連續傳輸的次數

    #define ADC_Channle 4 ADC通道

    for(i=0;i<(ADC_Channle*DMA_Count);i+=4)

    {

    Value1[j]=Buf[i+0];

    Sum1+=Value1[j];

    Value2[j]=Buf[i+1];

    Sum2+=Value2[j];

    Value3[j]=Buf[i+2];

    Sum3+=Value3[j];

    Value4[j]=Buf[i+3];

    Sum4+=Value4[j];

    j++;

    }

    Valu1=Sum1/DMA_Count;

    Valu2=Sum2/DMA_Count;

    Valu3=Sum3/DMA_Count;

    Valu4=Sum4/DMA_Count;

    Delay(100000);

    printf("rn當前AD_0值:0x%x,電壓值:%d.%d%dVnr",

    Valu1,((Valu1*100/4096)*33)/1000,((Valu1*100/4096)*33)%1000/100,((Valu1*100/4096)*33)%100/10);

    Delay(100000);

    printf("rn當前AD_1值:0x%x,電壓值:%d.%d%dVnr",

    Valu2,((Valu2*100/4096)*33)/1000,((Valu2*100/4096)*33)%1000/100,((Valu2*100/4096)*33)%100/10);

    Delay(100000);

    printf("rn當前AD_2值:0x%x,電壓值:%d.%d%dVnr",

    Valu3,((Valu3*100/4096)*33)/1000,((Valu3*100/4096)*33)%1000/100,((Valu3*100/4096)*33)%100/10);

    Delay(100000);

    printf("rn當前AD_3值:0x%x,電壓值:%d.%d%dVnr",

    Valu4,((Valu4*100/4096)*33)/1000,((Valu4*100/4096)*33)%1000/100,((Valu4*100/4096)*33)%100/10);

    Delay(100000);

    【轉自:http://www.21ic.com/app/analog/201203/112400.htm】

      本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發現有害或侵權內容,請點擊一鍵舉報。
      轉藏 分享 獻花(0

      0條評論

      發表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 中文字幕在线亚洲日韩6页| 无码国模国产在线观看免费| 亚洲欧美国产日韩天堂区| 人人人澡人人肉久久精品| 尹人香蕉久久99天天拍| 亚洲精品动漫免费二区| 国产永久免费高清在线观看| 国产成人一区二区三区视频免费| 思思久久96热在精品国产| 丁香婷婷色综合激情五月| 丰满少妇被猛烈进入高清播放| 亚洲国产精品一二三区| 人妻少妇精品无码专区动漫| 国产精品久久蜜臀av| 亚洲精品无码你懂的| av中文字幕一区二区| 老色鬼永久精品网站| 亚洲成人av免费一区| 亚洲精品无码久久久久去Q| 成人免费A级毛片无码片2022 | 狠狠色噜噜狠狠狠7777奇米| 午夜DY888国产精品影院| 国产成人久久精品一区二区三区| 人妻中文字幕精品系列| 午夜精品一区二区三区在线观看 | 欧美熟妇乱子伦XX视频| 亚洲AV无码一区二区三区性色| 老司机午夜精品视频资源| 无码人妻精品一区二区三区蜜桃 | 把女人弄爽大黄A大片片| 国产精品成人午夜福利| 国产精品自产拍在线观看| 精品免费看国产一区二区| 久久国产免费观看精品3| 亚洲午夜性猛春交XXXX| 亚洲香蕉网久久综合影视| 中文字幕无码日韩专区免费| 国产美女A做受大片观看| 国产亚洲国产精品二区| 亚洲精品午睡沙发系列| 做暖暖视频在线看片免费|