На практике оказалось иначе. Стартую преобразование, оно происходит один раз, причём вижу, что результат сохранился в регистре, а в PDC значение N(количество преобразований), стало равно N-1.
Далее отпускаю программу поработать какое-то время, затем останавливаю и вижу что в регистрах картина не изменилась. Тот же самый результат преобразования, теже значения в регистрах PDC.
Проверял в связке sam7x-ek + arm-elf-gdb + sam-ice + eclipse.
Собственно вопросы:
1. Может ли вообще АЦП работать таким образом? И если может, то почему у меня не работает?
2. А если не может, то на кой ляд они прикрутили к АЦП контроллер доступа к памяти, в чём его глубокий смысл?
вот код работы с АЦП
Код
void adcHandler(void)
{
if (AT91C_BASE_ADC->ADC_SR & AT91C_ADC_RXBUFF)
{
// Disable data ready Interrupt
AT91C_BASE_ADC->ADC_IDR = AT91C_ADC_RXBUFF;
// disables all channels
AT91C_BASE_ADC->ADC_CHDR = ALL_CHANNEL_DISABLE;
AdcInterrupt();
}
}
/******************************************************************************
Inits the ADC.
******************************************************************************/
void OpenAdc(AdcParams_t *param)
{
//enable the clock of ADC
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_ADC;
// initialization adc
// reset adc
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
/* disable receiver PDC transfer requests */
AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
// Starting a conversion is only possible by software. 8-bit resolution mode.
AT91C_BASE_ADC->ADC_MR = (uint32_t)sampleRate | AT91C_ADC_LOWRES;
/* set pdc pointer and counter */
AT91C_BASE_ADC->ADC_RCR = selectionsAmount;
AT91C_BASE_ADC->ADC_RPR = bufferPointer;
// disables all channels
AT91C_BASE_ADC->ADC_CHDR = ALL_CHANNEL_DISABLE;
// disable all adc interrupt
AT91C_BASE_ADC->ADC_IDR = ALL_PERIPHERIAL_INTERRUPT_DISABLE;
if (AT91C_BASE_AIC->AIC_SVR[AT91C_ID_ADC] != (uint32_t)adcHandler)
{ /*first start*/
/* Enable interrupts */
/* Disable the interrupt on the interrupt controller */
AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_ADC);
/* Save the interrupt handler routine pointer and the interrupt priority */
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_ADC] = (uint32_t)adcHandler;
/* Store the Source Mode Register */
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_ADC] = AT91C_AIC_SRCTYPE_HIGH_LEVEL |
AT91C_AIC_PRIOR_LOWEST;
/* Clear the interrupt on the interrupt controller */
AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_ADC);
/* Enable the interrupt on the interrupt controller */
AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_ADC);
}
}
/******************************************************************************
Starts convertion on the ADC channel.
Parameters:
channel - channel number.
******************************************************************************/
void StartAdc(AdcChannelNumber_t channel)
{
// enable current channel
AT91C_BASE_ADC->ADC_CHER = channel;
// enable receiver PDC transfer requests
AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
// enable receiver buffer full interrupt
AT91C_BASE_ADC->ADC_IER = AT91C_ADC_RXBUFF;
// Starts conversion
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
}
{
if (AT91C_BASE_ADC->ADC_SR & AT91C_ADC_RXBUFF)
{
// Disable data ready Interrupt
AT91C_BASE_ADC->ADC_IDR = AT91C_ADC_RXBUFF;
// disables all channels
AT91C_BASE_ADC->ADC_CHDR = ALL_CHANNEL_DISABLE;
AdcInterrupt();
}
}
/******************************************************************************
Inits the ADC.
******************************************************************************/
void OpenAdc(AdcParams_t *param)
{
//enable the clock of ADC
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_ADC;
// initialization adc
// reset adc
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
/* disable receiver PDC transfer requests */
AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
// Starting a conversion is only possible by software. 8-bit resolution mode.
AT91C_BASE_ADC->ADC_MR = (uint32_t)sampleRate | AT91C_ADC_LOWRES;
/* set pdc pointer and counter */
AT91C_BASE_ADC->ADC_RCR = selectionsAmount;
AT91C_BASE_ADC->ADC_RPR = bufferPointer;
// disables all channels
AT91C_BASE_ADC->ADC_CHDR = ALL_CHANNEL_DISABLE;
// disable all adc interrupt
AT91C_BASE_ADC->ADC_IDR = ALL_PERIPHERIAL_INTERRUPT_DISABLE;
if (AT91C_BASE_AIC->AIC_SVR[AT91C_ID_ADC] != (uint32_t)adcHandler)
{ /*first start*/
/* Enable interrupts */
/* Disable the interrupt on the interrupt controller */
AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_ADC);
/* Save the interrupt handler routine pointer and the interrupt priority */
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_ADC] = (uint32_t)adcHandler;
/* Store the Source Mode Register */
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_ADC] = AT91C_AIC_SRCTYPE_HIGH_LEVEL |
AT91C_AIC_PRIOR_LOWEST;
/* Clear the interrupt on the interrupt controller */
AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_ADC);
/* Enable the interrupt on the interrupt controller */
AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_ADC);
}
}
/******************************************************************************
Starts convertion on the ADC channel.
Parameters:
channel - channel number.
******************************************************************************/
void StartAdc(AdcChannelNumber_t channel)
{
// enable current channel
AT91C_BASE_ADC->ADC_CHER = channel;
// enable receiver PDC transfer requests
AT91C_BASE_ADC->ADC_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
// enable receiver buffer full interrupt
AT91C_BASE_ADC->ADC_IER = AT91C_ADC_RXBUFF;
// Starts conversion
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
}