2015-07-20 28 views
-1

我现在使用的是STM32F100RB,我想从电位器读取一个值并通过PWM信号显示。我所遇到的问题是我认为它们之间的联系。 PWM信号被通过该代码来生成:ADC通过PWM信号问题

GPIO_InitTypeDef GPIO_InitStructure; 
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
TIM_OCInitTypeDef TIM_OCInitStructure; 
uint32_t Prescaler, Period; 

/* Enable GPIO clock */ 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 

/* Enable TIM clock */ 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); 

/* Configure TIM1_CH1 as alternate function push-pull */ 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; // No point in overdriving 
GPIO_Init(GPIOA, &GPIO_InitStructure); 

/* Both these must ultimately fit in 16-bit, ie 1..65536 */ 

Prescaler = (SystemCoreClock/20000); // System -> 20 KHz 
Period = 2000; // 20 KHz -> 1 Hz 

/* Extra caution required with TIM1/TIM8 full function timers, to initialize ALL fields */ 

/* Time base configuration */ 
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(Prescaler - 1); 
TIM_TimeBaseStructure.TIM_Period = (uint16_t)(Period - 1); 
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // Where do those stairs go? They go up! 
TIM_TimeBaseStructure.TIM_ClockDivision = 0; // Not used 
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // Not used 

TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); 

/* PWM1 Mode configuration: Channel1 */ 
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
TIM_OCInitStructure.TIM_Pulse = (uint16_t)(Period/ADC1ConvertedValue[0]); // 50% 
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; 
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; 
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; 
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; 
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; 

TIM_OC1Init(TIM1, &TIM_OCInitStructure); 

/* TIM1 enable counter */ 
TIM_Cmd(TIM1, ENABLE); 

/* TIM1 Main Output Enable */ 
TIM_CtrlPWMOutputs(TIM1, ENABLE); 

while (1) 
    { 
    } 

PWM输出工作得很好,并显示它应该显示。这个问题伴随着ADC的出现,因为它看起来不应该如此(代码来自制造商网站),而这是完整的代码。

#include "stm32f10x.h" 
//#include "stm32f10x_conf.h" 
#include "stm32f10x_usart.h" 
#include "stm32f10x_rcc.h" 
#include "stm32f10x_gpio.h" 
#include "stm32f10x_tim.h" 
#include "stm32f10x_adc.h" 
#include "stm32f10x_dma.h" 
#include "stm32f10x_flash.h" 
#define ADC1_DR_Address ((uint32_t)0x4001244C) 
#define BufferLenght  4 
ADC_InitTypeDef ADC_InitStructure; 
DMA_InitTypeDef DMA_InitStructure; 
uint16_t ADC1ConvertedValue[BufferLenght]; 
ErrorStatus HSEStartUpStatus; 
void RCC_Configuration(void); 
void GPIO_Configuration(void); 
RCC_Configuration(); 
GPIO_Configuration(); 
/* DMA1 channel1 configuration ---------------------------------------------*/ 
DMA_DeInit(DMA1_Channel1); 
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; 
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC1ConvertedValue; 
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 
DMA_InitStructure.DMA_BufferSize = BufferLenght; 
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; 
DMA_InitStructure.DMA_Priority = DMA_Priority_High; 
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 
DMA_Init(DMA1_Channel1, &DMA_InitStructure); 

/* Enable DMA1 channel1 */ 
DMA_Cmd(DMA1_Channel1, ENABLE); 

/* ADC1 configuration ------------------------------------------------------*/ 
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 
ADC_InitStructure.ADC_ScanConvMode = ENABLE; 
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
ADC_InitStructure.ADC_NbrOfChannel = BufferLenght; 
ADC_Init(ADC1, &ADC_InitStructure); 

/* ADC1 regular channel11, channel14, channel16 and channel17 configurations */ 
ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_41Cycles5); 
ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 2, ADC_SampleTime_239Cycles5); 
ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 3, ADC_SampleTime_239Cycles5); 
ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 4, ADC_SampleTime_1Cycles5); 

/* Enable ADC1 DMA */ 
ADC_DMACmd(ADC1, ENABLE); 

/* Enable ADC1 */ 
ADC_Cmd(ADC1, ENABLE); 

/* Enable TempSensor and Vrefint channels: channel16 and Channel17 */ 
ADC_TempSensorVrefintCmd(ENABLE); 

/* Enable ADC1 reset calibaration register */ 
ADC_ResetCalibration(ADC1); 

/* Check the end of ADC1 reset calibration register */ 
while(ADC_GetResetCalibrationStatus(ADC1)); 

/* Start ADC1 calibaration */ 
ADC_StartCalibration(ADC1); 

/* Check the end of ADC1 calibration */ 
while(ADC_GetCalibrationStatus(ADC1)); 

/* Start ADC1 Software Conversion */ 
ADC_SoftwareStartConvCmd(ADC1, ENABLE); 

/* Test on Channel 1 DMA1_FLAG_TC flag */ 
while(!DMA_GetFlagStatus(DMA1_FLAG_TC1)); 

/* Clear Channel 1 DMA1_FLAG_TC flag */ 
DMA_ClearFlag(DMA1_FLAG_TC1); 


GPIO_InitTypeDef GPIO_InitStructure; 
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
    TIM_OCInitTypeDef TIM_OCInitStructure; 
    uint32_t Prescaler, Period; 
/* Enable GPIO clock */ 
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 

    /* Enable TIM clock */ 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); 

    /* Configure TIM1_CH1 as alternate function push-pull */ 
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; // No point in overdriving 
    GPIO_Init(GPIOA, &GPIO_InitStructure); 

    /* Both these must ultimately fit in 16-bit, ie 1..65536 */ 

    Prescaler = (SystemCoreClock/20000); // System -> 20 KHz 
    Period = 2000; // 20 KHz -> 1 Hz 

    /* Extra caution required with TIM1/TIM8 full function timers, to initialize ALL fields */ 

    /* Time base configuration */ 
    TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(Prescaler - 1); 
    TIM_TimeBaseStructure.TIM_Period = (uint16_t)(Period - 1); 
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // Where do those stairs go? They go up! 
    TIM_TimeBaseStructure.TIM_ClockDivision = 0; // Not used 
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // Not used 

    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); 

    /* PWM1 Mode configuration: Channel1 */ 
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
    TIM_OCInitStructure.TIM_Pulse = (uint16_t)(Period/ADC1ConvertedValue[0]); // 50% 
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; 
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; 
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; 
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; 
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; 

    TIM_OC1Init(TIM1, &TIM_OCInitStructure); 

    /* TIM1 enable counter */ 
    TIM_Cmd(TIM1, ENABLE); 

    /* TIM1 Main Output Enable */ 
    TIM_CtrlPWMOutputs(TIM1, ENABLE); 

while (1) 
{ 
} 
} 

/** 
* @brief Configures the different system clocks. 
* @param None 
* @retval None 
*/ 
void RCC_Configuration(void) 
{ 
    /* RCC system reset(for debug purpose) */ 
RCC_DeInit(); 

/* Enable HSE */ 
RCC_HSEConfig(RCC_HSE_ON); 

/* Wait till HSE is ready */ 
HSEStartUpStatus = RCC_WaitForHSEStartUp(); 

if(HSEStartUpStatus == SUCCESS) 
{ 
    /* Enable Prefetch Buffer */ 
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); 

    /* Flash 2 wait state */ 
    FLASH_SetLatency(FLASH_Latency_2); 

    /* HCLK = SYSCLK */ 
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 

    /* PCLK2 = HCLK */ 
    RCC_PCLK2Config(RCC_HCLK_Div1); 

    /* PCLK1 = HCLK/2 */ 
    RCC_PCLK1Config(RCC_HCLK_Div2); 

    /* ADCCLK = PCLK2/4 */ 
    RCC_ADCCLKConfig(RCC_PCLK2_Div4); 

#ifndef STM32F10X_CL 
    /* PLLCLK = 8MHz * 7 = 56 MHz */ 
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_7); 

#else 
    /* Configure PLLs *********************************************************/ 
    /* PLL2 configuration: PLL2CLK = (HSE/5) * 8 = 40 MHz */ 
    RCC_PREDIV2Config(RCC_PREDIV2_Div5); 
    RCC_PLL2Config(RCC_PLL2Mul_8); 

    /* Enable PLL2 */ 
    RCC_PLL2Cmd(ENABLE); 

    /* Wait till PLL2 is ready */ 
    while (RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET) 
    {} 

    /* PLL configuration: PLLCLK = (PLL2/5) * 7 = 56 MHz */ 
    RCC_PREDIV1Config(RCC_PREDIV1_Source_PLL2, RCC_PREDIV1_Div5); 
    RCC_PLLConfig(RCC_PLLSource_PREDIV1, RCC_PLLMul_7); 
#endif 

    /* Enable PLL */ 
    RCC_PLLCmd(ENABLE); 

    /* Wait till PLL is ready */ 
    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) 
    { 
    } 

    /* Select PLL as system clock source */ 
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 

    /* Wait till PLL is used as system clock source */ 
    while(RCC_GetSYSCLKSource() != 0x08) 
    { 
    } 
} 

    /* Enable DMA1 clock */ 
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 

/* Enable peripheral clocks  --------------------------------------------------*/ 
/* Enable ADC1 and GPIOC clock */ 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); 
} 

/** 
* @brief Configures the different GPIO ports. 
* @param None 
* @retval None 
*/ 
void GPIO_Configuration(void) 
{ 
GPIO_InitTypeDef GPIO_InitStructure; 

/* Configure PC.01 and PC.04 (Channel11 and Channel14) as analog input -----*/ 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 
GPIO_Init(GPIOC, &GPIO_InitStructure); 
} 

我在我应该除以TIM_Pulse被分配值的点相结合的代码那些两个部分: TIM_OCInitStructure.TIM_Pulse =(uint16_t)(周期/ ADC1ConvertedValue [0]);

我是嵌入式编程的新手,我刚开始玩这个主板,我想实现的目标是根据电位器的值设置脉冲长度。 谢谢你, 亚历克斯。

+0

好心的提示:直接编写硬件(编写驱动程序,而不是在程序的每个级别),而不是使用笨拙的ST库废话。无论如何,你最终都会阅读参考手册。这不会使开发变得更容易。 – Olaf

+0

我在尝试读取没有它的电位计值后,使用ST的ADC代码,并失败失败。我阅读了参考手册和数据表,我确信我没有误解任何东西。这仅仅是关于我不知道嵌入式编程的很多内容,我不确定它与软件编程相比如何。这就是为什么我要求你的帮助,因为我很确定这不是一件困难的事情,但对我来说,这看起来是不可能的。 – Alex

+0

不要忘记检查错误。现在的MCU远非完美,某些功能可能无法按预期工作。无论如何:使用调试器的时间(另一个原因是直接访问硬件比较容易:在中间没有ST-crap)。 STM32可以很好地单步执行。 – Olaf

回答

1

修改后的代码看起来是这样的:

#include "stm32f10x_conf.h" 
    #include "stm32f10x_gpio.h" 
    #include "stm32f10x_rcc.h" 
    #include "stm32f10x_adc.h" 
    #include "stm32f10x_tim.h" 

    double x = 0; 
    GPIO_InitTypeDef myGPIO; 
    ADC_InitTypeDef myADC; 

    void adc_config() 
    { 

    //ADC 
    myGPIO.GPIO_Pin = GPIO_Pin_6; //setat pe pin6 
    myGPIO.GPIO_Mode = GPIO_Mode_AIN; //setare ca analog 
    GPIO_Init(GPIOA, &myGPIO); //set to A6 

    RCC_ADCCLKConfig (RCC_PCLK2_Div6); //ceas pentru ADC (max 14MHz, 72/6=12MHz) 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); //ceas ADC 

    //configurare parametrii ADC 
    myADC.ADC_Mode = ADC_Mode_Independent; 
    myADC.ADC_ScanConvMode = DISABLE; 
    myADC.ADC_ContinuousConvMode = ENABLE; 
    myADC.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 
    myADC.ADC_DataAlign = ADC_DataAlign_Right; 
    myADC.ADC_NbrOfChannel = 1; 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_55Cycles5); //PA6 as Input 
    ADC_Init(ADC1, &myADC); 

    //enable 
    ADC_Cmd(ADC1, ENABLE); 


     ADC_ResetCalibration(ADC1); 
    while(ADC_GetResetCalibrationStatus(ADC1)); 
    ADC_StartCalibration(ADC1); 
    while(ADC_GetCalibrationStatus(ADC1)); 


    ADC_Cmd(ADC1, ENABLE); 
} 


    int getPot(void) 
{ 
    return ADC_GetConversionValue(ADC1); 
} 

    //configurare pini I/O 
    void GPIO_config(void) 
{ 

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); 
    //LED-pinC9 
    GPIO_StructInit(&myGPIO); 
    myGPIO.GPIO_Pin = GPIO_Pin_9; 
    myGPIO.GPIO_Mode = GPIO_Mode_Out_PP; 
    myGPIO.GPIO_Speed = GPIO_Speed_2MHz; 
    GPIO_Init(GPIOC, &myGPIO); 


} 

    int main(void) 
    { 
    GPIO_config(); //configurare pini 
     adc_config(); //configurare ADC 
     GPIO_InitTypeDef GPIO_InitStructure; 
      TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 
      TIM_OCInitTypeDef TIM_OCInitStructure; 
      uint32_t Prescaler, Period; 

      /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup 
       file (startup_stm32f10x_xx.s) before to branch to application main. 
       To reconfigure the default setting of SystemInit() function, refer to 
       system_stm32f10x.c file 
      */ 

      /* Enable GPIO clock */ 
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 

      /* Enable TIM clock */ 
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); 

      /* Configure TIM1_CH1 as alternate function push-pull */ 
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; // No point in overdriving 
      GPIO_Init(GPIOA, &GPIO_InitStructure); 

      /* Both these must ultimately fit in 16-bit, ie 1..65536 */ 

      Prescaler = (SystemCoreClock/200000); // System -> 20 KHz 
      Period = 2000; // 20 KHz -> 1 Hz 

      /* Extra caution required with TIM1/TIM8 full function timers, to initialize ALL fields */ 

      /* Time base configuration */ 
      TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)(Prescaler - 1); 
      TIM_TimeBaseStructure.TIM_Period = (uint16_t)(Period - 1); 
      TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // Where do those stairs go? They go up! 
      TIM_TimeBaseStructure.TIM_ClockDivision = 0; // Not used 
      TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; // Not used 

      TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); 
     while(1) 
     { 
      x = getPot()*3.3/4096; //obtinere valoare analog si convertirea in volti, 12bit ADC 
      /* PWM1 Mode configuration: Channel1 */ 
       TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
       TIM_OCInitStructure.TIM_Pulse = (uint16_t)(Period/x); // 50% 
       TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
       TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; 
       TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; 
       TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; 
       TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; 
       TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; 

       TIM_OC1Init(TIM1, &TIM_OCInitStructure); 

       /* TIM1 enable counter */ 
       TIM_Cmd(TIM1, ENABLE); 

       /* TIM1 Main Output Enable */ 
       TIM_CtrlPWMOutputs(TIM1, ENABLE); 

      if(x > 2) 
      { 
      GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_SET);//pornire Led 
      } 
      else { 
      GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_RESET);//oprire Led 
      } 

     } 

    } 

感谢@Olaf。

+0

嗯,我实际上建议摆脱STLib垃圾,直接进入硬件。虽然这可能需要多一点时间才能开始,但稍后可以安全起见,因为您只需要了解硬件(不可避免的用于非平凡的任务),而不需要STLib。 – Olaf

+0

我明白了,再次感谢队友^^。 – Alex