16-STM32 ADC外部觸發


STM32 ADC外部觸發

  1 #include "adc.h"
  2 
  3 //用來保存ADC各通道轉換完成后的數據
  4 vu16 ADC_ConvertedValue[4];
  5 
  6 
  7 
  8 //利用定時器TIM4的通道4的輸出比較功能,給ADC1提供采樣觸發信號,這里觸發周期為:100ms
  9 //觸發周期計算公式為:psc/72*period/1000000(單位為秒)
 10 
 11 void TIM_OCTigrConfig(void)
 12 {
 13     TIM_TimeBaseInitTypeDef TIM_timeBaseStucture;
 14     TIM_OCInitTypeDef TIM_ocInitStructure;
 15     
 16     u16 period     = 60000;                                            //設置周期值
 17     u16 pluse     = 30000;                                            //設置CRR值,這里的值可以隨便設置,不影響ADC采樣周期,但要保證在正確的范圍內
 18     
 19     //使能TIM4的時鍾,TIM4是掛在APB1總線上的,注意TIM4的時鍾是72M的
 20     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
 21     
 22     TIM_timeBaseStucture.TIM_Prescaler = 120-1;                        //預分頻,給TIMx_CNT驅動的時鍾
 23     TIM_timeBaseStucture.TIM_ClockDivision = TIM_CKD_DIV1;          //分頻因子,輸出給定時器的ETRP數字濾波器提供時鍾
 24     TIM_timeBaseStucture.TIM_CounterMode = TIM_CounterMode_Up;        //向上計數
 25     TIM_timeBaseStucture.TIM_Period = period;                        //設置周期,給ARR賦值
 26     TIM_TimeBaseInit(TIM4,&TIM_timeBaseStucture);
 27     
 28     //配置TIM4通道4的輸出比較
 29     TIM_ocInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                //PWM輸出模式為PWM1
 30     TIM_ocInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;        //設置有效電平的極性
 31     TIM_ocInitStructure.TIM_OutputState = TIM_OutputState_Enable;    //使能通道輸出
 32     TIM_ocInitStructure.TIM_Pulse = pluse;                            //設置PWM的脈沖寬度值,即CRR值
 33     TIM_OC4Init(TIM4,&TIM_ocInitStructure);
 34     
 35     TIM_ARRPreloadConfig(TIM4,ENABLE);                                //使能TIM4的寄存器ARR的預裝載功能,DISABLE時將會使改變ARR值時立即生效
 36     TIM_OC4PreloadConfig(TIM4,TIM_OCPreload_Enable);                //使能TIM4通道1的CCR的預裝載功能,DISABLE時將會使改變CRR值時立即生效
 37     
 38     //使能TIM4定時器
 39     TIM_Cmd(TIM4,ENABLE);
 40 }
 41 
 42 
 43  
 44 
 45 
 46 //利用TIM4通道4的輸出比較觸發ADC1開始采樣,並且ADC各通道的數據轉換完成后,觸發DMA
 47 //請求,將ADC_DR中的數據存入內存數組中,DMA傳輸完成后,觸發DMA傳輸完成中斷
 48 
 49 //PB0--ADC_Pitch
 50 //PB1--ADC_Roll
 51 //PA1--ADC_THR
 52 //PA2--ADC_Yaw
 53 void ADC_DmaConfig(void)
 54 {
 55     GPIO_InitTypeDef GPIO_initStructure;
 56     DMA_InitTypeDef DMA_initStructure;
 57     ADC_InitTypeDef ADC_initStructure;
 58     NVIC_InitTypeDef NVIC_InitStructure;
 59     
 60     //開啟DMA1時鍾
 61     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
 62     
 63     //配置DMA1通道1,將ADC采樣轉換得到的數據傳輸到內存數組中(協助CPU)
 64     DMA_initStructure.DMA_BufferSize = 4;                                        //每次傳輸的數據的個數,傳輸完時觸發中斷
 65     DMA_initStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                            //傳輸方向為:外設->內存
 66     DMA_initStructure.DMA_M2M = DMA_M2M_Disable;                                //失能內存到內存的傳輸方式
 67     DMA_initStructure.DMA_MemoryBaseAddr = (u32)ADC_ConvertedValue;                //數據保存到內存中數組的首地址(這里因為ADC_ConvertedValue是數組名,所以不用加&)
 68     DMA_initStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;            //以16位為單位進行數據的傳輸
 69     DMA_initStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                        //內存地址自增(這里地址是每次增加1,因為是以半字(16位)作為單位傳輸的)
 70     DMA_initStructure.DMA_Mode = DMA_Mode_Circular;                                //循環傳輸的方式,這里必須為循環傳輸方式,否則會導致DMA只能傳輸一次
 71     DMA_initStructure.DMA_PeripheralBaseAddr = ((u32)&ADC1->DR);                //&ADC1->DR
 72     DMA_initStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;    //以半字為單位進行數據的傳輸
 73     DMA_initStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;            //外設地址固定
 74     DMA_initStructure.DMA_Priority = DMA_Priority_Medium;                        //DMA通道1的優先級設置為中級,(這個優先級是當同一個DMA的不同通道同時有傳輸數據的要求時,優先級高的先進行傳輸)
 75     DMA_Init(DMA1_Channel1,&DMA_initStructure);
 76     
 77     DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE);                                //打開DMA通道1數據傳輸完成中斷
 78     NVIC_EnableIRQ(DMA1_Channel1_IRQn);                                            //打開NVIC中對應的DMA通道1的中斷通道
 79     
 80     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
 81     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 82     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 83     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
 84     NVIC_Init(&NVIC_InitStructure);
 85     
 86     //開啟DMA1的通道1
 87     DMA_Cmd(DMA1_Channel1,ENABLE);
 88     
 89     
 90     //使能ADC時鍾
 91     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_ADC1,ENABLE);
 92     
 93     GPIO_initStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;    //ADC1的通道1,2
 94     GPIO_initStructure.GPIO_Mode = GPIO_Mode_AIN;                    //ADC輸入管腳需要為模擬輸入模式
 95     GPIO_Init(GPIOA,&GPIO_initStructure);
 96     
 97     GPIO_initStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;    //ADC1的通道8,9
 98     GPIO_initStructure.GPIO_Mode = GPIO_Mode_AIN;                    //ADC輸入管腳需要為模擬輸入模式
 99     GPIO_Init(GPIOB,&GPIO_initStructure);
100     
101     //配置ADC1
102     ADC_initStructure.ADC_ContinuousConvMode = DISABLE;                            //單次采樣模式,每次由TIM4的CCR觸發采樣開始
103     ADC_initStructure.ADC_DataAlign = ADC_DataAlign_Right;                        //數據對齊模式為:右對齊
104     ADC_initStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T4_CC4;        //TIM4的通道4的CCR觸發采樣
105     ADC_initStructure.ADC_Mode = ADC_Mode_Independent;                            //各通道獨立
106     ADC_initStructure.ADC_NbrOfChannel = 4;                                        //一共要采樣的通道的數目
107     ADC_initStructure.ADC_ScanConvMode = ENABLE;                                //打開掃描模式,由於這里有四個通道要采集,所以開始用掃描模式
108     ADC_Init(ADC1,&ADC_initStructure);
109     
110     //開啟ADC
111     ADC_Cmd(ADC1,ENABLE);
112     
113     //開啟ADC——DMA數據傳輸通道
114     ADC_DMACmd(ADC1,ENABLE);
115     
116     //配置ADC采樣參考時鍾的預分頻值
117     RCC_ADCCLKConfig(RCC_PCLK2_Div8);                                            
118     
119     //配置ADC的規則通道的采樣順序和采樣時間
120     ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_71Cycles5);    
121     ADC_RegularChannelConfig(ADC1,ADC_Channel_2,2,ADC_SampleTime_71Cycles5);
122     ADC_RegularChannelConfig(ADC1,ADC_Channel_8,3,ADC_SampleTime_71Cycles5);
123     ADC_RegularChannelConfig(ADC1,ADC_Channel_9,4,ADC_SampleTime_71Cycles5);
124     
125     ADC_ResetCalibration(ADC1);                                                    //重置ADC采樣校准器,防止出現較大的誤差
126     while(ADC_GetCalibrationStatus(ADC1));                                        //等待校准成功
127     ADC_StartCalibration(ADC1);                                                    //開啟ADC采樣狀態
128     while(ADC_GetCalibrationStatus(ADC1));                                        //等到開啟成功
129     
130     //使能外部觸發ADC采樣
131     ADC_ExternalTrigConvCmd(ADC1,ENABLE);
132 }
133 
134 
135 //DMA1通道1中斷通道處理函數,觸發此中斷時,說明已經將數據從ADC轉移到內存數組中,可以觸發數據發送了
136 void DMA1_Channel1_IRQHandler(void){
137     if(DMA_GetITStatus(DMA1_IT_TC1)==SET){
138         
139         //printf("%d    %d    %d    %d\n",ADC_ConvertedValue[0],ADC_ConvertedValue[1],ADC_ConvertedValue[2],ADC_ConvertedValue[3]);
140         DMA_ClearITPendingBit(DMA1_IT_TC1);                        //清除DMA1通道1傳輸完成中斷
141     }
142 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM