Форум РадиоКот https://radiokot.ru/forum/ |
|
АЦП и внешнее прерывание в ATtiny13 https://radiokot.ru/forum/viewtopic.php?f=57&t=147096 |
Страница 1 из 1 |
Автор: | nightghost [ Ср июл 26, 2017 19:31:01 ] |
Заголовок сообщения: | АЦП и внешнее прерывание в ATtiny13 |
Здравствуйте! Друзья помогите разобраться с причиной того, почему не работает, АЦП и внешнее прерывание в tiny13? Возможно я, что-то напортачил с настройкой. При подключении переменника и вращении в определенный момент должен появляться высокий лог. уровень на PB4, тоже самое и с внешним прерыванием, при нажатии на кнопку. #include <avr/io.h> #define F_CPU 12000000UL #include <util/delay.h> #include <avr/interrupt.h> #include <avr/sfr_defs.h> unsigned char s; unsigned int RezultatACP; ISR (ADC_vect) RezultatACP = ADCW; if (RezultatACP < 2046) { s=1; } else { s=0; } ADCSRA = ADCSRA | 0x40; } ISR (INT0_vect) { _delay_ms(20); PORTB |= (1<<PB4); } int main(void) { DDRB |= (1<<PB2)|(1<<PB4); PORTB |= (1<<PB0); ADMUX = 3; ADCSRA = 0xCE MCUCR = (1<<ISC01)| (1<<ISC00); GIMSK = (1<<INT0); sei(); while(1) { if (bit_is_clear(PINB,PB0)) { if (s==1) { PORTB|=(1<<PB4); } } else { PORTB&=~(1<<PB4); } } } |
Автор: | COKPOWEHEU [ Чт июл 27, 2017 17:42:31 ] |
Заголовок сообщения: | Re: АЦП и внешнее прерывание в ATtiny13 |
Цитата: RezultatACP = ADCW; "тонкий" намек: какие значения может принимать регистр ADCW с вашими настройками?if (RezultatACP < 2046) Цитата: #define F_CPU 12000000UL За такое (и за отсутствие форматирования в целом) по рукам бить надо. Хотя прерывание Int0 настроено по-человечески (случайность?).ADMUX = 3; ADCSRA = 0xCE ADCSRA = ADCSRA | 0x40; Переменная RezultatACP (почему не назвать по-нормальному, adc_result хотя бы?..) объявлена глобальной, но используется только в прерывании. Логичнее было ее сделать локальной. Переменная s (офигеть информативное название) объявлена глобально, используется в прерывании и в основной программе, но не объявлена volatile. Это ошибка! Из описания непонятно чего вы пытаетесь добиться и что именно не получается. Вчитываться в этот неформатированный ужас особого желания нет, но, похоже, дребезг не обрабатывается. Если так, у вас программа на пограничных значениях будет постоянно в прерывание заходить. |
Автор: | nightghost [ Чт июл 27, 2017 18:36:05 ] |
Заголовок сообщения: | Re: АЦП и внешнее прерывание в ATtiny13 |
Цитата: RezultatACP = ADCW; "тонкий" намек: какие значения может принимать регистр ADCW с вашими настройками?if (RezultatACP < 2046) Цитата: #define F_CPU 12000000UL За такое (и за отсутствие форматирования в целом) по рукам бить надо. Хотя прерывание Int0 настроено по-человечески (случайность?).ADMUX = 3; ADCSRA = 0xCE ADCSRA = ADCSRA | 0x40; Переменная RezultatACP (почему не назвать по-нормальному, adc_result хотя бы?..) объявлена глобальной, но используется только в прерывании. Логичнее было ее сделать локальной. Переменная s (офигеть информативное название) объявлена глобально, используется в прерывании и в основной программе, но не объявлена volatile. Это ошибка! Из описания непонятно чего вы пытаетесь добиться и что именно не получается. Вчитываться в этот неформатированный ужас особого желания нет, но, похоже, дребезг не обрабатывается. Если так, у вас программа на пограничных значениях будет постоянно в прерывание заходить. Какая разница как назвать переменные от этого по другому они работать не станут? Просто назвал как удобнее)) Тогда как правильно (форматированно) обработать дребезг в прерывании? PS а намек понял...спасибо!) |
Автор: | COKPOWEHEU [ Пт июл 28, 2017 08:50:22 ] |
Заголовок сообщения: | Re: АЦП и внешнее прерывание в ATtiny13 |
Форматирование, комментарии и осмысленные названия переменных нужны не непосредственно для правильной работы программы, а чтобы упростить себе и другим анализ кода - где какой блок начинается и заканчивается, какая переменная для чего предназначена, чего автор хотел добиться тем или иным блоком кода. Туда же использование именованных битов в том же ADCSRA - я, например, не помню какой за что отвечает, но если бы было написано, скажем, ADCSRA = (1<<ADIE | 0b001<<ADPS0) была бы сразу заметна ошибка, а то и не одна. Кажется, у Макконела было что-то вроде "если мне принесут посмотреть вот такой код я скажу сначала привести его в читаемый вид. Если вот сякой - посмотрю по настроению, поскольку глаза не режет, а если вот эдакий - прочитаю обязательно". Потому что можно сконцентрироваться на логике, а не на подробностях реализации. Цитата: Тогда как правильно (форматированно) обработать дребезг в прерывании? А нужно ли в прерывании? Опрос кнопок (хоть одной, хоть всех) проще делать по таймеру с интервалом 10 - 500 мс, либо в бесконечном цикле с тем же периодом: точность времени тут не важна.Впрочем, я пока не представляю задачу в которой одновременно измеряется напряжение с помощью АЦП и приближенно оценивается его уровень с помощью внешнего прерывания. Требуется реакция на пересечение порога (угу, на IO выводе с неизвестным уровнем срабатывания и гистерезисом) со задержкой менее 30 мкс (что обеспечивается АЦП)? Даже если так, аналоговый компаратор точнее обычного прерывания. Цитата: PS а намек понял...спасибо!) А зря, потому что в зависимости от настроек диапазон меняется: (0...255), (0...1023), (0...65472) и даже (0...3). Кстати, может вам и не надо все 10 бит, а хватит и 8? Работа с 8-битными переменными проще и быстрее. Ну и не стоит использовать магические числа, берущиеся непонятно откуда. Лучше объявить константу или макрос (в gcc-avr макрос обычно удобнее), напримерКод: #define MAX_TEMPERATURE_C 100 //максимальная температура, в градусах Цельсия #define Temp2ADC(t) (1024*(t+273)) //например, такая формула. Взята от балды так что физический смысл коэффициентов не знаю, но в реальном коде его стоит расписать ... if( ADC > Temp2ADC(MAX_TEMPERATURE) ){...} В последнем проекте у меня фигурирует вот такой макрос Код: #define P_koeff ((uint32_t)( \ У всех входящих в него констант есть физический смысл - сопротивления резисторов (в Омах или миллиОмах), опорное напряжение АЦП (в милливольтах), разрядность каналов. Все их можно напрямую или косвенно измерить для конкретной платы и контроллера. Более правильно было бы хранить эту константу в EEPROM'e, но для одиночного изделия и так неплохо.
((( \ ((( \ ( ( (8* R_DL_Ohm*R_sh_mOhm*1024/ (R_DH_Ohm+R_DL_Ohm) )+1 )/2 ) \ *1024/U_ref_mV)+1)/2) \ *1000/U_ref_mV)+1)/2) \ )) |
Автор: | nightghost [ Пт июл 28, 2017 16:39:47 ] |
Заголовок сообщения: | Re: АЦП и внешнее прерывание в ATtiny13 |
Форматирование, комментарии и осмысленные названия переменных нужны не непосредственно для правильной работы программы, а чтобы упростить себе и другим анализ кода - где какой блок начинается и заканчивается, какая переменная для чего предназначена, чего автор хотел добиться тем или иным блоком кода. Туда же использование именованных битов в том же ADCSRA - я, например, не помню какой за что отвечает, но если бы было написано, скажем, ADCSRA = (1<<ADIE | 0b001<<ADPS0) была бы сразу заметна ошибка, а то и не одна. Кажется, у Макконела было что-то вроде "если мне принесут посмотреть вот такой код я скажу сначала привести его в читаемый вид. Если вот сякой - посмотрю по настроению, поскольку глаза не режет, а если вот эдакий - прочитаю обязательно". Потому что можно сконцентрироваться на логике, а не на подробностях реализации. Цитата: Тогда как правильно (форматированно) обработать дребезг в прерывании? А нужно ли в прерывании? Опрос кнопок (хоть одной, хоть всех) проще делать по таймеру с интервалом 10 - 500 мс, либо в бесконечном цикле с тем же периодом: точность времени тут не важна.Впрочем, я пока не представляю задачу в которой одновременно измеряется напряжение с помощью АЦП и приближенно оценивается его уровень с помощью внешнего прерывания. Требуется реакция на пересечение порога (угу, на IO выводе с неизвестным уровнем срабатывания и гистерезисом) со задержкой менее 30 мкс (что обеспечивается АЦП)? Даже если так, аналоговый компаратор точнее обычного прерывания. Цитата: PS а намек понял...спасибо!) А зря, потому что в зависимости от настроек диапазон меняется: (0...255), (0...1023), (0...65472) и даже (0...3). Кстати, может вам и не надо все 10 бит, а хватит и 8? Работа с 8-битными переменными проще и быстрее. Ну и не стоит использовать магические числа, берущиеся непонятно откуда. Лучше объявить константу или макрос (в gcc-avr макрос обычно удобнее), напримерКод: #define MAX_TEMPERATURE_C 100 //максимальная температура, в градусах Цельсия #define Temp2ADC(t) (1024*(t+273)) //например, такая формула. Взята от балды так что физический смысл коэффициентов не знаю, но в реальном коде его стоит расписать ... if( ADC > Temp2ADC(MAX_TEMPERATURE) ){...} В последнем проекте у меня фигурирует вот такой макрос Код: #define P_koeff ((uint32_t)( \ У всех входящих в него констант есть физический смысл - сопротивления резисторов (в Омах или миллиОмах), опорное напряжение АЦП (в милливольтах), разрядность каналов. Все их можно напрямую или косвенно измерить для конкретной платы и контроллера. Более правильно было бы хранить эту константу в EEPROM'e, но для одиночного изделия и так неплохо.((( \ ((( \ ( ( (8* R_DL_Ohm*R_sh_mOhm*1024/ (R_DH_Ohm+R_DL_Ohm) )+1 )/2 ) \ *1024/U_ref_mV)+1)/2) \ *1000/U_ref_mV)+1)/2) \ )) О форматировании кода вы меня убедили, будем стараться)) Конечно можно было проще использовать и компаратор, и опрос кнопок в прерываниях, но это просто эксперимент и изучение attiny13 на будущее. Жаль мало информации на русском об этом МК, надо курить даташит на заграничном, а времени совсем мало, видать в этом-то и проблема Как при 10 бит может быть (0...65472) (0...3)...? И о каких магические числах вы имеете в виду? |
Автор: | COKPOWEHEU [ Пт июл 28, 2017 19:33:44 ] |
Заголовок сообщения: | Re: АЦП и внешнее прерывание в ATtiny13 |
Вся информация из даташита переведена Евстифеевым "Микроконтроллеры AVR семейства tiny" Магические числа - 2048 с которым вы сравниваете результат АЦП, инициализирующие значения для ADCSRA и т.п. Про разрядность АЦП - бит ADLAR, выравнивание либо по старшему, либо по младшему биту. При выравнивании по младшему, можно использовать только ADCH - будет 2 значащих бита, диапазон (0...3), если выравнивание по старшему - парный регистр ADC принимает значения (0...65472) - 10 старших битов. Не особо представляю, где эти диапазоны могут пригодиться, но теоретически - возможно. |
Автор: | nightghost [ Сб июл 29, 2017 14:26:28 ] |
Заголовок сообщения: | Re: АЦП и внешнее прерывание в ATtiny13 |
Понятно, спасибо, что просветили ![]() |
Автор: | Z_h_e [ Сб июл 29, 2017 14:58:45 ] |
Заголовок сообщения: | Re: АЦП и внешнее прерывание в ATtiny13 |
COKPOWEHEU писал(а): Не особо представляю, где эти диапазоны могут пригодиться Если не нужен точный АЦП, настраиваете выравнивание слева и считываете только ADCH. Получается 8ми битный АЦП без дополнительных операций.
|
Автор: | COKPOWEHEU [ Сб июл 29, 2017 21:44:18 ] |
Заголовок сообщения: | Re: АЦП и внешнее прерывание в ATtiny13 |
Невнимательно читаете: речь шла про режимы с выравниванием младшего бита и считыванием ADCH - диапазон (0...3) и с выравниванием по старшему с использованием обоих регистров - диапазон (0...65472). Впрочем, последнее может и пригодиться если где-то в вычислениях нужно умножение на 16-64. |
Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |