воскресенье, 17 августа 2014 г.

Дополнительные режимы работы АЦП в MSP430. Часть 2.

Это руководство посвящено многоканальному режиму АЦП в микроконтроллере MSP430G2553 на плате Launchpad. В предыдущей части был рассмотрен одноканальный режим АЦП с прямым доступом к памяти DMA. Точно так же можно использовать АЦП и во многоканальном режиме. АЦП будет автоматически пересылать результаты преобразования со всех каналов на заданный адрес в памяти. В этом процессе ядро микроконтроллера не задействовано и может заниматься другими делами (например расчётами). Операции с АЦП выполняются как бы в отдельном потоке. Таким образом реализуется примитивная аппаратная многозадачность. Как это сделать рассмотрено под катом.

Чтобы перевести АЦП в повторяющийся многоканальный режим нужно установить биты CONSEQ_3 регистра ADC10CTL1 и задать количество каналов установив биты INCH_xx. В остальном процедура настройки АЦП не отличается от многоканального режима.

Если например установить биты INCH_7, то АЦП будет работать в восьмиканальном режиме. Микроконтроллер будет сканировать входы АЦП последовательно от седьмого до нулевого и каждый раз помещать результат преобразования в регистр ADC10MEM. Модуль DMA будет пересылать каждый раз результат из этого регистра на пользовательский адрес в памяти.

Значения регистра счётчика пересылок ADC10DTC1 нужно установить равным

ADC10CTL1 = число_каналов * количество_выборок

Результаты АЦП можно складывать в двухмерный массив, который следует объявить так

  1. uint16_t adc[Количество_выборок][Число_каналов];

Теперь рассмотрим пример. Переведём АЦП в восьмиканальный режим, сделаем усреднение по четырём выборкам и выведем результат по запросу с UART. Для этого сперва модифицируем функцию инициализации АЦП из файла adc.cследующим образом:

  1. #include "msp430.h"
  2. #include "stdint.h"
  3. #include "adc.h"
  4.  
  5. void ADC_init_intref_multichannel(uint16_t *buffer,uint16_t samples_cnt) // Init
  6. ADC single channel oneshot with internal reference 2.5V
  7. {
  8. ADC10CTL0 &= ~ENC; // Стоп АЦП
  9. ADC10CTL0 = MSC + // Разрешаем многократные выборки
  10. SREF_1 + // Внутренний ИОН
  11. ADC10SHT_2 + // Настраиваем скорость работы АЦП
  12. REF2_5V + // Напряжение ИОН VREF=2.5В
  13. REFON + // Включаем встроенный ИОН
  14. ADC10ON + // Включаем АЦП
  15. ADC10IE; // Разрешаем прерывание от АЦП
  16. ADC10CTL1 = INCH_7 + // Сканировать 8 каналов АЦП начиная с A7 до A0
  17. SHS_0 +
  18. ADC10SSEL_0 + // Источник тактирования АЦП = SMCLK
  19. ADC10DIV_0 + // без предделителя
  20. CONSEQ_3; // Переводим АЦП во многоканльный режим
  21. ADC10AE0 = BIT4+BIT5+BIT7; // Подключаем ножки P1.4, P1.5, P1.7
  22. // как аналоговый вход
  23. ADC10DTC0 = ADC10CT; // Разрешаем непрерывный перенос результатов
  24. ADC10DTC1 = samples_cnt; // Число пересылок
  25. //while (ADC10CTL1&BUSY);
  26. ADC10SA = (int) buffer; // Стартовый адрес, куда отсылать результат АЦП
  27. ADC10CTL0 |=ENC + ADC10SC; // Старт АЦП
  28. }

В файле объявляем двухмерный массив, где будут храниться результаты АЦП:

  1. #define SAMPLES_CNT 4 // Делаем 4 последовательных выборки
  2. #define CHANNELS_CNT 8 // По 8 каналам
  3.  
  4. uint16_t adc[SAMPLES_CNT][CHANNELS_CNT];

В этом массиве нумерация каналов идёт с конца. То есть элемент adc[0][0] будет соответствовать 0-й выборке с 7-го канала, adc[0][1] - 0-й выборке с 6-го канала и так до adc[3][7], который соответствует 3-й выборке с нулевого канала.

И модифицируем обработчик прерывания от UART:

  1. void uart_rx_isr(unsigned char c)
  2. {
  3. uint16_t mV=0; // Volatge in mV
  4. uint32_t adc_avg=0; // ADC average
  5. int i=0;
  6.  
  7. switch (c) {
  8. case '1': P1OUT ^=LED_RED;
  9. uart_puts("Red led toggled\n");
  10. break;
  11. case '2': P1OUT ^= LED_GREEN;
  12. uart_puts("Green led toggled\n");
  13. break;
  14. case '3': adc_avg=0;
  15. for (i=0;i < SAMPLES_CNT;i++) { // Вычисляем среднее напряжение
  16. // по 5-му каналу
  17. adc_avg += adc[i][((CHANNELS_CNT-1)-5)];
  18. }
  19. adc_avg /= SAMPLES_CNT;
  20. mV = (adc_avg*2500)/1024;
  21. printf("P1.5 pin voltage = %d mV\n",mV); // Печатаем напряжение
  22. // на ножке P1.5
  23. break;
  24. default: uart_putc(c);
  25. break;
  26. }
  27. }

Исходники для этого примера можно забрать с Гитхаба .

Комментариев нет:

Отправить комментарий