1. 程式人生 > 實用技巧 >16-STM32 ADC外部觸發

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 }