Страницы

Поиск по вопросам

Показаны сообщения с ярлыком микроконтроллеры. Показать все сообщения
Показаны сообщения с ярлыком микроконтроллеры. Показать все сообщения

вторник, 25 февраля 2020 г.

Как определить значение АЦП на языке C?

#c #микроконтроллеры #avr


В процессе программирования микроконтроллеров AVR появилась необходимость измерения
напряжения и передачи его на ПК. Передачу на ком порт я освоил по ранее заданному вопросу,
сейчас хотелось бы узнать как измерить напряжение? 
    


Ответы

Ответ 1



Для определния значения напряжения у МК должен быть встроенный АЦП, но по моему в прошлом вопросе Вы говорили что используете AtMega32, так вот у него аж 8 каналов. Ниже приведу программу для определения значения напряжения, но прежде попытаюсь разъеснить что к чему на Вашем конкретном МК. Каналов, как я сказал, восемь. АЦП 10 разрядный, но можно в настройках установить 8 разрядов. Точность измерения АЦП вплоть до младшего значения, то есть если мы берем 10 разрядный АЦП, то у него 1023 младшие единицы, а значит при опорном напряжении 5В точность будет 5000 мВ/1023 т.е. приблизительно 4мВ. В настройках необходимо будет указать частоту дискретизации. Так значит перейдем к ПО. Описывать особо не буду, всю информацию сможете подчеркнуть в комментариях. #include #include #include //Определим название канала с которого мы и будем считывать значение АЦП #define ADC_0 0 // функция read_adc() и будет нам возвращать значение АЦП unsigned char read_adc(unsigned char adc_input) { ADMUX=adc_input | (ADC_VREF_TYPE & 0xff); //Задержка необходимая для стабилизации значения АЦП delay_us(10); // Преобразование значения ADCSRA|=0x40; // Ожидаем окончания обработки while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; //Возвращаем значение АЦП return ADCH; } int adc; //Переменная которая будет хранить в себе текущее значение АЦП void main(void) { //Настраиваем МК PORTA=0x00; DDRA=0x00; PORTB=0x00; DDRB=0x0C; PORTC=0x00; DDRC=0xC3; PORTD=0x00; DDRD=0x88; TCCR0=0x6B; TCNT0=0x00; OCR0=0x5F; TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; ASSR=0x00; TCCR2=0x6C; TCNT2=0x00; OCR2=0x5F; MCUCR=0x00; MCUCSR=0x00; TIMSK=0x00; UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x19; ACSR=0x80; SFIOR=0x00; // Инициализация АЦП // Частота преобразования: 125,000 kHz // Ножка на которую будет подаваться опорное напряжение: AVCC pin ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0xA7; SFIOR&=0x1F; while (1) { //Присваиваем текущее значение АЦП переменной adc adc = read_adc(ADC_0); //Отправляем на ПК полученное значение, которое на нем вы сможете преобразовать в напряжение по формуле (adc/1023)*Vref, где Vref - опорное напряжение МК printf("%d\n\r ADC= ", adc); //Устанавливаем задержку после каждой отправки delay_ms(1000); } } Как принимать и отправлять я отвечал Вам в предыдущем вопросе: Как на Си передать информацию от микроконтроллера на COM- порт?

суббота, 8 февраля 2020 г.

Как на Си передать информацию от микроконтроллера на COM-порт?

#cpp #c #микроконтроллеры #com_порт


Занимаюсь изучением программирования микроконтроллеров АВР, и столкнулся с вопросом
передачи данных от микроконтроллера на ПК через ком порт. Пишу на Си, МК Atmel AtMega32. 
    


Ответы

Ответ 1



Для передачи информации от МК на COM-порт ПК используется интерфейс RS-232. На микроконтроллерах AVR он называется USART(универсальный синхронно-асинхронный приемо передатчик). Вы написали, что программа на Си, но не указали какой компилятор Вы используете, поэтому ниже приведу программу написанную в CodeVision AVR, но перенести ее на любой другой C компилятор микроконтроллеров AVR не должно составить особых сложностей. Есть два пути создания такого рода ПО. 1) Воспользоваться стандартным генератором начального кода, который имеется в CodeVisionAVR. Для этого нужно выполнить следующие шаги. а) при создании нового проекта, выбрать "использовать CodeWizard" б) перейти на вкладку USART и там поставить галочки перед приемником и передатчиком, то есть активизировать их. в) задать скорость приема передачи информации и другие параметры, синхронность асинхронность, кол-во стоп битов и т.д. г) нажать генерировать ПО д) далее используя стандартную библиотеку ввода-вывода отправлять и принимать информацию. 2) Написать ручками ниже приведенный код: #include #include #include void main(void) { // Input/Output Ports initialization // Port A initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTA=0x00; DDRA=0x00; // Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=0 State2=T State1=T State0=T PORTB=0x00; DDRB=0x0C; // Port C initialization // Func7=Out Func6=Out Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=Out // State7=0 State6=0 State5=T State4=T State3=T State2=T State1=0 State0=0 PORTC=0x00; DDRC=0xC3; // Port D initialization // Func7=Out Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=0 State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTD=0x00; DDRD=0x88; // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Mode: Fast PWM top=FFh // OC0 output: Non-Inverted PWM TCCR0=0x6B; TCNT0=0x00; OCR0=0x5F; // Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; // Timer/Counter 2 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Mode: Fast PWM top=FFh // OC2 output: Non-Inverted PWM ASSR=0x00; TCCR2=0x6C; TCNT2=0x00; OCR2=0x5F; // External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=0x00; MCUCSR=0x00; // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00; /// USART initialization // Параметры соединения: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: On // USART Mode: Asynchronous // USART Baud Rate: 38400 UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x19; // Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00; while (1) { int a; a = 5; unsigned char get; // Отправить что нибудь: printf("%d\n\r", a); // Принять get = getchar(); //Отправить принятое: printf("%d\n\r", get); } } Но не забывайте, прежде чем организовать прием-передачу информации посредством RS232 необходимо согласовать логические уровни. И соединять надо приемник с передатчиком!) Как то так.

Привязка контроллеров к USB-портам

#linux #usb #микроконтроллеры


Имеются два идентичных конторллера для управления шаговыми двигателями, подключенные
по USB. Если подключать их при работающей ОС, то первый подключенный вешается на /dev/USB0,
а второй на /dev/USB1.
Как сделать так, чтобы при старте системы первый контроллер всегда вешался на /dev/USB0,
а второй на /dev/USB1?     


Ответы

Ответ 1



Попробуйте создать правила для Ваших контроллеров через udev. Каждый раз при подключении или отключении устройства ядро посылает событие uevent, которое информирует udev о произошедших изменениях. Демон udev считывает правила для своей работы из каталога /etc/udev/rules.d/ единожды при своем запуске и затем хранит их в памяти. Каждое полученное событие сравнивается с набором загруженных правил. С помощью правил можно добавлять специфичные для окружения опции, создавать символические ссылки на создаваемый файл устройства или указать программу, запускаемую после того как файл устройства будет создан. События ядра uevents от драйверов устройств передаются через сокет ядра netlink. Нампример, здесь рассказывается, как создаются правила, но думаю, без труда найдете еще с десяток разных примеров и инструкций. Надеюсь, это то, что нужно! :)

четверг, 23 января 2020 г.

Литература по эффективному программированию процессоров (DMA, прерывания)

#микроконтроллеры #процессор


Всем привет!

Я хотел бы найти хорошую литературу по программированию микропроцессоров/микроконтроллеров
(например с ядром Cortex-M0, Cortex-M3), где качественно описывается использование
прерываний и контроллера ПДП. Не так как в даташите, сухой пример использования конкретной
периферии независимо от всего остального, а хорошее пособие по написанию программ.

Интересует прежде всего печатный вариант (книги, учебники) а не отдельные статьи,
но их тоже почитаю. Заранее прошу не предлагать статьи из первой страницы поиска в
гугле "использование DMA" и т.д., так я и сам умею.

Имеется опыт программирования контроллеров AVR, знания C/C++, ассемблера.
    


Ответы

Ответ 1



Подробные статьи по применению стоит посмотреть в ежеквартальнике Бюллютень TI, скачать можно на сайте scanti.ru. К сожалению подобные труды, которые вас интересуют, в природе маловероятны. Сам модуль DMA и его связи с периферией настолько узкоспециализированные и индивидуальные для каждого конкретного процессора, что паттернов его использования более глобальных чем "разгон" конкретного интерфейса и высвобождение процессорных ресурсов для задач не связанных с пересылкой данных в общем случае описать невозможно. Однако, если у вас есть конкретные вопросы по возможностям применерия, могу на них ответить.

среда, 25 декабря 2019 г.

Использование c++ в микроконтроллерах

#cpp #avr_gcc #микроконтроллеры


Подскажите пожалуйста, можно ли использовать C++ для программирования микроконтроллеров? 
Есть ли при этом какие либо ограничения для языка C++?    


Ответы

Ответ 1



использовать часто можно, но нужно смотреть на конкретную реализацию. К примеру, может не быть исключений. С другой стороны, с++ приносит определенный оверхед, а на микроконтроллерах часто бывает важный каждый байт, это не java c большими серверами, где можно докупить планку-другую. Но микроконтроллеры не стоят на месте и развиваются, как собственно и компиляторы. Возможно, для Вашего контроллера и Вашего случае С++ - лучший вариант.

Ответ 2



На самом деле никаких ограничений нет, просто нужен правильный скрипт линковщика с соответствующими секциями для поддержки исключений и виртуальных методов, а так-же релизация аллокаторов/деаллокаторов и STL (конечно это роскошь?). Найти какой скрипт в сети не сложно...

Ответ 3



C++ не только можно, но и нужно использовать для программирования микроконтроллеров. Как тут писалось, никаких исключений и операторов new. Для отмены исключений есть даже флаг компилятора, специально для нас. Чем С++ лучше си: Строгая типизация. Если что-то не так, получите ошибку при компиляции, а не поиск её в отладке. Наглядный пример, если в функцию передаётся тип перечисления, а вы в си вписали что-то не то (int, к примеру), то в си вы пройдёте компиляцию, в C++ получите ошибку компиляции. Ссылки. Философия С++: "не плати за то, что тебе не нужно". Ссылки не занимают место в памяти, код с ссылками смотрится аккуратнее, чем код с указателями. Всегда можно забыть поставить * или &. Классы (структуры). Банально удобно описывать не только саму структуру, но и действия с ней. Каждый регистр можно обернуть в классовую обёртку с методами, которые своим названием указывают, что вы делаете. Если код необходимо много комментировать, то это плохой код. Объекты. В функцию (класс, метод класса) можно передать ссылку на объект вывода микроконтроллера, а не писать кучу дефайнов всех регистров (легко ошибиться, много исправлять, особенно для всяких stm32). Шаблоны. Забудьте про многострочные макросы, ошибки в которых отладить крайне сложно, дебагер в них просто не войдёт. Шаблоны куда лучше препроцессора. Оверхеда нет. Это распространённый миф. Грамотный код, написанный на с++ даёт меньший объём бинарников, натыкался на исследования, даже ролики с конференций есть на ютьюбе. (полагаю всему виной ссылки вместо указателей и оптимизация шаблонов).

Ответ 4



Посмотрите на язык Wiring, используемый в Arduino. Это C++ без стандартной библиотеки и исключений, со своей специальной библиотекой. Компилируется он, кстати, упомянутым у вас в тегах avr-gcc.

четверг, 12 декабря 2019 г.

Возможно ли программно на Си организовать цифро-аналоговый преобразователь

#c #микроконтроллеры #avr


Можно ли используя восьмиразрядный микроконтроллер AVR, без встроенного ЦАП организовать
его программно на Си? Суть в том, что хочется получить пилообразный сигнал!    


Ответы

Ответ 1



Да это возможно. Что же для этого нужно! Первое - это применить не сложное схемотехническое решение. Схемку накидал быстро, поэтому строго не судите. Это так называемый R2R ЦАП, который позволяет превратить 8 обычных портов ввода-вывода в оди полноценный 8 битный цифро-аналоговый преобразователь. Вот схема: Далее пишем программу которая будет генерировать Ваш пилообразный сигнал! #include #include void main(void) { DDRA=(0< 0; i--) { PORTB = i; } } } Хочу добавить , что используя R2R цап собирал wav плеер, то есть возможности очень широки. Ниже вид сигнала который я получил этой программкой. 9393 Я даже видел как генерируют эротические сигналы, правда не знаю функцию которая за это отвечает, но можно разбить на несколько for по нарастанию и убыванию.

Ответ 2



Ещё один способ организации ЦАП - использование широтно-импульсного модулятора и сглаживающего фильтра (RC или LC цепочка). В этом случае напряжение ЦАПа задается коэффициентом заполнения ШИМа. Чем больше заполнение - тем больше напряжение. Такой подход позволяет экономить выводы микроконтроллера (один канал ЦАПа - один вывод), но не может обеспечить такую высокую частоту, как описанный vanyamelikov способ. Сигналы необычной формы необязательно генерировать в процессе работы. Обычно эффективнее на этапе написания программы сгенерировать массив, состоящий из значений этого сигнала, и в процессе выполнения последовательно выдавать каждое значение на ЦАП.

понедельник, 9 декабря 2019 г.

Выделение памяти на локальные и глобальные переменные

#cpp #c #микроконтроллеры #embedded


В программировании встраиваемых систем не рекомендуется использовать динамическое
выделение памяти. Отсюда у меня возник следующий вопрос. В случае глобальных переменных,
на сколько я знаю, память выделяется сразу. Что делать с локальными? Компилятор сразу
выделяет и на них память или возможна такая ситуация, что при вызове функции с локальными
переменными, память МК будет переполнена, что вызовет печальные последствия?
    


Ответы

Ответ 1



Компилятор не может "сразу" выделять память под локальные автоматические переменные, ибо при каждом рекурсивном входе в одну и ту же функцию она должна получать новый, независимый набор автоматических переменных. Это требует стекообразного динамического распределения памяти для локальных переменных во время выполнения. Что, разумеется, может приводить и к переполнению памяти во время выполнения. Если запретить рекурсивные вызовы в языке, то теоретически компилятор будет в состоянии предсказать максимальный вариант потребления памяти локальными переменными и даже выполнить "раннее" распределение памяти для таких переменных еще на этапе компиляции, фактически заменив их на глобальные переменные. Но что-то подобное можете сделать и вы сами, отказавшись от использования локальных переменных вообще. (Хотя даже в таком случае компилятору будет проще обеспечить максимальную экономию памяти путем "совместного использования" одних и тех же областей памяти теми локальными переменными, которые заведомо не могут существовать одновременно. Выполнить такую "упаковку" переменных вручную теоретически можно, но задача это тяжелая, трудноподдерживаемая и чреватая ошибками.)

Ответ 2



Да, это запросто - потому что локальные переменные выделяются в стеке, и его можно переполнить. Особенно при рекурсии или просто глубокой вложенности функций. Так что нужно или очень строго контролировать, что вызывается и как, и чего и сколько выделяется на стеке, или... С другой стороны, локальные переменные - если их немного - позволяют не заботиться о возможных неприятностях типа перекрытия имен и т.п. "По-моему, так" (с) Пух

где найти заземление

#микроконтроллеры #arduino #avr


есть AVR - ATmega32, и есть плата, в которой она уютно сидит. плата наподобие Arduino.

на плате есть удобные выводы по бокам для всех портов (A, B, C, D), и даже Vcc, а
вот GND вытащить забыли. и сейчас, чтобы просто замерить напряжение, мне нужно вставать
на ногу самого контроллера, а ещё и держать там щуп, что совсем неудобно. а недавно
появилась необходимость подключить диоды на беспаечную плату, а замли то нет.

предположим, что я вообще не знаю электроники.

как мне провести землю/ноль/-/GND на беспаечную/монтажную плату?

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


    


Ответы

Ответ 1



Там есть разъем ISP. У него 4 пина - это GND.

Ответ 2



распиновка интерфейсов ISP и JTAG. вывел землю из десятого пина, хотя второй тоже работает как ноль. оффтоп: спасибо всем участникам обсуждения.

суббота, 7 декабря 2019 г.

Автоматизация огорода [закрыт]

#java #delphi #usb #железо #микроконтроллеры


        
             
                
                    
                        
                            Closed. This question needs to be more focused. It is
not currently accepting answers.
                            
                        
                    
                
                            
                                
                
                        
                            
                        
                    
                        
                            Want to improve this question? Update the question so
it focuses on one problem only by editing this post.
                        
                        Closed 4 года назад.
                                                                                
           
                
        
Доброго время суток.
Подскажите, пожалуйста, планирую сделать автоматизированное управление (как бы смешно
не звучала огорода) т.к живу очень далеко а ездить каждые выходные что то не хочется. т.е 

датчик влажности почвы 
датчик влажности 
автоматический полив не по таймеру, а по влажности почвы.

Подскажите какую плату можно использовать? и контроллеры?
Планируется управление по wifi (или чем то еще но только без проводов)
Программировать планирую на delphi или Java, C# только изучаю.
Желательно детали недорогие если можно посоветовать.
У кого какие предложения?
Я никогда ранее не работал с микроконтроллерами и т.д. Извините за некомпетентность.    


Ответы

Ответ 1



Культивацией плантации собираетесь заниматься?) Датчики влажности, температуры и прочей электроники можно найти на китайский барахолках, типа http://dx.com За контроллер берите arduino mega, ибо его разъемов должно хватить почти на всё.

Ответ 2



Omron! Есть такая фирма, правда дороговато, но программирование их микроконтроллеров, похоже на построение электрических сетей(в их специальной программе есс-но, CX-Programmer вроде или CX-One)

Ответ 3



Если управление поливом будет автоматическое, то Atmel+Датчик влажности+исполнительное устройство включения полива. Если управление будет on-line, то добавляется огородный ПК с GPRS модемом, программа сбора показаний датчиков на огороде с отправкой данных оператору, программа управления на удаленном ПК, связь между ними можно организовать по технологии socket. Чтоб управление было стойкое к метеоусловиям передачу данных между ПК и контроллером на огороде лучше организовать по bluetooth (bluegiga, HC-07 ...). В общем это комплексный проект. И нужно изучить все его составляющие.

Ответ 4



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

среда, 4 декабря 2019 г.

Микроконтроллеры и Java

#java #jvm #микроконтроллеры


Интересует такой вопрос. Допустим, у меня есть какая-то кнопка, которая лежит на
столе. Какие микроконтроллеры, устройства и т.п. можно использовать, чтобы реализовать
взаимодействие этой кнопки и java?
    


Ответы

Ответ 1



Поскольку Java изначально разрабатывалась для программирования холодильников и кофеварок, было бы странно, если бы возможность работы с железом была утрачена напрочь. Самый простой вариант подключения кнопки к микроконтроллеру - это порты GPIO, которые широко распространены в embedded мире. Кнопка одним контактом подключается к выводу порта, другим - к земле (GND). Дальше микроконтроллер либо сам что-то делает, либо по UART/USB/Ethernet/WiFi/Bluetooth отправляет сообщение о нажатой кнопке куда-то еще. Непосредственно по железу варианты есть следующие. Использовать специализированный микроконтроллер, заточенный под Java. Да, такие есть. Например семейство 3G-модулей Centerion. Прошивка представляет собой мидлет Java ME и может заливаться в том числе по воздуху. Прослушивание порта выглядит как-то так: Vector inPins = new Vector(); inPins.addElement("GPIO11"); InPort inPort = new InPort(inPins); inPort.addListener(new InPortListener() { public void portValueChanged(int val) { System.out.println("Port value: " + val); } }); Использовать полноценную встраиваемую систему общего назначения на базе ARM-процессора, такую как BeagleBone или RaspberryPi. Там у вас будет полноценный Linux с возможностью установки полноценной Java SE или Java SE Embedded. А порты будут доступны через файловую систему как устройства вроде /sys/class/gpio/gpio49. Можно взаимодействовать с портом обычными средствами файлового ввода-вывода (что будет относительно медленно, хотя и достаточно для многих задач) или через прямой досутп к памяти через memory-mapped файл /dev/mem (что будет быстро). Но куда приятнее будет воспользоваться развесистым API сторонней библиотеки pi4j: GpioController gpioController = GpioFactory.getInstance(); GpioPinDigitalInput pin02 = gpioController.provisionDigitalInputPin(RaspiPin.GPIO_02,PinPullResistance.PULL_DOWN); pin02.addListener(new GpioPinListenerDigital() { @Override public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent gpioPinDigitalStateChangeEvent) { System.out.println("state: " + gpioPinDigitalStateChangeEvent.getState()); } }); Кроме того, существует еще и Java ME Embedded, предоставляющий нативный API доступа к портам в пакете com.oracle.deviceaccess: GPIOPin switchPin = null; switchPin = (GPIOPin) PeripheralManager.open(1); switchPin.setInputListener(new PinListener() { @Override public void valueChanged(PinEvent event) { // do something } }); К слову, жизнь тут не ограничена ARM, есть и MIPS и Intel Atom. Но подходы там те же. Очень интересными выглядят сторонние программные платформы на основе Java: MicroEJ. На Youtube есть ролик, где java-приложение с графикой исполняется на очень слабом железе (Cortex™-M0+ @48 MHz, 256 KB Flash, 32 KB RAM). Android Things от Google, ранее известная как Brillo. Удивительно, но на Java можно писать под 8-битные AVR-микроконтроллеры (те самые, на которых построена Arduino)! Это стало возможным благодаря HaikuVM, которая транслирует байткод Java из .class-файлов в С-структуры, линкует к ним интерпретатор и формирует на выходе обычный для AVR-микроконтроллеров HEX-файл, который шьется в железку как обычно. Еще есть: NanoVM - виртуальная машина подмножества Java, занимающая 8 кБ в флэш-памяти. uJ - эта VM крупнее (десятки килобайт), но обещает полную поддержку байткода, многопоточность и synchronized. Если вы хотите нопку подключить к Arduino, а его в свою очередь подключить к компьютеру и делать что-то на компьютере по нажатию на кнопку, попробуйте JArduino. Этот API требует залить на Arduino свою прошивку, после чего вы сможете взаимодействовать с устройством из обычной Java-программы на своем компьютере.

среда, 17 июля 2019 г.

Нужна информация по шедулерам для встроенных систем

Добрый день.
Когда-то давно я применял шедулер для микроконтроллера http://www.ucos-ii.com. Довольно приятная вещь, хотя и с ограниченной функциональностью. Но с тех пор эта контора заглохла. Подскажите информацию по подобным вещам. Может быть кто-нибудь знает форум, где обсуждаются похожие вещи.
Спасибо.
UPD1:
Оказалось, что контора не заглохла, просто переехала на другой хостинг: https://www.micrium.com/. И при этом контору купил Silicon Labs.


Ответ

Подобных ОСРВ для микроконтроллеров довольно много, перечень можно посмотреть здесь. Достаточно популярной является FreeRTOS (она бесплатна и по ней много материала в сети), embOS, MicroC/OS от Micrium

вторник, 14 мая 2019 г.

Как определить значение АЦП на языке C?

В процессе программирования микроконтроллеров AVR появилась необходимость измерения напряжения и передачи его на ПК. Передачу на ком порт я освоил по ранее заданному вопросу, сейчас хотелось бы узнать как измерить напряжение?


Ответ

Для определния значения напряжения у МК должен быть встроенный АЦП, но по моему в прошлом вопросе Вы говорили что используете AtMega32, так вот у него аж 8 каналов. Ниже приведу программу для определения значения напряжения, но прежде попытаюсь разъеснить что к чему на Вашем конкретном МК. Каналов, как я сказал, восемь. АЦП 10 разрядный, но можно в настройках установить 8 разрядов. Точность измерения АЦП вплоть до младшего значения, то есть если мы берем 10 разрядный АЦП, то у него 1023 младшие единицы, а значит при опорном напряжении 5В точность будет 5000 мВ/1023 т.е. приблизительно 4мВ. В настройках необходимо будет указать частоту дискретизации. Так значит перейдем к ПО. Описывать особо не буду, всю информацию сможете подчеркнуть в комментариях.
#include #include #include
//Определим название канала с которого мы и будем считывать значение АЦП #define ADC_0 0
// функция read_adc() и будет нам возвращать значение АЦП unsigned char read_adc(unsigned char adc_input) { ADMUX=adc_input | (ADC_VREF_TYPE & 0xff); //Задержка необходимая для стабилизации значения АЦП delay_us(10); // Преобразование значения ADCSRA|=0x40; // Ожидаем окончания обработки while ((ADCSRA & 0x10)==0); ADCSRA|=0x10; //Возвращаем значение АЦП return ADCH; }
int adc; //Переменная которая будет хранить в себе текущее значение АЦП
void main(void) { //Настраиваем МК PORTA=0x00; DDRA=0x00; PORTB=0x00; DDRB=0x0C; PORTC=0x00; DDRC=0xC3; PORTD=0x00; DDRD=0x88; TCCR0=0x6B; TCNT0=0x00; OCR0=0x5F; TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00; ASSR=0x00; TCCR2=0x6C; TCNT2=0x00; OCR2=0x5F; MCUCR=0x00; MCUCSR=0x00; TIMSK=0x00; UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x19; ACSR=0x80; SFIOR=0x00;
// Инициализация АЦП // Частота преобразования: 125,000 kHz // Ножка на которую будет подаваться опорное напряжение: AVCC pin ADMUX=ADC_VREF_TYPE & 0xff; ADCSRA=0xA7; SFIOR&=0x1F;
while (1) { //Присваиваем текущее значение АЦП переменной adc adc = read_adc(ADC_0); //Отправляем на ПК полученное значение, которое на нем вы сможете преобразовать в напряжение по формуле (adc/1023)*Vref, где Vref - опорное напряжение МК printf("%d

ADC= ", adc); //Устанавливаем задержку после каждой отправки delay_ms(1000); } }
Как принимать и отправлять я отвечал Вам в предыдущем вопросе: Как на Си передать информацию от микроконтроллера на COM- порт?

воскресенье, 14 апреля 2019 г.

Как на Си передать информацию от микроконтроллера на COM-порт?

Занимаюсь изучением программирования микроконтроллеров АВР, и столкнулся с вопросом передачи данных от микроконтроллера на ПК через ком порт. Пишу на Си, МК Atmel AtMega32.


Ответ

Для передачи информации от МК на COM-порт ПК используется интерфейс RS-232. На микроконтроллерах AVR он называется USART(универсальный синхронно-асинхронный приемо передатчик). Вы написали, что программа на Си, но не указали какой компилятор Вы используете, поэтому ниже приведу программу написанную в CodeVision AVR, но перенести ее на любой другой C компилятор микроконтроллеров AVR не должно составить особых сложностей. Есть два пути создания такого рода ПО. 1) Воспользоваться стандартным генератором начального кода, который имеется в CodeVisionAVR. Для этого нужно выполнить следующие шаги. а) при создании нового проекта, выбрать "использовать CodeWizard" б) перейти на вкладку USART и там поставить галочки перед приемником и передатчиком, то есть активизировать их. в) задать скорость приема передачи информации и другие параметры, синхронность асинхронность, кол-во стоп битов и т.д. г) нажать генерировать ПО д) далее используя стандартную библиотеку ввода-вывода отправлять и принимать информацию. 2) Написать ручками ниже приведенный код: #include #include #include
void main(void) {
// Input/Output Ports initialization // Port A initialization // Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTA=0x00; DDRA=0x00;
// Port B initialization // Func7=In Func6=In Func5=In Func4=In Func3=Out Func2=In Func1=In Func0=In // State7=T State6=T State5=T State4=T State3=0 State2=T State1=T State0=T PORTB=0x00; DDRB=0x0C;
// Port C initialization // Func7=Out Func6=Out Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=Out // State7=0 State6=0 State5=T State4=T State3=T State2=T State1=0 State0=0 PORTC=0x00; DDRC=0xC3;
// Port D initialization // Func7=Out Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In // State7=0 State6=T State5=T State4=T State3=T State2=T State1=T State0=T PORTD=0x00; DDRD=0x88;
// Timer/Counter 0 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Mode: Fast PWM top=FFh // OC0 output: Non-Inverted PWM TCCR0=0x6B; TCNT0=0x00; OCR0=0x5F;
// Timer/Counter 1 initialization // Clock source: System Clock // Clock value: Timer 1 Stopped // Mode: Normal top=FFFFh // OC1A output: Discon. // OC1B output: Discon. // Noise Canceler: Off // Input Capture on Falling Edge // Timer 1 Overflow Interrupt: Off // Input Capture Interrupt: Off // Compare A Match Interrupt: Off // Compare B Match Interrupt: Off TCCR1A=0x00; TCCR1B=0x00; TCNT1H=0x00; TCNT1L=0x00; ICR1H=0x00; ICR1L=0x00; OCR1AH=0x00; OCR1AL=0x00; OCR1BH=0x00; OCR1BL=0x00;
// Timer/Counter 2 initialization // Clock source: System Clock // Clock value: 250,000 kHz // Mode: Fast PWM top=FFh // OC2 output: Non-Inverted PWM ASSR=0x00; TCCR2=0x6C; TCNT2=0x00; OCR2=0x5F;
// External Interrupt(s) initialization // INT0: Off // INT1: Off // INT2: Off MCUCR=0x00; MCUCSR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=0x00;
/// USART initialization // Параметры соединения: 8 Data, 1 Stop, No Parity // USART Receiver: On // USART Transmitter: On // USART Mode: Asynchronous // USART Baud Rate: 38400 UCSRA=0x00; UCSRB=0x18; UCSRC=0x86; UBRRH=0x00; UBRRL=0x19;
// Analog Comparator initialization // Analog Comparator: Off // Analog Comparator Input Capture by Timer/Counter 1: Off ACSR=0x80; SFIOR=0x00;
while (1) { int a; a = 5; unsigned char get; // Отправить что нибудь: printf("%d

", a); // Принять get = getchar(); //Отправить принятое: printf("%d

", get); } } Но не забывайте, прежде чем организовать прием-передачу информации посредством RS232 необходимо согласовать логические уровни. И соединять надо приемник с передатчиком!) Как то так.

Привязка контроллеров к USB-портам

Имеются два идентичных конторллера для управления шаговыми двигателями, подключенные по USB. Если подключать их при работающей ОС, то первый подключенный вешается на /dev/USB0, а второй на /dev/USB1. Как сделать так, чтобы при старте системы первый контроллер всегда вешался на /dev/USB0, а второй на /dev/USB1?


Ответ

Попробуйте создать правила для Ваших контроллеров через udev. Каждый раз при подключении или отключении устройства ядро посылает событие uevent, которое информирует udev о произошедших изменениях. Демон udev считывает правила для своей работы из каталога /etc/udev/rules.d/ единожды при своем запуске и затем хранит их в памяти. Каждое полученное событие сравнивается с набором загруженных правил. С помощью правил можно добавлять специфичные для окружения опции, создавать символические ссылки на создаваемый файл устройства или указать программу, запускаемую после того как файл устройства будет создан. События ядра uevents от драйверов устройств передаются через сокет ядра netlink. Нампример, здесь рассказывается, как создаются правила, но думаю, без труда найдете еще с десяток разных примеров и инструкций. Надеюсь, это то, что нужно! :)

вторник, 27 ноября 2018 г.

Использование c++ в микроконтроллерах

Подскажите пожалуйста, можно ли использовать C++ для программирования микроконтроллеров? Есть ли при этом какие либо ограничения для языка C++?


Ответ

использовать часто можно, но нужно смотреть на конкретную реализацию. К примеру, может не быть исключений. С другой стороны, с++ приносит определенный оверхед, а на микроконтроллерах часто бывает важный каждый байт, это не java c большими серверами, где можно докупить планку-другую. Но микроконтроллеры не стоят на месте и развиваются, как собственно и компиляторы. Возможно, для Вашего контроллера и Вашего случае С++ - лучший вариант.

вторник, 30 октября 2018 г.

Возможно ли программно на Си организовать цифро-аналоговый преобразователь

Можно ли используя восьмиразрядный микроконтроллер AVR, без встроенного ЦАП организовать его программно на Си? Суть в том, что хочется получить пилообразный сигнал!


Ответ

Да это возможно. Что же для этого нужно! Первое - это применить не сложное схемотехническое решение. Схемку накидал быстро, поэтому строго не судите. Это так называемый R2R ЦАП, который позволяет превратить 8 обычных портов ввода-вывода в оди полноценный 8 битный цифро-аналоговый преобразователь. Вот схема:
Далее пишем программу которая будет генерировать Ваш пилообразный сигнал!
#include #include
void main(void) {
DDRA=(0< DDRB=(1< PORTB=(0< DDRC=(0< PORTC=(0< DDRD=(0< PORTD=(0< // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped // Mode: Normal top=0xFF // OC0 output: Disconnected TCCR0=(0< TCCR1A=(0< ASSR=0< // Timer(s)/Counter(s) Interrupt(s) initialization TIMSK=(0< MCUCR=(0< UCSRB=(0< ACSR=(1< // ADC initialization // ADC disabled ADCSRA=(0< SPCR=(0< TWCR=(0< while (1) { //Ниже код генерации такого пилообразного сигнала int i; for(i = 0; i <255; i++) { PORTB = i; } for(i = 255; i > 0; i--) { PORTB = i; } } } Хочу добавить , что используя R2R цап собирал wav плеер, то есть возможности очень широки. Ниже вид сигнала который я получил этой программкой.
9393
Я даже видел как генерируют эротические сигналы, правда не знаю функцию которая за это отвечает, но можно разбить на несколько for по нарастанию и убыванию.
alt text http://avrdevices.ru/wp-content/uploads/2010/08/tits.jpg

среда, 10 октября 2018 г.

Микроконтроллеры и Java

Интересует такой вопрос. Допустим, у меня есть какая-то кнопка, которая лежит на столе. Какие микроконтроллеры, устройства и т.п. можно использовать, чтобы реализовать взаимодействие этой кнопки и java?


Ответ

Поскольку Java изначально разрабатывалась для программирования холодильников и кофеварок, было бы странно, если бы возможность работы с железом была утрачена напрочь.
Самый простой вариант подключения кнопки к микроконтроллеру - это порты GPIO, которые широко распространены в embedded мире. Кнопка одним контактом подключается к выводу порта, другим - к земле (GND). Дальше микроконтроллер либо сам что-то делает, либо по UART/USB/Ethernet/WiFi/Bluetooth отправляет сообщение о нажатой кнопке куда-то еще.
Непосредственно по железу варианты есть следующие.
Использовать специализированный микроконтроллер, заточенный под Java.
Да, такие есть. Например семейство 3G-модулей Centerion. Прошивка представляет собой мидлет Java ME и может заливаться в том числе по воздуху. Прослушивание порта выглядит как-то так:
Vector inPins = new Vector(); inPins.addElement("GPIO11");
InPort inPort = new InPort(inPins); inPort.addListener(new InPortListener() { public void portValueChanged(int val) { System.out.println("Port value: " + val); } });

Использовать полноценную встраиваемую систему общего назначения на базе ARM-процессора, такую как BeagleBone или RaspberryPi.
Там у вас будет полноценный Linux с возможностью установки полноценной Java SE или Java SE Embedded. А порты будут доступны через файловую систему как устройства вроде /sys/class/gpio/gpio49. Можно взаимодействовать с портом обычными средствами файлового ввода-вывода (что будет относительно медленно, хотя и достаточно для многих задач) или через прямой досутп к памяти через memory-mapped файл /dev/mem (что будет быстро).
Но куда приятнее будет воспользоваться развесистым API сторонней библиотеки pi4j
GpioController gpioController = GpioFactory.getInstance(); GpioPinDigitalInput pin02 = gpioController.provisionDigitalInputPin(RaspiPin.GPIO_02,PinPullResistance.PULL_DOWN); pin02.addListener(new GpioPinListenerDigital() { @Override public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent gpioPinDigitalStateChangeEvent) { System.out.println("state: " + gpioPinDigitalStateChangeEvent.getState()); } });
Кроме того, существует еще и Java ME Embedded, предоставляющий нативный API доступа к портам в пакете com.oracle.deviceaccess
GPIOPin switchPin = null; switchPin = (GPIOPin) PeripheralManager.open(1); switchPin.setInputListener(new PinListener() { @Override public void valueChanged(PinEvent event) { // do something } });
К слову, жизнь тут не ограничена ARM, есть и MIPS и Intel Atom. Но подходы там те же.
Очень интересными выглядят сторонние программные платформы на основе Java:
MicroEJ. На Youtube есть ролик, где java-приложение с графикой исполняется на очень слабом железе (Cortex™-M0+ @48 MHz, 256 KB Flash, 32 KB RAM). Android Things от Google, ранее известная как Brillo.

Удивительно, но на Java можно писать под 8-битные AVR-микроконтроллеры (те самые, на которых построена Arduino)!
Это стало возможным благодаря HaikuVM, которая транслирует байткод Java из .class-файлов в С-структуры, линкует к ним интерпретатор и формирует на выходе обычный для AVR-микроконтроллеров HEX-файл, который шьется в железку как обычно.
Еще есть:
NanoVM - виртуальная машина подмножества Java, занимающая 8 кБ в флэш-памяти. uJ - эта VM крупнее (десятки килобайт), но обещает полную поддержку байткода, многопоточность и synchronized
Если вы хотите нопку подключить к Arduino, а его в свою очередь подключить к компьютеру и делать что-то на компьютере по нажатию на кнопку, попробуйте JArduino. Этот API требует залить на Arduino свою прошивку, после чего вы сможете взаимодействовать с устройством из обычной Java-программы на своем компьютере.