Исследование АЦП в МК Atmegaxxx и Attinyxxx
Таблица внешних опорников от Linear Technology
Программирование ATMEL в BASCOM. |
Привет, Гость! Войдите или зарегистрируйтесь.
Вы здесь » Программирование ATMEL в BASCOM. » Примеры применения в среде Баском » Исследование АЦП в МК Atmegaxxx и Attinyxxx
Исследование АЦП в МК Atmegaxxx и Attinyxxx
Таблица внешних опорников от Linear Technology
Компилятор: BASCOM-AVR 2.0.7.1
Для оптимального отображения псевдографики используйте шрифт в Bascom: Consolas; размер = 14
Кому надо симуляцию в Протеусе, пишите мыло, закину.
'===============================================================================
$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 Цикл_printWaitms 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
'===============================================================================
Исследование АЦП. Скоростной опрос АЦП МК Atmega328P. Кварц 30 МГЦ
Симуляция Протеус 7.10 sr0 + исходник Bascom 2.0.7.1 - скачать
Видео с осциллограммами - скачать - размер ~70 Мб
Документация производителя на Atmega48a-48pa-88a-88pa-168a-168pa-328-328p
$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 Данные_ацп
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) - скачать
Программное повышение разрядности АЦП, по буржуйски "оверсемплинг"
Документация Atmel по этому поводу
Кому нужен перевод, пишите в ЛС, скину на mail.
Минусы данного метода - снижение скорости получения готовых данных пропорционально повышению разрядности!
Но если скорость не важна, то метод получения более точных данных довольно удачный.
Ацп работает в фоновом режиме (Free), проверяете флаг, при флаг=1, получаете в переменной, готовые данные соответствующей разрядности.
'-------------------------------------------------------------------------------
$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
'===============================================================================
' Г Л А В Н Ы Й Ц И К Л
'===============================================================================
Главный_цикл:
nopIf Флаг_есть_данные_usart = 1 Then
Print 12_bit_данные_ацп
Флаг_есть_данные_usart = 0
End IfPower 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 бит.
Исходник выбрать в свойствах МК !!!
Дифференциальный режим работы АЦП, на примере термодатчика PT100 и МК Atbanned6A
Вход "+" = ADC3; Вход "-" = ADC2; Усиление = 20
Симуляция в Протеус 7.10 sr0 + исходник Bascom 2.0.7.1 - скачать
16-бит АЦП с помощью оверсемплинга (oversampling)
Документация Atmel по данному вопросу
$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
'===============================================================================
' Г Л А В Н Ы Й Ц И К Л
'===============================================================================
Главный_цикл:
nopIf Флаг_есть_данные_usart = 1 Then
Print 16_bit_данные_ацп
Флаг_есть_данные_usart = 0
End IfPower 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
'===============================================================================
Получение данных со всего АЦП по переполнению TIMER0, т.е., сработавшее прерывание TIMER0 запускает измерение АЦП, по готовности, генерируется прерывание от АЦП, идём и забираем данные.
Симуляция + исходник - скачать
Программное повышение разрядности АЦП, по буржуйски "оверсэмплинг", продолжение темы.
Снятие временных интервалов, и качества измерений
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 бит - 19659118 бит - 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
Всё одним архивом - скачать
Исходник'===============================================================================
$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 = ArefOn 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 IfPower 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 , R16Reset Осциллограф
Выход_прерывания_adc:
'Восстанавливаем регистры
!Pop R16!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Исходник'===============================================================================
$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 = ArefOn 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.00211_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 IfPower 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 , R26Reset Осциллограф
nop
Выход_прерывания_adc:
'Восстанавливаем регистры и SREG
!pop R27
!pop R26
!Out Sreg , R26
!Pop R26!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Исходник'===============================================================================
$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 = ArefOn 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.00112_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 IfPower 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 , R26Reset Осциллограф
nop
Выход_прерывания_adc:
'Восстанавливаем регистры и SREG
!pop R27
!pop R26
!Out Sreg , R26
!Pop R26!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Исходник'===============================================================================
$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 = ArefOn 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.000513_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 IfPower 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 , R26Reset Осциллограф
nop
Выход_прерывания_adc:
'Восстанавливаем регистры и SREG
!pop R27
!pop R26
!Out Sreg , R26
!Pop R26!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Исходник'===============================================================================
$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 = ArefOn 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 msIf Флаг_есть_14_бит_ацп <> 0 Then
'14 бит = оверсэмплинг из 256 измерений
14_bit_данные_ацп_single = 14_bit_данные_ацп * 0.0002514_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 IfPower 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 , R26Reset Осциллограф
nop
Выход_прерывания_adc:
'Восстанавливаем регистры и SREG
!pop R27
!pop R26
!Out Sreg , R26
!Pop R26!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Исходник'===============================================================================
$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 = ArefOn 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 msIf Флаг_есть_15_бит_ацп <> 0 Then
'15 бит = оверсэмплинг из 1024 измерений
15_bit_данные_ацп_single = 15_bit_данные_ацп * 0.00012515_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 IfPower 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 , R26Reset Осциллограф
nop
Выход_прерывания_adc:
'Восстанавливаем регистры и SREG
!pop R27
!pop R26
!Out Sreg , R26
!Pop R26!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Исходник'===============================================================================
$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 = ArefOn 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 msIf Флаг_есть_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 IfPower 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 , R26Reset Осциллограф
Выход_прерывания_adc:
'Восстанавливаем регистры и SREG
!pop R27
!pop R26
!Out Sreg , R26
!Pop R26!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Исходник'===============================================================================
$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 = ArefOn 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 msIf Флаг_есть_17_бит_ацп <> 0 Then
'17 бит = оверсэмплинг из 16384 измерений
17_bit_данные_ацп_single = 17_bit_данные_ацп * 0.0000312517_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 IfPower 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 , R26Reset Осциллограф
Выход_прерывания_adc:
'Восстанавливаем регистры и SREG
!pop R27
!pop R26
!Out Sreg , R26
!Pop R26!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Исходник'===============================================================================
$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 = ArefOn 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 msIf Флаг_есть_18_бит_ацп <> 0 Then
'18 бит = оверсэмплинг из 65536 измерений
18_bit_данные_ацп_single = 18_bit_данные_ацп * 0.00001562518_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 IfPower 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 , R26Reset Осциллограф
Выход_прерывания_adc:
'Восстанавливаем регистры и SREG
!pop R27
!pop R26
!Out Sreg , R26
!Pop R26!reti
'-------------------------------------------------------------------------------
Return
'===============================================================================
Измерение внутреннего источника опорного напряжения 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 = AvccDim Данные_ацп_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_strWait 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} , R17Admux = &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} , R17Admux = &B_0100_0000 'Сброс АЦП на 0 канал (ADC0)
Stop Adc 'Останавливаем АЦП
'-------------------------------------------------------------------------------
Return
'===============================================================================
Ещё вариант, больше кнопок, можно сделать клавиатурные блоки (по пару десятков кнопок в каждом), повесив каждый блок на свой канал АЦП:
Симуляция (Протеус 7.10) + исходник (Bascom 2.0.7.1) - скачать
Измерение 7 каналов АЦП в фоне, по прерываниям, готовность результата по флагу.
Симуляция (Протеус 7.10) + исходник (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 NosaveAdcsra.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 ByteDim 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 WordDim 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_adcSave_data_adc_0:
!sts {Data_adc_0_word} , R26
!sts {Data_adc_0_word + 1} , R27
!ldi R30 , Channel_adc_1
!rjmp Change_channel_adcSave_data_adc_1:
!sts {Data_adc_1_word} , R26
!sts {Data_adc_1_word + 1} , R27
!ldi R30 , Channel_adc_2
!rjmp Change_channel_adcSave_data_adc_2:
!sts {Data_adc_2_word} , R26
!sts {Data_adc_2_word + 1} , R27
!ldi R30 , Channel_adc_3
!rjmp Change_channel_adcSave_data_adc_3:
!sts {Data_adc_3_word} , R26
!sts {Data_adc_3_word + 1} , R27
!ldi R30 , Channel_adc_4
!rjmp Change_channel_adcSave_data_adc_4:
!sts {Data_adc_4_word} , R26
!sts {Data_adc_4_word + 1} , R27
!ldi R30 , Channel_adc_5
!rjmp Change_channel_adcSave_data_adc_5:
!sts {Data_adc_5_word} , R26
!sts {Data_adc_5_word + 1} , R27
!ldi R30 , Channel_adc_6
!rjmp Change_channel_adcSave_data_adc_6:
!sts {Data_adc_6_word} , R26
!sts {Data_adc_6_word + 1} , R27
!ldi R30 , Channel_adc_7
!rjmp Change_channel_adcSave_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
'===============================================================================
Измерение 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 'Массив данных ответа датчика DS18x20Dim Count_time_upd_ds18b20 As Word
Dim Time_upd_ds18b20 As Word
Dim Flag_upd_ds18b20 As ByteDim 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 IntegerDim 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
#endifAdcsra.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_0000Admux = 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 ByteDim 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 WordDim 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 SingleDim 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.5Config Timer1 = Counter , _
Prescale = Const_div_sys_timer , _
Compare A = Disconnect , _
Compare B = Disconnect , _
Clear Timer = 1On 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 ByteDim 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 в msLocate 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 , SignedIf 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 IfIf 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 IfElse
Буфер_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 ThenIf 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_strLocate 2 , 3
Lcd Data_adc_3_str
Locate 2 , 10
Lcd Data_adc_4_str
Locate 2 , 17
Lcd Data_adc_5_strLocate 3 , 3
Lcd Data_adc_6_str
Locate 3 , 10
Lcd Data_adc_7_str
End IfIf Flag_upd_ds18b20_lcd > 0 Then
Locate 4 , 1
Lcd Буфер_lcd_4_строка_strFlag_upd_ds18b20_lcd = 0
End IfFlag_upd_lcd = 0
Goto Main
End IfIdle
'===============================================================================
Goto Main
End
'==============================================================================='===============================================================================
Function 1wire_read_bit_usart() As Byte 'Принимаем бит ROM от устройства
'-------------------------------------------------------------------------------
Used_baud_rate = Const_usart_115200Used_udr0 = &HFF
Gosub 1wire_wait_byte_reception
If 1wire_temp_udr = &HFF Then
1ware_tmp_bit = 1
Else
1ware_tmp_bit = 0
End If1wire_read_bit_usart = 1ware_tmp_bit
'-------------------------------------------------------------------------------
End Function
'==============================================================================='===============================================================================
Sub 1wire_write_bit_usart(byval Copy_byte As Byte)
'-------------------------------------------------------------------------------
Used_baud_rate = Const_usart_115200If Copy_byte = 0 Then
Used_udr0 = &H00
Else
Used_udr0 = &HFF
End IfGosub 1wire_wait_byte_reception
'-------------------------------------------------------------------------------
End Sub
'==============================================================================='===============================================================================
Sub 1wire_read_usart(byval Copy_count As Byte)
'-------------------------------------------------------------------------------
1ware_tmp_count = Copy_countFor 1ware_tmp_count_1 = 1 To 1ware_tmp_count
For 1ware_tmp_count_2 = 0 To 7Used_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 IfNext 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_dataUsed_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 IfGosub 1wire_wait_byte_reception
Next 1ware_tmp_count
'-------------------------------------------------------------------------------
End Sub
'==============================================================================='===============================================================================
Sub 1wire_reset_usart()
'-------------------------------------------------------------------------------
Used_baud_rate = Const_usart_9600Used_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_transfers1wire_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_lcdCounter_time_upd_lcd:
!sbiw R30 , 1
!rjmp Save_Time_upd_lcdReload_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_ds18b20Counter_time_upd_ds18b20:
!sbiw R30 , 1
!rjmp Save_Time_upd_ds18b20Reload_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_adcSave_data_adc_0:
!sts {Data_adc_0_word} , R26
!sts {Data_adc_0_word + 1} , R27
!ldi R30 , Channel_adc_1
!rjmp Change_channel_adcSave_data_adc_1:
!sts {Data_adc_1_word} , R26
!sts {Data_adc_1_word + 1} , R27
!ldi R30 , Channel_adc_2
!rjmp Change_channel_adcSave_data_adc_2:
!sts {Data_adc_2_word} , R26
!sts {Data_adc_2_word + 1} , R27
!ldi R30 , Channel_adc_3
!rjmp Change_channel_adcSave_data_adc_3:
!sts {Data_adc_3_word} , R26
!sts {Data_adc_3_word + 1} , R27
!ldi R30 , Channel_adc_4
!rjmp Change_channel_adcSave_data_adc_4:
!sts {Data_adc_4_word} , R26
!sts {Data_adc_4_word + 1} , R27
!ldi R30 , Channel_adc_5
!rjmp Change_channel_adcSave_data_adc_5:
!sts {Data_adc_5_word} , R26
!sts {Data_adc_5_word + 1} , R27
!ldi R30 , Channel_adc_6
!rjmp Change_channel_adcSave_data_adc_6:
!sts {Data_adc_6_word} , R26
!sts {Data_adc_6_word + 1} , R27
!ldi R30 , Channel_adc_7
!rjmp Change_channel_adcSave_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
'===============================================================================
Вы здесь » Программирование ATMEL в BASCOM. » Примеры применения в среде Баском » Исследование АЦП в МК Atmegaxxx и Attinyxxx