2013-11-21 07:23 AM
Hello,
I have a problem with the RCC_ADCCLKConfig, I want to change the ADC frequency and I followed the example from st. /* Configure the ADC clock */ RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div64); /* Enable ADC1 clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ADC12, ENABLE); /* ADC Channel configuration */ /* GPIOC Periph clock enable */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); /* Configure ADC Channel7 as analog input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_StructInit(&ADC_InitStructure); .... after I check the ADC frequency these commands RCC_ClocksTypeDef ClockHw; RCC_GetClocksFreq(&ClockHw); the frequency hasn't modified, 48MHz, so I check step by step and I found a strange part. in Rcc.h #define RCC_ADC12PLLCLK_Div64 ((uint32_t)0x00000190) in Rcc.c , void RCC_ADCCLKConfig(uint32_t RCC_PLLCLK) when I call this function I check the writter, and it's ok , RCC->CFGR2 |= RCC_PLLCLK; = 400 When I check the frequency with this function RCC_GetClocksFreq() /* Get ADC12CLK prescaler */ tmp = RCC->CFGR2 & RCC_CFGR2_ADCPRE12;//here cfgr2 = 0x190 and ADCPRE12 = 0x1F0 , so the result is 0x190 (dec 400)
tmp = tmp >> 4;// 400/16 => 25
presc = ADCPrescTable[tmp];//here ADCPrescTable is a table with 13 cases, and I try to read the 25 case!!!! //ADCPrescTable[13] = {0, 1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256};
if ((presc & 0x10) != 0)// so the test is false I go in the else part
{ /* ADC12CLK clock frequency is derived from PLL clock */ RCC_Clocks->ADC12CLK_Frequency = pllclk / presc; } else { /* ADC12CLK clock frequency is AHB clock */ RCC_Clocks->ADC12CLK_Frequency = RCC_Clocks->SYSCLK_Frequency;//same frequency as before 48MHz
} My first opinion , I think the mask is wrong RCC_CFGR2_ADCPRE12 the value is 0x1F0 I think with 0xF0 it's best but not perfect... so I could have an information about that, maybe I don't use correctly the ADC/RCC function thanks a lot2013-11-21 10:37 AM
The code definitely appears to be broken, though not perfect I think they were aiming for something like this.
tmp = tmp >> 4;
presc = ADCPrescTable[tmp & 0x0F];
if (((tmp & 0x10) != 0) && (presc != 0))
{
/* ADC12CLK clock frequency is derived from PLL clock */
RCC_Clocks->ADC12CLK_Frequency = pllclk / presc;
}
else
{
/* ADC12CLK clock frequency is AHB clock */
RCC_Clocks->ADC12CLK_Frequency = RCC_Clocks->SYSCLK_Frequency; //same frequency as before 48MHz
}
#define RCC_CFGR2_ADCPRE12_NO ((uint32_t)0x00000000) /*!< ADC12 clock disabled, ADC12 can use AHB clock */
#define RCC_CFGR2_ADCPRE12_DIV1 ((uint32_t)0x00000100) /*!< ADC12 PLL clock divided by 1 */
#define RCC_CFGR2_ADCPRE12_DIV2 ((uint32_t)0x00000110) /*!< ADC12 PLL clock divided by 2 */
#define RCC_CFGR2_ADCPRE12_DIV4 ((uint32_t)0x00000120) /*!< ADC12 PLL clock divided by 4 */
#define RCC_CFGR2_ADCPRE12_DIV6 ((uint32_t)0x00000130) /*!< ADC12 PLL clock divided by 6 */
#define RCC_CFGR2_ADCPRE12_DIV8 ((uint32_t)0x00000140) /*!< ADC12 PLL clock divided by 8 */
#define RCC_CFGR2_ADCPRE12_DIV10 ((uint32_t)0x00000150) /*!< ADC12 PLL clock divided by 10 */
#define RCC_CFGR2_ADCPRE12_DIV12 ((uint32_t)0x00000160) /*!< ADC12 PLL clock divided by 12 */
#define RCC_CFGR2_ADCPRE12_DIV16 ((uint32_t)0x00000170) /*!< ADC12 PLL clock divided by 16 */
#define RCC_CFGR2_ADCPRE12_DIV32 ((uint32_t)0x00000180) /*!< ADC12 PLL clock divided by 32 */
#define RCC_CFGR2_ADCPRE12_DIV64 ((uint32_t)0x00000190) /*!< ADC12 PLL clock divided by 64 */
#define RCC_CFGR2_ADCPRE12_DIV128 ((uint32_t)0x000001A0) /*!< ADC12 PLL clock divided by 128 */
#define RCC_CFGR2_ADCPRE12_DIV256 ((uint32_t)0x000001B0) /*!< ADC12 PLL clock divided by 256 */
2013-11-21 12:13 PM
thanks for your answer.
yes you solve the mistake, but what do I do? because I need to control my code and I must check each part, so I must modifie the st library?2013-11-21 01:14 PM
yes you solve the mistake, but what do I do? because I need to control my code and I must check each part, so I must modify the st library?
That's your call, I've pushed this thread to the moderators. I don't work for ST, just confirming it looks buggy, and that you described the flaw well enough for it to be identified. I'd keep the whole library within the source management system, and fix the bugs locally, and note the same within my app's description/notes.
2013-11-21 11:26 PM
thanks for your suggestion.
but the modification isn't perfect because if I want to prescale by 64 , with your suggestion ADCPrescTable[tmp & 0x0F]; //0x19 & 0x0F ==> 0x09 ==> static __I uint16_t ADCPrescTable[13] = {0, 1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256}; the result is 32 so I think we need to add 1 when we mask the tmp and it's ok2013-11-22 07:22 AM
Ok, so a more considered table
static const uint8_t ADCPrescTable[16] = { 1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256, 0, 0, 0, 0 }; And fixing the 12 and 34 code paths