|
|
  |
В чем практический смысл отличий регулярных и инжектированных каналов АЦП в STM32F103? |
|
|
|
Feb 22 2015, 20:50
|
Местный
  
Группа: Участник
Сообщений: 466
Регистрация: 17-11-12
Пользователь №: 74 443

|
Как я понял из даташита - у регулярных каналов только один общий регистр, где хранится результат преобразования, а у инжектирвоанны, хоть их и всего 4 - свои собственные. Мне с трудом верится, что разработчики поскупились на лишние регистры, более того, затеяли мороку с инжектированными каналами. Ведь куда было бы проще - 16 каналов, 16 регистров. Возникает мысль, что в создании инжектированных каналов есть какой-то сакральный смысл? Какой?
Опять-таки, если я настроил 2 регулярных канала, в режиме сканирования и в какой-то определенный момент я полез прочитать результат измерения, как мне понять с какого канал он пришел? Или с кучей регулярных каналов можно работать только через DMA ?
|
|
|
|
|
Feb 23 2015, 08:09
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Salamander @ Feb 22 2015, 22:50)  Возникает мысль, что в создании инжектированных каналов есть какой-то сакральный смысл? Какой? В том, что их преобразование происходит сразу по сигналу начала преобразования и может прерывать преобразование регулярных каналов. Прерванное преобразование регулярного канала производится заново после окончания инжектированного. Цитата(Salamander @ Feb 22 2015, 22:50)  Опять-таки, если я настроил 2 регулярных канала, в режиме сканирования и в какой-то определенный момент я полез прочитать результат измерения, как мне понять с какого канал он пришел? Или с кучей регулярных каналов можно работать только через DMA ? Понять никак. Или ПДП, или после каждого преобразования вычитывать результат и вести свой счетчик текущего канала. ПДП удобнее.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 23 2015, 16:51
|
Местный
  
Группа: Участник
Сообщений: 466
Регистрация: 17-11-12
Пользователь №: 74 443

|
Вот что я нашел в мануалах CODE STM32F10x Standard Peripherals Firmware Library Main Page Related Pages Modules Data Structures Files Directories File List Globals STM32F10x_StdPeriph_Lib_V3.5.0 Project STM32F10x_StdPeriph_Examples ADC ADC1_DMA STM32F10x_StdPeriph_Examples/ADC/ADC1_DMA/main.c Go to the documentation of this file. 00001 /** 00002 ****************************************************************************** 00003 * @file ADC/ADC1_DMA/main.c 00004 * @author MCD Application Team 00005 * @version V3.5.0 00006 * @date 08-April-2011 00007 * @brief Main program body 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS 00012 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE 00013 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY 00014 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING 00015 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE 00016 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. 00017 * 00018 * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2> 00019 ****************************************************************************** 00020 */ 00021 00022 /* Includes ------------------------------------------------------------------*/ 00023 #include "stm32f10x.h" 00024 00025 /** @addtogroup STM32F10x_StdPeriph_Examples 00026 * @{ 00027 */ 00028 00029 /** @addtogroup ADC_ADC1_DMA 00030 * @{ 00031 */ 00032 00033 00034 /* Private typedef -----------------------------------------------------------*/ 00035 /* Private define ------------------------------------------------------------*/ 00036 #define ADC1_DR_Address ((uint32_t)0x4001244C) 00037 00038 /* Private macro -------------------------------------------------------------*/ 00039 /* Private variables ---------------------------------------------------------*/ 00040 ADC_InitTypeDef ADC_InitStructure; 00041 DMA_InitTypeDef DMA_InitStructure; 00042 __IO uint16_t ADCConvertedValue; 00043 00044 /* Private function prototypes -----------------------------------------------*/ 00045 void RCC_Configuration(void); 00046 void GPIO_Configuration(void); 00047 00048 /* Private functions ---------------------------------------------------------*/ 00049 00050 /** 00051 * @brief Main program 00052 * @param None 00053 * @retval None 00054 */ 00055 int main(void) 00056 { 00057 /*!< At this stage the microcontroller clock setting is already configured, 00058 this is done through SystemInit() function which is called from startup 00059 file (startup_stm32f10x_xx.s) before to branch to application main. 00060 To reconfigure the default setting of SystemInit() function, refer to 00061 system_stm32f10x.c file 00062 */ 00063 00064 /* System clocks configuration ---------------------------------------------*/ 00065 RCC_Configuration(); 00066 00067 /* GPIO configuration ------------------------------------------------------*/ 00068 GPIO_Configuration(); 00069 00070 /* DMA1 channel1 configuration ----------------------------------------------*/ 00071 DMA_DeInit(DMA1_Channel1); 00072 DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; 00073 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADCConvertedValue; 00074 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 00075 DMA_InitStructure.DMA_BufferSize = 1; 00076 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 00077 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; 00078 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 00079 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 00080 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; 00081 DMA_InitStructure.DMA_Priority = DMA_Priority_High; 00082 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 00083 DMA_Init(DMA1_Channel1, &DMA_InitStructure); 00084 00085 /* Enable DMA1 channel1 */ 00086 DMA_Cmd(DMA1_Channel1, ENABLE); 00087 00088 /* ADC1 configuration ------------------------------------------------------*/ 00089 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 00090 ADC_InitStructure.ADC_ScanConvMode = ENABLE; 00091 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 00092 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 00093 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 00094 ADC_InitStructure.ADC_NbrOfChannel = 1; 00095 ADC_Init(ADC1, &ADC_InitStructure); 00096 00097 /* ADC1 regular channel14 configuration */ 00098 ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_55Cycles5); 00099 00100 /* Enable ADC1 DMA */ 00101 ADC_DMACmd(ADC1, ENABLE); 00102 00103 /* Enable ADC1 */ 00104 ADC_Cmd(ADC1, ENABLE); 00105 00106 /* Enable ADC1 reset calibration register */ 00107 ADC_ResetCalibration(ADC1); 00108 /* Check the end of ADC1 reset calibration register */ 00109 while(ADC_GetResetCalibrationStatus(ADC1)); 00110 00111 /* Start ADC1 calibration */ 00112 ADC_StartCalibration(ADC1); 00113 /* Check the end of ADC1 calibration */ 00114 while(ADC_GetCalibrationStatus(ADC1)); 00115 00116 /* Start ADC1 Software Conversion */ 00117 ADC_SoftwareStartConvCmd(ADC1, ENABLE); 00118 00119 while (1) 00120 { 00121 } 00122 } 00123 00124 /** 00125 * @brief Configures the different system clocks. 00126 * @param None 00127 * @retval None 00128 */ 00129 void RCC_Configuration(void) 00130 { 00131 #if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) 00132 /* ADCCLK = PCLK2/2 */ 00133 RCC_ADCCLKConfig(RCC_PCLK2_Div2); 00134 #else 00135 /* ADCCLK = PCLK2/4 */ 00136 RCC_ADCCLKConfig(RCC_PCLK2_Div4); 00137 #endif 00138 /* Enable peripheral clocks ------------------------------------------------*/ 00139 /* Enable DMA1 clock */ 00140 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); 00141 00142 /* Enable ADC1 and GPIOC clock */ 00143 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOC, ENABLE); 00144 } 00145 00146 /** 00147 * @brief Configures the different GPIO ports. 00148 * @param None 00149 * @retval None 00150 */ 00151 void GPIO_Configuration(void) 00152 { 00153 GPIO_InitTypeDef GPIO_InitStructure; 00154 00155 /* Configure PC.04 (ADC Channel14) as analog input -------------------------*/ 00156 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 00157 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; 00158 GPIO_Init(GPIOC, &GPIO_InitStructure); 00159 } 00160 00161 #ifdef USE_FULL_ASSERT 00162 00163 /** 00164 * @brief Reports the name of the source file and the source line number 00165 * where the assert_param error has occurred. 00166 * @param file: pointer to the source file name 00167 * @param line: assert_param error line source number 00168 * @retval None 00169 */ 00170 void assert_failed(uint8_t* file, uint32_t line) 00171 { 00172 /* User can add his own implementation to report the file name and line number, 00173 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ 00174 00175 /* Infinite loop */ 00176 while (1) 00177 { 00178 } 00179 } 00180 00181 #endif 00182 00183 /** 00184 * @} 00185 */ 00186 00187 /** 00188 * @} 00189 */ 00190 00191 /******************* © COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ For complete documentation on STM32(CORTEX M3) 32-bit Microcontrollers platform visit www.st.com/STM32
Как, положим добавить туда еще один канал, я знаю. Но мне непонятны две вещи 1. Как прочесть данные из определенного канала? 2. Как при срабатывании Analog Watchdog понять какой канал вызвал прерывание и нужен ли DMA, если мне не интересны данные, а важен сам факт срабатывания аналоговой собачки?
Сообщение отредактировал Salamander - Feb 23 2015, 17:00
|
|
|
|
|
Feb 24 2015, 08:23
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(Salamander @ Feb 23 2015, 18:51)  1. Как прочесть данные из определенного канала? Пользование библиотеками не отменяет необходимости чтения документации. Цитата(Salamander @ Feb 23 2015, 18:51)  2. Как при срабатывании Analog Watchdog понять какой канал вызвал прерывание Прочитать результаты преобразования каждого канала и сравнить с вашими пределами. Аппаратного указателя на сработавший канал не предусмотрено. Цитата(Salamander @ Feb 23 2015, 18:51)  и нужен ли DMA, если мне не интересны данные, а важен сам факт срабатывания аналоговой собачки? В свете предыдущего ответа - да.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 26 2015, 03:23
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(Salamander @ Feb 23 2015, 19:51)  1. Как прочесть данные из определенного канала? При использовании регулярных каналов данные складываются последовательно с каждого канала в определенный массив. Достаточно объявить этот массив как двумерный: CODE /** * Configuration: * Defines the size of the ADC sample array. Defining a larger value here will significantly increase * the amount of static RAM usage, but more values will be used for averaging, leading to lower noise. */ #define ADCNUMCHAN 5 /* Number of channel */ #define ADCNUMSAMPLES 16 /* Number of samples */ #define ADCCONVERTEDVALUES_BUFFER_SIZE ((uint32_t)(ADCNUMCHAN*ADCNUMSAMPLES)) /* Size of array ADCxConvertedValues[num_chan * num_samples]: set to ADC sequencer number of ranks converted, to have a rank in each address */ /* Array containing ADC conversions results */ __IO uint16_t ADCxConvertedValues[ADCNUMSAMPLES][ADCNUMCHAN]; -------------------- // -- Enables ADC DMA request if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t*)&ADCxConvertedValues, ADCCONVERTEDVALUES_BUFFER_SIZE) != HAL_OK) { Error_Handler(); }
... и в обработчике прерывания ADC-DMA всей последовательности: CODE void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { uint32_t accum = 0;
for (uint8_t ch = 0; ch < ADCNUMCHAN; ch++) { for (uint16_t i = 0; i < ADCNUMSAMPLES; i++) { accum += ADCxConvertedValues[i][ch]; } Value.codeADC[ch] = accum / ADCNUMSAMPLES; accum = 0;}
|
|
|
|
|
Feb 26 2015, 07:26
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(alux @ Feb 26 2015, 05:23)  Достаточно объявить этот массив как двумерный: Бррр... И помнить, какой канал в каком элементе вложенного массива? Код struct regular_result { sample_t DTMF; sample_t Audio; sample_t RSSI; };
typedef regular_result buffer[ADC_BUFFER_SIZE]; buffer Buffer[2]; // twice the buffer size, to get DMA "half ready" int in the middle
adc::regular_result const * ADC_data = (DMA1->ISR & DMA_ISR_HTIF1) ? Buffer[0] : Buffer[1]; // это для примера. Разумеется, флаг анализируется в прерывании for(uint_fast8_t i = 0; i < adc::ADC_BUFFER_SIZE; ++i) { MM24_demod.set_rssi(ADC_data[i]->RSSI); CID_receiver.dtmf_process(ADC_data[i]->DTMF); MM24_demod.sample(ADC_data[i]->Audio); }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 26 2015, 15:48
|
Местный
  
Группа: Участник
Сообщений: 466
Регистрация: 17-11-12
Пользователь №: 74 443

|
Эх... с инжектированными каналами я разобрался. И с аналоговой собачкой тоже. и озвученный уважаемым Борщом принцип Цитата Прочитать результаты преобразования каждого канала и сравнить с вашими пределами. Аппаратного указателя на сработавший канал не предусмотрено. реализовал. Но уперся в интересную штуку.... Смотрите, мне нужно анализировать 3 канала, ловить импульсы. С одним каналом получилось - я поставил пределы от 0 до 2048, соответственно ловлю фронт. А поймав, чтобы собакотаймер не гавкал каждый такт, перевожу пределы в диапазон от 2048 до 4096. Соответственно, после этого я ловлю только спад. Но... если у меня 3 канала и на каждом независимо идущие импульсы.... Да, я поймав прерывание могу проанализировать с какого канала оно пришло, как посоветовал Борщ. Но если я изменю пределы, то это повлияет на анализ импульсов других каналов. Решаема ли эта задача средствами STM32 ?
|
|
|
|
|
Feb 26 2015, 17:12
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(Salamander @ Feb 26 2015, 22:48)  Решаема ли эта задача средствами STM32 ? Если ничего не получается попробуйте применить DMA. На STM32 это часто помогает  Можно попробовать запускать сразу два канала DMA, один будет как обычно вычитывать результат преобразования из DR, а второй пересылать в регистры HTR и LTR пороги для следующего канала.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|