Страница 1 из 1
STM32L-DISCOVERY - проблема с АЦП
Добавлено: Ср ноя 09, 2011 06:01:04
vadim_ova
Добрый день!
В двух словах, проблема такая.
когда зашивается вот этот код:
Код: Выделить всё
int main(void)
{
volatile int i;
int adc_channel_0_value;
/*led*/
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
GPIOB->MODER |= GPIO_MODER_MODER6_0;
/*ADC Prescaler =2 */
ADC->CCR &= 0xFFFCFFFF;
ADC->CCR |= ADC_CCR_ADCPRE_0;
/*add clock*/
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
/*PIN A0 - ADC_IN0*/
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
GPIOA->MODER |= GPIO_MODER_MODER0;
ADC1->SQR5 |= ADC_SQR5_SQ1_0;
ADC1->CR2 = ADC_CR2_EXTSEL_0 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTEN;
/*add power*/
ADC1->CR2 |= ADC_CR2_ADON;
/* Wait until the ADC1 is ready */
while((ADC1->SR & ADC_FLAG_ADONS) == (uint32_t)RESET);
while(1)
{
ADC1->CR2 |= ADC_CR2_SWSTART;
while ((ADC1->SR & ADC_SR_EOC) != ADC_SR_EOC);
adc_channel_0_value = ADC1->DR;
GPIOB->BSRRL = GPIO_BSRR_BS_6;
for( i=0 ;i<100000;i++){};
GPIOB->BSRRH = GPIO_BSRR_BS_6;
for( i=0 ;i<100000;i++){};
}
return 0;
}
Вот, перед началом последнего бесконечного цикла на строке:
Код: Выделить всё
while((ADC1->SR & ADC_FLAG_ADONS) == (uint32_t)RESET);
он виснет. Значит, АЦП никак не выйдет в состояние готовности. Ну что же я сделал не так?!
Спасибо!
Re: STM32L-DISCOVERY - проблема с АЦП
Добавлено: Ср ноя 09, 2011 09:55:11
Satyr
Проверь, меняются ли вобще регистры настройки ADC, что ты выставляешь или нет.
Вобще, сначала надо подкать клок и убрать резет с переферии, а потом уже с ним работать. У тебя наоборот.
Если не поможет - то далее проверять, все ли и правильные регистры поставил.
Re: STM32L-DISCOVERY - проблема с АЦП
Добавлено: Ср ноя 09, 2011 13:19:09
vadim_ova
так-с.
Как я понял, надо сначала резет поставить и сбросить, а потом включить тактирование АЦП? это приведено в коде ниже.
Далее, я завел переменную и с ее помощью по очереди проверил все регистры.
Сначала нашелся косяк в SR, там стояла неготовность регулярных каналов, я это исправил, сейчас там стабильно все нули.
Вот окончательный код:
Код: Выделить всё
int main(void)
{
/* Configure SysTick IRQ and SysTick Timer to generate interrupts every 500µs */
volatile int i;
int adc_channel_0_value;
/*
RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
GPIOB->MODER |= GPIO_MODER_MODER6_0;
*/
test = RCC->APB2RSTR;
RCC->APB2RSTR|= RCC_APB2RSTR_ADC1RST;
test = RCC->APB2RSTR;
RCC->APB2RSTR&= !(RCC_APB2RSTR_ADC1RST);
test = RCC->APB2RSTR;
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
test = RCC->APB2ENR;
/*ADC Prescaler =2 */
ADC->CCR &= 0xFFFCFFFF;
ADC->CCR |= ADC_CCR_ADCPRE_0;
test = ADC->CCR;
/*A0 - ADC*/
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
GPIOA->MODER |= GPIO_MODER_MODER0;
/*when ADONS == 1*/
// ADC1->CR2 = ADC_CR2_EXTSEL_0 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTEN;
/*Regular chamnel*/
ADC1->SMPR3 |= ADC_SMPR3_SMP0;
// ADC1->SQR5 |= ADC_SQR5_SQ1_0;
ADC1->CR2 |= ADC_CR2_ADON;
test = ADC1->CR2;
test = ADC1->CR2;
// RCC->APB2RSTR|= RCC_APB2RSTR_ADC1RST;
// RCC->APB2RSTR&= !(RCC_APB2RSTR_ADC1RST);
test = ADC1->CR2;
ADC1->CR1 &= !(ADC_CR1_PDD);
ADC1->CR1 &= !(ADC_CR1_PDI);
test = ADC1->CR2;
test = ADC1->SR;
/* Wait until the ADC1 is ready */
while((ADC1->SR & ADC_FLAG_ADONS) == (uint32_t)RESET)
{
test = ADC1->SR;
}
while(1)
{
ADC1->CR2 |= ADC_CR2_SWSTART;
while ((ADC1->SR & ADC_SR_EOC) != ADC_SR_EOC);
adc_channel_0_value = ADC1->DR;
GPIOB->BSRRL = GPIO_BSRR_BS_6;
for( i=0 ;i<100000;i++){};
GPIOB->BSRRH = GPIO_BSRR_BS_6;
for( i=0 ;i<100000;i++){};
}
return 0;
}
Но при этом в SR - все нули и ADONS все равно не ставится.... Проверял все регистры - все путем. Может быть еще что-то? не так поставил? или порядок не тот? или что упустил?
Re: STM32L-DISCOVERY - проблема с АЦП
Добавлено: Ср ноя 09, 2011 15:09:12
Satyr
Это глянь.
http://radiokot.ru/forum/download/file.php?id=81574
использую cmsis и periph. lib под STM32, что идет с IARом. там, впринципе, функции крошечные, только из структур в регистры ставят, быстро скомпонуешь.
Это по крайней мере работает, включая каллибрацию
Re: STM32L-DISCOVERY - проблема с АЦП
Добавлено: Ср ноя 09, 2011 17:18:58
GRAF
vadim_ova, сначала включается тактирование нужного модуля, потом делаются настройки, иначе все регистры будут сброшены. Это ко всей перефирии относится.
Re: STM32L-DISCOVERY - проблема с АЦП
Добавлено: Ср ноя 09, 2011 19:15:35
vadim_ova
Satyr писал(а):Это глянь.
http://radiokot.ru/forum/download/file.php?id=81574
использую cmsis и periph. lib под STM32, что идет с IARом. там, впринципе, функции крошечные, только из структур в регистры ставят, быстро скомпонуешь.
Это по крайней мере работает, включая каллибрацию
на моем проце нет регистра, касающегося калибровки вообще))))
ну это не важно, остальное очень схоже.
Но выставляется бит RCNR - то есть, не готовы каналы. как я понял:
RCNR: Regular channel not ready
This bit is set and cleared by hardware after one of the SQRx register is written or after the
OVR bit is cleared. It indicates if a new regular conversion can be launched (by setting the
SWSTART bit).
0: Regular channel ready
1: Regular channel not ready, SWSTART must not be set
что менять-то нужно?
у меня же нулевой канал и преобразование всего одно в очереди - значит, SQR0 должен нулям равняться - что и показывает отладка.
Как тогда быть?
может быть, он требует настройки свойств таких как режим преобразования (непрерывный и т.д.) и тому подобных? этого я не успел сделать еще.
Re: STM32L-DISCOVERY - проблема с АЦП
Добавлено: Ср ноя 09, 2011 19:17:59
vadim_ova
GRAF писал(а):vadim_ova, сначала включается тактирование нужного модуля, потом делаются настройки, иначе все регистры будут сброшены. Это ко всей перефирии относится.
спасибо! звучит очень логично, так и поступил. тоже, правда, не помогло.
Re: STM32L-DISCOVERY - проблема с АЦП
Добавлено: Пн июн 04, 2012 12:24:15
Delfer
Сейчас с тем же бьюсь(
Код: Выделить всё
//ADC & SYSCFG
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_SYSCFG, ENABLE);
/* Enable the GPIOs Clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
//ADC PA5
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//ADC com conf
ADC_CommonInitTypeDef ADC_CommonStr;
ADC_CommonStructInit (&ADC_CommonStr);
ADC_CommonStr.ADC_Prescaler = ADC_Prescaler_Div1;
ADC_CommonInit (&ADC_CommonStr);
// define ADC config
ADC_InitTypeDef ADC_InitStructure;
ADC_StructInit(&ADC_InitStructure);
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // we work in continuous sampling mode
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_Init ( ADC1, &ADC_InitStructure); //set config of ADC1
ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_384Cycles); // define regular conversion config
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Wait until the ADC1 is ready */
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == SET);
ADC_ContinuousModeCmd(ADC1, ENABLE);
// start conversion
//ADC_Cmd (ADC1,ENABLE); //enable ADC1
ADC_SoftwareStartConv(ADC1); // start conversion (will be endless as we are in continuous mode)
...
int bf;
bf = ADC_GetConversionValue(ADC1);
Получается всегда 0, так же висит бит RCNR.
Re: STM32L-DISCOVERY - проблема с АЦП
Добавлено: Пн июн 04, 2012 14:07:57
Shapa
ADC_InitStructure.ADC_NbrOfConversion = 1;
Посмотрите хидер, где описана структура ADC_InitTypeDef, данного поля, лично я не нахожу.
Если это не поможет, вот вам живой пример инициализации ( STM32F100C8R6)
Код: Выделить всё
void adcInit(){
ADC_InitTypeDef ADCInitStructure;
ADCChannelInit();
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
ADCInitStructure.ADC_Mode = ADC_Mode_Independent;
ADCInitStructure.ADC_ScanConvMode = ENABLE;
ADCInitStructure.ADC_ContinuousConvMode = ENABLE;
ADCInitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADCInitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADCInitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADCInitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_55Cycles5);
ADC_Cmd(ADC1, 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);
}
Только переконфигурируйте под свой канал
Re: STM32L-DISCOVERY - проблема с АЦП
Добавлено: Пн июн 04, 2012 15:33:35
Delfer
Нашел ответ.
Не был выбран источник тактового, и, как следствие, тактирование шло от MSI. АЦП по какой то причине не хотел с этим мириться. Я не знаю по какой причине. Ничего в REFERENCE MANUAL и в ERRATA не нашел(
По диаграмме тактирования такты должны доходить.
Добавление строчек помогло.
Код: Выделить всё
/* Enable HSI Clock */
RCC_HSICmd(ENABLE);
/*!< Wait till HSI is ready */
while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET)
{}
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
И в ожидании готовности у меня ошибка была
Код: Выделить всё
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Wait until ADC1 ON status */
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);
Re: STM32L-DISCOVERY - проблема с АЦП
Добавлено: Пн июн 04, 2012 17:01:46
vadim_ova
Delfer писал(а):Нашел ответ.
Не был выбран источник тактового, и, как следствие, тактирование шло от MSI. АЦП по какой то причине не хотел с этим мириться. Я не знаю по какой причине. Ничего в REFERENCE MANUAL и в ERRATA не нашел(
По диаграмме тактирования такты должны доходить.
Добавление строчек помогло.
Код: Выделить всё
/* Enable HSI Clock */
RCC_HSICmd(ENABLE);
/*!< Wait till HSI is ready */
while (RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET)
{}
RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);
И в ожидании готовности у меня ошибка была
Код: Выделить всё
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Wait until ADC1 ON status */
while (ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET);
оо, отлично!
Все-таки в тактировании дело)