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 阅读(3275) 评论(0) 编辑 收藏 举报