通过pwm控制ADC转换一直不得要领。

2019-08-14 00:17发布



我想通过PWM控制ADC采128个点,但不知道哪里出了问题。

我在本论坛和网上其他地方找了很多这方面的资料,但还是不得要领。

希望有哪位大神能帮忙看看,如果能用通俗的方法解释一下当然是最好的。

我这个问题解决之后我会把我试验通过的代码贴出来,希望能帮一下后来者

也许他也有这样的困惑。

void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void USART_Configuration(void);
void ADC_Configuration(void);
void DMA_Configuration(void);
void TIM2_Configuration(void);


//u16 ADCData[128];
/**********************************************************
函数名:int fputc(int ch,FILE *f)
功  能:把usart功能改为 printf输出
备  注:  
**********************************************************/
int fputc(int ch,FILE *f)
{
        USART_SendData(USART1,(u8)ch);
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
        return ch;
}




int main(void)
{
//  u32 ad=0;


   RCC_Configuration();        //系统时钟初始化
   GPIO_Configuration();//端口初始化
   USART_Configuration();
   NVIC_Configuration();
   ADC_Configuration();
   DMA_Configuration();
   TIM2_Configuration();
        while(1)
        {


               
         ;;
}         
         }
void RCC_Configuration(void)
{
  SystemInit();//系统时钟72m
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
        RCC_ADCCLKConfig(RCC_PCLK2_Div6);//ADC频率6分频12M  最大14M

}

/**********************************************************
函数名:GPIO_Configuration(void)
功  能:串口;ADC引脚配置
备  注:  
**********************************************************/
void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;       

        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;             //TX  串口
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIO_Init(GPIOA,&GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;            //RX  串口
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA,&GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;             //ADC通道10
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
        GPIO_Init(GPIOC,&GPIO_InitStructure);
       
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;             //ADC通道11
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;
        GPIO_Init(GPIOC,&GPIO_InitStructure);
       
       
}
/**********************************************************
函数名:NVIC_Configuration(void)
功  能:串口中断配置
备  注:  
**********************************************************/
void NVIC_Configuration(void)
{
           NVIC_InitTypeDef NVIC_InitStructure;

           NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

          NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
          NVIC_Init(&NVIC_InitStructure);
       
    NVIC_InitStructure.NVIC_IRQChannel =DMA1_Channel1_IRQn;  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
       
       
}

/**********************************************************
函数名:USART_Configuration(void)
功  能:串口配置
备  注:  
**********************************************************/
void USART_Configuration(void)
{
    USART_InitTypeDef  USART_InitStructure;

        USART_InitStructure.USART_BaudRate=9600;                  //波特率
        USART_InitStructure.USART_WordLength=USART_WordLength_8b; //数据宽度
        USART_InitStructure.USART_StopBits=USART_StopBits_1;      //停止位数目
        USART_InitStructure.USART_Parity=USART_Parity_No;         //奇偶失能
        USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//硬件流控制失能
        USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//接收使能.发送使能

        USART_Init(USART1,&USART_InitStructure);//初始化
        USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//使能 USART 中断
        USART_Cmd(USART1,ENABLE);              //使能串口
        USART_ClearFlag(USART1,USART_FLAG_TC);//清除串口线
}
/**********************************************************
函数名:ADC_Configuration(void)
功  能:ADC配置
备  注:  
**********************************************************/
void ADC_Configuration(void)
{
        ADC_InitTypeDef ADC_InitStructure;

        ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;  //ADC1 和 ADC2 工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode=DISABLE;  //单次(单通道)模式
        ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;  //单次模式
        ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_T2_CC2;  //
                        //ADC_ExternalTrigConvCmd  
        ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;  //ADC 数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel=1;  //ADC 通道的数目

        ADC_RegularChannelConfig(ADC1,ADC_Channel_11,1,ADC_SampleTime_55Cycles5);
       
        ADC_Init(ADC1,&ADC_InitStructure);  //初始化ADC
        ADC_Cmd(ADC1,ENABLE); //使能ADC
       
    ADC_DMACmd(ADC1,ENABLE);//使能DMA
       
        ADC_ResetCalibration(ADC1);  //重置指定的 ADC 的校准寄存器
        while(ADC_GetResetCalibrationStatus(ADC1));

        ADC_StartCalibration(ADC1);  //开始指定 ADC 的校准状态
        while(ADC_GetCalibrationStatus(ADC1));


}

/**********************************************************
函数名: DMA_Configuration(void)
功  能: DMA配置
备  注:  
**********************************************************/
void DMA_Configuration(void)
{
        DMA_InitTypeDef DMA_InitStructure;

        DMA_DeInit(DMA1_Channel1);//将 DMA 的通道 1寄存器重设为缺省值

        DMA_InitStructure.DMA_PeripheralBaseAddr=(u32)&ADC1->DR;//DMA 外设基地址
        DMA_InitStructure.DMA_MemoryBaseAddr=(u32)&ADCData;     // DMA 内存基地址

        DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralSRC;      //外设作为数据传输的来源
        DMA_InitStructure.DMA_BufferSize=128;                  //缓存大小

        DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址寄存器不变
        DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;         //内存地址寄存器递增
       
       
        DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//数据宽度为 16 位
        DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//数据宽度为 16 位

        DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;   //工作在循环模式
        DMA_InitStructure.DMA_Priority=DMA_Priority_High;//DMA 通道1拥有高优先级
       
        DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;       //DMA 通道 x 没有设置为内存到内存传输

        DMA_Init(DMA1_Channel1,&DMA_InitStructure);     //初始化DMA
        DMA_Cmd(DMA1_Channel1,ENABLE);                   //使能DMA
       
        DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);   //使能传输完成中断
       
        DMA_ClearITPendingBit(DMA1_IT_TC1);
}

/**********************************************************
函数名: TIM2_Configuration(void)
功  能: ADC同过定时器产生pwm触发配置配置
备  注:  
**********************************************************/
void TIM2_Configuration(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
        TIM_OCInitTypeDef TIM_OCInitStructure;

        //GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3,ENABLE);

        //
        TIM_TimeBaseStruct.TIM_Period=11250-1;        //初值,900-1
        TIM_TimeBaseStruct.TIM_Prescaler=0;       //分频系数
        TIM_TimeBaseStruct.TIM_ClockDivision=0;   //时钟分割
        TIM_TimeBaseStruct.TIM_CounterMode=TIM_CounterMode_Up;//TIM 向上计数模式

        TIM_TimeBaseInit(TIM2,&TIM_TimeBaseStruct);//初始化
       

        TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//TIM 脉冲宽度调制模式 1
       
        TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//使用 TIM 通道 1
       
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;//TIM 输出比较极性低

        TIM_OC2Init(TIM2,&TIM_OCInitStructure);//初始化

        TIM_OC2PreloadConfig(TIM2,TIM_OCPreload_Enable);//预装载寄存器
       
    TIM_SetCompare2(TIM2,250);

        TIM_Cmd(TIM2,ENABLE);
                 
}



以下为中断服务函数

void USART1_IRQHandler(void)
{
// if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)
//  {
                USART_SendData(USART1,USART_ReceiveData(USART1));
                while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
// }
}

void DMA1_Channel1_IRQHandler(void)

{
        int i=0;
  u32 k=0;
  if(DMA_GetITStatus(DMA1_IT_TC1)!=RESET)
               
                for(i=0;i<128;i++)
{
        k+=ADCData[i];
                                k=k/128;
                                 printf("k =%f ",3.3/4095*k);
            }
         DMA_ClearITPendingBit(DMA1_IT_TC1);
}


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
5条回答
zsl666888
1楼-- · 2019-08-14 04:50
顶!!!
主音调
2楼-- · 2019-08-14 07:03
zsl666888 发表于 2017-9-18 22:23
顶!!!

您有这方面资料没。
正点原子
3楼-- · 2019-08-14 09:53
搞不清你想做什么
主音调
4楼-- · 2019-08-14 14:11
正点原子 发表于 2017-9-19 00:18
搞不清你想做什么

ADC通过pwm触发采集128个点,通过dma传输到数组。
通过DMA传输完成中断,在中断函数里对数组累加求平均。
求得的数通过串口输出。

这个程序我是想以后用来采集交流电做均方根用的。

这个程序DMA的时钟没打开,我打开后也不行。

昨天晚上我又看了一下,感觉还有几个地方有错误。

原子哥,我开始学STM32的时候觉得不 怎么难,但学到后面
发现它很灵活,但由于很灵活所以难度也增加了。上次看你
们有在广州开面授课程,但时间有限所以有心也没办法。
有心的原因是在于以工程为中心的教学。我想说的是您能否
多出一些提高篇的教学视频,对于这款芯片的各个功能相互
配合有一个深入的了解。(比如就ADC得使用我都发现有很多种方法)
因为我不管在哪里找资料感觉都是浅浅点到为止,走了很多弯路。
不知道我说清楚了没有
对于教学视频我是可以付费的。这个不是问题。

正点原子
5楼-- · 2019-08-14 18:05
 精彩回答 2  元偷偷看……

一周热门 更多>