Darren_pty

导航

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 }

 

posted on 2020-12-06 21:11  Darren_pty  阅读(3012)  评论(0编辑  收藏  举报