Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Примеры применения в среде Баском » Исследование АЦП в МК Atmegaxxx и Attinyxxx


Исследование АЦП в МК Atmegaxxx и Attinyxxx

Сообщений 1 страница 14 из 14

1

Исследование АЦП в МК Atmegaxxx и Attinyxxx



Таблица внешних опорников от Linear Technology

Параметрический поиск


Таблица внешних опорников от Analog Devices

Параметрический поиск

0

2

Компилятор: BASCOM-AVR 2.0.7.1

Для оптимального отображения псевдографики используйте шрифт в Bascom: Consolas; размер = 14

Кому надо симуляцию в Протеусе, пишите мыло, закину.

Опрос 6 каналов АЦП в фоновом режиме

'===============================================================================
  $map              ' Получаем карту распределения памяти
  $regfile = "m328Pdef.dat"       ' Используемый контроллер
'  $crystal = 1000000
  $crystal = 7372800       ' 7,3728 МГц, кварц для стабильной работы USART во всём диапазоне скоростей передачи и приёма
  $framesize = 32   'размер области используемой и необходимой для преобразований
  $hwstack = 40     ' Размер аппаратного стека
  $swstack = 16     ' Размер программного стека
  $baud = 38400     '1200     '2400     '4800     '9600     '19200     '38400     '57600     '115000    '230400

'  Ucsr0a.1 = 1      ' Двойная скорость работы USART, скорость трансляции = $baud * 2
'===============================================================================

'----------  Конфигурация АЦП, измерения проходят в фоновом режиме  ------------

'  Config Adc = Free , Prescaler = 2 , Reference = Off

' значение регистра при включении МК, ADMUX = &B00000000
  Admux = &B00000000
'           ||||||||
'           |||||||+--- 0 - MUX0 - выбор входа АЦП для измерения
'           ||||||+---- 1 - MUX1 - выбор входа АЦП для измерения
'           |||||+----- 2 - MUX2 - выбор входа АЦП для измерения
'           ||||+------ 3 - MUX3 - выбор входа АЦП для измерения
'           |||+------- 4 - резерв
'           ||+-------- 5 - ADLAR - выравнивание результата измерения по левому краю
'           |+--------- 6 - REFS0 - выбор источника опорного напряжения
'           +---------- 7 - REFS1 - выбор источника опорного напряжения

'--------------------------------------------------------------------------------------------------------+
'| REFS1 | REFS0 |  Источник опорного напряжения дла работы АЦП                                          |
'|-------|-------|---------------------------------------------------------------------------------------|
'|   0   |   0   |  Внешний источник опорного напряжения на вывод AREF                                   |
'|   0   |   1   |  Источник опорного напряжения с вывода AVCC                                           |
'|   1   |   0   |  Резерв                                                                               |
'|   1   |   1   |  Внутренний источник опорного напряжения 1.1V, вывод AREF через конденсатор на землю  |
'--------------------------------------------------------------------------------------------------------+

'------------------------------------------------------------------------
'| MUX3 | MUX2 | MUX1 | MUX0 |   Источник измеряемого сигнала           |
'|------|------|------|------|------------------------------------------|
'|   0  |   0  |   0  |   0  |   ADC0, 23 вывод МК, для корпуса DIP-28  |
'|   0  |   0  |   0  |   1  |   ADC1, 24 вывод МК, для корпуса DIP-28  |
'|   0  |   0  |   1  |   0  |   ADC2, 25 вывод МК, для корпуса DIP-28  |
'|   0  |   0  |   1  |   1  |   ADC3, 26 вывод МК, для корпуса DIP-28  |
'|   0  |   1  |   0  |   0  |   ADC4, 27 вывод МК, для корпуса DIP-28  |
'|   0  |   1  |   0  |   1  |   ADC5, 28 вывод МК, для корпуса DIP-28  |
'|   0  |   1  |   1  |   0  |   ADC6                                   |
'|   0  |   1  |   1  |   1  |   ADC7                                   |
'|   1  |   0  |   0  |   0  |   ADC8, внутренний датчик температуры МК |
'|   1  |   0  |   0  |   1  |   резерв                                 |
'|   1  |   0  |   1  |   0  |   резерв                                 |
'|   1  |   0  |   1  |   1  |   резерв                                 |
'|   1  |   1  |   0  |   0  |   резерв                                 |
'|   1  |   1  |   0  |   1  |   резерв                                 |
'|   1  |   1  |   1  |   0  |   1,1V                                   |
'|   1  |   1  |   1  |   1  |   0V (Gnd)                               |
'------------------------------------------------------------------------

' значение регистра при включении МК, ADCSRA = &B00000000
  Adcsra = &B11001000
'            ||||||||
'            |||||||+--- 0 - ADPS0 - выбор делителя частоты АЦП
'            ||||||+---- 1 - ADPS1 - выбор делителя частоты АЦП
'            |||||+----- 2 - ADPS2 - выбор частоты делителя АЦП
'            ||||+------ 3 - ADIE  - разрешение прерывания по окончании прелбразования
'            |||+------- 4 - ADIF  - флаг окончание преобразования
'            ||+-------- 5 - ADATE - АЦП Auto Trigger Включить
'            |+--------- 6 - ADSC  - АЦП старт преобразования
'            +---------- 7 - ADEN  - включение АЦП

'--------------------------------------
'| ADPS2 | ADPS1 | ADPS0 |   Делитель |
'|-------|-------|-------|------------|
'|   0   |   0   |   0   |      2     |
'|   0   |   0   |   1   |      2     |
'|   0   |   1   |   0   |      4     |
'|   0   |   1   |   1   |      8     |
'|   1   |   0   |   0   |     16     |
'|   1   |   0   |   1   |     32     |
'|   1   |   1   |   0   |     64     |
'|   1   |   1   |   1   |    128     |
'--------------------------------------

' значение регистра при включении МК, ADCSRB = &B00000000
  Adcsrb = &B00000000
'            ||||||||
'            |||||||+--- 0 - ADTS0 - выбор источника-инициатора начала измерения
'            ||||||+---- 1 - ADTS1 - выбор источника-инициатора начала измерения
'            |||||+----- 2 - ADTS2 - выбор источника-инициатора начала измерения
'            ||||+------ 3 - резерв
'            |||+------- 4 - резерв
'            ||+-------- 5 - резерв
'            |+--------- 6 - ACME
'            +---------- 7 - резерв

'----------------------------------------------------------+
'| ADTS2 | ADTS1 | ADTS0 |     источника-инициатора        |
'|-------|-------|-------|---------------------------------|
'|   0   |   0   |   0   |  Free Running mode              |
'|   0   |   0   |   1   |  Analog Comparator              |
'|   0   |   1   |   0   |  External Interrupt Request 0   |
'|   0   |   1   |   1   |  Timer/Counter0 Compare Match A |
'|   1   |   0   |   0   |  Timer/Counter0 Overflow        |
'|   1   |   0   |   1   |  Timer/Counter1 Compare Match B |
'|   1   |   1   |   0   |  Timer/Counter1 Overflow        |
'|   1   |   1   |   1   |  Timer/Counter1 Capture Event   |
'----------------------------------------------------------+

' значение регистра при включении МК, DIDR0 = &B00000000
  Didr0 = &B00000000       ' Вкл/Откл цифровых входов МК
'           ||||||||
'           |||||||+--- 0 - ADC0D
'           ||||||+---- 1 - ADC1D
'           |||||+----- 2 - ADC2D
'           ||||+------ 3 - ADC3D
'           |||+------- 4 - ADC4D
'           ||+-------- 5 - ADC5D
'           |+--------- 6 - резерв
'           +---------- 7 - резерв

'------------  Переход к подпрограмме обработки прерывания АЦП  ----------------

  On Adc Обработка_прерывания_ацп Nosave

'-------------------  Используемые переменные  ---------------------------------

  Dim Цикл_print As Byte

'-------------  Для 6-ти каналов АЦП  ------------------------------------------

  Dim Данные_ацп(6) As Word       ' At $200       ' Привязываем переменную к конкретному адресу в оперативке МК
  Dim Temp_данные_ацп As Word
  Dim Сырые_данные_ацп(2) As Byte At Temp_данные_ацп Overlay

'------------  Разрешаем работу всех включенных прерываний  --------------------

  Enable Interrupts

'Ждём первого измерения АЦП, последующие измерения происходят в фоновом режиме

  Power Adcnoise

'===============================================================================

'                   Г Л А В Н Ы Й         Ц И К Л

'===============================================================================
  Главный_цикл:

    nop

    For Цикл_print = 1 To 6
        Print "Тест АЦП " ; Цикл_print ; ": " ; Данные_ацп(цикл_print)
    Next Цикл_print

    Print

    Waitms 50

   Idle
  Goto Главный_цикл
End
'===============================================================================

'                        П О Д П Р О Г Р А М М Ы

'===============================================================================

'===============================================================================
  Обработка_прерывания_ацп:
'-------------------------------------------------------------------------------
nop
'------  Сохраняем используемые регистры и SREG  -------

    !push R24
    !in R24 , sreg
    !push r24

    !push R25
    !push R26
    !push R27

'----  Выключаем прерывание от АЦП  ----

    !in R25 , adcsra       ' Читаем значение, время выполнения инструкции - 1 такт
    !CBR R25 , &B00001000       ' Сбросить бит в регистре, время выполнения инструкции - 1 такт
    !out Adcsra , R25       ' Пишем значение, время выполнения инструкции - 1 такт

'----  Забираем данные из регистров АЦП  ----

    !in R26 , adcl
    !sts {Сырые_данные_ацп(1)} , R26

    !in R26 , adch
    !sts {Сырые_данные_ацп(2)} , R26

'------  Готовим следующий канал АЦП  -------

    !in R26 , ADMUX ' Читаем ADMUX
    !ANDI R26 , &H07       ' Маской отрезаем лишние биты. Получаем номер канала
    !inc R26
    !ANDI R26 , &H07       ' Обрезаем лишние биты, чтобы не было переполнения

    !cpi R26 , 6
    !BRLO Выбор_входа_ацп       ' Перейти если меньше
    !ldi R26 , 0

   Выбор_входа_ацп:

    !IN R27 , ADMUX ' Читаем ADMUX
    !ANDI R27 , &HF8       ' Маской отрезаем биты номера канала, получаем настройку АЦП
    !OR R27 , R26   ' Сложили настройки АЦП c новым значением номера канала, т.е., сделали MUX = MUX + 1
    !OUT ADMUX , R27       ' Закидываем полученное значение в регистр АЦП

'------  Забираем готовые данные АЦП в массив  -------

    !cpi R26 , 0
    !BREQ Ацп_0     ' (BREQ) Если равно перейти на метку, время выполнения 2 такта, если не равно 1 такт

    !cpi R26 , 1
    !BREQ Ацп_1     ' (BREQ) Если равно перейти на метку, время выполнения 2 такта, если не равно 1 такт

    !cpi R26 , 2
    !BREQ Ацп_2     ' (BREQ) Если равно перейти на метку, время выполнения 2 такта, если не равно 1 такт

    !cpi R26 , 3
    !BREQ Ацп_3     ' (BREQ) Если равно перейти на метку, время выполнения 2 такта, если не равно 1 такт

    !cpi R26 , 4
    !BREQ Ацп_4     ' (BREQ) Если равно перейти на метку, время выполнения 2 такта, если не равно 1 такт

    !cpi R26 , 5
    !BREQ Ацп_5     ' (BREQ) Если равно перейти на метку, время выполнения 2 такта, если не равно 1 такт

   Ацп_0:
    Данные_ацп(6) = Temp_данные_ацп
    !rjmp Запуск_ацп

   Ацп_1:
    Данные_ацп(1) = Temp_данные_ацп
    !rjmp Запуск_ацп

   Ацп_2:
    Данные_ацп(2) = Temp_данные_ацп
    !rjmp Запуск_ацп

   Ацп_3:
    Данные_ацп(3) = Temp_данные_ацп
    !rjmp Запуск_ацп

   Ацп_4:
    Данные_ацп(4) = Temp_данные_ацп
    !rjmp Запуск_ацп

   Ацп_5:
    Данные_ацп(5) = Temp_данные_ацп
    !rjmp Запуск_ацп

'----  Включаем прерывание от АЦП  ----
   Запуск_ацп:

    !in R25 , adcsra       ' Читаем значение, время выполнения инструкции - 1 такт
    !SBR R25 , &B01001000       ' Установить бит в регистре, время выполнения инструкции - 1 такт
    !out Adcsra , R25       ' Пишем значение, время выполнения инструкции - 1 такт

'------  Восстанавливаем ранее сохранённые регистры и SREG  -------

    !pop R27
    !pop R26
    !pop R25

    !pop R24
    !Out Sreg , R24
    !pop R24

'------  Выходим из прерывания  -------
nop
    !reti

'-------------------------------------------------------------------------------
  Return
'===============================================================================

+1

3

Исследование АЦП. Скоростной опрос АЦП МК Atmega328P. Кварц 30 МГЦ

Симуляция Протеус 7.10 sr0 + исходник Bascom 2.0.7.1  -  скачать   

Видео с осциллограммами  -  скачать    -   размер ~70 Мб

Документация производителя на Atmega48a-48pa-88a-88pa-168a-168pa-328-328p

+1

4

Исходник, при данных настройках время преобразования ~50 мкс, АЦП работает в фоновом режиме (Free)

$map              ' Получаем карту распределения памяти
  $regfile = "m328pdef.dat"       ' Используемый контроллер
  $crystal = 1000000       ' 1 МГц
'  $crystal = 8000000       ' 8 МГц
  $framesize = 32   'размер области используемой и необходимой для преобразований
  $hwstack = 40     ' Размер аппаратного стека
  $swstack = 16     ' Размер программного стека
  $baud = 4800      '4800     '9600     '19200     '38400

'----------------------  Конфигурация АЦП  -------------------------------------
  Config Adc = Free , Prescaler = 4 , Reference = Avcc
  On Adc Обработка_прерывания_ацп Nosave
'----------------------  Используемые переменные  ------------------------------
  Dim Данные_ацп As Word
  Dim Сырые_данные_ацп(2) As Byte At Данные_ацп Overlay
'------------------  Запуск и предварительные настройки  -----------------------
  Start Adc
'--------------  Разрешаем работу необходимых прерываний  ----------------------
  Enable Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
'===============================================================================
  Главный_цикл:

    nop

    Print Данные_ацп
    Print

   Power Adcnoise
  Goto Главный_цикл
End
'===============================================================================
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_ацп:
'-------------------------------------------------------------------------------
    !Push R26       ' Сохраняем регистры, которые используем в обработке
    !push R27

    !in R26 , adcl
    !in R27 , adch

    !sts {Сырые_данные_ацп(1)} , R26
    !sts {Сырые_данные_ацп(2)} , R27

    !pop R27        ' Восстанавливаем регистры, которые используем в обработке
    !pop R26
    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

Симуляция (Протеус 7.10) + исходник (Bascom 2.0.7.1) - скачать

http://s7.uploads.ru/t/sWAf9.jpg

0

5

Программное повышение разрядности АЦП, по буржуйски "оверсемплинг"

Документация Atmel по этому поводу

Кому нужен перевод, пишите в ЛС, скину на mail.


Минусы данного метода - снижение скорости получения готовых данных пропорционально повышению разрядности!
Но если скорость не важна, то метод получения более точных данных довольно удачный.


Ацп работает в фоновом режиме (Free), проверяете флаг, при флаг=1, получаете в переменной, готовые данные соответствующей разрядности.

12-ти битный вариант с обработчиком прерывания АЦП силами Bascom

'-------------------------------------------------------------------------------
  $map              ' Получаем карту распределения памяти
  $regfile = "m328pdef.dat"       ' Используемый контроллер
'  $crystal = 1000000       ' 1 МГц
  $crystal = 8000000       ' 8 МГц
  $framesize = 32   'размер области используемой и необходимой для преобразований
  $hwstack = 40     ' Размер аппаратного стека
  $swstack = 16     ' Размер программного стека
'----------------------  Конфигурация USART  -----------------------------------
  $baud = 19200     '1200     '2400     '4800     '9600     '19200     '38400     '57600     '115000    '230400
'  Ucsr0a.1 = 1      ' Двойная скорость работы USART
  Dim Флаг_есть_данные_usart As Byte
'----------------------  Конфигурация АЦП  -------------------------------------
  Config Adc = Free , Prescaler = 128 , Reference = Avcc       ' Фоновая работа АЦП, делитель=128, опорное=U питания МК
  On Adc Обработка_прерывания_ацп       ' Ссылка на обработчик прерывания от АЦП
'----------------------  Используемые переменные  ------------------------------
  Dim Данные_ацп As Word       ' Готовые данные АЦП
  Dim Сырые_данные_ацп(2) As Byte At Данные_ацп Overlay       ' Переменные для сырых данных АЦП (ADCL и ADCH), собираются оверлеем в переменную "Данные_ацп"

  Dim Сумма_ацп As Word
  Dim 12_bit_данные_ацп As Word
  Dim Счетчик_измерений_ацп As Byte
'--------------  Разрешаем работу необходимых прерываний  ----------------------
  Enable Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
'===============================================================================
  Главный_цикл:
    nop

    If Флаг_есть_данные_usart = 1 Then
        Print 12_bit_данные_ацп
        Print
        Флаг_есть_данные_usart = 0
    End If

   Power Adcnoise
  Goto Главный_цикл
End
'===============================================================================
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_ацп:
'-------------------------------------------------------------------------------

'Забираем, что намеряли, номер канала выставляется в настройках регистр ADMUX, первые 4 бита

'    Сырые_данные_ацп(1) = Adcl
'    Сырые_данные_ацп(2) = Adch

' или так если нужно выбрать номер канала

    Данные_ацп = Getadc(0)

'------  Набираем сумму измерений для 12 бит  ----------

    Сумма_ацп = Сумма_ацп + Данные_ацп

    Incr Счетчик_измерений_ацп

    If Счетчик_измерений_ацп = 16 Then
        Счетчик_измерений_ацп = 0
        Shift Сумма_ацп , Right , 2
        12_bit_данные_ацп = Сумма_ацп
        Флаг_есть_данные_usart = 1
        Сумма_ацп = 0
    End If

'-------------------------------------------------------------------------------
  Return
'===============================================================================


Симуляция в Протеус 7.10 sr0 + исходники Bascom 2.0.7.1  -  скачать

В архиве доступны варианты: 10 бит; 11 бит; 12 бит; 13 бит; 14 бит; 15 бит; 16 бит.

Исходник выбрать в свойствах МК !!!

http://s0.uploads.ru/t/7nPNJ.jpg

+1

6

Дифференциальный режим работы АЦП, на примере термодатчика PT100 и МК Atbanned6A

Вход "+" = ADC3; Вход "-" = ADC2; Усиление = 20

Симуляция в Протеус 7.10 sr0 + исходник Bascom 2.0.7.1  -  скачать

http://s1.uploads.ru/t/pv1Fe.jpg

+1

7

16-бит АЦП с помощью оверсемплинга (oversampling)

Документация Atmel по данному вопросу

Исходник на ASM AVR

$map       ' Получаем карту распределения памяти
  $regfile = "m328pdef.dat"       ' Используемый контроллер
'  $crystal = 1000000       ' 1 МГц
  $crystal = 8000000       ' 8 МГц
  $framesize = 32       'размер области используемой и необходимой для преобразований
  $hwstack = 40       ' Размер аппаратного стека
  $swstack = 16       ' Размер программного стека

  $baud = 19200       '1200     '2400     '4800     '9600     '19200     '38400     '57600     '115000    '230400
'  Ucsr0a.1 = 1      ' Двойная скорость работы USART
  Dim Флаг_есть_данные_usart As Byte

'----------------------  Конфигурация АЦП  -------------------------------------
  Config Adc = Free , Prescaler = 128 , Reference = Avcc
  On Adc Обработка_прерывания_ацп Nosave
  Dim Сумма_ацп As Long
  Dim 16_bit_данные_ацп As Word
  Dim Счетчик_измерений_ацп As Word

'--------------  Разрешаем работу необходимых прерываний  ----------------------
  Enable Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
'===============================================================================
  Главный_цикл:
    nop

      If Флаг_есть_данные_usart = 1 Then
          Print 16_bit_данные_ацп
          Print
          Флаг_есть_данные_usart = 0
      End If

   Power Adcnoise
  Goto Главный_цикл
End
'===============================================================================
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_ацп:
'-------------------------------------------------------------------------------
' Сохраняем SREG
    !Push R26
    !In R26 , Sreg
    !Push R26
' Сохраняем регистры, которые используем в обработке
    !Push R27
    !Push R30
    !push R31

'------  Забираем, что намеряли  ---------------
    !in R30 , adcl
    !in R31 , adch

'------  Набираем сумму измерений для 16 бит  ----------
    !lds   R26  ,  {Сумма_ацп}       ' Время выполнения инструкции 2 такта
    !add   R26  ,  R30       ' Время выполнения инструкции 1 такт
    !sts   {Сумма_ацп}  ,  R26       ' Время выполнения инструкции 2 такта
    !lds   R26  ,  {Сумма_ацп + 1}       ' Время выполнения инструкции 2 такта
    !adc   R26  ,  R31       ' Время выполнения инструкции 1 такт
    !sts   {Сумма_ацп + 1}  ,  R26       ' Время выполнения инструкции 2 такта
    !lds   R26  ,  {Сумма_ацп + 2}       ' Время выполнения инструкции 2 такта
    !clr   R27       ' Время выполнения инструкции 1 такт
    !adc   R26  ,  R27       ' Время выполнения инструкции 1 такт
    !sts   {Сумма_ацп + 2}  ,  R26       ' Время выполнения инструкции 2 такта
    !lds   R26  ,  {Сумма_ацп + 3}       ' Время выполнения инструкции 2 такта
    !adc   R26  ,  R27       ' Время выполнения инструкции 1 такт
    !sts   {Сумма_ацп + 3}  ,  R26       ' Время выполнения инструкции 2 такта

   'Считаем 4096 раз, количество измерений для 16-бит АЦП
    !lds R26 , {Счетчик_измерений_ацп}
    !lds R27 , {Счетчик_измерений_ацп + 1}
    !subi R26 , (-1)
    !sbci R27 , (-1)
    !sts {Счетчик_измерений_ацп} , R26
    !sts {Счетчик_измерений_ацп + 1} , R27

   'Если Счетчик_измерений_ацп > 4095
    !cpi R26 , &HFF
    !ldi R26 , &H0F
    !cpc R27 , R26
    !brcs Выход_прерывание_ацп
    !breq Выход_прерывание_ацп

   'Сброс "Счетчик_измерений_ацп" в "0"
    !ldi R26 , 0
    !sts {Счетчик_измерений_ацп} , R26
    !sts {Счетчик_измерений_ацп + 1} , R26

   'Деление на "64" или сдвиг вправо на "6", кому, как больше нравится
    !ldi R26 , 6
    !mov R8 , R26

    !lds R26 , {Сумма_ацп}
    !lds R27 , {Сумма_ацп + 1}
    !lds R30 , {Сумма_ацп + 2}
    !lds R31 , {Сумма_ацп + 3}

   Сдвиг_вправо:
    !lsr R31
    !ror R30
    !ror R27
    !ror R26
    !dec R8
    !brne Сдвиг_вправо

   'Забираем данные
    !sts {16_bit_данные_ацп} , R26
    !sts {16_bit_данные_ацп + 1} , R27
    !sts {16_bit_данные_ацп + 2} , R30
    !sts {16_bit_данные_ацп + 3} , R31

   'Обнуление переменной
    !ldi R16 , 0
    !sts {Сумма_ацп} , R16
    !sts {Сумма_ацп + 1} , R16
    !sts {Сумма_ацп + 2} , R16
    !sts {Сумма_ацп + 3} , R16

   'Поднимаем флаг
    !ldi R16 , 1
    !sts {Флаг_есть_данные_usart} , R16

   Выход_прерывание_ацп:

'Восстанавливаем регистры, которые используем в обработке
    !pop R31
    !pop R30
    !pop R27
'Восстанавливаем SREG
    !pop R26
    !Out Sreg , R26
    !Pop R26
    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

+1

8

Получение данных со всего АЦП по переполнению TIMER0, т.е., сработавшее прерывание TIMER0 запускает измерение АЦП, по готовности, генерируется прерывание от АЦП, идём и забираем данные.   

Симуляция + исходник  -  скачать

http://se.uploads.ru/t/qwy4r.jpg

0

9


Программное повышение разрядности АЦП, по буржуйски "оверсэмплинг", продолжение темы.


Снятие временных интервалов, и качества измерений


U питания МК = 5 V (очень стабилизированое и отфильтрованное = тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> LM7805 ==> 2 200 мкф ==> МК)

Aref = 4.096 V (= тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> REF198E)

Частота МК Atmega328P = 8 МГц - внутренний генератор
Prescaler АЦП = 2
Режим запуска АЦП = Free

Дискретность 4 mV, время 10-ти битного измерения в реальном железе = ~ 9 мкс
Дискретность 2 mV, время 11-ти битного измерения в реальном железе = ~ 50 мкс
Дискретность 1 mV, время 12-ти битного измерения в реальном железе = ~ 200 мкс
Дискретность 500 мкV, время 13-ти битного измерения в реальном железе = ~ 800 мкс
Дискретность 250 мкV, время 14-ти битного измерения в реальном железе = ~ 3,5 ms
Дискретность 125 мкV, время 15-ти битного измерения в реальном железе = ~ 14 ms
Дискретность 62,5 мкV, время 16-ти битного измерения в реальном железе = ~ 55 ms
Дискретность 31,25 мкV, время 17-ти битного измерения в реальном железе = ~ 219 ms
Дискретность 15,625 мкV, время 18-ти битного измерения в реальном железе = ~ 862 ms


Измерение напряжения батарейки CR2032, измерялось через переменный резистивный делитель 2 МОм
меняется каждый из (262144) отсчет АЦП в 18 битном режиме, соответственно меньшая битность, тоже меняется, каждый отсчёт.

Меняется каждый отсчет АЦП

18 бит - 196608
18 бит - 3.072000023
18 бит - 196608
18 бит - 3.072000023
18 бит - 196608
18 бит - 3.072000023
18 бит - 196607
18 бит - 3.071984288
18 бит - 196606
18 бит - 3.071968791
18 бит - 196606
18 бит - 3.071968791
18 бит - 196605
18 бит - 3.071953055
18 бит - 196603
18 бит - 3.071921821
18 бит - 196605
18 бит - 3.071953055
18 бит - 196604
18 бит - 3.071937559
18 бит - 196604
18 бит - 3.071937559
18 бит - 196606
18 бит - 3.071968791
18 бит - 196603
18 бит - 3.071921821
18 бит - 196605
18 бит - 3.071953055
18 бит - 196604
18 бит - 3.071937559
18 бит - 196603
18 бит - 3.071921821
18 бит - 196599
18 бит - 3.071859357
18 бит - 196599
18 бит - 3.071859357
18 бит - 196600
18 бит - 3.071875092
18 бит - 196594
18 бит - 3.071781157
18 бит - 196592
18 бит - 3.071749922
18 бит - 196591
18 бит - 3.071734425
18 бит - 196594
18 бит - 3.071781157
18 бит - 196591

18 бит - 3.071734425
18 бит - 196592
18 бит - 3.071749922
18 бит - 196591
18 бит - 3.071734425
18 бит - 196588
18 бит - 3.071687456
18 бит - 196587
18 бит - 3.071671959
18 бит - 196588
18 бит - 3.071687456
18 бит - 196591
18 бит - 3.071734425
18 бит - 196587
18 бит - 3.071671959
18 бит - 196588
18 бит - 3.071687456
18 бит - 196587
18 бит - 3.071671959
18 бит - 196580
18 бит - 3.071562524
18 бит - 196581
18 бит - 3.071578260
18 бит - 196583
18 бит - 3.071609495
18 бит - 196582
18 бит - 3.071593756

10 бит - 768
10 бит -  3.072000023
11 бит - 1536
11 бит -  3.072000023
12 бит - 3072
12 бит -  3.072000023
13 бит - 6144
13 бит -  3.072000023
14 бит - 12288
14 бит -  3.072000023
15 бит - 24576
15 бит -  3.072000023
16 бит - 49152
16 бит -  3.072000023
17 бит - 98304
17 бит - 3.072000023
18 бит - 196608
18 бит - 3.072000023


Всё одним архивом - скачать


10 бит

http://s1.uploads.ru/t/bjYAt.jpg

Исходник

'===============================================================================

  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       'Документация Atmel - http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 8000000
  $framesize = 32       ' Размер области используемой и необходимой для преобразований
  $hwstack = 40       ' Размер аппаратного стека
  $swstack = 16       ' Размер программного стека

  $baud = 38400       ': Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'===============================================================================
'          Настройка вывода МК для работы с осциллографом (разные измерения)
'===============================================================================
  Осциллограф Alias Portb.0 : Config Осциллограф = Output : Reset Осциллограф

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
  Config Adc = Free , Prescaler = 2 , Reference = Aref

  On Adc Обработка_прерывания_adc Nosave

'----------------------  Используемые переменные  ------------------------------
  Dim Флаг_работа_паяльника As Byte
  Dim Флаг_есть_10_бит_ацп As Byte
  Dim Счетчик_измерений_ацп As Byte
  Dim Сумма_ацп As Word
  Dim 10_bit_данные_ацп As Word
  Dim 10_bit_данные_ацп_single As Single
  Dim 10_bit_данные_ацп_str As String * 15

'--------------  Разрешаем работу необходимых прерываний  ----------------------

'Правильно работает только при такой инициализации
  Adcsra.aden = 1       ' Bit 7 – ADEN: ADC Enable / Disable
  Adcsra.adsc = 1       ' Bit 6 – ADSC: ADC Start / Stop Conversion
  Adcsra.adate = 0       ' Bit 5 – ADATE: ADC Auto Trigger Enable
  Adcsra.adif = 0       ' Bit 4 – ADIF: ADC Interrupt Flag
  Adcsra.adie = 1       ' Bit 3 – ADIE: ADC Interrupt Enable / Disable

'  Enable Adc : Start Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

     'U питания МК = 5 V (очень стабилизированое и отфильтрованное = тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> LM7805 ==> 2 200 мкф ==> МК)
     'Aref = 4.096 V (= тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> REF198E)

     'Частота МК Atmega328P = 8 МГц - внутренний генератор
     'Prescaler АЦП = 2
     'Режим запуска АЦП = Free
     'Дискретность 4 mV
     'Время 10-ти битного измерения в реальном железе = ~ 9 мкс

      If Флаг_есть_10_бит_ацп <> 0 Then

          10_bit_данные_ацп_single = 10_bit_данные_ацп * 0.004

          10_bit_данные_ацп_str = Fusing(10_bit_данные_ацп_single , "#.&&&&&&&&&")

          10_bit_данные_ацп_str = Format(10_bit_данные_ацп_str , "           0")

          Print "10 бит - " ; 10_bit_данные_ацп

          Print "10 бит - " ; 10_bit_данные_ацп_str

          Waitms 500

          Set Осциллограф

          Флаг_есть_10_бит_ацп = 0
          Goto Главный_цикл
      End If

      Power Adcnoise       ' -  нельзя использовать по причине неработы прерываний INT0 (смотреть документацию с.39 (Power Managementand Sleep Modes))

'===============================================================================
  Goto Главный_цикл
End
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
    !Push R16

    !in R16 , adcl
    !sts {10_bit_данные_ацп} , R16
    !in R16 , adch
    !sts {10_bit_данные_ацп + 1} , R16

   'Поднимаем флаг о готовности результата
    !ldi R16 , 1
    !sts {Флаг_есть_10_бит_ацп} , R16

   'Выключаем прерывание от АЦП
'    !lds R16 , ADCSRA
'    !andi R16 , &B_1111_0111       ' Bit 3 – ADIE: ADC Interrupt Disable
'    !sts ADCSRA , R16

    Reset Осциллограф

   Выход_прерывания_adc:
   'Восстанавливаем регистры
    !Pop R16

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

11 бит

http://s1.uploads.ru/t/sp3wf.jpg

Исходник

'===============================================================================

  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       'Документация Atmel - http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 8000000
  $framesize = 32       ' Размер области используемой и необходимой для преобразований
  $hwstack = 40       ' Размер аппаратного стека
  $swstack = 16       ' Размер программного стека

  $baud = 38400       ': Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'===============================================================================
'          Настройка вывода МК для работы с осциллографом (разные измерения)
'===============================================================================
  Осциллограф Alias Portb.0 : Config Осциллограф = Output : Reset Осциллограф

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
  Config Adc = Free , Prescaler = 2 , Reference = Aref

  On Adc Обработка_прерывания_adc Nosave

'----------------------  Используемые переменные  ------------------------------
  Dim Флаг_работа_паяльника As Byte
  Dim Флаг_есть_11_бит_ацп As Byte
  Dim Счетчик_измерений_ацп As Byte
  Dim Сумма_ацп As Word
  Dim 11_bit_данные_ацп As Word
  Dim 11_bit_данные_ацп_single As Single
  Dim 11_bit_данные_ацп_str As String * 15

'--------------  Разрешаем работу необходимых прерываний  ----------------------

'Правильно работает только при такой инициализации
  Adcsra.aden = 1       ' Bit 7 – ADEN: ADC Enable / Disable
  Adcsra.adsc = 1       ' Bit 6 – ADSC: ADC Start / Stop Conversion
  Adcsra.adate = 0       ' Bit 5 – ADATE: ADC Auto Trigger Enable
  Adcsra.adif = 0       ' Bit 4 – ADIF: ADC Interrupt Flag
  Adcsra.adie = 1       ' Bit 3 – ADIE: ADC Interrupt Enable / Disable

'  Enable Adc : Start Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

     'U питания МК = 5 V (очень стабилизированое и отфильтрованное = тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> LM7805 ==> 2 200 мкф ==> МК)
     'Aref = 4.096 V (= тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> REF198E)

     'Частота МК Atmega328P = 8 МГц - внутренний генератор
     'Prescaler АЦП = 2
     'Режим запуска АЦП = Free
     'Дискретность 2 mV
     'Время 11-ти битного измерения в реальном железе = ~ 50 мкс

      If Флаг_есть_11_бит_ацп <> 0 Then

         '11 бит = оверсэмплинг из  4 измерений
          11_bit_данные_ацп_single = 11_bit_данные_ацп * 0.002

          11_bit_данные_ацп_str = Fusing(11_bit_данные_ацп_single , "#.&&&&&&&&&")

          11_bit_данные_ацп_str = Format(11_bit_данные_ацп_str , "           0")

          Print "11 бит - " ; 11_bit_данные_ацп

          Print "11 бит - " ; 11_bit_данные_ацп_str

          Waitms 500

          Set Осциллограф

          Флаг_есть_11_бит_ацп = 0
          Goto Главный_цикл
      End If

      Power Adcnoise       ' -  нельзя использовать по причине неработы прерываний INT0 (смотреть документацию с.39 (Power Managementand Sleep Modes))

'===============================================================================
  Goto Главный_цикл
End
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
   'Т.к., используются логические операции, обязательно сохраняем SREG
    !Push R26
    !In R26 , Sreg
    !Push R26
    !Push R27

   'Набираем сумму из 4 измерений, для получения 11 бит
    !lds R26 , {Сумма_ацп}
    !in R27 , adcl
    !add R26 , R27
    !sts {Сумма_ацп} , R26

    !lds R26 , {Сумма_ацп + 1}
    !in R27 , adch
    !adc R26 , R27
    !sts {Сумма_ацп + 1} , R26

   'Считаем измерения
    !lds R26 , {Счетчик_измерений_ацп}
    !inc R26
    !sts {Счетчик_измерений_ацп} , R26
   'Если =4
    !cpi R26 , 4
    !BREQ Получение_11_бит
    !rjmp Выход_прерывания_adc

   Получение_11_бит:
    !lds R26, {Сумма_ацп}
    !lds R27 , {Сумма_ацп + 1}

   'Cдвиг:
    !lsr R27
    !ror R26

   'Забираем готовые 11 бит данные
    !sts {11_bit_данные_ацп} , R26
    !sts {11_bit_данные_ацп + 1} , R27

   'Обнуляем переменные для следующего измерения
    !ldi R26 , 0
    !sts {Сумма_ацп} , R26
    !sts {Сумма_ацп + 1} , R26
    !sts {Счетчик_измерений_ацп} , R26

   'Поднимаем флаг о готовности результата
    !ldi R26 , 1
    !sts {Флаг_есть_11_бит_ацп} , R26

   'Выключаем прерывание от АЦП
'    !lds R26 , ADCSRA
'    !andi R26 , &B_1111_0111       ' Bit 3 – ADIE: ADC Interrupt Disable
'    !sts ADCSRA , R26

    Reset Осциллограф

    nop

   Выход_прерывания_adc:
   'Восстанавливаем регистры и SREG
    !pop R27
    !pop R26
    !Out Sreg , R26
    !Pop R26

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

12 бит

http://sh.uploads.ru/t/KbVoh.jpg

Исходник

'===============================================================================

  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       'Документация Atmel - http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 8000000
  $framesize = 32       ' Размер области используемой и необходимой для преобразований
  $hwstack = 40       ' Размер аппаратного стека
  $swstack = 16       ' Размер программного стека

  $baud = 38400       ': Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'===============================================================================
'          Настройка вывода МК для работы с осциллографом (разные измерения)
'===============================================================================
  Осциллограф Alias Portb.0 : Config Осциллограф = Output : Reset Осциллограф

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
  Config Adc = Free , Prescaler = 2 , Reference = Aref

  On Adc Обработка_прерывания_adc Nosave

'----------------------  Используемые переменные  ------------------------------
  Dim Флаг_работа_паяльника As Byte
  Dim Флаг_есть_12_бит_ацп As Byte
  Dim Счетчик_измерений_ацп As Byte
  Dim Сумма_ацп As Word
  Dim 12_bit_данные_ацп As Word
  Dim 12_bit_данные_ацп_single As Single
  Dim 12_bit_данные_ацп_str As String * 15

'--------------  Разрешаем работу необходимых прерываний  ----------------------

'Правильно работает только при такой инициализации
  Adcsra.aden = 1       ' Bit 7 – ADEN: ADC Enable / Disable
  Adcsra.adsc = 1       ' Bit 6 – ADSC: ADC Start / Stop Conversion
  Adcsra.adate = 0       ' Bit 5 – ADATE: ADC Auto Trigger Enable
  Adcsra.adif = 0       ' Bit 4 – ADIF: ADC Interrupt Flag
  Adcsra.adie = 1       ' Bit 3 – ADIE: ADC Interrupt Enable / Disable

'  Enable Adc : Start Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

     'U питания МК = 5 V (очень стабилизированое и отфильтрованное = тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> LM7805 ==> 2 200 мкф ==> МК)
     'Aref = 4.096 V (= тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> REF198E)

     'Частота МК Atmega328P = 8 МГц - внутренний генератор
     'Prescaler АЦП = 2
     'Режим запуска АЦП = Free
     'Дискретность 1 mV
     'Время 12-ти битного измерения в реальном железе = ~ 200 мкс

      If Флаг_есть_12_бит_ацп <> 0 Then

         '12 бит = оверсэмплинг из  16 измерений
          12_bit_данные_ацп_single = 12_bit_данные_ацп * 0.001

          12_bit_данные_ацп_str = Fusing(12_bit_данные_ацп_single , "#.&&&&&&&&&")

          12_bit_данные_ацп_str = Format(12_bit_данные_ацп_str , "           0")

          Print "12 бит - " ; 12_bit_данные_ацп

          Print "12 бит - " ; 12_bit_данные_ацп_str

          Waitms 500

          Set Осциллограф

          Флаг_есть_12_бит_ацп = 0
          Goto Главный_цикл
      End If

      Power Adcnoise       ' -  нельзя использовать по причине неработы прерываний INT0 (смотреть документацию с.39 (Power Managementand Sleep Modes))

'===============================================================================
  Goto Главный_цикл
End
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
   'Т.к., используются логические операции, обязательно сохраняем SREG
    !Push R26
    !In R26 , Sreg
    !Push R26
    !Push R27

   'Набираем сумму из 16 измерений, для получения 12 бит
    !lds R26 , {Сумма_ацп}
    !in R27 , adcl
    !add R26 , R27
    !sts {Сумма_ацп} , R26

    !lds R26 , {Сумма_ацп + 1}
    !in R27 , adch
    !adc R26 , R27
    !sts {Сумма_ацп + 1} , R26

   'Считаем измерения
    !lds R26 , {Счетчик_измерений_ацп}
    !inc R26
    !sts {Счетчик_измерений_ацп} , R26
   'Если =16
    !cpi R26 , 16
    !BREQ Получение_12_бит
    !rjmp Выход_прерывания_adc

   Получение_12_бит:
    !lds R26, {Сумма_ацп}
    !lds R27 , {Сумма_ацп + 1}

   'Cдвиг:
    !lsr R27
    !ror R26
    !lsr R27
    !ror R26
'    !lsr R27
'    !ror R26

   'Забираем готовые 12 бит данные
    !sts {12_bit_данные_ацп} , R26
    !sts {12_bit_данные_ацп + 1} , R27

   'Обнуляем переменные для следующего измерения
    !ldi R26 , 0
    !sts {Сумма_ацп} , R26
    !sts {Сумма_ацп + 1} , R26
    !sts {Счетчик_измерений_ацп} , R26

   'Поднимаем флаг о готовности результата
    !ldi R26 , 1
    !sts {Флаг_есть_12_бит_ацп} , R26

   'Выключаем прерывание от АЦП
'    !lds R26 , ADCSRA
'    !andi R26 , &B_1111_0111       ' Bit 3 – ADIE: ADC Interrupt Disable
'    !sts ADCSRA , R26

    Reset Осциллограф

    nop

   Выход_прерывания_adc:
   'Восстанавливаем регистры и SREG
    !pop R27
    !pop R26
    !Out Sreg , R26
    !Pop R26

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

13 бит

http://sg.uploads.ru/t/gOHAS.jpg

Исходник

'===============================================================================

  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       'Документация Atmel - http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 8000000
  $framesize = 32       ' Размер области используемой и необходимой для преобразований
  $hwstack = 40       ' Размер аппаратного стека
  $swstack = 16       ' Размер программного стека

  $baud = 38400       ': Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'===============================================================================
'          Настройка вывода МК для работы с осциллографом (разные измерения)
'===============================================================================
  Осциллограф Alias Portb.0 : Config Осциллограф = Output : Reset Осциллограф

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
  Config Adc = Free , Prescaler = 2 , Reference = Aref

  On Adc Обработка_прерывания_adc Nosave

'----------------------  Используемые переменные  ------------------------------
  Dim Флаг_работа_паяльника As Byte
  Dim Флаг_есть_13_бит_ацп As Byte
  Dim Счетчик_измерений_ацп As Byte
  Dim Сумма_ацп As Word
  Dim 13_bit_данные_ацп As Word
  Dim 13_bit_данные_ацп_single As Single
  Dim 13_bit_данные_ацп_str As String * 15

'--------------  Разрешаем работу необходимых прерываний  ----------------------

'Правильно работает только при такой инициализации
  Adcsra.aden = 1       ' Bit 7 – ADEN: ADC Enable / Disable
  Adcsra.adsc = 1       ' Bit 6 – ADSC: ADC Start / Stop Conversion
  Adcsra.adate = 0       ' Bit 5 – ADATE: ADC Auto Trigger Enable
  Adcsra.adif = 0       ' Bit 4 – ADIF: ADC Interrupt Flag
  Adcsra.adie = 1       ' Bit 3 – ADIE: ADC Interrupt Enable / Disable

'  Enable Adc : Start Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

     'U питания МК = 5 V (очень стабилизированое и отфильтрованное = тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> LM7805 ==> 2 200 мкф ==> МК)
     'Aref = 4.096 V (= тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> REF198E)

     'Частота МК Atmega328P = 8 МГц - внутренний генератор
     'Prescaler АЦП = 2
     'Режим запуска АЦП = Free
     'Дискретность 500 мкV
     'Время 13-ти битного измерения в реальном железе = ~ 800 мкс

      If Флаг_есть_13_бит_ацп <> 0 Then

         '13 бит = оверсэмплинг из  64 измерений
          13_bit_данные_ацп_single = 13_bit_данные_ацп * 0.0005

          13_bit_данные_ацп_str = Fusing(13_bit_данные_ацп_single , "#.&&&&&&&&&")

          13_bit_данные_ацп_str = Format(13_bit_данные_ацп_str , "           0")

          Print "13 бит - " ; 13_bit_данные_ацп

          Print "13 бит - " ; 13_bit_данные_ацп_str

          Waitms 500

          Set Осциллограф

          Флаг_есть_13_бит_ацп = 0
          Goto Главный_цикл
      End If

      Power Adcnoise       ' -  нельзя использовать по причине неработы прерываний INT0 (смотреть документацию с.39 (Power Managementand Sleep Modes))

'===============================================================================
  Goto Главный_цикл
End
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
   'Т.к., используются логические операции, обязательно сохраняем SREG
    !Push R26
    !In R26 , Sreg
    !Push R26
    !Push R27

   'Набираем сумму из 64 измерений, для получения 13 бит
    !lds R26 , {Сумма_ацп}
    !in R27 , adcl
    !add R26 , R27
    !sts {Сумма_ацп} , R26

    !lds R26 , {Сумма_ацп + 1}
    !in R27 , adch
    !adc R26 , R27
    !sts {Сумма_ацп + 1} , R26

   'Считаем измерения
    !lds R26 , {Счетчик_измерений_ацп}
    !inc R26
    !sts {Счетчик_измерений_ацп} , R26
   'Если =64
    !cpi R26 , 64
    !BREQ Получение_13_бит
    !rjmp Выход_прерывания_adc

   Получение_13_бит:
    !lds R26, {Сумма_ацп}
    !lds R27 , {Сумма_ацп + 1}

   'Cдвиг:
    !lsr R27
    !ror R26
    !lsr R27
    !ror R26
    !lsr R27
    !ror R26

   'Забираем готовые 13 бит данные
    !sts {13_bit_данные_ацп} , R26
    !sts {13_bit_данные_ацп + 1} , R27

   'Обнуляем переменные для следующего измерения
    !ldi R26 , 0
    !sts {Сумма_ацп} , R26
    !sts {Сумма_ацп + 1} , R26
    !sts {Счетчик_измерений_ацп} , R26

   'Поднимаем флаг о готовности результата
    !ldi R26 , 1
    !sts {Флаг_есть_13_бит_ацп} , R26

   'Выключаем прерывание от АЦП
'    !lds R26 , ADCSRA
'    !andi R26 , &B_1111_0111       ' Bit 3 – ADIE: ADC Interrupt Disable
'    !sts ADCSRA , R26

    Reset Осциллограф

    nop

   Выход_прерывания_adc:
   'Восстанавливаем регистры и SREG
    !pop R27
    !pop R26
    !Out Sreg , R26
    !Pop R26

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

14 бит

http://sh.uploads.ru/t/uJZfG.jpg

Исходник

'===============================================================================

  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       'Документация Atmel - http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 8000000
  $framesize = 32       ' Размер области используемой и необходимой для преобразований
  $hwstack = 40       ' Размер аппаратного стека
  $swstack = 16       ' Размер программного стека

  $baud = 38400       ': Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'===============================================================================
'          Настройка вывода МК для работы с осциллографом (разные измерения)
'===============================================================================
  Осциллограф Alias Portb.0 : Config Осциллограф = Output : Reset Осциллограф

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
  Config Adc = Free , Prescaler = 2 , Reference = Aref

  On Adc Обработка_прерывания_adc Nosave

'----------------------  Используемые переменные  ------------------------------
  Dim Флаг_работа_паяльника As Byte
  Dim Флаг_есть_14_бит_ацп As Byte
  Dim Счетчик_измерений_ацп As Byte
  Dim Сумма_ацп As Long
  Dim 14_bit_данные_ацп As Word
  Dim 14_bit_данные_ацп_single As Single
  Dim 14_bit_данные_ацп_str As String * 15

'--------------  Разрешаем работу необходимых прерываний  ----------------------

'Правильно работает только при такой инициализации
  Adcsra.aden = 1       ' Bit 7 – ADEN: ADC Enable / Disable
  Adcsra.adsc = 1       ' Bit 6 – ADSC: ADC Start / Stop Conversion
  Adcsra.adate = 0       ' Bit 5 – ADATE: ADC Auto Trigger Enable
  Adcsra.adif = 0       ' Bit 4 – ADIF: ADC Interrupt Flag
  Adcsra.adie = 1       ' Bit 3 – ADIE: ADC Interrupt Enable / Disable

'  Enable Adc : Start Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

     'U питания МК = 5 V (очень стабилизированое и отфильтрованное = тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> LM7805 ==> 2 200 мкф ==> МК)
     'Aref = 4.096 V (= тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> REF198E)

     'Частота МК Atmega328P = 8 МГц - внутренний генератор
     'Prescaler АЦП = 2
     'Режим запуска АЦП = Free
     'Дискретность 250 мкV
     'Время 14-ти битного измерения в реальном железе = ~ 3,5 ms

      If Флаг_есть_14_бит_ацп <> 0 Then

         '14 бит = оверсэмплинг из  256 измерений
          14_bit_данные_ацп_single = 14_bit_данные_ацп * 0.00025

          14_bit_данные_ацп_str = Fusing(14_bit_данные_ацп_single , "#.&&&&&&&&&")

          14_bit_данные_ацп_str = Format(14_bit_данные_ацп_str , "           0")

          Print "14 бит - " ; 14_bit_данные_ацп

          Print "14 бит - " ; 14_bit_данные_ацп_str

          Waitms 500

          Set Осциллограф

          Флаг_есть_14_бит_ацп = 0
          Goto Главный_цикл
      End If

      Power Adcnoise       ' -  нельзя использовать по причине неработы прерываний INT0 (смотреть документацию с.39 (Power Managementand Sleep Modes))

'===============================================================================
  Goto Главный_цикл
End
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
   'Т.к., используются логические операции, обязательно сохраняем SREG
    !Push R26
    !In R26 , Sreg
    !Push R26
    !Push R27

   'Набираем сумму из 256 измерений, для получения 14 бит
    !lds R26 , {Сумма_ацп}
    !in R27 , adcl
    !add R26 , R27
    !sts {Сумма_ацп} , R26

    !lds R26 , {Сумма_ацп + 1}
    !in R27 , adch
    !adc R26 , R27
    !sts {Сумма_ацп + 1} , R26

    !lds   R26  ,  {Сумма_ацп + 2}
    !clr   R27
    !adc   R26  ,  R27
    !sts   {Сумма_ацп + 2}  ,  R26

    !lds   R26  ,  {Сумма_ацп + 3}
    !adc   R26  ,  R27
    !sts   {Сумма_ацп + 3}  ,  R26

   'Считаем измерения
    !lds R26 , {Счетчик_измерений_ацп}
    !inc R26
    !sts {Счетчик_измерений_ацп} , R26
   'Если =256
    !cpi R26 , 0
    !BREQ Получение_14_бит
    !rjmp Выход_прерывания_adc

   Получение_14_бит:
    !Push R16
    !Push R17
    !Push R18
    !Push R19

    !ldi R26 , 4

    !lds R16 , {Сумма_ацп}
    !lds R17 , {Сумма_ацп + 1}
    !lds R18 , {Сумма_ацп + 2}
    !lds R19 , {Сумма_ацп + 3}

   Еще_сдвиг:
    !lsr R19
    !ror R18
    !ror R17
    !ror R16

    !dec R26
    !brne Еще_сдвиг

   'Забираем готовые 14 бит данные
    !sts {14_bit_данные_ацп} , R16
    !sts {14_bit_данные_ацп + 1} , R17
    !sts {14_bit_данные_ацп + 2} , R18
    !sts {14_bit_данные_ацп + 3} , R19

    !pop R19
    !pop R18
    !pop R17
    !pop R16

   'Обнуляем переменные для следующего измерения
    !ldi R26 , 0
    !sts {Сумма_ацп} , R26
    !sts {Сумма_ацп + 1} , R26
    !sts {Сумма_ацп + 2} , R26
    !sts {Сумма_ацп + 3} , R26
    !sts {Счетчик_измерений_ацп} , R26

   'Поднимаем флаг о готовности результата
    !ldi R26 , 1
    !sts {Флаг_есть_14_бит_ацп} , R26

   'Выключаем прерывание от АЦП
'    !lds R26 , ADCSRA
'    !andi R26 , &B_1111_0111       ' Bit 3 – ADIE: ADC Interrupt Disable
'    !sts ADCSRA , R26

    Reset Осциллограф

    nop

   Выход_прерывания_adc:
   'Восстанавливаем регистры и SREG
    !pop R27
    !pop R26
    !Out Sreg , R26
    !Pop R26

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

15 бит

http://sg.uploads.ru/t/4LMe5.jpg

Исходник

'===============================================================================

  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       'Документация Atmel - http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 8000000
  $framesize = 32       ' Размер области используемой и необходимой для преобразований
  $hwstack = 40       ' Размер аппаратного стека
  $swstack = 16       ' Размер программного стека

  $baud = 38400       ': Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'===============================================================================
'          Настройка вывода МК для работы с осциллографом (разные измерения)
'===============================================================================
  Осциллограф Alias Portb.0 : Config Осциллограф = Output : Reset Осциллограф

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
  Config Adc = Free , Prescaler = 2 , Reference = Aref

  On Adc Обработка_прерывания_adc Nosave

'----------------------  Используемые переменные  ------------------------------
  Dim Флаг_есть_15_бит_ацп As Byte
  Dim Счетчик_256_измерений_ацп As Byte
  Dim Счетчик_1024_измерений_ацп As Byte
  Dim Сумма_ацп As Long
  Dim 15_bit_данные_ацп As Long
  Dim 15_bit_данные_ацп_single As Single
  Dim 15_bit_данные_ацп_str As String * 15

'--------------  Разрешаем работу необходимых прерываний  ----------------------

'Правильно работает только при такой инициализации
  Adcsra.aden = 1       ' Bit 7 – ADEN: ADC Enable / Disable
  Adcsra.adsc = 1       ' Bit 6 – ADSC: ADC Start / Stop Conversion
  Adcsra.adate = 0       ' Bit 5 – ADATE: ADC Auto Trigger Enable
  Adcsra.adif = 0       ' Bit 4 – ADIF: ADC Interrupt Flag
  Adcsra.adie = 1       ' Bit 3 – ADIE: ADC Interrupt Enable / Disable

'  Enable Adc : Start Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

     'U питания МК = 5 V (очень стабилизированое и отфильтрованное = тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> LM7805 ==> 2 200 мкф ==> МК)
     'Aref = 4.096 V (= тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> REF198E)

     'Частота МК Atmega328P = 8 МГц - внутренний генератор
     'Prescaler АЦП = 2
     'Режим запуска АЦП = Free
     'Дискретность 125 мкV
     'Время 15-ти битного измерения в реальном железе = ~ 14 ms

      If Флаг_есть_15_бит_ацп <> 0 Then

         '15 бит = оверсэмплинг из  1024 измерений
          15_bit_данные_ацп_single = 15_bit_данные_ацп * 0.000125

          15_bit_данные_ацп_str = Fusing(15_bit_данные_ацп_single , "#.&&&&&&&&&")

          15_bit_данные_ацп_str = Format(15_bit_данные_ацп_str , "           0")

          Print "15 бит - " ; 15_bit_данные_ацп

          Print "15 бит - " ; 15_bit_данные_ацп_str

          Waitms 500

          Set Осциллограф

          Флаг_есть_15_бит_ацп = 0
          Goto Главный_цикл
      End If

      Power Adcnoise       ' -  нельзя использовать по причине неработы прерываний INT0 (смотреть документацию с.39 (Power Managementand Sleep Modes))

'===============================================================================
  Goto Главный_цикл
End
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
   'Т.к., используются логические операции, обязательно сохраняем SREG
    !Push R26
    !In R26 , Sreg
    !Push R26
    !Push R27

   'Набираем сумму из 1024 измерений, для получения 15 бит
    !lds R26 , {Сумма_ацп}
    !in R27 , adcl
    !add R26 , R27
    !sts {Сумма_ацп} , R26

    !lds R26 , {Сумма_ацп + 1}
    !in R27 , adch
    !adc R26 , R27
    !sts {Сумма_ацп + 1} , R26

    !lds   R26  ,  {Сумма_ацп + 2}
    !clr   R27
    !adc   R26  ,  R27
    !sts   {Сумма_ацп + 2}  ,  R26

    !lds   R26  ,  {Сумма_ацп + 3}
    !adc   R26  ,  R27
    !sts   {Сумма_ацп + 3}  ,  R26

   'Считаем 1024 измерениz, 2 байтовых счётчика, так быстрее
   Считаем_256:
    !lds R26 , {Счетчик_256_измерений_ацп}
    !inc R26
    !sts {Счетчик_256_измерений_ацп} , R26
   'Если =256
    !cpi R26 , 0
    !BREQ Считаем_1024
    !rjmp Выход_прерывания_adc

   Считаем_1024:
    !lds R26 , {Счетчик_1024_измерений_ацп}
    !inc R26
    !sts {Счетчик_1024_измерений_ацп} , R26
   'Если =4, почему 4 (4 * 256 = 1024)
    !cpi R26 , 4
    !BREQ Получение_15_бит
    !rjmp Выход_прерывания_adc

   Получение_15_бит:
    !Push R16
    !Push R17
    !Push R18
    !Push R19

    !ldi R26 , 5

    !lds R16 , {Сумма_ацп}
    !lds R17 , {Сумма_ацп + 1}
    !lds R18 , {Сумма_ацп + 2}
    !lds R19 , {Сумма_ацп + 3}

   Еще_сдвиг:
    !lsr R19
    !ror R18
    !ror R17
    !ror R16

    !dec R26
    !brne Еще_сдвиг

   'Забираем готовые 15 бит данные
    !sts {15_bit_данные_ацп} , R16
    !sts {15_bit_данные_ацп + 1} , R17
    !sts {15_bit_данные_ацп + 2} , R18
    !sts {15_bit_данные_ацп + 3} , R19

    !pop R19
    !pop R18
    !pop R17
    !pop R16

   'Обнуляем переменные для следующего измерения
    !ldi R26 , 0
    !sts {Сумма_ацп} , R26
    !sts {Сумма_ацп + 1} , R26
    !sts {Сумма_ацп + 2} , R26
    !sts {Сумма_ацп + 3} , R26
    !sts {Счетчик_256_измерений_ацп} , R26
    !sts {Счетчик_1024_измерений_ацп} , R26

   'Поднимаем флаг о готовности результата
    !ldi R26 , 1
    !sts {Флаг_есть_15_бит_ацп} , R26

   'Выключаем прерывание от АЦП
'    !lds R26 , ADCSRA
'    !andi R26 , &B_1111_0111       ' Bit 3 – ADIE: ADC Interrupt Disable
'    !sts ADCSRA , R26

    Reset Осциллограф

    nop

   Выход_прерывания_adc:
   'Восстанавливаем регистры и SREG
    !pop R27
    !pop R26
    !Out Sreg , R26
    !Pop R26

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

16 бит

http://sh.uploads.ru/t/agrhR.jpg

Исходник

'===============================================================================

  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       'Документация Atmel - http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 8000000
  $framesize = 32       ' Размер области используемой и необходимой для преобразований
  $hwstack = 40       ' Размер аппаратного стека
  $swstack = 16       ' Размер программного стека

  $baud = 38400       ': Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'===============================================================================
'          Настройка вывода МК для работы с осциллографом (разные измерения)
'===============================================================================
  Осциллограф Alias Portb.0 : Config Осциллограф = Output : Reset Осциллограф

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
  Config Adc = Free , Prescaler = 2 , Reference = Aref

  On Adc Обработка_прерывания_adc Nosave

'----------------------  Используемые переменные  ------------------------------
  Dim Флаг_работа_паяльника As Byte
  Dim Флаг_есть_16_бит_ацп As Byte
  Dim Счетчик_256_измерений_ацп As Byte
  Dim Счетчик_4096_измерений_ацп As Byte
  Dim Сумма_ацп As Long
  Dim 16_bit_данные_ацп As Word
  Dim 16_bit_данные_ацп_single As Single
  Dim 16_bit_данные_ацп_str As String * 15

'--------------  Разрешаем работу необходимых прерываний  ----------------------

'Правильно работает только при такой инициализации
  Adcsra.aden = 1       ' Bit 7 – ADEN: ADC Enable / Disable
  Adcsra.adsc = 1       ' Bit 6 – ADSC: ADC Start / Stop Conversion
  Adcsra.adate = 0       ' Bit 5 – ADATE: ADC Auto Trigger Enable
  Adcsra.adif = 0       ' Bit 4 – ADIF: ADC Interrupt Flag
  Adcsra.adie = 1       ' Bit 3 – ADIE: ADC Interrupt Enable / Disable

'  Enable Adc : Start Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

     'U питания МК = 5 V (очень стабилизированое и отфильтрованное = тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> LM7805 ==> 2 200 мкф ==> МК)
     'Aref = 4.096 V (= тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> REF198E)

     'Частота МК Atmega328P = 8 МГц - внутренний генератор
     'Prescaler АЦП = 2
     'Режим запуска АЦП = Free
     'Дискретность 62,5 мкV
     'Время 16-ти битного измерения в реальном железе = ~ 55 ms

      If Флаг_есть_16_бит_ацп <> 0 Then

          16_bit_данные_ацп_single = 16_bit_данные_ацп * 0.0000625

          16_bit_данные_ацп_str = Fusing(16_bit_данные_ацп_single , "#.&&&&&&&&&")

          16_bit_данные_ацп_str = Format(16_bit_данные_ацп_str , "           0")

          Print "16 бит - " ; 16_bit_данные_ацп

          Print "16 бит - " ; 16_bit_данные_ацп_str

          Waitms 500
          Set Осциллограф

          Флаг_есть_16_бит_ацп = 0
          Goto Главный_цикл
      End If

     Power Adcnoise       ' -  нельзя использовать по причине неработы прерываний INT0 (смотреть документацию с.39 (Power Managementand Sleep Modes))

'===============================================================================
  Goto Главный_цикл
End
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
   'Т.к., используются логические операции, обязательно сохраняем SREG
    !Push R26
    !In R26 , Sreg
    !Push R26
    !Push R27

   'Набираем сумму из 4096 измерений, для получения 16 бит
    !lds R26 , {Сумма_ацп}
    !in R27 , adcl
    !add R26 , R27
    !sts {Сумма_ацп} , R26

    !lds R26 , {Сумма_ацп + 1}
    !in R27 , adch
    !adc R26 , R27
    !sts {Сумма_ацп + 1} , R26

    !lds   R26  ,  {Сумма_ацп + 2}
    !clr   R27
    !adc   R26  ,  R27
    !sts   {Сумма_ацп + 2}  ,  R26

    !lds   R26  ,  {Сумма_ацп + 3}
    !adc   R26  ,  R27
    !sts   {Сумма_ацп + 3}  ,  R26

   'Считаем 4096 измерений, 2 байтовых счётчика, так быстрее
   Считаем_256:
    !lds R26 , {Счетчик_256_измерений_ацп}
    !inc R26
    !sts {Счетчик_256_измерений_ацп} , R26
   'Если =256
    !cpi R26 , 0
    !BREQ Считаем_4096
    !rjmp Выход_прерывания_adc

   Считаем_4096:
    !lds R26 , {Счетчик_4096_измерений_ацп}
    !inc R26
    !sts {Счетчик_4096_измерений_ацп} , R26
   'Если =16, почему 16 (16 * 256 = 4096)
    !cpi R26 , 16
    !BREQ Получение_16_бит
    !rjmp Выход_прерывания_adc

   Получение_16_бит:
    !Push R16
    !Push R17
    !Push R18
    !Push R19

    !ldi R26 , 6

    !lds R16 , {Сумма_ацп}
    !lds R17 , {Сумма_ацп + 1}
    !lds R18 , {Сумма_ацп + 2}
    !lds R19 , {Сумма_ацп + 3}

   Еще_сдвиг:
    !lsr R19
    !ror R18
    !ror R17
    !ror R16

    !dec R26
    !brne Еще_сдвиг

   'Забираем готовые 16 бит данные
    !sts {16_bit_данные_ацп} , R16
    !sts {16_bit_данные_ацп + 1} , R17
    !sts {16_bit_данные_ацп + 2} , R18
    !sts {16_bit_данные_ацп + 3} , R19

    !pop R19
    !pop R18
    !pop R17
    !pop R16

   'Обнуляем переменные для следующего измерения
    !ldi R26 , 0
    !sts {Сумма_ацп} , R26
    !sts {Сумма_ацп + 1} , R26
    !sts {Сумма_ацп + 2} , R26
    !sts {Сумма_ацп + 3} , R26
    !sts {Счетчик_256_измерений_ацп} , R26
    !sts {Счетчик_4096_измерений_ацп} , R26

   'Поднимаем флаг о готовности результата
    !ldi R26 , 1
    !sts {Флаг_есть_16_бит_ацп} , R26

   'Выключаем прерывание от АЦП
'    !lds R26 , ADCSRA
'    !andi R26 , &B_1111_0111       ' Bit 3 – ADIE: ADC Interrupt Disable
'    !sts ADCSRA , R26

    Reset Осциллограф

   Выход_прерывания_adc:
   'Восстанавливаем регистры и SREG
    !pop R27
    !pop R26
    !Out Sreg , R26
    !Pop R26

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

17 бит

http://s0.uploads.ru/t/wCjny.jpg

Исходник

'===============================================================================

  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       'Документация Atmel - http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 8000000
  $framesize = 32       ' Размер области используемой и необходимой для преобразований
  $hwstack = 40       ' Размер аппаратного стека
  $swstack = 16       ' Размер программного стека

  $baud = 38400       ': Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'===============================================================================
'          Настройка вывода МК для работы с осциллографом (разные измерения)
'===============================================================================
  Осциллограф Alias Portb.0 : Config Осциллограф = Output : Reset Осциллограф

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
  Config Adc = Free , Prescaler = 2 , Reference = Aref

  On Adc Обработка_прерывания_adc Nosave

'----------------------  Используемые переменные  ------------------------------
  Dim Флаг_работа_паяльника As Byte
  Dim Флаг_есть_17_бит_ацп As Byte
  Dim Счетчик_256_измерений_ацп As Byte
  Dim Счетчик_16384_измерений_ацп As Byte
  Dim Сумма_ацп As Long
  Dim 17_bit_данные_ацп As Long
  Dim 17_bit_данные_ацп_single As Single
  Dim 17_bit_данные_ацп_str As String * 15

'--------------  Разрешаем работу необходимых прерываний  ----------------------

'Правильно работает только при такой инициализации
  Adcsra.aden = 1       ' Bit 7 – ADEN: ADC Enable / Disable
  Adcsra.adsc = 1       ' Bit 6 – ADSC: ADC Start / Stop Conversion
  Adcsra.adate = 0       ' Bit 5 – ADATE: ADC Auto Trigger Enable
  Adcsra.adif = 0       ' Bit 4 – ADIF: ADC Interrupt Flag
  Adcsra.adie = 1       ' Bit 3 – ADIE: ADC Interrupt Enable / Disable

'  Enable Adc : Start Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

     'U питания МК = 5 V (очень стабилизированое и отфильтрованное = тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> LM7805 ==> 2 200 мкф ==> МК)
     'Aref = 4.096 V (= тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> REF198E)

     'Частота МК Atmega328P = 8 МГц - внутренний генератор
     'Prescaler АЦП = 2
     'Режим запуска АЦП = Free
     'Дискретность 31,25 мкV
     'Время 17-ти битного измерения в реальном железе = ~ 219 ms

      If Флаг_есть_17_бит_ацп <> 0 Then

         '17 бит = оверсэмплинг из  16384 измерений
          17_bit_данные_ацп_single = 17_bit_данные_ацп * 0.00003125

          17_bit_данные_ацп_str = Fusing(17_bit_данные_ацп_single , "#.&&&&&&&&&")

          17_bit_данные_ацп_str = Format(17_bit_данные_ацп_str , "         0")

          Print "17 бит - " ; 17_bit_данные_ацп

          Print "17 бит - " ; 17_bit_данные_ацп_str

          Waitms 200
          Set Осциллограф

          Флаг_есть_17_бит_ацп = 0
          Goto Главный_цикл
      End If

   Power Adcnoise       ' -  нельзя использовать по причине неработы прерываний INT0 (смотреть документацию с.39 (Power Managementand Sleep Modes))

'===============================================================================
  Goto Главный_цикл
End
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
   'Т.к., используются логические операции, обязательно сохраняем SREG
    !Push R26
    !In R26 , Sreg
    !Push R26
    !Push R27

   'Набираем сумму из 16384 измерений, для получения 17 бит
    !lds R26 , {Сумма_ацп}
    !in R27 , adcl
    !add R26 , R27
    !sts {Сумма_ацп} , R26

    !lds R26 , {Сумма_ацп + 1}
    !in R27 , adch
    !adc R26 , R27
    !sts {Сумма_ацп + 1} , R26

    !lds   R26  ,  {Сумма_ацп + 2}
    !clr   R27
    !adc   R26  ,  R27
    !sts   {Сумма_ацп + 2}  ,  R26

    !lds   R26  ,  {Сумма_ацп + 3}
    !adc   R26  ,  R27
    !sts   {Сумма_ацп + 3}  ,  R26

   'Считаем 16384 измерения, 2 байтовых счётчика, так быстрее
   Считаем_256:
    !lds R26 , {Счетчик_256_измерений_ацп}
    !inc R26
    !sts {Счетчик_256_измерений_ацп} , R26
   'Если =256
    !cpi R26 , 0
    !BREQ Считаем_16384
    !rjmp Выход_прерывания_adc

   Считаем_16384:
    !lds R26 , {Счетчик_16384_измерений_ацп}
    !inc R26
    !sts {Счетчик_16384_измерений_ацп} , R26
   'Если =64, почему 64 (64 * 256 = 16384)
    !cpi R26 , 64
    !BREQ Получение_17_бит
    !rjmp Выход_прерывания_adc

   Получение_17_бит:
    !Push R16
    !Push R17
    !Push R18
    !Push R19

    !ldi R26 , 7

    !lds R16 , {Сумма_ацп}
    !lds R17 , {Сумма_ацп + 1}
    !lds R18 , {Сумма_ацп + 2}
    !lds R19 , {Сумма_ацп + 3}

   Еще_сдвиг:
    !lsr R19
    !ror R18
    !ror R17
    !ror R16

    !dec R26
    !brne Еще_сдвиг

   'Забираем готовые 17 бит данные
    !sts {17_bit_данные_ацп} , R16
    !sts {17_bit_данные_ацп + 1} , R17
    !sts {17_bit_данные_ацп + 2} , R18
    !sts {17_bit_данные_ацп + 3} , R19

    !pop R19
    !pop R18
    !pop R17
    !pop R16

   'Обнуляем переменные для следующего измерения
    !ldi R26 , 0
    !sts {Сумма_ацп} , R26
    !sts {Сумма_ацп + 1} , R26
    !sts {Сумма_ацп + 2} , R26
    !sts {Сумма_ацп + 3} , R26
    !sts {Счетчик_256_измерений_ацп} , R26
    !sts {Счетчик_16384_измерений_ацп} , R26

   'Поднимаем флаг о готовности результата
    !ldi R26 , 1
    !sts {Флаг_есть_17_бит_ацп} , R26

   'Выключаем прерывание от АЦП
'    !lds R26 , ADCSRA
'    !andi R26 , &B_1111_0111       ' Bit 3 – ADIE: ADC Interrupt Disable
'    !sts ADCSRA , R26

    Reset Осциллограф

   Выход_прерывания_adc:
   'Восстанавливаем регистры и SREG
    !pop R27
    !pop R26
    !Out Sreg , R26
    !Pop R26

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

18 бит

http://sh.uploads.ru/t/BdKSu.jpg

Исходник

'===============================================================================

  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       'Документация Atmel - http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 8000000
  $framesize = 32       ' Размер области используемой и необходимой для преобразований
  $hwstack = 40       ' Размер аппаратного стека
  $swstack = 16       ' Размер программного стека

  $baud = 38400       ': Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'===============================================================================
'          Настройка вывода МК для работы с осциллографом (разные измерения)
'===============================================================================
  Осциллограф Alias Portb.0 : Config Осциллограф = Output : Reset Осциллограф

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
  Config Adc = Free , Prescaler = 2 , Reference = Aref

  On Adc Обработка_прерывания_adc Nosave

'----------------------  Используемые переменные  ------------------------------
  Dim Флаг_есть_18_бит_ацп As Byte
  Dim Счетчик_256_измерений_ацп As Byte
  Dim Счетчик_65536_измерений_ацп As Byte
  Dim Сумма_ацп As Long
  Dim 18_bit_данные_ацп As Long
  Dim 18_bit_данные_ацп_single As Single
  Dim 18_bit_данные_ацп_str As String * 15

'--------------  Разрешаем работу необходимых прерываний  ----------------------

'Правильно работает только при такой инициализации
  Adcsra.aden = 1       ' Bit 7 – ADEN: ADC Enable / Disable
  Adcsra.adsc = 1       ' Bit 6 – ADSC: ADC Start / Stop Conversion
  Adcsra.adate = 0       ' Bit 5 – ADATE: ADC Auto Trigger Enable
  Adcsra.adif = 0       ' Bit 4 – ADIF: ADC Interrupt Flag
  Adcsra.adie = 1       ' Bit 3 – ADIE: ADC Interrupt Enable / Disable

'  Enable Adc : Start Adc
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

     'U питания МК = 5 V (очень стабилизированое и отфильтрованное = тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> LM7805 ==> 2 200 мкф ==> МК)
     'Aref = 4.096 V (= тороидальный трансформатор ==> мостик ==> 10 000 мкф ==> LM7808 ==> 2 200 мкф ==> REF198E)

     'Частота МК Atmega328P = 8 МГц - внутренний генератор
     'Prescaler АЦП = 2
     'Режим запуска АЦП = Free
     'Дискретность 15,625 мкV
     'Время 18-ти битного измерения в реальном железе = ~ 862 ms

      If Флаг_есть_18_бит_ацп <> 0 Then

         '18 бит = оверсэмплинг из  65536 измерений
          18_bit_данные_ацп_single = 18_bit_данные_ацп * 0.000015625

          18_bit_данные_ацп_str = Fusing(18_bit_данные_ацп_single , "#.&&&&&&&&&")

          18_bit_данные_ацп_str = Format(18_bit_данные_ацп_str , "         0")

          Print "18 бит - " ; 18_bit_данные_ацп

          Print "18 бит - " ; 18_bit_данные_ацп_str

          Waitms 50
          Set Осциллограф

          Флаг_есть_18_бит_ацп = 0
          Goto Главный_цикл
      End If

   Power Adcnoise       ' -  нельзя использовать по причине неработы прерываний INT0 (смотреть документацию с.39 (Power Managementand Sleep Modes))

'===============================================================================
  Goto Главный_цикл
End
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Обработка_прерывания_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
   'Т.к., используются логические операции, обязательно сохраняем SREG
    !Push R26
    !In R26 , Sreg
    !Push R26
    !Push R27

   'Набираем сумму из 65536 измерений, для получения 18 бит
    !lds R26 , {Сумма_ацп}
    !in R27 , adcl
    !add R26 , R27
    !sts {Сумма_ацп} , R26

    !lds R26 , {Сумма_ацп + 1}
    !in R27 , adch
    !adc R26 , R27
    !sts {Сумма_ацп + 1} , R26

    !lds   R26  ,  {Сумма_ацп + 2}
    !clr   R27
    !adc   R26  ,  R27
    !sts   {Сумма_ацп + 2}  ,  R26

    !lds   R26  ,  {Сумма_ацп + 3}
    !adc   R26  ,  R27
    !sts   {Сумма_ацп + 3}  ,  R26

   'Считаем 65536 измерений, 2 байтовых счётчика, так быстрее
   Считаем_256:
    !lds R26 , {Счетчик_256_измерений_ацп}
    !inc R26
    !sts {Счетчик_256_измерений_ацп} , R26
   'Если =256
    !cpi R26 , 0
    !BREQ Считаем_65536
    !rjmp Выход_прерывания_adc

   Считаем_65536:
    !lds R26 , {Счетчик_65536_измерений_ацп}
    !inc R26
    !sts {Счетчик_65536_измерений_ацп} , R26
   'Если =256, почему 256 (256 * 256 = 65536)
    !cpi R26 , 0
    !BREQ Получение_18_бит
    !rjmp Выход_прерывания_adc

   Получение_18_бит:
    !Push R16
    !Push R17
    !Push R18
    !Push R19

    !ldi R26 , 8

    !lds R16 , {Сумма_ацп}
    !lds R17 , {Сумма_ацп + 1}
    !lds R18 , {Сумма_ацп + 2}
    !lds R19 , {Сумма_ацп + 3}

   Еще_сдвиг:
    !lsr R19
    !ror R18
    !ror R17
    !ror R16

    !dec R26
    !brne Еще_сдвиг

   'Забираем готовые 18 бит данные
    !sts {18_bit_данные_ацп} , R16
    !sts {18_bit_данные_ацп + 1} , R17
    !sts {18_bit_данные_ацп + 2} , R18
    !sts {18_bit_данные_ацп + 3} , R19

    !pop R19
    !pop R18
    !pop R17
    !pop R16

   'Обнуляем переменные для следующего измерения
    !ldi R26 , 0
    !sts {Сумма_ацп} , R26
    !sts {Сумма_ацп + 1} , R26
    !sts {Сумма_ацп + 2} , R26
    !sts {Сумма_ацп + 3} , R26
    !sts {Счетчик_256_измерений_ацп} , R26
    !sts {Счетчик_65536_измерений_ацп} , R26

   'Поднимаем флаг о готовности результата
    !ldi R26 , 1
    !sts {Флаг_есть_18_бит_ацп} , R26

   'Выключаем прерывание от АЦП
'    !lds R26 , ADCSRA
'    !andi R26 , &B_1111_0111       ' Bit 3 – ADIE: ADC Interrupt Disable
'    !sts ADCSRA , R26

    Reset Осциллограф

   Выход_прерывания_adc:
   'Восстанавливаем регистры и SREG
    !pop R27
    !pop R26
    !Out Sreg , R26
    !Pop R26

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

+1

10

Измерение внутреннего источника опорного напряжения 1.1V  Atmega328P, согласно рекомендациям Atmel  стр.9., п.п.3.4 Band gap measurement

Напряжение питания МК = 5 V, реализовано на стабилизаторе LT1086

Исходник + документация  -  скачать

Исходник

'===============================================================================
  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       ' http://www.atmel.com/images/Atmel-8271- … mplete.pdf
  $crystal = 8000000       ' 8 МГц
  $framesize = 128       ' Размер области используемой и необходимой для преобразований
  $hwstack = 128       ' Размер аппаратного стека
  $swstack = 128       ' Размер программного стека
  $baud = 38400

'===============================================================================
'                      Н А С Т Р О Й К А     АЦП
'===============================================================================
  Config Adc = Single , Prescaler = 128 , Reference = Avcc

  Dim Данные_ацп_1_1_word As Word : Данные_ацп_1_1_word = 0
  Dim Данные_ацп_1_1_single As Single : Данные_ацп_1_1_single = 0
  Dim Данные_ацп_1_1_str As String * 5 : Данные_ацп_1_1_str = "-.-"

  Dim Данные_ацп_0_word As Word : Данные_ацп_0_word = 0
  Dim Данные_ацп_0_single As Single : Данные_ацп_0_single = 0
  Dim Данные_ацп_0_str As String * 5 : Данные_ацп_0_str = "-.-"

'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
  Главный_цикл:
'===============================================================================

    Gosub Измерение_internal_1_1

    Данные_ацп_1_1_single = Данные_ацп_1_1_word * 0.00488
    Данные_ацп_1_1_str = Fusing(данные_ацп_1_1_single , "&.&&")
    Данные_ацп_1_1_str = Format(данные_ацп_1_1_str , "   0")

    Print Данные_ацп_0_word
    Print Данные_ацп_1_1_word
    Print Данные_ацп_1_1_str

     Wait 1

'===============================================================================
  Goto Главный_цикл
End
'===============================================================================

'===============================================================================
  Измерение_internal_1_1:
'-------------------------------------------------------------------------------
    Start Adc       'Запускаем АЦП
    Admux = &B_0100_1111       'Готовимся разряжать ёмкость
    Waitus 70       'Ждём, пока разрядится ёмкость, рекомендовано Atmel  стр.9., п.п.3.4 Band gap measurement (http://www.atmel.com/images/doc8444.pdf)

    Adcsra.adsc = 1       'Bit 6 – ADSC: ADC Start Conversion

   Ждем_измерение_0:
    !lds R16 , ADCSRA
   'Ждём флага готового измерения АЦП (Bit 4 – ADIF: ADC Interrupt Flag)
    !SBRs R16 , ADIF       'Ждём флага готовности результата
    !rjmp Ждем_измерение_0
   'Забираем результат, должен быть 0
    !lds R16 , adcl
    !lds R17 , adch

    !sts {Данные_ацп_0_word} , R16
    !sts {Данные_ацп_0_word + 1} , R17

    Admux = &B_0100_1110       'Готовимся измерять внутренний источник опорного напряжения 1.1V ±10%

    Waitus 70       'Время ожидания заряда ёмкости, рекомендовано Atmel  стр.9., п.п.3.4 Band gap measurement (http://www.atmel.com/images/doc8444.pdf)

    Adcsra.adsc = 1       'Bit 6 – ADSC: ADC Start Conversion

   Ждем_измерение_1_1:
    !lds R16 , ADCSRA
   'Ждём флага готового измерения АЦП (Bit 4 – ADIF: ADC Interrupt Flag)
    !SBRs R16 , ADIF       'Ждём флага готовности результата
    !rjmp Ждем_измерение_1_1
   'Забираем результат, должен быть 226 или 1.1V ±10%
    !lds R16 , adcl
    !lds R17 , adch

    !sts {Данные_ацп_1_1_word} , R16
    !sts {Данные_ацп_1_1_word + 1} , R17

    Admux = &B_0100_0000       'Сброс АЦП на 0 канал (ADC0)

    Stop Adc       'Останавливаем АЦП

'-------------------------------------------------------------------------------
  Return
'===============================================================================

http://s7.uploads.ru/t/OCeBL.jpg

+2

11

Обработка клавиатуры с помощью АЦП

Симуляция (Протеус 7.10) + исходник (Bascom 2.0.7.1)   -   скачать

http://sh.uploads.ru/t/et0S4.jpg
http://s3.uploads.ru/t/rzq2L.jpg
http://s6.uploads.ru/t/wJinB.jpg

+2

12

Ещё вариант, больше кнопок, можно сделать клавиатурные блоки (по пару десятков кнопок в каждом), повесив каждый блок на свой канал АЦП:

Симуляция (Протеус 7.10) + исходник (Bascom 2.0.7.1)   -   скачать

http://s3.uploads.ru/t/h9Mu1.jpg http://sd.uploads.ru/t/JEzZv.jpg

+2

13

Измерение 7 каналов АЦП в фоне, по прерываниям, готовность результата по флагу.

Симуляция (Протеус 7.10) + исходник (Bascom 2.0.7.1)  -  скачать

Исходник (Bascom 2.0.7.1)

$map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m324padef.dat"       'Документация Atmel - http://www.atmel.com/ru/ru/images/atmel … ummary.pdf
  $crystal = 8000000       '11059200
  $framesize = 128       ' Размер области используемой и необходимой для преобразований
  $hwstack = 128       ' Размер аппаратного стека
  $swstack = 128       ' Размер программного стека

  $baud = 38400
  Config Com1 = Baud , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0

'===============================================================================
'     Настройка вывода МК для работы с осциллографом (разные измерения)
'===============================================================================
  Oscill Alias Portb.0 : Config Oscill = Output : Reset Oscill

'Для работы с осциллографом на ASM AVR
  In_oscil_port Alias Pinb : In_oscil_pin Alias &B_0000_0001
  Out_oscil_port Alias Portb : Out_oscil_pin Alias &B_0000_0001

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
'Одиночные измерения с частотой АЦП = f_МК / Prescaler (8 МГц / 128 = 62 500)
  Config Adc = Single , Prescaler = 128 , Reference = Avcc

'Ссылка на подпрограмму обработчика прерывания АЦП
  On Adc Interrupt_processing_adc Nosave

  Adcsra.aden = 1       'Включаем АЦП
  Waitms 10       'Ждём когда всё запустится и выйдет на рабочие уровни

'Номера каналов АЦП
  Channel_adc_0 Alias &B_0000_0000       'Опорное Aref, 0 канал
  Channel_adc_1 Alias &B_0000_0001       'Опорное Aref, 1 канал
  Channel_adc_2 Alias &B_0000_0010       'Опорное Aref, 2 канал
  Channel_adc_3 Alias &B_0000_0011       'Опорное Aref, 3 канал
  Channel_adc_4 Alias &B_0000_0100       'Опорное Aref, 4 канал
  Channel_adc_5 Alias &B_0000_0101       'Опорное Aref, 5 канал
  Channel_adc_6 Alias &B_0000_0110       'Опорное Aref, 6 канал
  Channel_adc_7 Alias &B_0000_0111       'Опорное Aref, 7 канал

  Dim Count_adc As Byte
  Dim Sum_data_adc As Word
  Dim Skip_1_measurement As Byte
  Dim Flag_data_adc_ready As Byte

  Dim Data_adc_0_word As Word
  Dim Data_adc_1_word As Word
  Dim Data_adc_2_word As Word
  Dim Data_adc_3_word As Word
  Dim Data_adc_4_word As Word
  Dim Data_adc_5_word As Word
  Dim Data_adc_6_word As Word
  Dim Data_adc_7_word As Word

  Dim Data_adc_0_sin As Single
  Dim Data_adc_1_sin As Single
  Dim Data_adc_2_sin As Single
  Dim Data_adc_3_sin As Single
  Dim Data_adc_4_sin As Single
  Dim Data_adc_5_sin As Single
  Dim Data_adc_6_sin As Single
  Dim Data_adc_7_sin As Single

'===============================================================================
          'Разрешаем работу необходимых прерываний
'===============================================================================
  Adcsra.adif = 1       'Сброс флага прерывания
  Adcsra.adsc = 1       'Запуск измерения
  Enable Adc       'Разрешение прерываний АЦП

'===============================================================================
          'Разрешаем работу всех включенных прерываний
'===============================================================================
  Enable Interrupts
'===============================================================================

  Main:

'===============================================================================

      If Flag_data_adc_ready > 0 Then

          Toggle Oscill

          Flag_data_adc_ready = 0
          Goto Main
      End If

'===============================================================================
  Goto Main
End
'===============================================================================

'===============================================================================
  Interrupt_processing_adc_1:
'-------------------------------------------------------------------------------
    !clr R26
    !sts {Skip_1_measurement} , R26
    !rjmp Start_measurement_adc
'===============================================================================
  Interrupt_processing_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
   'Т.к., используются логические операции, обязательно сохраняем SREG
    !push R26
    !in R26 , sreg
    !push R26
    !push R27

   'Если сменили канал, пропускаем первое измерение
    !lds R26 , {Skip_1_measurement}
    !tst R26
    !brne Interrupt_processing_adc_1

   'Набираем сумму из 64 измерений, для усреднения показаний
    !lds R26 , {Sum_data_adc}
    !in R27 , adcl
    !add R26 , R27
    !sts {Sum_data_adc} , R26

    !lds R26 , {Sum_data_adc + 1}
    !in R27 , adch
    !adc R26 , R27
    !sts {Sum_data_adc + 1} , R26

   'Считаем количество измерений
    !lds R26 , {count_adc}
    !inc R26
    !sts {count_adc} , R26
   'Если набрали 64 измерения
    !cpi R26 , 64
    !BREQ Mean
    !rjmp Start_measurement_adc

  'Усреднение из 64 измерений
   Mean:
    !push R16
    !push R17
    !Push R30
    !Push R31

    !ldi R30 , 6
    !lds R26 , {Sum_data_adc}
    !lds R27 , {Sum_data_adc + 1}
  'Сдвиг вправо на 6 бит, или деление на 64
   More_shift:
    !lsr R27
    !ror R26
    !dec R30
    !brne More_shift

   'Читаем текущий номер канала АЦП
    !lds R16 , admux
    !andi R16 , &B_0001_1111

   '13 тактов МК, самый быстрый вариант (аналог Goto Переменная Label)
    !clr R17
    !ldi R30 , low(_Save_data_adc_0)
    !ldi R31 , high(_Save_data_adc_0)
    !add R30 , R16
    !adc R31 , R17
    !ijmp

    _save_data_adc_0:
                     !rjmp Save_data_adc_0
    _save_data_adc_1:
                     !rjmp Save_data_adc_1
    _save_data_adc_2:
                     !rjmp Save_data_adc_2
    _save_data_adc_3:
                     !rjmp Save_data_adc_3
    _save_data_adc_4:
                     !rjmp Save_data_adc_4
    _save_data_adc_5:
                     !rjmp Save_data_adc_5
    _save_data_adc_6:
                     !rjmp Save_data_adc_6
    _save_data_adc_7:
                     !rjmp Save_data_adc_7

    !ldi R30 , Channel_adc_0
    !rjmp Change_channel_adc

   Save_data_adc_0:
    !sts {Data_adc_0_word} , R26
    !sts {Data_adc_0_word + 1} , R27
    !ldi R30 , Channel_adc_1
    !rjmp Change_channel_adc

   Save_data_adc_1:
    !sts {Data_adc_1_word} , R26
    !sts {Data_adc_1_word + 1} , R27
    !ldi R30 , Channel_adc_2
    !rjmp Change_channel_adc

   Save_data_adc_2:
    !sts {Data_adc_2_word} , R26
    !sts {Data_adc_2_word + 1} , R27
    !ldi R30 , Channel_adc_3
    !rjmp Change_channel_adc

   Save_data_adc_3:
    !sts {Data_adc_3_word} , R26
    !sts {Data_adc_3_word + 1} , R27
    !ldi R30 , Channel_adc_4
    !rjmp Change_channel_adc

   Save_data_adc_4:
    !sts {Data_adc_4_word} , R26
    !sts {Data_adc_4_word + 1} , R27
    !ldi R30 , Channel_adc_5
    !rjmp Change_channel_adc

   Save_data_adc_5:
    !sts {Data_adc_5_word} , R26
    !sts {Data_adc_5_word + 1} , R27
    !ldi R30 , Channel_adc_6
    !rjmp Change_channel_adc

   Save_data_adc_6:
    !sts {Data_adc_6_word} , R26
    !sts {Data_adc_6_word + 1} , R27
    !ldi R30 , Channel_adc_7
    !rjmp Change_channel_adc

   Save_data_adc_7:
    !sts {Data_adc_7_word} , R26
    !sts {Data_adc_7_word + 1} , R27
    !ldi R30 , Channel_adc_0

    !ldi R26 , 1
    !sts {Flag_data_adc_ready} , R26
    '!rjmp Change_channel_adc

  'Переключаем канал АЦП
   Change_channel_adc:
    !sts admux , R30

    !pop R31
    !pop R30
    !pop R17
    !pop R16

   'Обнуляем переменные для следующего измерения
    !ldi R26 , 0
    !ldi R27 , 1
    !sts {Count_adc} , R26
    !sts {Sum_data_adc} , R26
    !sts {Sum_data_adc + 1} , R26
   'Подымаем флаг смены канала, что бы пропустить первое измерение
    !sts {Skip_1_measurement} , R27

  'Запускаем следующее измерение, режиму "Free" нужен спящий режим "Idle" или "Power Adcnoise"
   Start_measurement_adc:
    !lds R26 , ADCSRA
    !ori R26 , &B_0100_0000
    !sts ADCSRA , R26

  'Восстанавливаем регистры и SREG
   Exit_interrupt_adc:
    !pop R27
    !pop R26
    !out sreg , R26
    !pop R26

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

http://s3.uploads.ru/t/mljrV.jpg

+2

14

Измерение 7 каналов АЦП в фоне, по прерываниям, готовность результата по флагу + опрос ds18b20 через USART

'Количество измерений одного канала АЦП для получения выборки
'Варианты 4, 8, 16, 32, 64
  Const Sample_adc = 64

  Time_upd_lcd = 250       'Время обновления LCD в ms
  Time_upd_ds18b20 = 2000       'Время обновления ds18b20 в ms

Исходник

$regfile = "m328pdef.dat"
  $crystal = 8000000
  $framesize = 64
  $hwstack = 64
  $swstack = 64

'===============================================================================
' Подключение библиотеки, для работы с шиной 1Wire через USART (аппаратная симуляция шины)
'===============================================================================

  Const Const_overheat = 80

'===============================================================================
'Настройка USART для работы с шиной 1Wire
'===============================================================================
  Config Com1 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
  Used_baud_rate Alias Ubrr0
  Used_udr0 Alias Udr0
  Used_ucsr0a Alias Ucsr0a
  Used_txc Alias Txc0
  Used_rxc Alias Rxc0
'===============================================================================
' Настройка скорости USART для работы с шиной 1Wire
'===============================================================================
  Const Const_usart_9600 = _xtal /(9600 * 16) - 1       'Расчёт скорости трансляции 9600 бод
  Const Const_usart_115200 = _xtal /(115200 * 16) - 1       'Расчёт скорости трансляции 115200 бод
'===============================================================================
' Команды для работы с шиной 1Wire и датчиками ds1820; ds18S20; ds18b20
'===============================================================================
  Const Search_all_id_ds18x20 = &HF0       ' Чтение ID всех подключенных устройств
  Const Read_id_one_ds18x20 = &H33       ' Чтение ID единственного подключенного устройства
  Const Alarm_search_ds18x20 = &HEC       ' Команда используется для поиска датчиков с сработавшим состоянием тревоги
  Const Temperature_conversion_ds18x20 = &H44       ' Команда используется для запуска измерения датчиком Ds18b20
  Const Read_temperature_ds18x20 = &HBE       ' Команда используется для чтения ОЗУ датчиков Ds18b20
  Const Copy_scratchpad_ds18b20 = &H48       ' Команда используется для записи данных из ОЗУ в ПЗУ датчика, для последующего использования
  Const Read_scratchpad_ds18b20 = &HBE       ' Команда используется для чтения данных в ОЗУ датчика
  Const Write_scratchpad_ds18b20 = &H4E       ' Команда используется для записи данных в ОЗУ датчика
  Const Skip_rom_ds18x20 = &HCC       ' Команда используется, чтобы обратиться ко всем подключенным устройствам на шине одновременно
  Const Match_rom_ds18x20 = &H55       ' Команда используется для поиска датчиков с конкретным, ранее считанным номером (id)
  Const Read_power_supply = &HB4       ' Команда используется для определения паразитного питания Ds18b20
'===============================================================================
' Переменные, которые непосредственно участвуют в работе с шиной 1wire
'===============================================================================
  Dim 1ware_tmp_count As Byte
  Dim 1ware_tmp_count_1 As Byte
  Dim 1ware_tmp_count_2 As Byte
  Dim 1ware_tmp_amount_devices As Byte
  Dim 1ware_tmp_udr As Byte
  Dim 1ware_tmp_bit As Byte
  Dim 1ware_tmp_byte As Byte
  Dim 1wire_error As Byte       'Переменная для хранения ошибки шины 1Wire
  Dim 1wire_temp_udr As Byte       'Переменная для хранения принятого в USART байта
'===============================================================================
' Подпрограммы и функции, которые непосредственно участвуют в работе с шиной 1wire
'===============================================================================
  Declare Sub 1wire_reset_usart()       'Reset шины 1Wire
  Declare Function 1wire_read_bit_usart() As Byte       'Чтение 1 бита шины 1Wire
  Declare Sub 1wire_read_usart(byval Copy_count As Byte)       'Чтение 1 байта шины 1Wire
  Declare Sub 1wire_write_bit_usart(byval Copy_byte As Byte)       'Запись бита шины 1Wire
  Declare Sub 1wire_write_byte_usart(byval Copy_data As Byte)       'Запись байта шины 1Wire
'===============================================================================
' Переменные, которые непосредственно участвуют в работе с датчиками ds18x20
'===============================================================================
  Dim Temperature_int As Integer       ' Температура с сигнатурой (знак температуры (+ или -)) в HEX формате
  Dim Data_ds18x20(10) As Byte At Temperature_int Overlay       'Массив данных ответа датчика DS18x20

  Dim Count_time_upd_ds18b20 As Word
  Dim Time_upd_ds18b20 As Word
  Dim Flag_upd_ds18b20 As Byte

  Dim Flag_error As Byte
  Dim Flag_fan As Byte
  Dim Temperature_byte As Byte
  Dim Flag_read_temperature As Byte
  Dim Data_temperature_int As Integer

  Dim Temperature_str As String * 8 : Temperature_str = "---"

'===============================================================================

'===============================================================================
'          Настройка МК для работы с LCD на базе контроллера hd44780
'   Обратите внимание, библиотеки не используются, выводы могут быть любые
'===============================================================================
  Config Lcdpin = Pin , Rs = Portb.5 , E = Portb.4 , Db4 = Portb.3 , Db5 = Portb.2 , Db6 = Portb.1 , Db7 = Portb.0
  Config Lcd = 20 * 4       ' Используемый LCD
  Initlcd       ' Инициализируем LCD
  Waitms 50       ' Ждем пока все запустится
  Cursor Off Noblink       ' Выключаем неморгающий курсор
'  Cursor On Noblink         ' Включаем неморгающий курсор
'  Cursor On Blink       ' Включаем моргающий курсор
'  Upperline  1 строка, Lowerline  2 строка, Thirdline  3 строка, Fourthline 4 строка  - один из вариантов перехода на строку
  Cls       ' Чистим экран, на всякий случай

'-------  Используемые дополнительные_символы, выводимые на LCD  -------

  Deflcdchar 1 , 12 , 18 , 18 , 12 , 32 , 32 , 32 , 32       ' значек градуса
  Deflcdchar 2 , 14 , 10 , 10 , 10 , 14 , 31 , 31 , 14       ' термометр
  Deflcdchar 3 , 32 , 8 , 5 , 14 , 20 , 2 , 32 , 32       ' значек вентилятора
'-------------------------------------------------------------------------------

  Const Const_буфер_lcd = 20

  Dim Флаг_обновить_lcd As Byte

  Dim Буфер_lcd_1_строка_str As String * Const_буфер_lcd
  Dim Буфер_lcd_2_строка_str As String * Const_буфер_lcd
  Dim Буфер_lcd_3_строка_str As String * Const_буфер_lcd
  Dim Буфер_lcd_4_строка_str As String * Const_буфер_lcd

'===============================================================================
'                     Конфигурация АЦП
'===============================================================================
'Одиночные измерения с частотой АЦП = f_МК / Prescaler (8 МГц / 128 = 62 500)
  Config Adc = Single , Prescaler = 128 , Reference = Avcc

'Ссылка на подпрограмму обработчика прерывания АЦП
  On Adc Interrupt_processing_adc Nosave

'Количество измерений одного канала АЦП для получения выборки
'Варианты 4, 8, 16, 32, 64
  Const Sample_adc = 64

  #if Sample_adc = 4
      Const Const_averaging = 2
  #endif
  #if Sample_adc = 8
      Const Const_averaging = 3
  #endif
  #if Sample_adc = 16
      Const Const_averaging = 4
  #endif
  #if Sample_adc = 32
      Const Const_averaging = 5
  #endif
  #if Sample_adc = 64
      Const Const_averaging = 6
  #endif

  Adcsra.aden = 1       'Включаем АЦП
  Waitms 10       'Ждём когда всё запустится и выйдет на рабочие уровни

'Номера каналов АЦП
  Channel_adc_0 Alias &B_0100_0000       'Опорное Avcc, 0 канал
  Channel_adc_1 Alias &B_0100_0001       'Опорное Avcc, 1 канал
  Channel_adc_2 Alias &B_0100_0010       'Опорное Avcc, 2 канал
  Channel_adc_3 Alias &B_0100_0011       'Опорное Avcc, 3 канал
  Channel_adc_4 Alias &B_0100_0100       'Опорное Avcc, 4 канал
  Channel_adc_5 Alias &B_0100_0101       'Опорное Avcc, 5 канал
  Channel_adc_6 Alias &B_0100_0110       'Опорное Avcc, 6 канал
  Channel_adc_7 Alias &B_0100_0111       'Опорное Avcc, 7 канал

  Ref_aref_adc Alias &B_0000_0000
  Ref_avcc_adc Alias &B_0100_0000
  Ref_internal_1_1v_adc Alias &B_1100_0000

  Admux = Channel_adc_0

  Dim Count_adc As Byte
  Dim Sum_data_adc As Word
  Dim Skip_1_measurement As Byte
  Dim Flag_data_adc_ready As Byte

  Dim Data_adc_0_word As Word
  Dim Data_adc_1_word As Word
  Dim Data_adc_2_word As Word
  Dim Data_adc_3_word As Word
  Dim Data_adc_4_word As Word
  Dim Data_adc_5_word As Word
  Dim Data_adc_6_word As Word
  Dim Data_adc_7_word As Word

  Dim Data_adc_0_sin As Single
  Dim Data_adc_1_sin As Single
  Dim Data_adc_2_sin As Single
  Dim Data_adc_3_sin As Single
  Dim Data_adc_4_sin As Single
  Dim Data_adc_5_sin As Single
  Dim Data_adc_6_sin As Single
  Dim Data_adc_7_sin As Single

  Dim Data_adc_0_str As String * 5
  Dim Data_adc_1_str As String * 5
  Dim Data_adc_2_str As String * 5
  Dim Data_adc_3_str As String * 5
  Dim Data_adc_4_str As String * 5
  Dim Data_adc_5_str As String * 5
  Dim Data_adc_6_str As String * 5
  Dim Data_adc_7_str As String * 5

'===============================================================================
            'Настройка системного времени, 1 ms
'===============================================================================
  Const Const_t_sys = 1000       'Период прерываний в мкс

  Const Const_div_sys_timer = 64       'Аппаратный делитель используемого таймера
  Const F_clk = _xtal / 1000000       'Частота МК в МГц
  Const Const_time_sys =((_xtal / 1000000) * Const_t_sys / Const_div_sys_timer) - 0.5

  Config Timer1 = Counter , _
                            Prescale = Const_div_sys_timer , _
                            Compare A = Disconnect , _
                            Compare B = Disconnect , _
                            Clear Timer = 1

  On Compare1a Interrupt_compare1a Nosave

  Compare1a = Const_time_sys

  Dim Count_time_upd_lcd As Word
  Dim Time_upd_lcd As Word
  Dim Flag_upd_lcd As Byte

  Dim Flag_upd_adc_lcd As Byte
  Dim Flag_upd_ds18b20_lcd As Byte

'===============================================================================
'           Предварительное заполнение переменных и LCD
'===============================================================================
  Time_upd_lcd = 250       'Время обновления LCD в ms
  Time_upd_ds18b20 = 2000       'Время обновления ds18b20 в ms

  Locate 1 , 1
  Lcd "0=     1=     2=    "
  Locate 2 , 1
  Lcd "3=     4=     5=    "
  Locate 3 , 1
  Lcd "6=     7=           "

  Locate 4 , 1
  Lcd Chr(2) + " = " + "---" + Chr(1) + "C  "

'===============================================================================
          'Разрешаем работу необходимых прерываний
'===============================================================================
  Adcsra.adif = 1       'Сброс флага прерывания
  Adcsra.adsc = 1       'Запуск измерения
  Enable Adc       'Разрешение прерываний АЦП

  Enable Compare1a

'===============================================================================
          'Разрешаем работу всех включенных прерываний
'===============================================================================
  Enable Interrupts
'===============================================================================

  Main:

'===============================================================================


'===============================================================================
'              Работа с АЦП
'===============================================================================
      If Flag_data_adc_ready > 0 Then
          Data_adc_0_sin = Data_adc_0_word * 0.0488
          Data_adc_0_str = Fusing(data_adc_0_sin , "0.0")
          Data_adc_0_str = Format(data_adc_0_str , "   0")
          Data_adc_1_sin = Data_adc_1_word * 0.0488
          Data_adc_1_str = Fusing(data_adc_1_sin , "0.0")
          Data_adc_1_str = Format(data_adc_1_str , "   0")
          Data_adc_2_sin = Data_adc_2_word * 0.0488
          Data_adc_2_str = Fusing(data_adc_2_sin , "0.0")
          Data_adc_2_str = Format(data_adc_2_str , "   0")
          Data_adc_3_sin = Data_adc_3_word * 0.0488
          Data_adc_3_str = Fusing(data_adc_3_sin , "0.0")
          Data_adc_3_str = Format(data_adc_3_str , "   0")
          Data_adc_4_sin = Data_adc_4_word * 0.0488
          Data_adc_4_str = Fusing(data_adc_4_sin , "0.0")
          Data_adc_4_str = Format(data_adc_4_str , "   0")
          Data_adc_5_sin = Data_adc_5_word * 0.0488
          Data_adc_5_str = Fusing(data_adc_5_sin , "0.0")
          Data_adc_5_str = Format(data_adc_5_str , "   0")
          Data_adc_6_sin = Data_adc_6_word * 0.0488
          Data_adc_6_str = Fusing(data_adc_6_sin , "0.0")
          Data_adc_6_str = Format(data_adc_6_str , "   0")
          Data_adc_7_sin = Data_adc_7_word * 0.0488
          Data_adc_7_str = Fusing(data_adc_7_sin , "0.0")
          Data_adc_7_str = Format(data_adc_7_str , "   0")
          Flag_data_adc_ready = 0
          Flag_upd_adc_lcd = 1
          Goto Main
      End If

'===============================================================================
'              Работа с датчиком температуры ds18b20
'===============================================================================
      If Flag_upd_ds18b20 > 0 Then
         Call 1wire_reset_usart()       'Аналог команды "1wreset"

         If 1wire_error = 0 Then
                Call 1wire_write_byte_usart(skip_rom_ds18x20)
                Call 1wire_write_byte_usart(read_temperature_ds18x20)       'Аналог команды "1wwrite read_temperature_ds18x20"
                Call 1wire_read_usart(2)       'Получение данных, аналог команды "1wread(9)"
                Shift Temperature_int , Right , 4 , Signed

                If Temperature_int < 0 Then
                    Temperature_int = 0
                End If
'                If Temperature_int > 99 Then
'                    Temperature_int = 99
'                End If
                Temperature_byte = Temperature_int
                Temperature_str = Str(temperature_byte)
                Temperature_str = Format(temperature_str , "  0")
                If Temperature_byte > Const_overheat Then
                    Flag_fan = 1
                  Else
                    Flag_fan = 0
                End If

                If Flag_fan = 0 Then
                    Буфер_lcd_4_строка_str = Chr(2) + " = " + Temperature_str + Chr(1) + "C  "
                  Else
                    Буфер_lcd_4_строка_str = Chr(2) + " = " + Temperature_str + Chr(1) + "C " + Chr(3)
                End If

              Else
                Буфер_lcd_4_строка_str = Chr(2) + " = " + "Error " + Chr(3)
                Flag_fan = 1
         End If
         Call 1wire_reset_usart()       'Аналог команды "1wreset"
         If 1wire_error = 0 Then
             Call 1wire_write_byte_usart(skip_rom_ds18x20)
             Call 1wire_write_byte_usart(temperature_conversion_ds18x20)
         End If
          Flag_upd_ds18b20 = 0
          Flag_upd_ds18b20_lcd = 1
          Goto Main
      End If
'===============================================================================

'===============================================================================
'              Вывод на LCD
'===============================================================================
      If Flag_upd_lcd > 0 Then

          If Flag_upd_adc_lcd > 0 Then
              Locate 1 , 3
              Lcd Data_adc_0_str
              Locate 1 , 10
              Lcd Data_adc_1_str
              Locate 1 , 17
              Lcd Data_adc_2_str

              Locate 2 , 3
              Lcd Data_adc_3_str
              Locate 2 , 10
              Lcd Data_adc_4_str
              Locate 2 , 17
              Lcd Data_adc_5_str

              Locate 3 , 3
              Lcd Data_adc_6_str
              Locate 3 , 10
              Lcd Data_adc_7_str
          End If

          If Flag_upd_ds18b20_lcd > 0 Then

              Locate 4 , 1
              Lcd Буфер_lcd_4_строка_str

              Flag_upd_ds18b20_lcd = 0
          End If

          Flag_upd_lcd = 0
          Goto Main
      End If

   Idle
'===============================================================================
  Goto Main
End
'===============================================================================

'===============================================================================
  Function 1wire_read_bit_usart() As Byte       'Принимаем бит ROM от устройства
'-------------------------------------------------------------------------------
    Used_baud_rate = Const_usart_115200

    Used_udr0 = &HFF

    Gosub 1wire_wait_byte_reception

    If 1wire_temp_udr = &HFF Then
        1ware_tmp_bit = 1
      Else
        1ware_tmp_bit = 0
    End If

    1wire_read_bit_usart = 1ware_tmp_bit
'-------------------------------------------------------------------------------
  End Function
'===============================================================================

'===============================================================================
  Sub 1wire_write_bit_usart(byval Copy_byte As Byte)
'-------------------------------------------------------------------------------
    Used_baud_rate = Const_usart_115200

    If Copy_byte = 0 Then
        Used_udr0 = &H00
      Else
        Used_udr0 = &HFF
    End If

    Gosub 1wire_wait_byte_reception
'-------------------------------------------------------------------------------
  End Sub
'===============================================================================

'===============================================================================
  Sub 1wire_read_usart(byval Copy_count As Byte)
'-------------------------------------------------------------------------------
     1ware_tmp_count = Copy_count

     For 1ware_tmp_count_1 = 1 To 1ware_tmp_count
         For 1ware_tmp_count_2 = 0 To 7

             Used_udr0 = &HFF

             Gosub 1wire_wait_byte_reception

             If 1wire_temp_udr = &HFF Then
                 Data_ds18x20(1ware_tmp_count_1).1ware_tmp_count_2 = 1
               Else
                 Data_ds18x20(1ware_tmp_count_1).1ware_tmp_count_2 = 0
             End If

         Next 1ware_tmp_count_2
     Next 1ware_tmp_count_1
'-------------------------------------------------------------------------------
  End Sub
'===============================================================================

'===============================================================================
  Sub 1wire_write_byte_usart(byval Copy_data As Byte)
'-------------------------------------------------------------------------------
    1ware_tmp_byte = Copy_data

    Used_baud_rate = Const_usart_115200

    For 1ware_tmp_count = 0 To 7

        If 1ware_tmp_byte.1ware_tmp_count = 0 Then
            Used_udr0 = &H00
          Else
            Used_udr0 = &HFF
        End If

        Gosub 1wire_wait_byte_reception

    Next 1ware_tmp_count
'-------------------------------------------------------------------------------
  End Sub
'===============================================================================

'===============================================================================
  Sub 1wire_reset_usart()
'-------------------------------------------------------------------------------
    Used_baud_rate = Const_usart_9600

    Used_udr0 = &HF0

    Gosub 1wire_wait_byte_reception

    If 1wire_temp_udr <> &HF0 Then
        1wire_error = 0
      Else
        1wire_error = 1
    End If
'-------------------------------------------------------------------------------
  End Sub
'===============================================================================

'===============================================================================
  1wire_wait_byte_reception:       'Передача и приём 1 бита данных 1wire
'-------------------------------------------------------------------------------
    1wire_wait_byte_transfers:
      !lds R16 , Used_ucsr0a
      !SBRS R16 , Used_txc       '6 бит регистра Ucsr1a, ждём отправки байта
    !rjmp 1wire_Wait_Byte_transfers

    1wire_wait_byte_reception_1:
      !lds R16 , Used_ucsr0a
      !SBRS R16 , Used_rxc       '7 бит регистра Ucsr1a, ждём приёма байта
    !rjmp 1wire_wait_byte_reception_1
      !lds R16 , Used_udr0
      !sts {1wire_temp_udr} , R16
'-------------------------------------------------------------------------------
  Return
'===============================================================================

'===============================================================================
  Interrupt_compare1a:
'-------------------------------------------------------------------------------
    !push R16
    !in R16 , sreg
    !push R16
    !push R30
    !push R31

    !rcall Count_time_upd_lcd_1

    !rcall Count_time_upd_ds18b20_1

   Exit_interrupt_compare1a:
    !pop R31
    !pop R30
    !pop R16
    !out sreg , R16
    !pop R16

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

'===============================================================================
  Count_time_upd_lcd_1:
'-------------------------------------------------------------------------------
    !clr R16
    !lds R30 , {Count_time_upd_lcd}
    !lds R31 , {Count_time_upd_lcd + 1}

    !cpi R31 , 0
    !cpc R30 , R16
    !brcs Reload_Time_upd_lcd
    !breq Reload_Time_upd_lcd
    !rjmp Counter_Time_upd_lcd
    !rjmp Reload_Time_upd_lcd

   Counter_time_upd_lcd:
    !sbiw R30 , 1
    !rjmp Save_Time_upd_lcd

   Reload_time_upd_lcd:
    !ldi R16 , 1
    !sts {Flag_upd_lcd} , R16
    !lds R30 , {Time_upd_lcd}
    !lds R31 , {Time_upd_lcd + 1}

   Save_time_upd_lcd:
    !sts {Count_time_upd_lcd} , R30
    !sts {Count_time_upd_lcd + 1} , R31
'-------------------------------------------------------------------------------
  Return
'===============================================================================

'===============================================================================
  Count_time_upd_ds18b20_1:
'-------------------------------------------------------------------------------
    !clr R16
    !lds R30 , {Count_time_upd_ds18b20}
    !lds R31 , {Count_time_upd_ds18b20 + 1}

    !cpi R31 , 0
    !cpc R30 , R16
    !brcs Reload_Time_upd_ds18b20
    !breq Reload_Time_upd_ds18b20
    !rjmp Counter_Time_upd_ds18b20
    !rjmp Reload_Time_upd_ds18b20

   Counter_time_upd_ds18b20:
    !sbiw R30 , 1
    !rjmp Save_Time_upd_ds18b20

   Reload_time_upd_ds18b20:
    !ldi R16 , 1
    !sts {Flag_upd_ds18b20} , R16
    !lds R30 , {Time_upd_ds18b20}
    !lds R31 , {Time_upd_ds18b20 + 1}

   Save_time_upd_ds18b20:
    !sts {Count_time_upd_ds18b20} , R30
    !sts {Count_time_upd_ds18b20 + 1} , R31
'-------------------------------------------------------------------------------
  Return
'===============================================================================


'===============================================================================
  Interrupt_processing_adc_1:
'-------------------------------------------------------------------------------
    !clr R26
    !sts {Skip_1_measurement} , R26
    !rjmp Start_measurement_adc
'===============================================================================
  Interrupt_processing_adc:
'-------------------------------------------------------------------------------
   'Сохраняем регистры
   'Т.к., используются логические операции, обязательно сохраняем SREG
    !push R26
    !in R26 , sreg
    !push R26
    !push R27

   'Если сменили канал, пропускаем первое измерение
    !lds R26 , {Skip_1_measurement}
    !tst R26
    !brne Interrupt_processing_adc_1

   'Набираем сумму из 64 измерений, для усреднения показаний
    !lds R26 , {Sum_data_adc}
    !in R27 , adcl
    !add R26 , R27
    !sts {Sum_data_adc} , R26

    !lds R26 , {Sum_data_adc + 1}
    !in R27 , adch
    !adc R26 , R27
    !sts {Sum_data_adc + 1} , R26

   'Считаем количество измерений
    !lds R26 , {count_adc}
    !inc R26
    !sts {count_adc} , R26
   'Если набрали 64 измерения
    !cpi R26 , Sample_adc
    !BREQ Mean
    !rjmp Start_measurement_adc

  'Усреднение из 64 измерений
   Mean:
    !push R16
    !push R17
    !Push R30
    !Push R31

    !ldi R30 , Const_averaging
    !lds R26 , {Sum_data_adc}
    !lds R27 , {Sum_data_adc + 1}
  'Сдвиг вправо на 6 бит, или деление на 64
   More_shift:
    !lsr R27
    !ror R26
    !dec R30
    !brne More_shift

   'Читаем текущий номер канала АЦП
    !lds R16 , admux
    !andi R16 , &B_0001_1111

   '13 тактов МК, самый быстрый вариант (аналог Goto Переменная Label)
    !clr R17
    !ldi R30 , low(_Save_data_adc_0)
    !ldi R31 , high(_Save_data_adc_0)
    !add R30 , R16
    !adc R31 , R17
    !ijmp

    _save_data_adc_0:
                     !rjmp Save_data_adc_0
    _save_data_adc_1:
                     !rjmp Save_data_adc_1
    _save_data_adc_2:
                     !rjmp Save_data_adc_2
    _save_data_adc_3:
                     !rjmp Save_data_adc_3
    _save_data_adc_4:
                     !rjmp Save_data_adc_4
    _save_data_adc_5:
                     !rjmp Save_data_adc_5
    _save_data_adc_6:
                     !rjmp Save_data_adc_6
    _save_data_adc_7:
                     !rjmp Save_data_adc_7

    !ldi R30 , Channel_adc_0
    !rjmp Change_channel_adc

   Save_data_adc_0:
    !sts {Data_adc_0_word} , R26
    !sts {Data_adc_0_word + 1} , R27
    !ldi R30 , Channel_adc_1
    !rjmp Change_channel_adc

   Save_data_adc_1:
    !sts {Data_adc_1_word} , R26
    !sts {Data_adc_1_word + 1} , R27
    !ldi R30 , Channel_adc_2
    !rjmp Change_channel_adc

   Save_data_adc_2:
    !sts {Data_adc_2_word} , R26
    !sts {Data_adc_2_word + 1} , R27
    !ldi R30 , Channel_adc_3
    !rjmp Change_channel_adc

   Save_data_adc_3:
    !sts {Data_adc_3_word} , R26
    !sts {Data_adc_3_word + 1} , R27
    !ldi R30 , Channel_adc_4
    !rjmp Change_channel_adc

   Save_data_adc_4:
    !sts {Data_adc_4_word} , R26
    !sts {Data_adc_4_word + 1} , R27
    !ldi R30 , Channel_adc_5
    !rjmp Change_channel_adc

   Save_data_adc_5:
    !sts {Data_adc_5_word} , R26
    !sts {Data_adc_5_word + 1} , R27
    !ldi R30 , Channel_adc_6
    !rjmp Change_channel_adc

   Save_data_adc_6:
    !sts {Data_adc_6_word} , R26
    !sts {Data_adc_6_word + 1} , R27
    !ldi R30 , Channel_adc_7
    !rjmp Change_channel_adc

   Save_data_adc_7:
    !sts {Data_adc_7_word} , R26
    !sts {Data_adc_7_word + 1} , R27
    !ldi R30 , Channel_adc_0

    !ldi R26 , 1
    !sts {Flag_data_adc_ready} , R26
    !rjmp Change_channel_adc

  'Переключаем канал АЦП
   Change_channel_adc:
'    !lds R31 , admux
'    !andi R31 , &B_0100_0000
'    !or R31 , R30
    !sts admux , R30

    !pop R31
    !pop R30
    !pop R17
    !pop R16

   'Обнуляем переменные для следующего измерения
    !ldi R26 , 0
    !ldi R27 , 1
    !sts {Count_adc} , R26
    !sts {Sum_data_adc} , R26
    !sts {Sum_data_adc + 1} , R26
   'Подымаем флаг смены канала, что бы пропустить первое измерение
    !sts {Skip_1_measurement} , R27

  'Запускаем следующее измерение, режиму "Free" нужен спящий режим "Idle" или "Power Adcnoise"
   Start_measurement_adc:
    !lds R26 , ADCSRA
    !ori R26 , &B_0100_0000
    !sts ADCSRA , R26

  'Восстанавливаем регистры и SREG
   Exit_interrupt_adc:
    !pop R27
    !pop R26
    !out sreg , R26
    !pop R26

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================

https://upforme.ru/uploads/0000/25/b8/1217/t597592.jpg

+3


Вы здесь » Программирование ATMEL в BASCOM. » Примеры применения в среде Баском » Исследование АЦП в МК Atmegaxxx и Attinyxxx