Цитата(dimon_rub @ Nov 12 2016, 08:28)

НО как потом узначт в каком канале авария?????
Зависит от того в каком режиме работает АЦП, в случае сканирования с DMA просмотреть буфер.
Цитата
(примеры будут вообще СУПЕР) как реализовать опрос более 10 каналов АЦП
Ниже фрагмент кода десятиканального вольтметра. Устройство сделал, когда только начинал осваивать STM32, еще на халявной дискавери. Код полностью рабочий, вырезал инициализацию портов и не имеющие к делу куски. Написано для STM32F100, работать должно и на F103.
Основной цикл!
CODE
float adc_data [10]; // Результат измерения
u16 adc_buf [10]; // Буфер куда пишет DMA
u32 adc_buf_t [10]; // Накопление результата
float adc_coff [10] ={ // Калибровочные константы
0.00008467,// 0.0000893721, // U 1
0.00008455, // U 2
0.00008653, // U 3
0.00008543, // U 4
0.00008529, // U 5
0.00008556, // U 6
0.00008333, // U 7
0.00008442, // U 8
0.00008475, // U 9
0.00008392// U 10
};
float adc_zero[11] ={ // Нули
28994.0, // U 1
28859.0, // U 2
27527.0, // U 3
26274.0, // U 4
28885.0, // U 5
27621.0, // U 6
34047.0, // U 7
28648.0, // U 8
26955.0, // U 9
26136.0 // U 10
};
u8 adc_data_rd = 0; // Флаг есть результат
int main(void)
{
while( 1)
{
if (adc_data_rd == 1){
adc_data_rd = 0; // Обнуляем флаг конца измерения
for (u8 i = 0; i<=9;i++)
{
adc_data[i] = (((float)adc_buf_t[i] - adc_zero[i]) * adc_coff[i]); // Результат с учетом калибровочных констант и нулей
adc_buf_t[i] = 0; // Обнуляем буфер усреднения
}
// Здесь отображаем результата или все что угодно!
// Старт следующего измерения
DMA1_Channel1->CCR |= DMA_CCR1_EN; // разрешаем работу DMA и ADC
ADC1->CR2 |= ADC_CR2_ADON;
}
}}
Инициализация АЦП и ДМА
CODE
//------------------------------------------------------------------------------
void AdcInit(void)
{
RCC->AHBENR |= RCC_AHBENR_DMA1EN; //
DMA1_Channel1->CPAR = (uint32_t) &ADC1->DR; // адрес периферийного устройства
DMA1_Channel1->CMAR = (unsigned int) adc_buf; // адрес буфера в памяти
DMA1_Channel1->CNDTR = 10; // количество данных для обмена
DMA1_Channel1->CCR &=~DMA_CCR1_EN; // разрешаем работу
DMA1_Channel1->CCR |= DMA_CCR1_MSIZE_0; // размер памяти 16 bit
DMA1_Channel1->CCR |= DMA_CCR1_PSIZE_0; // размер периферии 16 bit
DMA1_Channel1->CCR |= DMA_CCR1_MINC; // memory increment mode
DMA1_Channel1->CCR |= DMA_CCR1_CIRC;
DMA1_Channel1->CCR |= DMA_CCR1_TCIE; // прерывание по окончанию передачи
DMA1_Channel1->CCR |= DMA_CCR1_EN; // разрешаем работу
NVIC_SetPriority(DMA1_Channel1_IRQn, 10);
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
RCC->CFGR &= ~RCC_CFGR_ADCPRE;
RCC->CFGR |= RCC_CFGR_ADCPRE_DIV8;
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
ADC1->SQR3 = 0; // 1
ADC1->SQR3 |= 1<<5; // 2 Слева номер канала справа сдвиг
ADC1->SQR3 |= 2<<10; // 3
ADC1->SQR3 |= 3<<15; // 4
ADC1->SQR3 |= 4<<20; // 5
ADC1->SQR3 |= 5<<25; // 6
ADC1->SQR2 = 6; // 7
ADC1->SQR2 |= 7<<5; // 8
ADC1->SQR2 |= 8<<10; // 9
ADC1->SQR2 |= 9<<15; // 10
ADC1->CR2 = ADC_CR2_EXTSEL_0 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTSEL_2 | ADC_CR2_EXTTRIG;
ADC1->SMPR1 = 0; //очистка регистров времени выборки
ADC1->SMPR2 = 0; //
ADC1->SMPR2 |= (uint32_t)(6<<(0*3)); //канал 0, время преобразования 6 мкс
ADC1->SMPR2 |= (uint32_t)(6<<(1*3)); //канал 1, время преобразования 6 мкс
ADC1->SMPR2 |= (uint32_t)(6<<(2*3)); //канал 2, время преобразования 6 мкс
ADC1->SMPR2 |= (uint32_t)(6<<(3*3)); //канал 3, время преобразования 6 мкс
ADC1->SMPR2 |= (uint32_t)(6<<(4*3)); //канал 4, время преобразования 6 мкс
ADC1->SMPR2 |= (uint32_t)(6<<(5*3)); //канал 5, время преобразования 6 мкс
ADC1->SMPR2 |= (uint32_t)(6<<(6*3)); //канал 6, время преобразования 6 мкс
ADC1->SMPR2 |= (uint32_t)(6<<(7*3)); //канал 7, время преобразования 6 мкс
ADC1->SMPR2 |= (uint32_t)(6<<(8*3)); //канал 8, время преобразования 6 мкс
ADC1->SMPR2 |= (uint32_t)(6<<(9*3)); //канал 9, время преобразования 6 мкс
ADC1->SMPR1 |= (uint32_t)(6<<(0*3)); //канал 10, время преобразования 6 мкс
ADC1->CR2 |= ADC_CR2_ADON;
ADC1->CR2 |= ADC_CR2_RSTCAL;
while ((ADC1->CR2 & ADC_CR2_RSTCAL) == ADC_CR2_RSTCAL){}
ADC1->CR2 |= ADC_CR2_CAL;
while ((ADC1->CR2 & ADC_CR2_RSTCAL) == ADC_CR2_CAL) {}
ADC1->SQR1 |= 9<<20; // Количество преобразования
ADC1->CR1 |= ADC_CR1_SCAN; // Режим сканирования
ADC1->CR2 |= ADC_CR2_DMA; // DMA on
// ADC1->CR2 |= ADC_CR2_CONT;
// ADC1->CR2 |= ADC_CR2_SWSTART;
ADC1->CR2 |= ADC_CR2_ADON;
}
Прерывание от ДМА
CODE
u32 adc_count = 0; // Счетчик числа усреднений
void DMA1_Channel1_IRQHandler(void)
{
DMA1->IFCR = DMA_IFCR_CGIF1 | DMA_IFCR_CTCIF1; // clear DMA interrupt flags
DMA1_Channel1->CCR &=~DMA_CCR1_EN; // Запрещаем работу
for (u8 i = 0; i<=9;i++)
{
adc_buf_t[i]+= adc_buf[i]; // Накапливаем сумму в буфере
}
adc_count++;
if (adc_count >=5000) // Счетчик усреднений
{
adc_count = 0;
adc_data_rd = 1; // Флаг готовности АЦП
test_count++;
return;
}
DMA1_Channel1->CCR |= DMA_CCR1_EN; // разрешаем работу
ADC1->CR2 |= ADC_CR2_ADON;
}
//------------------------------------------------------------------------------
Сообщение отредактировал IgorKossak - Nov 14 2016, 21:58
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
Разработка и производство электроники.