2015-07-20 61 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