Anomalous high ADC rate at stm32f103cb
Hello! I need an advice. My stm32f103cb chip has ADC with 0.39 us per point conversion rate on one channel. But datasheet says its max rate is 1 Msps (1us). I checked sampling rate with external oscillograph (1 Gsps Tektronics) and external signal generator (Tektronics). I sent to ADC square wave with width of 10 us ON and of 10 us OFF (0-3V) and recieve with my delphi programm also square signal with flat level ON and OFF for 26 points of each. Also I was able to view sine wave signal up to 200 kHz (0-3V) with good resolution. The code is below. The basis was USB-CDC loop example from latest stmm32f1xx perif library. On EP3 event my parser starts GetData function where firstly resets DMA to set Memory base address to start of data array and then starts ADC conversion with direct DMA to record adc data to my array [992 elements] (dma mode is normal, not cyclic). After transfer is done - all data sends to usb-com and my delphi programm recieve it and plots a graph.
The code:// Variant with 0.39 us sampling rate - read freq up to 20o kHz
#include ''hw_config.h''
#include ''usb_lib.h''
#include ''usb_desc.h'' //
#include ''usb_pwr.h'' //
#define ADC1_DR_Address ((uint32_t)0x4001244C)
uint32_t packet_sent=1;
uint32_t packet_receive=1;
extern
__IO uint8_t Receive_Buffer[64];
extern
__IO uint32_t Receive_length ;
uint16_t ADC_Buffer[992];
uint8_t TxBuffer[64];
uint32_t i,j,d;
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
void
ADC_settings(
void
);
void
parser(
void
);
// need to declare
void
getFirmware(
void
);
void
GetData(
void
);
void
SendError(
void
);
void
delay(uint32_t delayValue);
void
init_pwm(
void
);
int
main()
{
init_pwm();
Set_System();
Set_USBClock();
USB_Interrupts_Config();
USB_Init();
ADC_settings();
while
(1) { }
}
void
ADC_settings() {
/* ADCCLK = PCLK2/4 */
RCC_ADCCLKConfig(RCC_PCLK2_Div4);
/* Enable DMA1 clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* Enable ADC1 and GPIOC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
/* Configure PA.01 (ADC Channel_1) as analog input -------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* DMA1 channel1 configuration ----------------------------------------------*/
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Buffer[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 992;
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_Normal;
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 = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channel1 configuration */
//- PIN10 Mapple Mini
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_1Cycles5);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);
/* Enable ADC1 reset calibration register */
ADC_ResetCalibration(ADC1);
/* Check the end of ADC1 reset calibration register */
while
(ADC_GetResetCalibrationStatus(ADC1));
/* Start ADC1 calibration */
ADC_StartCalibration(ADC1);
/* Check the end of ADC1 calibration */
while
(ADC_GetCalibrationStatus(ADC1));
}
void
parser() {
// executes at EP3 irq at incoming packet in file usb_endp.c
if
( Receive_Buffer[0] == 0xAA) {
switch
( Receive_Buffer[1] )
{
case
0xCB:
getFirmware();
break
;
case
0x01:
GetData();
break
;
default
:
break
;
}
}
else
{
SendError();
}
packet_receive = 0;
}
void
getFirmware() {
TxBuffer[0] = 0xAA;
TxBuffer[1] = 0xBC;
CDC_Send_DATA ((unsigned
char
*)TxBuffer,2);
}
void
SendError() {
TxBuffer[0] = 0xAA;
TxBuffer[1] = 0xEE;
CDC_Send_DATA ((unsigned
char
*)TxBuffer,2);
}
void
GetData() {
DMA_Cmd(DMA1_Channel1, DISABLE);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_Buffer[0];
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC1->CR2 |= ((uint32_t)0x00500000);
// start ADC
while
(!DMA_GetFlagStatus(DMA1_FLAG_TC1));
ADC1->CR2 &= ((uint32_t)0xFFAFFFFF);
// stop ADC
DMA_ClearFlag(DMA1_FLAG_TC1);
for
(j=0;j<32;j++) {
for
(i=0;i<31;i++) {
TxBuffer[i*2] = (ADC_Buffer[i+31*j] & 0x0000FF00) >> 8;
TxBuffer[i*2+1] = (ADC_Buffer[i+31*j] & 0x000000FF);
}
CDC_Send_DATA ((unsigned
char
*)TxBuffer,62);
// 63 bytes max!
delay(10000);
}
}
void
delay(uint32_t delayValue) {
for
( d = 0 ; d < delayValue ; d++) {};
}
void
init_pwm() {
GPIO_InitTypeDef pwmGPIO;
TIM_TimeBaseInitTypeDef pwm;
TIM_OCInitTypeDef pwmOC;
// enable
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
// init gpio
pwmGPIO.GPIO_Pin = GPIO_Pin_0;
pwmGPIO.GPIO_Mode = GPIO_Mode_AF_PP;
pwmGPIO.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &pwmGPIO);
// init TIM3 ch.3 - PIN3 Mapple Mini
/* Time base configuration */
pwm.TIM_Prescaler = 36 - 1;
pwm.TIM_Period = 19;
// 0 - also 1 tick - now 50 us ON and 50 us OFF
pwm.TIM_ClockDivision = 0;
pwm.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &pwm);
// for 3600-1 and 2000 and 50 = T=1sec Pulse = 25 ms
/* PWM1 Mode configuration: Channel3 */
pwmOC.TIM_OCMode = TIM_OCMode_PWM1;
pwmOC.TIM_OutputState = TIM_OutputState_Enable;
// ON first
pwmOC.TIM_Pulse = 10;
// go to 50 pulses and LED OFF
pwmOC.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC3Init(TIM3, &pwmOC);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void
assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */
/* Infinite loop */
while
(1)
{
}
}
#endif
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
#stm32f103cb #adc #adc #stm32f103cb