Hedhehog Опубликовано 22 июня, 2015 Поделиться Опубликовано 22 июня, 2015 (изменено) Доброго всем времени суток! Ковыряя свое устройство наткнулся на некоторую интересную особенность контроллера, связанную то ли с моей реализацией, то ли с контроллером. Есть задача: сделать устройство, принимающее данные с АЦП и передающее его на карту с помощью SPI (почему не SDIO не спрашивайте-не моя прихоть) с достаточно большой частотой. Есть реализация: сделано АЦП, циклический буфер для АЦП объемом 8192 элемента, сделано взаимодействие с картой. Есть проблема: буфер сделан по прерыванию таймера (около микросекунды-несколько меньше). Частота контроллера-максимальная. Так вот, стоит начинать уменьшать делитель таймера-программа беспомощно зависает в прерывании (тупо не выходит из него). Делитель АЦП равен 2. Если оставлять все как есть-запись со скоростью всего лишь 140 -150 секторов в секунду (маловато будет-хорошо бы 300 и более). Привожу код: Инициализация АЦП void init_ADC() { RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); GPIO_InitTypeDef gpio; gpio.GPIO_Mode=GPIO_Mode_AN; gpio.GPIO_OType=GPIO_OType_PP; gpio.GPIO_Pin=GPIO_Pin_0; gpio.GPIO_PuPd=GPIO_PuPd_NOPULL; gpio.GPIO_Speed=GPIO_Speed_50MHz; GPIO_Init(GPIOA,&gpio); ADC_InitTypeDef adc; adc.ADC_Resolution = ADC_Resolution_12b; adc.ADC_ScanConvMode = DISABLE; adc.ADC_ContinuousConvMode = ENABLE; adc.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; adc.ADC_DataAlign = ADC_DataAlign_Right; adc.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &adc); ADC_CommonInitTypeDef adc_common; adc_common.ADC_Mode = ADC_Mode_Independent; adc_common.ADC_Prescaler = ADC_Prescaler_Div2; adc_common.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; adc_common.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&adc_common); ADC_RegularChannelConfig(ADC1, ADC_Channel_Vbat, 1, ADC_SampleTime_3Cycles); ADC_Cmd(ADC1, ENABLE); ADC_VBATCmd(ENABLE); ADC_SoftwareStartConv(ADC1); } Инициализация таймера: [/size][/font][/color] [color=#000000][font=Lucida Grande', ', ', 'Trebuchet MS', ', Helvetica, Arial, sans-serif][size=3]void init_Timer() { RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); TIM_TimeBaseInitTypeDef tim; tim.TIM_Prescaler=6;//26 и более работает, 14-уже нет, 15 нестабильно. tim.TIM_CounterMode=TIM_CounterMode_Up; tim.TIM_Period = 1; tim.TIM_ClockDivision = 0; tim.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM1, &tim); TIM_UpdateRequestConfig (TIM1, TIM_UpdateSource_Global); TIM_UpdateDisableConfig (TIM1,DISABLE); TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); TIM_Cmd(TIM1, DISABLE); NVIC_InitTypeDef NVIC_InitStructure NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } Кольцевой буфер: void TIM1_UP_TIM10_IRQHandler(void) { if(ADC_Free_Index + 1 == ADC_Busy_Index) { TIM_ClearITPendingBit(TIM1, TIM_IT_Update); return; } GPIO_SetBits(GPIOB,GPIO_Pin_14); ADC_Buffer[ADC_Free_Index++] = ADC_GetConversionValue(ADC1); if(ADC_Free_Index==8192) if(ADC_Busy_Index!=0) ADC_Free_Index=0; else ADC_Free_Index--; TIM_ClearITPendingBit(TIM1, TIM_IT_Update); }[/size][/font][/color] [color=#000000][font=Lucida Grande', 'Trebuchet MS', Helvetica, Arial, sans-serif][size=3]int16_t Get_Byte()// функция забора байт, есть еще функция упаковки, однако в случае зависания туда программа не добирается. { if(ADC_Busy_Index==ADC_Free_Index) return -1;[/size][/font][/color] uint16_t saveInd = ADC_Busy_Index; if(++ADC_Busy_Index == 8192) ADC_Busy_Index=0; return (int16_t)ADC_Buffer[saveInd]; } Main [/size][/font][/color] [color=#000000][font=Lucida Grande', 'Trebuchet MS', Helvetica, Arial, sans-serif][size=3]void main() { for(uint16_t i = 0; i < 8192; i++) ADC_Buffer[i] = 0; __enable_irq(); maxADR.MaxAdr=0; adr.Nseg=0x0; init_LED(); init_USART(); init_SPI(); init_ADC(); Init_Card(); Send_CSD(); Fast_SPI(); init_Timer(); TIM_Cmd(TIM1, ENABLE); while(1) { Pack_Block(); Write_Block(); } } Что еще хотелось бы узнать-так это нормальную скорость передачи на данном интерфейсе. Заранее благодарен за любую помощь. З.Ы. Не понял как код убрать в спойлер и как убрать сообщения о размере шрифтов-они появляются вновь-поэтому получилось кривовастенько)) Изменено 22 июня, 2015 пользователем Hedhehog 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.