diff --git a/README.md b/README.md index 18ed584..5d8d228 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,43 @@ # elbear_arduino_bsp -Пакет поддержки платы Elbear Ace-Uno на базе микроконтроллера MIK32 Амур в среде программирования Arduino IDE. +Пакет поддержки плат на базе микроконтроллера MIK32 Амур в среде программирования Arduino IDE. ## Установка пакета в ArduinoIDE Для установки пакета в параметрах ArduinoIDE необходимо добавить ссылку `https://elron.tech/files/package_elbear_beta_index.json` в поле "Дополнительные ссылки для Менеджера плат". -Подробные шаги по установке и начальной настройке описаны в [инструкции](./Instructions.md). +Подробные шаги по установке и начальной настройке описаны в [инструкции](./docs/Instructions.md). -## Функциональное назначение выводов -![Pinout](docs/pinout.PNG) +## Платы, входящие в состав пакета +Пакет включает в себя поддержку следующих плат: +- [Elbear Ace-Uno](./docs/Elbear_description.md) 8 Mb / 16 Mb / 32 Mb +- [START-MIK32](./docs/Start_mik32_description.md) -## Особенности использования платы Elbear Ace-Uno в ArduinoIDE +## Особенности использования пакета в ArduinoIDE ### Цифровые выводы -На плате Elbear Ace-Uno доступны встроенные светодиод и кнопка. Для их использования необходимо воспользоваться макросами `LED_BUILTIN` и `BTN_BUILTIN`, передавая их в качестве аргументов функции вместо номера цифрового вывода. Макросу `LED_BUILTIN` соответствует номер вывода D22, а макросу `BTN_BUILTIN` - D23. -В отличие от стандартного функционала Arduino, на плате Elbear Ace-Uno невозможно управлять притяжками цифрового вывода, настроенного на вход, с помощью функции `void digitalWrite(uint32_t PinNumber, uint32_t Val)`. Для включения притяжки к питанию необходимо воспользоваться функцией `void pinMode(PinNumber, INPUT_PULLUP)`. +В отличие от стандартного функционала Arduino на платах, входящих в состав пакета, невозможно управлять притяжками цифрового вывода, настроенного на вход, с помощью функции `void digitalWrite(uint32_t PinNumber, uint32_t Val)`. Для включения притяжки к питанию необходимо воспользоваться функцией `void pinMode(PinNumber, INPUT_PULLUP)`. Для инвертирования состояния цифровых выводов доступна функция `void digitalToggle(uint32_t PinNumber)`. ### Аналоговые выводы #### АЦП Встроенный в MIK32 АЦП обладает разрешением 12 бит, однако по умолчанию в Arduino IDE применяется разрешение 10 бит. С помощью функции `void analogReadResolution(uint8_t resolution)` можно изменять разрешение в диапазоне от 1 до 32 бит. Функция `uint32_t analogRead(uint32_t PinNumber)` возвращает результаты измерения после усреднения по 10 значениям. +Номера выводов, поддерживающих АЦП, отличаются для каждой платы и перечислены в их описаниях. #### ШИМ -На плате Elbear Ace-Uno доступны следующие выводы для формирования ШИМ-сигнала: D3, D5, D6, D9, D10, D11. Генерация сигнала осуществляется с помощью 32-битного таймера. Выводы D3, D5, D6, D9 подключены к таймеру 1, выводы D10, D11 подключены к таймеру 2. Выводы, подключенные к одному и тому же таймеру, выдают ШИМ-сигнал одинаковой частоты. -Цифровой вывод D10 не может быть использован для генерации ШИМ, если одновременно активен интерфейс SPI. Это ограничение связано с особенностями работы микроконтроллера. Ограничение не распространяется на использование D10 в качестве цифрового вывода при активном SPI. По умолчанию частота сформированного ШИМ-сигнала составляет 1 кГц. Функция `void analogWriteFrequency(uint32_t freq)` позволяет изменить частоту сигнала в диапазоне от 1 Гц до 1 МГц. По умолчанию разрешение, используемое в функции `void analogWrite(uint32_t PinNumber, uint32_t writeVal)`, составляет 8 бит. Функция `void analogWriteResolution(uint8_t resolution)` позволяет измененить разрешение в диапазоне от 1 до 32 бит. -Остановить генерацию ШИМ-сигнала можно, вызвав функцию `void analogWriteStop(uint32_t PinNumber)` или функции `void digitalWrite(uint32_t PinNumber, uint32_t Val)`/`int digitalRead(uint32_t PinNumber)`. +Остановить генерацию ШИМ-сигнала можно, вызвав функцию `void analogWriteStop(uint32_t PinNumber)` или функции `void digitalWrite(uint32_t PinNumber, uint32_t Val)`/`int digitalRead(uint32_t PinNumber)`. +Номера выводов, поддерживающих ШИМ, отличаются для каждой платы и перечислены в их описаниях. ### Прерывания -На плате Elbear Ace-Uno доступно 7 прерываний, настраиваемых функцией `void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)`: - -|Цифровой вывод|Номер прерывания| -|---------|---------| -|D2|0| -|D3|1| -|D4|2| -|D5|3| -|D8|4| -|D9|5| -|`BTN_BUILTIN`|6| - +Платы, входящих в состав пакета, позволяют использовать прерывания, настраиваемые функцией `void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)`. Номера выводов, поддерживающих прерывания, отличаются для каждой платы и перечислены в их описаниях. Для получения номера прерывания по номеру вывода существует функция `int8_t digitalPinToInterrupt(uint32_t digPinNumber)`. В микроконтроллере MIK32 предусмотрен всего один вектор прерывания. Когда срабатывает прерывание от любого источника, общая функция-обработчик последовательно проверяет все возможные источники и, при необходимости, вызывает соответствующие обработчики конкретных модулей. Поэтому важно, чтобы функции, вызываемые при прерываниях, были небольшими и обеспечивали максимально быстрое завершение обработки. Это позволит избежать задержек и снизит риск пропуска последующих прерываний. Общая функция-обработчик прерываний располагается в RAM памяти. Это позволяет устранить задержки, связанные с кэшированием при работе из FLASH памяти. Обработчики прерываний, назначаемые на цифровые выводы с помощью функции `void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)`, и обработчик прерывания для функции `tone()` так же располагаются в памяти RAM. +Глобальное разрешение прерываний активируется после завершения функции `setup()`. Если необходимо использовать прерывания внутри самой функции `setup()`, их можно включить вручную, вызвав функцию `interrupts()` перед вызовом функций, работающих с прерываниями. Прерывания используются для приема данных модулями `Serial`, `Wire`, для работы библиотеки `Servo`, функцией `tone()`. + ### Serial -Для работы доступно два последовательных интерфейса. Нулевой интерфейс доступен на выводах D0, D1, для работы с ним используется экземпляр класса под названием `Serial`. Нулевой интерфейс используется для вывода информации в Монитор порта в Arduino IDE. -Первый интерфейс доступен на выводах D7, D8, используемый экземпляр класса - `Serial1`. +Для работы доступно два последовательных интерфейса. Нулевой интерфейс используется экземпляром класса `Serial`. Информации в Монитор порта в Arduino IDE поступает через него. Первый интерфейс используется экземпляром класса `Serial1`. Выводы, на которых доступны указанные интерфейсы, перечислены в описании отдельных плат. Доступны следующие макросы для настройки режима работы каждого интерфейса в функции `Serial.begin()`: `SERIAL_7N1`, `SERIAL_8N1`, `SERIAL_7N2`, `SERIAL_8N2`, `SERIAL_7E1`, `SERIAL_8E1`, `SERIAL_7E2`, `SERIAL_8E2`, `SERIAL_7O1`, `SERIAL_8O1`, `SERIAL_7O2`, `SERIAL_8O2`. Здесь длина данных - 7 или 8 бит; бит четности - нет(N), четный(E), нечетный(O); стоп бит - 1 или 2 бита. ### Предупреждения об ошибках @@ -58,7 +49,7 @@ |Библиотека|Описание|Заметки| |---------|---------|------| -|[SPI](https://docs.arduino.cc/language-reference/en/functions/communication/SPI/)|Библиотека для работы с интерфейсом SPI|Для работы используется встроенный SPI1. Доступные делители частоты - `SPI_CLOCK_DIV4`, `SPI_CLOCK_DIV8`, `SPI_CLOCK_DIV16`, `SPI_CLOCK_DIV32`, `SPI_CLOCK_DIV64`, `SPI_CLOCK_DIV128`, `SPI_CLOCK_DIV256`, обеспечивают частоту работы от 125 кГц до 8 МГц. Скорость работы по умолчанию - 4 МГц. Для задания режима и скорости работы рекомендуется использовать `SPISettings(uint32_t speedMaximum, uint8_t dataOrder, uint8_t dataMode)`, а не соответствующие отдельные функции| +|[SPI](https://docs.arduino.cc/language-reference/en/functions/communication/SPI/)|Библиотека для работы с интерфейсом SPI|Для работы используется встроенный SPI1. Доступные делители частоты - `SPI_CLOCK_DIV2`, `SPI_CLOCK_DIV4`, `SPI_CLOCK_DIV8`, `SPI_CLOCK_DIV16`, `SPI_CLOCK_DIV32`, `SPI_CLOCK_DIV64`, `SPI_CLOCK_DIV128`, `SPI_CLOCK_DIV256`, обеспечивают частоту работы от 125 кГц до 16 МГц. Скорость работы по умолчанию - 4 МГц. Для задания режима и скорости работы рекомендуется использовать `SPISettings(uint32_t speedMaximum, uint8_t dataOrder, uint8_t dataMode)`, а не соответствующие отдельные функции| |[Wire](https://docs.arduino.cc/language-reference/en/functions/communication/Wire/)|Библиотека для работы с интерфейсом I2C|Для работы используется встроенный I2C1. Доступные частоты работы интерфейса: 100 кГц (`WIRE_FREQ_100K`), 400 кГц (`WIRE_FREQ_400K`), 1000 кГц (`WIRE_FREQ_1000K`). Скорость работы по умолчанию - 100 кГц. В режиме работы в качестве ведомого устройства функции, заданные через `void onReceive( void (*)(int)` и `void onRequest( void (*)(void) )`, выполняются в прерывании| |[SoftwareSerial](https://docs.arduino.cc/learn/built-in-libraries/software-serial/)|Библиотека, реализующая программный последовательный интерфейс.|Доступные скорости работы - от 300 до 57600 бод. Для отправки данных (TX) можно использовать любой цифровой вывод. Для приема данных (RX) можно использовать только выводы, поддерживающие прерывания. Обработчик прерывания и связанные с ним функции располагаются в памяти RAM| |[EEPROM](https://docs.arduino.cc/learn/built-in-libraries/eeprom/)|Библиотека для работы с памятью EEPROM|Для использования доступно 1024 байта встроенной EEPROM памяти. Для корректной работы библиотеки обязательно вызывать функцию `void EEPROM.begin()` перед началом работы с памятью| @@ -86,10 +77,21 @@ |[RF24](https://docs.arduino.cc/libraries/rf24/)|Драйвер радиоустройств, библиотека для работы с микросхемами nRF24L01(+)| |[Bonezegei_ULN2003_Stepper](https://docs.arduino.cc/libraries/bonezegei_uln2003_stepper/)|Библиотека драйвера шагового двигателя, управляемого микросхемой ULN2003| |[Ethernet](https://docs.arduino.cc/libraries/ethernet/)|Библиотека, позволяющая использовать Ethernet шилд для подключения к Интернету| +|[AGS10_sensor](https://github.com/gina-seth/AGS10_sensor)|Библиотека для работы с датчиком газа AGS10| +|[TinyGPSPlus](https://docs.arduino.cc/libraries/tinygpsplus/)|Библиотека позволяет расшифровать данные GPS, сформированные по протоколу NMEA| +|[GPRS_Shield_Arduino](https://github.com/amperka/gprs-shield)|Библиотека для Arduino, позволяющая управлять GPRS Shield’ом от Амперки| +|[Adafruit GFX](https://docs.arduino.cc/libraries/adafruit-gfx-library/)|Базовая графическая библиотека, от которой происходят все остальные графические библиотеки Adafruit| +|[Adafruit_SH110X](https://docs.arduino.cc/libraries/adafruit-sh110x/)|Библиотека драйверов SH110X OLED для монохромных дисплеев с драйверами SH1107 или SH1106G| +|[Adafruit_SSD1306](https://docs.arduino.cc/libraries/adafruit-ssd1306/)|Библиотека драйвера SSD1306 OLED для монохромных дисплеев с расширениями 128x64 и 128x32| +|[Adafruit_ST7789](https://docs.arduino.cc/libraries/adafruit-st7735-and-st7789-library/)|Библиотека для работы с дисплеем ST7789 по SPI| +|[Adafruit_ILI9341](https://docs.arduino.cc/libraries/adafruit-ili9341/)|Библиотека для работы с дисплеем Adafruit ILI9341| +|[TFT](https://docs.arduino.cc/libraries/tft/)|Графическая библиотека, совместимая с большинством TFT-дисплеев на базе чипа ST7735| +|[Adafruit_TCS34725](https://docs.arduino.cc/libraries/adafruit-tcs34725/)|Библиотека для работы с датчиком цвета с ИК-фильтром TCS34725| # Полезные ссылки * [Материалы по платам ELBEAR ACE-UNO](https://elron.tech/support/#elbear) * [Телеграмм-канал компании (обновления по проекту ELBEAR и другим)](https://t.me/elrontech) +* [Материалы по плате START-MIK32](https://wiki.mik32.ru/%D0%9E%D1%82%D0%BB%D0%B0%D0%B4%D0%BE%D1%87%D0%BD%D0%B0%D1%8F_%D0%BF%D0%BB%D0%B0%D1%82%D0%B0_%D0%A1%D1%82%D0%B0%D1%80%D1%82) При возникновении вопросов или выявлении проблем можно оставить заявку [здесь](https://gitflic.ru/project/elron-tech/elbear_arduino_bsp/issue). diff --git a/boards.txt b/boards.txt index 2ad43bd..0e5ff7b 100644 --- a/boards.txt +++ b/boards.txt @@ -9,18 +9,20 @@ aceUno8Mb.upload.tool=elbear_uploader aceUno8Mb.upload.protocol=elbear_uploader aceUno8Mb.upload.maximum_size=8388608 aceUno8Mb.upload.maximum_data_size=16384 +aceUno8Mb.upload.speed=230400 # tool for bootloader update aceUno8Mb.bootloader.tool=mik32_upload aceUno8Mb.bootloader.tool.default=mik32_upload aceUno8Mb.bootloader.file=ace-uno/bootloader.hex +aceUno8Mb.bootloader.interface=ftdi/mikron-link.cfg # build options aceUno8Mb.build.mcu=MIK32_Amur aceUno8Mb.build.f_cpu=32000000UL aceUno8Mb.build.board=ACE_UNO_8MB aceUno8Mb.build.core=arduino -aceUno8Mb.build.variant=standart +aceUno8Mb.build.variant=elbear_ace_uno aceUno8Mb.build.extra_flags= aceUno8Mb.build.flags= @@ -33,18 +35,20 @@ aceUno16Mb.upload.tool=elbear_uploader aceUno16Mb.upload.protocol=elbear_uploader aceUno16Mb.upload.maximum_size=16777216 aceUno16Mb.upload.maximum_data_size=16384 +aceUno16Mb.upload.speed=230400 # tool for bootloader update aceUno16Mb.bootloader.tool=mik32_upload aceUno16Mb.bootloader.tool.default=mik32_upload aceUno16Mb.bootloader.file=ace-uno/bootloader.hex +aceUno16Mb.bootloader.interface=ftdi/mikron-link.cfg # build options aceUno16Mb.build.mcu=MIK32_Amur aceUno16Mb.build.f_cpu=32000000UL aceUno16Mb.build.board=ACE_UNO_16MB aceUno16Mb.build.core=arduino -aceUno16Mb.build.variant=standart +aceUno16Mb.build.variant=elbear_ace_uno aceUno16Mb.build.extra_flags= aceUno16Mb.build.flags= @@ -57,17 +61,45 @@ aceUno32Mb.upload.tool=elbear_uploader aceUno32Mb.upload.protocol=elbear_uploader aceUno32Mb.upload.maximum_size=33554432 aceUno32Mb.upload.maximum_data_size=16384 +aceUno32Mb.upload.speed=230400 # tool for bootloader update aceUno32Mb.bootloader.tool=mik32_upload aceUno32Mb.bootloader.tool.default=mik32_upload aceUno32Mb.bootloader.file=ace-uno/bootloader.hex +aceUno32Mb.bootloader.interface=ftdi/mikron-link.cfg # build options aceUno32Mb.build.mcu=MIK32_Amur aceUno32Mb.build.f_cpu=32000000UL aceUno32Mb.build.board=ACE_UNO_32MB aceUno32Mb.build.core=arduino -aceUno32Mb.build.variant=standart +aceUno32Mb.build.variant=elbear_ace_uno aceUno32Mb.build.extra_flags= -aceUno32Mb.build.flags= \ No newline at end of file +aceUno32Mb.build.flags= + + +##################### START-MIK32-V1 ##################### +start-mik32-v1.name=START-MIK32-V1 + +# tool for firmware update +start-mik32-v1.upload.tool=elbear_uploader +start-mik32-v1.upload.protocol=elbear_uploader +start-mik32-v1.upload.maximum_size=4194304 +start-mik32-v1.upload.maximum_data_size=16384 +start-mik32-v1.upload.speed=120000 + +# tool for bootloader update +start-mik32-v1.bootloader.tool=mik32_upload +start-mik32-v1.bootloader.tool.default=mik32_upload +start-mik32-v1.bootloader.file=start-mik32/bootloader.hex +start-mik32-v1.bootloader.interface=start-link.cfg + +# build options +start-mik32-v1.build.mcu=MIK32_Amur +start-mik32-v1.build.f_cpu=32000000UL +start-mik32-v1.build.board=START_MIK32_V1 +start-mik32-v1.build.core=arduino +start-mik32-v1.build.variant=start +start-mik32-v1.build.extra_flags= +start-mik32-v1.build.flags= \ No newline at end of file diff --git a/bootloaders/start-mik32/bootloader.hex b/bootloaders/start-mik32/bootloader.hex new file mode 100644 index 0000000..d9a2f5b --- /dev/null +++ b/bootloaders/start-mik32/bootloader.hex @@ -0,0 +1,262 @@ +:020000040100F9 +:10000000FD62938202400100FD12E39E02FE374131 +:10001000000213010100B701000293810100B7152E +:100020000001938505003716000113060603B70685 +:1000300000029386060039A083A2050023A0560083 +:1000400091059106E3EAC5FEB71500019385050306 +:100050003716000113060603B7060002938606262C +:1000600039A083A2050023A0560091059106E3EA7A +:10007000C5FEB70500029385050337060002130687 +:10008000062621A023A005009105E3EDC5FEB700DB +:100090000001E780C00AB7000001E780C00AB7107E +:1000A0000001E780808473005010F5BF828000005B +:1000B0000000000000000000000000000000000040 +:1000C0006F004000197106C20AC40EC612C816CAD3 +:1000D0001ACC1ECE22D026D22AD42ED632D836DA48 +:1000E0003ADC3EDEC2C0C6C2CAC4CEC6D2C8D6CA78 +:1000F000DACCDECEE2D0E6D2EAD4EED6F2D8F6DA28 +:10010000FADCFEDE970000009380E00482909240CB +:100110002241B2414242D2426243F24302549254DB +:100120002255B2554256D2566257F2570648964863 +:100130002649B649464AD64A664BF64B065C965C5B +:10014000265DB65D465ED65E665FF65F096173004A +:10015000203001A03D432A876373C3029377F700E1 +:10016000BDEFADE5937606FF3D8ABA960CC34CC34E +:100170000CC74CC74107E36BD7FE11E28280B30680 +:10018000C3408A069702000096966780A600230760 +:10019000B700A306B7002306B700A305B7002305E1 +:1001A000B700A304B7002304B700A303B7002303D9 +:1001B000B700A302B7002302B700A301B7002301D1 +:1001C000B700A300B7002300B700828093F5F50FB6 +:1001D00093968500D58D93960501D58D61B793963D +:1001E00027009702000096968682E78086FA96801E +:1001F000C1171D8F3E96E374C3F8A5B7B707050076 +:100200000947D8CFB7170500938707C0984385667D +:1002100093860640558F98C398471367074098C741 +:10022000B71708009387074023A0070023A2070001 +:1002300023A407001307B010D8C77D57D8CF354780 +:1002400098C3D84F935657018D8AE5DE8280B71741 +:1002500008009387074023A0070023A2070023A4D8 +:10026000070023A607007D57D8CF23A40702B7179E +:100270000500938707C09843F1769386F63F758F04 +:1002800098C398471377F7BF98C7B7070500094782 +:1002900098D38280B71708009387074088D7D84F34 +:1002A000137707046DDF82803707000203234704BA +:1002B000B706000237150800B7450F0023A406044F +:1002C0008147014613050540938515240328C50180 +:1002D000B308F30013780802630C080205C2232256 +:1002E000170537470F0023A4F60413070724639765 +:1002F000E700B707000205472383E700B7170800A8 +:1003000093870740C85342054181828005467DBFDF +:100310008507E39DB7FE7DD2B7470F00938707247B +:1003200023A4F60423221705E9B7411106C622C407 +:1003300026C2AA84EF003024E1689388086A014845 +:100340008147014781460146B70520C72685379476 +:100350009800EF00B007130414687D1419E40D45EC +:10036000B240224492444101828085452685EF00B7 +:10037000F02105897DF10145E5B7411122C437041B +:100380000002930704008C43B70700804AC0BE9563 +:10039000B707000223AEB70206C626C293974501EF +:1003A000130404003709000289E713058900EF00F0 +:1003B000102B0C40B70400029386C40413060010EF +:1003C00013058900EF00F0241C4037070002835614 +:1003D0008703938707101CC013060010B68763F4C9 +:1003E000C600930700101384C4041305F400938718 +:1003F00007F01306100F814513040410231CF702A5 +:10040000913BA2851385C4043D46EF00902923202B +:1004100004002322040023240400231604002307DD +:100420000400B240224492440249410182805D713D +:10043000130680028145280886C6293BBD47230C48 +:10044000F1008947230EF1003ED2E1779387070838 +:100450002C080A85231AF102F52BB64061618280CF +:100460005D71A2C4370400021305840086C6A6C2CB +:10047000CAC0C12513058400EF00007F8545130520 +:100480008400EF00B0108D47814463E3A700AA8485 +:10049000894513058400EF00700F937725002A86A5 +:1004A00089E7136625001376F60FA68513058400E9 +:1004B000EF003011E1689388086A014881470147DD +:1004C00081460146B7052038130584000127E168FD +:1004D00038009388086A1308000285468147014660 +:1004E000B70599EB1305840023040100C525B71552 +:1004F00000015146938585FE6800EF00901A1309AC +:100500008400832709006C0051463ED085473ED2C7 +:100510006810C1673ED4EF00D018B70607009C42B0 +:100520003707F1FF7D17F98F08109CC2A925B64047 +:1005300026449644064961618280411106C6013B0A +:100540000537B707008073905730B700008082905E +:10055000B2404101828041113707000222C406C621 +:100560009307070083C76700854613040700638E5F +:10057000D70009476388E70023030400B240224400 +:10058000410182801305000F3133B71708009387AC +:100590000740D84F218B09C7D84F13678700D8CFA2 +:1005A000693FD9BF411106C622C426C24AC083474B +:1005B000350005476383E70811472A846389E7000C +:1005C0008DCFB24022449244024941018280B70754 +:1005D000000283D7870391C34D3383474400034709 +:1005E0005400E2074207BA97370700022320F704B6 +:1005F000370700022320F700E9B7370900028354C8 +:1006000089030346050093054500370500021305DD +:10061000C5042695EF00F00883470400BE94C20489 +:10062000C180231C99029307F00FE3FC97F8224442 +:10063000B24092440249410189B33D45A139B7070F +:10064000000283D7870391C30D3B2244B2409244FA +:1006500002494101DDB53707000241119306070049 +:1006600003DF460026C4B704000283A2840422C626 +:100670003715080037040002B7480F0037430F0052 +:10068000370E00024AC28147232A04021309FFFFE2 +:10069000814E814681458143014801461307070089 +:1006A000130505409388182413030324130ECE1555 +:1006B000636FE60363850E0009462303C70089C6FE +:1006C000B7060002A388F60299C1232A74026304C4 +:1006D000080023A4540483476700A9E73244A244D6 +:1006E0001249370500021305C515410165BD814258 +:1006F0000328C50113780802631B08028502E399E9 +:1007000012FF89C6B7060002A388F60299C1232A00 +:100710007402B7470F009387072423A4F404854786 +:100720002303F7003244A244124941018280E38A44 +:1007300062FC03284502937FF80F637D260113783E +:10074000F80FC29385453308CE002300F801050653 +:100750000548B9BFB307704093F7F70F6394FF00E4 +:100760008546D5B7854EEDBF011122CC4EC652C489 +:1007700037040002B7490F00371ADCBA26CA4AC844 +:1007800056C25AC006CE13040400370900029389EA +:10079000F923930A0003B7040002391A370B000249 +:1007A000213683274904A303A40063F3F9007133BE +:1007B0008347640099C34533E5B783467400638873 +:1007C0005605930700066381F60603C704038D47A9 +:1007D000998F8E07B357FA0093F7F70F6393F606D6 +:1007E0009307170093F7F70F2388F4021147639DCF +:1007F000E7003D45453413058B00053E29C113052F +:10080000000F493C238804022322090451BF3D45BF +:100810002322090423880402B53C793405052312F8 +:10082000A4003D45853CADBF3D45232209042388F6 +:1008300004028D340D3583476400B5FFDDB73D45B7 +:10084000C9B723880402A9BF011106CE22CCC53640 +:100850003704000213058400E92C130584002921C4 +:10086000E1689388086A0148814778008546014617 +:10087000B705D9EB1305840023060100812EE1683A +:100880009388086A01488147014781460146B705B8 +:1008900038FF130584001D2E9532F9350547AA87C8 +:1008A0006305E50209476300E506054591EBB706D8 +:1008B0000600DC4A7D771307F73FF98FDCCA014554 +:1008C00082807D1719EB0D4582809306004037A783 +:1008D000070013070712B7050500905D7D8E75D2DE +:1008E000370606005C4A7D771307F73FF98FD58FEF +:1008F00041115CCA02C613073006B2476359F700BC +:10090000014541018280856693860680C9B7B2475A +:1009100085073EC6DDB791476307F50263EAA70086 +:100920008547630AF50489476309F5040545828014 +:10093000A147E31DF5FE0947094501A8FD1781EF11 +:10094000C8D20D45828005470D45B7A7070093879C +:100950000712B7060500905E798E6DD28A05C98DA3 +:100960004111CCD202C613073006B247635AF700D2 +:100970000145410182801147C9BF21470145F1B7B7 +:10098000B24785073EC6D5B70547AA876305E50286 +:1009900009476304E506054591EBB70606009C4A46 +:1009A0007D771307F73FF98F9CCA014582807D1739 +:1009B00019EB0D4582809306004037A70700130707 +:1009C0000712B7050500905D7D8E75D237070600CA +:1009D0001C4B7D761306F63FF18FD58F1CCB232C55 +:1009E000070085471CCF411102C613073006B247E6 +:1009F0006359F70001454101828085669386068030 +:100A00006DBFB24785073EC6DDB711C98547630D87 +:100A1000F50205458280FD1791EB0D458280094660 +:100A2000B7A7070093870712B7060500985E718F76 +:100A30007DD34111C8D602C613073006B2476357AB +:100A4000F7000145410182800546D9BFB2478507BD +:100A50003EC6EDB7011126CAB7040600DC4806CE33 +:100A600022CC4AC84EC652C456C2F19BDCC89C4830 +:100A70002A89C845F19B9CC8D84883C7C5012E84E4 +:100A8000137737C08A07D98FDCC883C7D501984848 +:100A90009A071377F7C393F7073CD98F9CC8FD3BA0 +:100AA0000C44AA8A03454400BD351848B707050021 +:100AB0002A8A98C358480850D8C3184C98C7E935B3 +:100AC000AA8948509937834704002A8793F617006C +:100AD00089E6D44893E62600D4C893F6270099E621 +:100AE00037060600544A93E6160054CA93F64700A8 +:100AF00099E637060600144A93E6260014CAA18B2D +:100B000099E7B70606009C4A93E717009CCAF24093 +:100B10006244232059012322490123243901232639 +:100B2000E900D244B249224A924A4A8542490561C3 +:100B30008280011106CE22CC02C402C62147B7072B +:100B4000050037550800D8C705448D478A85130529 +:100B500005803EC022C2292A375508009307C003EA +:100B60008A851305058022C222C43EC01122F240AC +:100B7000624405618280411122C406C62A84553F21 +:100B800018405C4F93E707015CCF1C441CCB5C40D2 +:100B900085CB1C43B7061000D58F1CC3144C5C4892 +:100BA000B240D606CE07D58F83460401C206D58F44 +:100BB0008346C4012244E206D58F1CCF41018280C6 +:100BC0001C43B706F0FFFD16F58FC1BF03230500D8 +:100BD0002A8E0325C30113650502232EA3002324B7 +:100BE000C3001396260149824D8E2326030123223A +:100BF000C300139605016354060299C20545B1CBA3 +:100C000001476346D700639C08020D458280338606 +:100C1000E700034606000507230AC300DDB799C2B3 +:100C2000054505CB8147E3D0D7FE03260E000345DB +:100C300046013306F70085072300A600EDB783279A +:100C40000E00FD18DC4F93F70702D5DF11656D8D9F +:100C500011E18280B707070083C7470113F58500BC +:100C60001D8D3335A00082801C414147D8CF828042 +:100C7000B7470800938707402A886304F508B757E9 +:100C80000800938707806304F50A37470800630D5F +:100C9000E50A05458280331E1F013376DE0129C631 +:100CA00083A3450088431393180033966F001346BF +:100CB000F6FF13F43300718D33146400418D88C343 +:100CC000638B5302638C0302084303AEC500718D2E +:100CD000331E6E003365C50108C38842698E88459E +:100CE00033156500498E90C2850833D51E0145F540 +:100CF0003244410182802326C801F9B72324C80168 +:100D0000E1B7B716050037170500B717050093863A +:100D100046C1130707C19387C7C083AE050081484A +:100D2000054F8D4F914233D51E0105ED8280B716D8 +:100D3000050037170500B7170500938606C213078D +:100D4000C7C1938787C1D1BFB71605003717050004 +:100D5000B7170500938686C0130747C0938707C05F +:100D60006DBF331E1F013376DE0119E2850865BFB2 +:100D7000411122C635B7E1689388086A0148814766 +:100D8000014781460146B705200689B5011106CE07 +:100D9000A307010089476393F502B7052035E16891 +:100DA0001307F1009388086A014881478546014688 +:100DB000313DF2400345F10005618280B705200511 +:100DC000F9BF011106CE22CC26CA2306B100AA849F +:100DD000A306C1004D37E1689388086A01487C008A +:100DE000014789460146B785200126850964F93BFC +:100DF000130414717D1419E40D45F2406244D24489 +:100E000005618280854526855137058965F501454F +:100E1000EDB7011106CE22CC26CA2E844AC8AA8478 +:100E2000328936C6893FB247E16822869388086ACC +:100E300001480147CA86B7858002268561647933F7 +:100E40001304146A7D1411C48545268581370589EC +:100E500075F9F2406244D244424905618280011131 +:100E600006CE22CC26CA2EC6AA8431373246E16885 +:100E70009388086A0148814701478146B705802069 +:100E800026856164A1331304146A7D1411C4854559 +:100E90002685ED3D058975F9F2406244D24405612D +:100EA0008280B3C7A5008D8BB308C500B1E78D471D +:100EB00063F4C704937735002A87B9EB13F6C8FFAC +:100EC000B306E6409307000263C8D706AE86BA872A +:100ED0006371C70203A806009107910623AE07FFBE +:100EE000E3EAC7FE9307F6FF998FF19B91073E97C0 +:100EF000BE956366170182802A87637E150383C7C8 +:100F0000050005078505A30FF7FEE39AE8FE82803A +:100F100083C60500050793773700A30FD7FE850525 +:100F2000D1DF83C60500050793773700A30FD7FEEF +:100F30008505F9FF61B78280411122C613040002C2 +:100F400083A3050083A2450083AF850003AFC500DE +:100F500083AE050103AE450103A3850103A8C501C6 +:100F6000945113074702B307E640232E77FC232052 +:100F700057FE2322F7FF2324E7FF2326D7FF23284A +:100F8000C7FF232A67FE232C07FF232ED7FE938556 +:100F90004502E347F4FAAE86BA876371C70203A835 +:100FA00006009107910623AE07FFE3EAC7FE930709 +:100FB000F6FF998FF19B91073E97BE9563651701E8 +:100FC00032444101828083C7050005078505A30FD0 +:100FD000F7FEE387E8FE83C7050005078505A30F35 +:100FE000F7FEE392E8FEE9BF2000000001000000E8 +:100FF0000300000006000000EB00000000000000FD +:101000000000008000000000000007000000000059 +:1010100000000000000000000000000000000000D0 +:1010200000000000000000000000000000000000C0 +:0400000501000000F6 +:00000001FF diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c index 93a9353..6b4783f 100644 --- a/cores/arduino/WInterrupts.c +++ b/cores/arduino/WInterrupts.c @@ -27,24 +27,24 @@ void noInterrupts(void) } // we can provide no more than 8 interrupts on gpio at the same time -static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = +static volatile voidFuncPtr intFunc[EXTERNAL_INTERRUPTS_QTY] = { -#if EXTERNAL_NUM_INTERRUPTS > 7 +#if EXTERNAL_INTERRUPTS_QTY > 7 nothing, #endif -#if EXTERNAL_NUM_INTERRUPTS > 6 +#if EXTERNAL_INTERRUPTS_QTY > 6 nothing, #endif -#if EXTERNAL_NUM_INTERRUPTS > 5 +#if EXTERNAL_INTERRUPTS_QTY > 5 nothing, #endif -#if EXTERNAL_NUM_INTERRUPTS > 4 +#if EXTERNAL_INTERRUPTS_QTY > 4 nothing, #endif -#if EXTERNAL_NUM_INTERRUPTS > 3 +#if EXTERNAL_INTERRUPTS_QTY > 3 nothing, #endif -#if EXTERNAL_NUM_INTERRUPTS > 2 +#if EXTERNAL_INTERRUPTS_QTY > 2 nothing, #endif nothing, @@ -54,7 +54,7 @@ static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] = void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) { // if the interrupt number does not exceed the total number - if(interruptNum < EXTERNAL_NUM_INTERRUPTS) + if(interruptNum < EXTERNAL_INTERRUPTS_QTY) { intFunc[interruptNum] = userFunc; // save pointer to irq handler @@ -85,7 +85,7 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) void detachInterrupt(uint8_t interruptNum) { - if(interruptNum < EXTERNAL_NUM_INTERRUPTS) + if(interruptNum < EXTERNAL_INTERRUPTS_QTY) { // disable the interrupt in line HAL_GPIO_DeInitInterruptLine(interruptToGpioIntLine(interruptNum)); @@ -98,7 +98,7 @@ void detachInterrupt(uint8_t interruptNum) // disable single interrupt void disableInterrupt(uint8_t interruptNum) { - if(interruptNum < EXTERNAL_NUM_INTERRUPTS) + if(interruptNum < EXTERNAL_INTERRUPTS_QTY) // disable gpio interrupt line GPIO_IRQ_LINE_DISABLE(interruptToGpioIntLine(interruptNum)); } @@ -106,7 +106,7 @@ void disableInterrupt(uint8_t interruptNum) // enable single interrupt void enableInterrupt(uint8_t interruptNum) { - if(interruptNum < EXTERNAL_NUM_INTERRUPTS) + if(interruptNum < EXTERNAL_INTERRUPTS_QTY) // enable gpio interrupt line GPIO_IRQ_LINE_ENABLE(interruptToGpioIntLine(interruptNum)); } @@ -115,7 +115,7 @@ void enableInterrupt(uint8_t interruptNum) void __attribute__((noinline, section(".ram_text"), optimize("O3"))) gpio_interrupt_handler(void) { // go through all the interrupts and call the handler for the triggered line - for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++) + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { if (GPIO_IRQ_LINE_STATE(interruptToGpioIntLine(i))) intFunc[i](); diff --git a/cores/arduino/trap_handler.c b/cores/arduino/trap_handler.c index b491eae..99a1172 100644 --- a/cores/arduino/trap_handler.c +++ b/cores/arduino/trap_handler.c @@ -1,5 +1,5 @@ -#include "mik32_hal_irq.h" -#include "wiring_LL.h" +#include "mik32_hal_irq.h" +#include "wiring_LL.h" // isr functions extern void serial_interrupt_handler(uint8_t uartNumInt); @@ -11,12 +11,37 @@ void __attribute__((weak)) wire_interrupt_handler(void) } void __attribute__((weak)) servo_interrupt_handler(void) { - // dummy function for case when wire library is not in use + // dummy function for case when servo library is not in use +} + +void __attribute__((weak)) ISR(void) +{ + /* + A dummy function for the case when additional interrupts are not used in the project. + In the project, you need to create a function of the form: + extern "C" void ISR() + { + // timer16 is taken as an example + if (TIM16_GET_ARRM_INT_STATUS(htimer16_1_)) + { + // necessary actions + } + // reset timer interrupt flags + TIM16_CLEAR_INT_MASK(htimer16_1_, 0xFFFFFFFF); + } + libraries required to use this example: + #include "mik32_hal_timer16.h" + #include "mik32_hal_irq.h" + #include "wiring_LL.h" + */ } // ---------------------------------------------- // void __attribute__((noinline, section(".ram_text"), optimize("O3"))) trap_handler (void) { + // custom interrupt + ISR(); + // gpio interrupt if (EPIC_CHECK_GPIO_IRQ()) gpio_interrupt_handler(); @@ -36,7 +61,7 @@ void __attribute__((noinline, section(".ram_text"), optimize("O3"))) trap_handle // uart1 interrupt if (EPIC_CHECK_UART_1()) serial_interrupt_handler(1); - + // i2c interrupt if (EPIC_CHECK_I2C_1()) wire_interrupt_handler(); diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c index c7e5c35..44a481b 100644 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -42,18 +42,8 @@ uint32_t analogRead(uint32_t PinNumber) uint32_t adcChannel = analogInputToChannelNumber(PinNumber); if (adcChannel != NC) { - // if we use pin A5, we need to set SELA45 (1.15) to 1 to switch the output from A4 to A5 - if (PinNumber == A5) - { - HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_15, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA); - HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_15, GPIO_PIN_HIGH); - } - else if(PinNumber == A4) - { - // return the switch to A4 in case A5 was previously read - HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_15, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA); - HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_15, GPIO_PIN_LOW); - } + additionalPinsInit(PinNumber); + // init channel hadc.Init.Sel = adcChannel; HAL_ADC_Init(&hadc); @@ -147,8 +137,6 @@ void analogWrite(uint32_t PinNumber, uint32_t writeVal) HAL_Timer32_Start(&htimer32); pwmIsInited++; // increase inited channels qty } - else if(PinNumber == 10) // pin d10 has pwm, but you cannot use it while spi is running - ErrorMsgHandler("analogWrite(): D10 cannot be used as PWM pin while SPI is running"); else ErrorMsgHandler("analogWrite(): invalid pwm pin number"); } diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c index 1894c4f..3e24bc6 100644 --- a/cores/arduino/wiring_digital.c +++ b/cores/arduino/wiring_digital.c @@ -40,59 +40,30 @@ void pinMode(uint32_t PinNumber, uint32_t PinMode) // if the pin can use PWM, disable PWM analogWriteStop(PinNumber); - // adjusting pins - if (PinNumber == BTN_BUILTIN) + // determine the port and the pin number in the port + GPIO_TypeDef *GPIO_addr = digitalPinToPort(PinNumber); + GPIO_InitStruct.Pin = digitalPinToBitMask(PinNumber); + + // set up direction and pull up/down + switch (PinMode) { - // always set the button to input, otherwise the controller may burn out when pressed - GPIO_InitStruct.Pin = GPIO_PIN_6; - GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT; - GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE; - HAL_GPIO_Init(GPIO_2, &GPIO_InitStruct); - } - else // other pins - { - // determine the port and the pin number in the port - GPIO_TypeDef *GPIO_addr = digitalPinToPort(PinNumber); - GPIO_InitStruct.Pin = digitalPinToBitMask(PinNumber); - - // set up direction and pull up/down - switch (PinMode) - { - case INPUT: - GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT; - GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE; - break; - case INPUT_PULLUP: - GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT; - GPIO_InitStruct.Pull = HAL_GPIO_PULL_UP; - break; - case OUTPUT: - GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_OUTPUT; - GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE; - break; - } - - // init pin - HAL_GPIO_Init(GPIO_addr, &GPIO_InitStruct); - - // if we use pin A5, we need to set SELA45 (1.15) to 1 to switch the output from A4 to A5 - if (PinNumber == A5) - { - GPIO_InitStruct.Pin = GPIO_PIN_15; + case INPUT: + GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT; + GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE; + break; + case INPUT_PULLUP: + GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT; + GPIO_InitStruct.Pull = HAL_GPIO_PULL_UP; + break; + case OUTPUT: GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_OUTPUT; GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE; - HAL_GPIO_Init(GPIO_1, &GPIO_InitStruct); - HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_15, GPIO_PIN_HIGH); - } - else if(PinNumber == A4) - { - GPIO_InitStruct.Pin = GPIO_PIN_15; - GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_OUTPUT; - GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE; - HAL_GPIO_Init(GPIO_1, &GPIO_InitStruct); - HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_15, GPIO_PIN_LOW); - } + break; } + + // init pin + HAL_GPIO_Init(GPIO_addr, &GPIO_InitStruct); + additionalPinsInit(PinNumber); } // write pin @@ -108,11 +79,7 @@ void digitalWrite(uint32_t PinNumber, uint32_t Val) // if the pin can use PWM, disable PWM analogWriteStop(PinNumber); - // just in case let's move on to the hal library state terms - GPIO_PinState pinState = (Val == HIGH) ? GPIO_PIN_HIGH : GPIO_PIN_LOW; - - if (PinNumber != BTN_BUILTIN) // don't write anything to the button - HAL_GPIO_WritePin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber), pinState); + HAL_GPIO_WritePin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber), (Val == HIGH) ? GPIO_PIN_HIGH : GPIO_PIN_LOW); } // read pin @@ -128,8 +95,7 @@ int digitalRead(uint32_t PinNumber) analogWriteStop(PinNumber); GPIO_PinState pinState = HAL_GPIO_ReadPin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber)); - int state = (pinState == GPIO_PIN_LOW) ? LOW : HIGH; - return state; + return (pinState == GPIO_PIN_LOW) ? LOW : HIGH; } // toggle pin @@ -144,8 +110,7 @@ void digitalToggle(uint32_t PinNumber) // if the pin can use PWM, disable PWM analogWriteStop(PinNumber); - if (PinNumber != BTN_BUILTIN) // don't write anything to the button - HAL_GPIO_TogglePin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber)); + HAL_GPIO_TogglePin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber)); } #ifdef __cplusplus diff --git a/cores/arduino/wiring_private.h b/cores/arduino/wiring_private.h index 970a7cc..d498ef3 100644 --- a/cores/arduino/wiring_private.h +++ b/cores/arduino/wiring_private.h @@ -11,7 +11,7 @@ extern "C"{ #endif // available interrupts number -#define EXTERNAL_NUM_INTERRUPTS 7 +#define EXTERNAL_NUM_INTERRUPTS EXTERNAL_INTERRUPTS_QTY typedef void (*voidFuncPtr)(void); diff --git a/docs/Bootloader.png b/docs/Bootloader.png index 32ea0c3..d9a452e 100644 Binary files a/docs/Bootloader.png and b/docs/Bootloader.png differ diff --git a/docs/Build_project.png b/docs/Build_project.png index e8372b9..19fdbcb 100644 Binary files a/docs/Build_project.png and b/docs/Build_project.png differ diff --git a/docs/Elbear_description.md b/docs/Elbear_description.md new file mode 100644 index 0000000..150508e --- /dev/null +++ b/docs/Elbear_description.md @@ -0,0 +1,25 @@ +# Elbear Ace-Uno +Особенности работы с платами Elbear Ace-Uno в среде программирования ArduinoIDE. +### Функциональное назначение выводов +![Pinout](pinout.PNG) +### Цифровые выводы +На плате Elbear Ace-Uno доступны встроенные светодиод и кнопка. Для их использования необходимо воспользоваться макросами `LED_BUILTIN` и `BTN_BUILTIN`, передавая их в качестве аргументов функции вместо номера цифрового вывода. Макросу `LED_BUILTIN` соответствует номер вывода D22, а макросу `BTN_BUILTIN` - D23. +#### ШИМ +На плате Elbear Ace-Uno доступны следующие выводы для формирования ШИМ-сигнала: D3, D5, D6, D9, D10, D11. Генерация сигнала осуществляется с помощью 32-битного таймера. Выводы D3, D5, D6, D9 подключены к таймеру 1, выводы D10, D11 подключены к таймеру 2. Выводы, подключенные к одному и тому же таймеру, выдают ШИМ-сигнал одинаковой частоты. +Цифровой вывод D10 не может быть использован для генерации ШИМ, если одновременно активен интерфейс SPI. Это ограничение связано с особенностями работы микроконтроллера. Ограничение не распространяется на использование D10 в качестве цифрового вывода при активном SPI. +### Прерывания +На плате Elbear Ace-Uno доступно 7 прерываний, настраиваемых функцией `void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)`: + +|Цифровой вывод|Номер прерывания| +|---------|---------| +|D2|0| +|D3|1| +|D4|2| +|D5|3| +|D8|4| +|D9|5| +|`BTN_BUILTIN`|6| + +### Serial +Интерфейс UART0 доступен на выводах D0, D1, для работы с ним используется экземпляр класса под названием `Serial`. +Интерфейс UART1 доступен на выводах D7, D8, используемый экземпляр класса - `Serial1`. \ No newline at end of file diff --git a/docs/Flash_project.png b/docs/Flash_project.png index 5f17dbe..243bc96 100644 Binary files a/docs/Flash_project.png and b/docs/Flash_project.png differ diff --git a/docs/Install_board.PNG b/docs/Install_board.PNG index 36cc1d9..b6a559d 100644 Binary files a/docs/Install_board.PNG and b/docs/Install_board.PNG differ diff --git a/docs/Installation_process.PNG b/docs/Installation_process.PNG index e5b4330..9142182 100644 Binary files a/docs/Installation_process.PNG and b/docs/Installation_process.PNG differ diff --git a/Instructions.md b/docs/Instructions.md similarity index 54% rename from Instructions.md rename to docs/Instructions.md index 17f5d0c..6e4088a 100644 --- a/Instructions.md +++ b/docs/Instructions.md @@ -3,38 +3,41 @@ 2. Откройте меню `Файл -> Параметры`. 3. Вставьте данную ссылку в поле "Дополнительные ссылки для Менеджера плат": `https://elron.tech/files/package_elbear_beta_index.json` -![Add_board](docs/Add_board.PNG) +![Add_board](Add_board.PNG) 4. Откройте меню `Инструменты -> Плата -> Менеджер плат...`. -5. В поиске найдите плату `Elbear Ace-Uno`, выберите нужную версию и нажмите кнопку `Установить`. -![Install_board](docs/Install_board.PNG) +5. В поиске найдите пакет `MIK32 Boards (Arduino BSP by Elron)`, выберите нужную версию пакета и нажмите кнопку `Установить`. +![Install_board](Install_board.PNG) 6. Процесс установки может занять некоторое время. Результаты установки отобразятся в поле `Вывод`, а так же во всплывающих уведомлениях. -![Installation_process](docs/Installation_process.PNG) - -Для загрузки скетчей по USB в ArduinoIDE необходимо, чтобы на плате Elbear Ace-Uno был специальный начальный загрузчик ([elbear_fw_bootloader](https://gitflic.ru/project/elron-tech/elbear_fw_bootloader)). Если он уже есть на плате, можно сразу переходить к работе. Если загрузчика еще нет или необходимо обновить его на плате, ниже описан процесс загрузки. Актуальная версия начального загрузчика входит в состав пакета поддержки, отдельно скачивать его не нужно. - -Платы ревизии 1.1.0 готовы к использованию в ArduinoIDE из коробки, так как поставляются с предварительно записанным начальным загрузчиком. +![Installation_process](Installation_process.PNG) ## Запись начального загрузчика через ArduinoIDE -1. Подключите плату Elbear Ace-Uno к ПК через программатор ELJTAG. +Для загрузки скетчей по USB в ArduinoIDE необходимо, чтобы на плате был специальный начальный загрузчик ([elbear_fw_bootloader](https://gitflic.ru/project/elron-tech/elbear_fw_bootloader) для плат Elbear Ace-Uno). Если он уже есть на плате, можно сразу переходить к работе. Если загрузчика еще нет или необходимо обновить его на плате, ниже описан процесс загрузки. Актуальная версия начального загрузчика входит в состав пакета поддержки для всех плат, отдельно скачивать его не нужно. + +Платы Elbear Ace-Uno ревизии 1.1.0 готовы к использованию в ArduinoIDE из коробки, так как поставляются с предварительно записанным начальным загрузчиком. + +Для записи начального загрузчика: +1. Подключите плату к ПК по интерфейсу JTAG. +Для подключения платы Elbear Ace-Uno потребуется программатор [ELJTAG](https://elron.tech/eljtag-programmator-risc-v-mcu/). +Для подключения платы START-MIK32 необходимо перевести переключатель режима программатора в положение JTAG и подключить плату к ПК через USB разъем. 2. В ArduinoIDE выберите программатор: `Инструменты -> Программатор -> mik32 uploader`. 3. Для записи начального загрузчика выберите `Инструменты -> Записать Загрузчик`. -![Bootloader](docs/Bootloader.png) -4. При возникновении проблем с загрузкой ознакомьтесь с разделом `Настройка программатора` в [инструкции](https://elron.tech/wp-content/uploads/2024/05/instrukcija-po-pervomu-zapusku.pdf) по первому запуску платы ELBEAR ACE-UNO. +![Bootloader](Bootloader.png) +4. При возникновении проблем с загрузкой ознакомьтесь с разделом `Настройка программатора` в [инструкции](https://elron.tech/wp-content/uploads/2024/05/instrukcija-po-pervomu-zapusku.pdf) по первому запуску платы ELBEAR ACE-UNO или с [документацией](https://wiki.mik32.ru/%D0%9E%D1%82%D0%BB%D0%B0%D0%B4%D0%BE%D1%87%D0%BD%D0%B0%D1%8F_%D0%BF%D0%BB%D0%B0%D1%82%D0%B0_%D0%A1%D1%82%D0%B0%D1%80%D1%82) по запуску платы START-MIK32. Теперь можно загружать скетчи в плату по USB. ## Начало работы 1. Подключите плату к ПК по USB. 2. Откройте ArduinoIDE и загрузите необходимый скетч. Для начала работы можно воспользоваться готовыми примерами, например - `Файл -> Примеры -> 01.Basics -> Blink`. -![Blink_example](docs/Blink_example.png) +![Blink_example](Blink_example.png) 3. Выберите активную плату - `Инструменты -> Плата`. -![Set_board](docs/Set_board.png) +![Set_board](Set_board.png) 4. Выберите используемый COM порт - `Инструменты -> Порт`. -![Set_port](docs/Set_port.png) +![Set_port](Set_port.png) Выбранные плата и порт в ArduinoIDE должны отображаться следующим образом: -![Selected_board_port](docs/Selected_board_port.png) +![Selected_board_port](Selected_board_port.png) 5. Проверьте скетч, нажав соответствующую кнопку. -![Build_project](docs/Build_project.png) +![Build_project](Build_project.png) 6. Загрузите полученную прошивку на плату. -![Flash_project](docs/Flash_project.png) +![Flash_project](Flash_project.png) 7. При необходимости можно открыть терминал и получать сообщения от платы по интерфейсу Serial. Для этого добавьте в скетч работу с интерфейсом и после загрузки прошивки выберите `Инструменты -> Монитор порта`. -![Monitor](docs/Monitor.png) \ No newline at end of file +![Monitor](Monitor.png) \ No newline at end of file diff --git a/docs/Monitor.png b/docs/Monitor.png index d7e226b..675d331 100644 Binary files a/docs/Monitor.png and b/docs/Monitor.png differ diff --git a/docs/Selected_board_port.png b/docs/Selected_board_port.png index cb8c373..a00ec20 100644 Binary files a/docs/Selected_board_port.png and b/docs/Selected_board_port.png differ diff --git a/docs/Set_board.png b/docs/Set_board.png index b5638ef..f230da2 100644 Binary files a/docs/Set_board.png and b/docs/Set_board.png differ diff --git a/docs/Set_port.png b/docs/Set_port.png index afd4554..6b75b55 100644 Binary files a/docs/Set_port.png and b/docs/Set_port.png differ diff --git a/docs/Start_V1_pinout.png b/docs/Start_V1_pinout.png new file mode 100644 index 0000000..3b663ce Binary files /dev/null and b/docs/Start_V1_pinout.png differ diff --git a/docs/Start_mik32_description.md b/docs/Start_mik32_description.md new file mode 100644 index 0000000..e3f909d --- /dev/null +++ b/docs/Start_mik32_description.md @@ -0,0 +1,59 @@ +# START-MIK32 +Особенности работы с платой START-MIK32 в среде программирования ArduinoIDE. +### Функциональное назначение выводов +![Start_V1_pinout.png](Start_V1_pinout.png) + +### Загрузка скетчей +Для загрузки скетчей в ArduinoIDE необходимо передвинуть переключатель режима программатора на плате в положение `COM`. Так же необходимо установить две перемычки на разъем 5 - первой перемычкой замкнуть выводы `COM_RX` и `MCU_TX`, а второй - выводы `COM_TX` и `MCU_RX`. +### Цифровые выводы +Выводы на плате START-MIK32 пронумерованы в соответствии с их принадлежностью к определенному GPIO-порту и конкретному пину внутри порта. Чтобы использовать цифровой вывод, необходимо передать в функцию номер порта и номер пина в формате `P0_1`, где "0" — это номер порта, а "1" — номер пина внутри порта. Например, для инициализации вывода 5 порта 2 на выход необходимо вызвать функцию `pinMode(P2_5, OUTPUT)`. +Для использования доступны следующие выводы: `P0_0 ... P0_15, P1_0 ... P1_15, P2_0 ... P2_7`. +На плате есть встроенные светодиоды и кнопка. Светодиоды подключены к выводам P0_3, P1_3. Кнопка подключена к выводу Р0_8. Для удобства при работе с ними можно воспользоваться макросами `LED_BUILTIN`(P0_3), `LED_BUILTIN1`(P1_3) и `BTN_BUILTIN`, передавая их в качестве аргументов функции вместо номера цифрового вывода. +### АЦП +На плате доступно 8 выводов, которые можно использовать в качестве каналов АЦП. Для работы с ними в функцию `analogRead()` необходимо передать номер канала или номер соответствующего цифрового вывода. Доступные каналы и их соответствие номерам выводов платы: + +|Цифровой вывод|Номер канала АЦП| +|---------|---------| +|P1_5|A0| +|P1_7|A1| +|P0_2|A2| +|P0_4|A3| +|P0_7|A4| +|P0_9|A5| +|P0_11|A6| +|P0_13|A7| +#### ШИМ +На плате START-MIK32 в ArduinoIDE доступно 8 выводов для формирования ШИМ-сигнала. Генерация сигнала осуществляется с помощью 32-битного таймера. Выводы, подключенные к одному и тому же таймеру, выдают ШИМ-сигнал одинаковой частоты. +Доступные выводы: + +|Цифровой вывод|Используемый таймер| +|---------|---------| +|P0_0|таймер 1| +|P0_1|таймер 1| +|P0_2|таймер 1| +|P0_3|таймер 1| +|P1_0|таймер 2| +|P1_1|таймер 2| +|P1_2|таймер 2| +|P1_3|таймер 2| + +При использовании SPI формирование ШИМ сигнала на выводах P1_0 ... P1_3 недоступно. +### Прерывания +На плате START-MIK32 доступно 8 прерываний, настраиваемых функцией `void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)`: + +|Цифровой вывод|Номер прерывания| +|---------|---------| +|`BTN_BUILTIN` (P0_8)|0| +|P1_9|1| +|P0_10|2| +|P1_15|3| +|P0_12|4| +|P0_13|5| +|P0_14|6| +|P0_15|7| + +### Serial +Интерфейс UART0 доступен на выводах P0_5, P0_6, для работы с ним используется экземпляр класса под названием `Serial`. +Интерфейс UART1 доступен на выводах P1_8, P1_9, используемый экземпляр класса - `Serial1`. +USB-UART преобразователь, установленный на плате, поддерживает стандартные скорости UART до 57600 бод. Нестандартные скорости должны быть кратны +12*32=384, например, 240000 бод, 768000 бод. \ No newline at end of file diff --git a/libraries/NeoPixel/examples/simple/simple.ino b/libraries/NeoPixel/examples/simple/simple.ino index eb42d35..b888daa 100644 --- a/libraries/NeoPixel/examples/simple/simple.ino +++ b/libraries/NeoPixel/examples/simple/simple.ino @@ -1,7 +1,7 @@ #include #define PIN 2 -#define NUMPIXELS 8 +#define NUMPIXELS 1 NeoPixel pixels(NUMPIXELS, PIN); diff --git a/libraries/NeoPixel/examples/simpleWithSerial/simpleWithSerial.ino b/libraries/NeoPixel/examples/simpleWithSerial/simpleWithSerial.ino index 062ca31..ff59018 100644 --- a/libraries/NeoPixel/examples/simpleWithSerial/simpleWithSerial.ino +++ b/libraries/NeoPixel/examples/simpleWithSerial/simpleWithSerial.ino @@ -1,7 +1,7 @@ #include #define PIN 2 -#define NUMPIXELS 8 +#define NUMPIXELS 1 NeoPixel pixels(NUMPIXELS, PIN); diff --git a/libraries/SPI/keywords.txt b/libraries/SPI/keywords.txt index 1906b7f..99c75df 100644 --- a/libraries/SPI/keywords.txt +++ b/libraries/SPI/keywords.txt @@ -24,6 +24,7 @@ setClockDivider KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### +SPI_CLOCK_DIV2 LITERAL1 SPI_CLOCK_DIV4 LITERAL1 SPI_CLOCK_DIV8 LITERAL1 SPI_CLOCK_DIV16 LITERAL1 diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index ad30a09..1670372 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -21,14 +21,14 @@ void SPISettings::spiUpdateSettings(uint32_t speedMaximum, uint8_t dataOrder, ui // Find the fastest clock that is less than or equal to the // given clock rate. If nothing is slow enough - use the slowest. // mik32v2 has the set of deviders, that can be calculate as: - // div = 2 << (1...7). Value in braсkets is a value for config register + // div = 2 << (0...7). Value in braсkets is a value for config register uint8_t divRegVal = 0; // start from minimal divider (maximum speed) - while(divRegVal < 7) + while(divRegVal <= 7) { - divRegVal++; // values from 1 to 7 if ((F_CPU/(2 << divRegVal)) <= speedMaximum) // find suitable divider break; + divRegVal++; } // if break didn't call in cycle, it will be the greatest divRegVal (and divider) @@ -95,7 +95,7 @@ void SPIClass::end() void SPIClass::usingInterrupt(uint8_t interruptNumber) { - if(interruptNumber < EXTERNAL_NUM_INTERRUPTS) + if(interruptNumber < EXTERNAL_INTERRUPTS_QTY) { noInterrupts(); // prevent transactionBegin interruptMask |= (1 << interruptNumber); // add new interrupt to mask @@ -107,7 +107,7 @@ void SPIClass::usingInterrupt(uint8_t interruptNumber) void SPIClass::notUsingInterrupt(uint8_t interruptNumber) { - if(interruptNumber < EXTERNAL_NUM_INTERRUPTS) + if(interruptNumber < EXTERNAL_INTERRUPTS_QTY) { noInterrupts(); // prevent transactionBegin interruptMask &= ~(1< 0)) { - for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++) + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { if (interruptMask & (1 << i)) // disable every interrupt by it's number @@ -234,7 +234,7 @@ void SPIClass::endTransaction(void) // enable interrupts in use if (spiInUse && (interruptMode > 0)) { - for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++) + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { if (interruptMask & (1 << i)) // enable every interrupt in use by it's number @@ -270,10 +270,10 @@ void SPIClass::setClockDivider(uint8_t clockDiv) if (spiInUse) { // if divider is valid - if ((clockDiv == SPI_CLOCK_DIV4) || (clockDiv == SPI_CLOCK_DIV8) || - (clockDiv == SPI_CLOCK_DIV16) || (clockDiv == SPI_CLOCK_DIV32) || - (clockDiv == SPI_CLOCK_DIV64) || (clockDiv == SPI_CLOCK_DIV128) || - (clockDiv == SPI_CLOCK_DIV256)) + if ((clockDiv == SPI_CLOCK_DIV2) || (clockDiv == SPI_CLOCK_DIV4) || + (clockDiv == SPI_CLOCK_DIV8) || (clockDiv == SPI_CLOCK_DIV16) || + (clockDiv == SPI_CLOCK_DIV32) || (clockDiv == SPI_CLOCK_DIV64) || + (clockDiv == SPI_CLOCK_DIV128) || (clockDiv == SPI_CLOCK_DIV256)) { hspi.Init.BaudRateDiv = clockDiv; currentSpeed = F_CPU >> (clockDiv+1); diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 91ae176..b54e6b2 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -34,6 +34,7 @@ // dividers for setClockDivider() +#define SPI_CLOCK_DIV2 0x00 // 16 MHz #define SPI_CLOCK_DIV4 0x01 // 8 MHz #define SPI_CLOCK_DIV8 0x02 // 4 MHz #define SPI_CLOCK_DIV16 0x03 // 2 MHz diff --git a/libraries/Start_mik32_Guide/.gitignore b/libraries/Start_mik32_Guide/.gitignore new file mode 100644 index 0000000..5bce97a --- /dev/null +++ b/libraries/Start_mik32_Guide/.gitignore @@ -0,0 +1,2 @@ +installed.json +.vscode/ \ No newline at end of file diff --git a/libraries/Start_mik32_Guide/examples/Circuit_1_Blink/Circuit_1_Blink.ino b/libraries/Start_mik32_Guide/examples/Circuit_1_Blink/Circuit_1_Blink.ino new file mode 100644 index 0000000..6619475 --- /dev/null +++ b/libraries/Start_mik32_Guide/examples/Circuit_1_Blink/Circuit_1_Blink.ino @@ -0,0 +1,13 @@ +// функция настройки запускается один раз при нажатии кнопки reset или подаче питания на плату +void setup() { + // Инициализация пина P0_3 как выход + pinMode(LED_BUILTIN, OUTPUT); +} + +// функция цикла выполняется снова и снова бесконечно +void loop() { + digitalWrite(LED_BUILTIN, HIGH); // включить светодиод (HIGH - высокий уровень напряжения) + delay(1000); // Секунда ожидания + digitalWrite(LED_BUILTIN, LOW); // выключить светодиод (LOW - низкий уровень напряжения) + delay(1000); // Секунда ожидания +} diff --git a/libraries/Start_mik32_Guide/examples/Circuit_2_Button/Circuit_2_Button.ino b/libraries/Start_mik32_Guide/examples/Circuit_2_Button/Circuit_2_Button.ino new file mode 100644 index 0000000..ff23f9d --- /dev/null +++ b/libraries/Start_mik32_Guide/examples/Circuit_2_Button/Circuit_2_Button.ino @@ -0,0 +1,22 @@ +int buttonS = 0; // задаем переменную для хранения состояния кнопки + +// функция настройки запускается один раз при нажатии кнопки reset или подаче питания на плату +void setup() { + pinMode(LED_BUILTIN, OUTPUT); // P0_3 + pinMode(LED_BUILTIN1, OUTPUT); // P1_3 + pinMode(BTN_BUILTIN, INPUT); // P0_8 +} + +// функция цикла выполняется снова и снова бесконечно +void loop() { + buttonS = digitalRead(BTN_BUILTIN); // считываем значение с кнопки + if (buttonS == 0) // если кнопка нажата, то + { + digitalWrite(LED_BUILTIN, HIGH); // включить светодиод на пине P0_3 + digitalWrite(LED_BUILTIN1, LOW); // выключить светодиод на пине P1_3 + } else // если кнопка отпущена, то + { + digitalWrite(LED_BUILTIN, LOW); // выключить светодиод на пине P0_3 + digitalWrite(LED_BUILTIN1, HIGH); // включить светодиод на пине P1_3 + } +} diff --git a/libraries/Start_mik32_Guide/examples/Circuit_3_Buttons/Circuit_3_Buttons.ino b/libraries/Start_mik32_Guide/examples/Circuit_3_Buttons/Circuit_3_Buttons.ino new file mode 100644 index 0000000..4124914 --- /dev/null +++ b/libraries/Start_mik32_Guide/examples/Circuit_3_Buttons/Circuit_3_Buttons.ino @@ -0,0 +1,37 @@ +const int button1Pin = P0_2; // кнопка №1 - пин P0_2 +const int button2Pin = P0_3; // кнопка №2 - пин P0_3 +const int ledPin = P1_3; // пин P1_3, для светодиода + +// функция настройки запускается один раз при нажатии кнопки reset или подаче питания на плату +void setup() { + // Установим пины кнопок как входящие: + pinMode(button1Pin, INPUT); + pinMode(button2Pin, INPUT); + + // Установим пин светодиода как исходящий: + pinMode(ledPin, OUTPUT); +} + +// функция цикла выполняется снова и снова бесконечно +void loop() { + int button1State, button2State; // Переменные для сохранения состояния кнопок + + /* + * Здесь мы читаем текущее состояние кнопок и помещаем их значение + * в две пепременные. + */ + button1State = digitalRead(button1Pin); + button2State = digitalRead(button2Pin); + + if (((button1State == LOW) || (button2State == LOW)) // Проверяем нажата ли только одна из кнопок + && !((button1State == LOW) && (button2State == LOW))) { + digitalWrite(ledPin, HIGH); // Включаем светодиод + } else // иначе + { + digitalWrite(ledPin, LOW); // Выключаем светодиод + } +} + + + + diff --git a/libraries/Start_mik32_Guide/examples/Circuit_4_Potentiometer/Circuit_4_Potentiometer.ino b/libraries/Start_mik32_Guide/examples/Circuit_4_Potentiometer/Circuit_4_Potentiometer.ino new file mode 100644 index 0000000..82ca9ad --- /dev/null +++ b/libraries/Start_mik32_Guide/examples/Circuit_4_Potentiometer/Circuit_4_Potentiometer.ino @@ -0,0 +1,18 @@ +const int ledPin = LED_BUILTIN; // Пин P0_3 для светодиода. +const int sensorPin = P1_5; // Пин, к которому подключается средний вывод потенциометра. +int sensorValue = 0; // Переменная для хранения значения потенциометра + +// функция настройки запускается один раз при нажатии кнопки reset или подаче питания на плату +void setup() { + // Установим пин светодиода как выход + pinMode(ledPin, OUTPUT); +} + +// функция цикла выполняется снова и снова бесконечно +void loop() { + sensorValue = analogRead(sensorPin); // считываем значение с потенциометра + digitalWrite(ledPin, HIGH); // Включить светодиод + delay(sensorValue); // Задержка на sensorValue мс + digitalWrite(ledPin, LOW); // Выключить светодиод + delay(sensorValue); // Задержка на sensorValue мс +} diff --git a/libraries/Start_mik32_Guide/examples/Circuit_5_Brightness/Circuit_5_Brightness.ino b/libraries/Start_mik32_Guide/examples/Circuit_5_Brightness/Circuit_5_Brightness.ino new file mode 100644 index 0000000..dcb4b6f --- /dev/null +++ b/libraries/Start_mik32_Guide/examples/Circuit_5_Brightness/Circuit_5_Brightness.ino @@ -0,0 +1,37 @@ +// Имена для пинов светодиода и потенциометра (англ potentiometr или "pot") +#define LED_PIN P0_0 +#define POT_PIN P1_5 + +// функция настройки запускается один раз при нажатии кнопки reset или подаче питания на плату +void setup() { + // Установим пин светодиода как выход + pinMode(LED_PIN, OUTPUT); +} + +// функция цикла выполняется снова и снова бесконечно +void loop() { + // Переменные для хранения значения потенциометра и яркости светодиода + int rotation, brightness; + + /* + * Считываем в rotation напряжение с потенциометра: + * микроконтроллер выдаст число от 0 до 1023 + * пропорциональное углу поворота ручки. + */ + rotation = analogRead(POT_PIN); + + /* + * В brightness записывается полученное ранее значение rotation + * деленное на 4. Поскольку в переменных типа int хранятся целые + * значения, дробная часть от деления будет отброшена. + * В итоге мы получим целое число от 0 до 255. + */ + brightness = rotation / 4; + + // Итоговое напряжение подается на светодиод. + analogWrite(LED_PIN, brightness); +} + + + + diff --git a/libraries/Start_mik32_Guide/examples/Circuit_6_RGB_LED/Circuit_6_RGB_LED.ino b/libraries/Start_mik32_Guide/examples/Circuit_6_RGB_LED/Circuit_6_RGB_LED.ino new file mode 100644 index 0000000..e75706d --- /dev/null +++ b/libraries/Start_mik32_Guide/examples/Circuit_6_RGB_LED/Circuit_6_RGB_LED.ino @@ -0,0 +1,153 @@ +// Имена пинов для светодиодов +const int RED_PIN = P0_0; +const int GREEN_PIN = P0_1; +const int BLUE_PIN = P0_2; + +/* + * Следующая переменная контролирует, насколько быстро выполняется цикл по смене + * цветов (в качестве эксперимента попробуйте поменять ее значение). + */ +int DISPLAY_TIME = 1000; // в миллисекундах + +// Объявление функций +void mainColors(); +void showRGB(int color); +void showSpectrum(); + +// функция настройки запускается один раз при нажатии кнопки reset или подаче питания на плату +void setup() { + // Настройка пинов для управления RGB светодиодом: + pinMode(RED_PIN, OUTPUT); + pinMode(GREEN_PIN, OUTPUT); + pinMode(BLUE_PIN, OUTPUT); +} + +// функция цикла выполняется снова и снова бесконечно +void loop() { + + /* + * В этом примере показаны два способа управления RGB светодиодом. + * Первый способ состоит из включения и выключения красного, зеленого и синего + * в различных сочетаниях. Такие сочетания дают восемь цветов, если считать + * "черный" в качестве цвета. + */ + + /* + * Функция mainColors() проходит через все восемь цветов. + * Эта функция включает и выключает отдельно каждый светодиод. + * Если Вы хотите получить больше чем восемь цветов, Вам придется изменять + * яркость каждого светодиода. Для этого можно использовать функцию + * analogWrite(), - градация яркости от 0 до 255. + */ + mainColors(); + showSpectrum(); // Функция showSpectrum() плавно проследует через каждые из 8 цветов. +} + + +void mainColors() { + // Все светодиоды выключены + digitalWrite(RED_PIN, LOW); + digitalWrite(GREEN_PIN, LOW); + digitalWrite(BLUE_PIN, LOW); + delay(DISPLAY_TIME); + + // Красный включен + digitalWrite(RED_PIN, HIGH); + digitalWrite(GREEN_PIN, LOW); + digitalWrite(BLUE_PIN, LOW); + delay(DISPLAY_TIME); + + // Зеленый включен + digitalWrite(RED_PIN, LOW); + digitalWrite(GREEN_PIN, HIGH); + digitalWrite(BLUE_PIN, LOW); + delay(DISPLAY_TIME); + + // Синий включен + digitalWrite(RED_PIN, LOW); + digitalWrite(GREEN_PIN, LOW); + digitalWrite(BLUE_PIN, HIGH); + delay(DISPLAY_TIME); + + // Желтый (красный и зеленый) + digitalWrite(RED_PIN, HIGH); + digitalWrite(GREEN_PIN, HIGH); + digitalWrite(BLUE_PIN, LOW); + delay(DISPLAY_TIME); + + // Бирюзовый (зеленый и синий) + digitalWrite(RED_PIN, LOW); + digitalWrite(GREEN_PIN, HIGH); + digitalWrite(BLUE_PIN, HIGH); + delay(DISPLAY_TIME); + + // Фиолетовый (красный и синий) + digitalWrite(RED_PIN, HIGH); + digitalWrite(GREEN_PIN, LOW); + digitalWrite(BLUE_PIN, HIGH); + delay(DISPLAY_TIME); + + // Белый (красный, зеленый и синий) + digitalWrite(RED_PIN, HIGH); + digitalWrite(GREEN_PIN, HIGH); + digitalWrite(BLUE_PIN, HIGH); + delay(DISPLAY_TIME); +} + + +/* + * showRGB() - выводит один цвет на светодиод. Когда Вам необходим + * опережеленный цвет, вызовите showRGB() с нужным Вам цветом. + * Эта функция переводит число от 0 до 767 в определенный цвет. + * Если плавно пройтись по этому числовому ряду, то светодиод будет + * плавно менять цвет через весь цветовой спектр. + * + * int colot - код цвета от 0 до 767. + * Базовые цифры: + * 0 - чистый красный + * 255 - чистый зеленый + * 511 - чистый синий + * 767 - чистый красный + * + * Числа между вышеуказанных создают промежуточные цвета. + * Например, 640 находится между 512 (синий) и 767 (красный). + * Это даст смесь синего и красного, в результате чего получится фиолетовый. + */ +void showRGB(int color) { + int redIntensity; // Яркость красного светодиода + int greenIntensity; // Яркость зеленого светодиода + int blueIntensity; // Яркость синего светодиода + + if (color <= 255) // зона 1 + { + redIntensity = 255 - color; // красный меняется из включенного на выключенный + greenIntensity = color; // зеленый меняется из выключенного во включенный + blueIntensity = 0; // голубой всегда выключен + } else if (color <= 511) // зона 2 + { + redIntensity = 0; // красный всегда выключен + greenIntensity = 255 - (color - 256); // зеленый меняется от включенного в выключенный + blueIntensity = color - 256; // синий меняется от выключенного к включенному + } else if (color >= 512) // зона 3 + { + redIntensity = color - 512; // красный меняется от выключенного к включенному + greenIntensity = 0; // зеленый всегда выключен + blueIntensity = 255 - (color - 512); // синий меняется от включенного к выключенному + } + + // Функциям передаются установленные значения яркости. + analogWrite(RED_PIN, redIntensity); + analogWrite(BLUE_PIN, blueIntensity); + analogWrite(GREEN_PIN, greenIntensity); +} + +/* + * showSpectrum() - выводит все цвета по очереди. Функция циклически + * вызывает showRGB() для смены цвета с аргументом от 0 до 768. + */ +void showSpectrum() { + for (int x = 0; x < 768; x++) { + showRGB(x); + delay(10); + } +} diff --git a/libraries/Start_mik32_Guide/examples/Circuit_7_Photoresistor/Circuit_7_Photoresistor.ino b/libraries/Start_mik32_Guide/examples/Circuit_7_Photoresistor/Circuit_7_Photoresistor.ino new file mode 100644 index 0000000..f299cc5 --- /dev/null +++ b/libraries/Start_mik32_Guide/examples/Circuit_7_Photoresistor/Circuit_7_Photoresistor.ino @@ -0,0 +1,120 @@ +// Константы с именами для используемых пинов. +const int sensorPin = P1_5; +const int ledPin = P0_0; + +/* + * Глобальны переменные для уровней яркости: + * high (высокий), low (низкий). + */ +int lightLevel, high = 0, low = 1023; + +// Объявление функций +void manualTune(); +void autoTune(); + +// функция настройки запускается один раз при нажатии кнопки reset или подаче питания на плату +void setup() { + // Настройка пинов для управления светодиодом: + pinMode(ledPin, OUTPUT); + + // Для отладки, чтобы увидеть показания датчиков через "Serial Monitor". + Serial.begin(9600); +} + +// функция цикла выполняется снова и снова бесконечно +void loop() { + lightLevel = analogRead(sensorPin); + + manualTune(); // Ручное изменение диапазона от светлого к темному + // autoTune(); // Автоматическое изменение диапазона + + /* + * Вышеупомянутые функции будут изменять "lightLevel" до максимамльных + * значений от "Полностью Вкл" к "Полному Выкл". И это значит, что теперь + * мы сможем регулировать яркость светодиода в широких пределах. + */ + analogWrite(ledPin, lightLevel); + + /* + * Выражение выше будет увеличивать яркость светодиода с увеличением + * сопротивления фоторезистора. Чтобы сделать наоборот, нужно в + * analogWrite(ledPin, lightLevel) значение "lightLevel" на "255 - lightLevel". + */ + + /* + * Для отладки, чтобы увидть показания датчиков через "монитор порта", + * расскомментируйте следующие строчки. + */ + // Serial.println(lightLevel); // Вывод данных с фоторезистора (0 - 1023) + // delay(500); // пауза 500 мс +} + +void manualTune() +{ + int lowValue = 0; + int highValue = 1023; + /* + * Функция analogRead() возвращает значение в диапазоне от 0 до 1023, + * а функция для управления светодиодом analogwrite() работает с диапазоном + * от 0 до 255. + * Функция map() может преобразовать значение одного диапазона в соответсвующее + * значение другого диапазона. + * Так map(lightLevel, 0, 1023, 0, 255) преобразует 0 в 0, 1023 в 255, а среднее + * значение 500 станет приблизительно 125. + */ + lightLevel = map(lightLevel, lowValue, highValue, 0, 255); + /* + * Функция map(lightLevel, 0, 1023, 0, 255) преобразует входное значение + * lightLevel даже если оно не входит в диапазон от 0 до 1023. + * Для ограничения диапазона используется функция constrain(). + * Так constrain(lightLevel, 0, 255) преобразует все значения lightLevel + * выше 255 в 255, а значения ниже 0 в 0. + */ + lightLevel = constrain(lightLevel, 0, 255); + + /* + * Изменение освещенности может быть недостаточно чтобы функция analogRead() + * вернула значение от 0 до 1023. В реальности диапазон может быть меньше. + * Приблизительно от 300 (светло) до 800 (темно). + * Поэтому, если светодиод светит тускло или его яркость меняется слабо, + * то можно уменьшить входной диапазон функции map(). + * Например, измените lowValue на 300, а highValue на 800. + */ +} + +void autoTune() +{ + /* + * В функции manualTune() входной диапазон функции map() нужно изменять + * вручную. Но это можно автоматизировать. + * В этой функции отслеживаются самые высокие и низкие значения lightLevel, + * которые мы получаем функцией analogRead(). + * В начале программы объявлены переменные для входного диапазона low и high, + * которые и будут автоматически изменяться. + * Низкому уровню специально присвоено максимальное значение 1023, чтобы + * первое полученное значение lightLevel было гарантированно меньше значния + * low. По аналогии значение high = 0. + */ + + if(lightLevel < low) + { + low = lightLevel; + } + + if(lightLevel > high) + { + high = lightLevel; + } + + /* + * После выполнения условий выше получится, что значению low соответсвует + * минимальное значение из полученных lightLevel, а значнию high максимальное. + */ + + /* + * Если светодиод начинает мерцать, нужно в функции map добавить к low или high + * небольшое смещение для сужения диапазона. + */ + lightLevel = map(lightLevel, low, high, 0, 255); + lightLevel = constrain(lightLevel, 0, 255); +} diff --git a/libraries/Start_mik32_Guide/examples/Circuit_8_Buzzer/Circuit_8_Buzzer.ino b/libraries/Start_mik32_Guide/examples/Circuit_8_Buzzer/Circuit_8_Buzzer.ino new file mode 100644 index 0000000..ad01304 --- /dev/null +++ b/libraries/Start_mik32_Guide/examples/Circuit_8_Buzzer/Circuit_8_Buzzer.ino @@ -0,0 +1,47 @@ +#include "notes.h" // Библиотека с частотой нот + +// Константы с именами для используемых пинов. +const int buzzerPin = P0_0; + +/* + * BPM (bpm, англ. beats per minute[1], удары в минуту) в музыке — показатель, определяющий скорость исполнения + * или воспроизведения композиции. BPM — это количество четвертных нот в минуту, например, 120 BPM означает, что + * в минуту играется 120 четвертных нот (следовательно, 2 четверти в секунду). + */ +int tempo = 138; + +// функция настройки запускается один раз при нажатии кнопки reset или подаче питания на плату +void setup() { + // Настройка пинов для управления пьезоэлементом: + pinMode(buzzerPin, OUTPUT); +} + +// функция цикла выполняется снова и снова бесконечно +void loop() { + for(int i = 0; i < sizeof(badApple)/sizeof(*badApple); i += 2) + { + int duration = badApple[i+1]/(tempo/60); // Рассчитывается продолжительность звучания ноты в миллисекундах + if(badApple[i] != NOTE_PAUSE) // Если не пауза, то играть ноту + { + tone(buzzerPin, badApple[i], duration); + } + else // Если пауза, то выключить звук + { + noTone(buzzerPin); + } + delay(duration); // Задержка для выдерживания продолжительности ноты или паузы + delay(1); // Небольшая задержка между нотами + } + + delay(3000); +} + + + + + + + + + + diff --git a/libraries/Start_mik32_Guide/examples/Circuit_8_Buzzer/notes.h b/libraries/Start_mik32_Guide/examples/Circuit_8_Buzzer/notes.h new file mode 100644 index 0000000..71b239c --- /dev/null +++ b/libraries/Start_mik32_Guide/examples/Circuit_8_Buzzer/notes.h @@ -0,0 +1,386 @@ +/* + * Обозначние нот + * С - До + * CS - До-диез + * D - Ре + * DS - Ре-диез + * E - Ми + * F - Фа + * FS - Фа-диез + * G - Соль + * GS - Соль-диез + * A - Ля + * AS - Ля-диез. Альтернативное обозначение B - Си-бемоль + * H - Си + */ + + +#define NOTE_PAUSE 0 // Пауза + +// Суб-контp октава +#define NOTE_E0 21 +#define NOTE_F0 22 +#define NOTE_FS0 23 +#define NOTE_G0 25 +#define NOTE_GS0 26 +#define NOTE_A0 28 +#define NOTE_AS0 29 +#define NOTE_H0 31 + +// Контp октава +#define NOTE_C1 33 +#define NOTE_CS1 35 +#define NOTE_D1 37 +#define NOTE_DS1 39 +#define NOTE_E1 41 +#define NOTE_F1 44 +#define NOTE_FS1 46 +#define NOTE_G1 49 +#define NOTE_GS1 52 +#define NOTE_A1 55 +#define NOTE_AS1 58 +#define NOTE_H1 62 + +// Большая октава +#define NOTE_C2 65 +#define NOTE_CS2 69 +#define NOTE_D2 74 +#define NOTE_DS2 78 +#define NOTE_E2 82 +#define NOTE_F2 87 +#define NOTE_FS2 93 +#define NOTE_G2 98 +#define NOTE_GS2 104 +#define NOTE_A2 110 +#define NOTE_AS2 117 +#define NOTE_H2 123 + +// Малая октава +#define NOTE_C3 131 +#define NOTE_CS3 139 +#define NOTE_D3 147 +#define NOTE_DS3 156 +#define NOTE_E3 165 +#define NOTE_F3 175 +#define NOTE_FS3 185 +#define NOTE_G3 196 +#define NOTE_GS3 207 +#define NOTE_A3 220 +#define NOTE_AS3 233 +#define NOTE_H3 247 + +// 1я октава +#define NOTE_C4 262 +#define NOTE_CS4 277 +#define NOTE_D4 294 +#define NOTE_DS4 311 +#define NOTE_E4 330 +#define NOTE_F4 349 +#define NOTE_FS4 370 +#define NOTE_G4 392 +#define NOTE_GS4 415 +#define NOTE_A4 440 +#define NOTE_AS4 466 +#define NOTE_H4 494 + +// 2я октава +#define NOTE_C5 523 +#define NOTE_CS5 554 +#define NOTE_D5 587 +#define NOTE_DS5 622 +#define NOTE_E5 659 +#define NOTE_F5 698 +#define NOTE_FS5 740 +#define NOTE_G5 784 +#define NOTE_GS5 831 +#define NOTE_A5 880 +#define NOTE_AS5 932 +#define NOTE_H5 988 + +// 3я октава +#define NOTE_C6 1047 +#define NOTE_CS6 1109 +#define NOTE_D6 1175 +#define NOTE_DS6 1245 +#define NOTE_E6 1319 +#define NOTE_F6 1397 +#define NOTE_FS6 1480 +#define NOTE_G6 1568 +#define NOTE_GS6 1661 +#define NOTE_A6 1720 +#define NOTE_AS6 1865 +#define NOTE_H6 1976 + +// 4я октава +#define NOTE_C7 2093 +#define NOTE_CS7 2217 +#define NOTE_D7 2349 +#define NOTE_DS7 2489 +#define NOTE_E7 2637 +#define NOTE_F7 2793 +#define NOTE_FS7 2960 +#define NOTE_G7 3136 +#define NOTE_GS7 3332 +#define NOTE_A7 3440 +#define NOTE_AS7 3729 +#define NOTE_H7 3951 + +// 5я октава +#define NOTE_C8 4186 +#define NOTE_CS8 4435 +#define NOTE_D8 4698 +#define NOTE_DS8 4978 +#define NOTE_E8 5274 + +// Длительности +// Длительности измеряются относительно четвертой. +// То есть, четвертая это 1, целая это 4 (4 четвертых). +// Для удобного перевода в миллисекунды, значение умножены на 1000. +#define DURATION_1_256 1000*1/64 // Двести пятьдесят шестая +#define DURATION_1_128 1000*1/32 // Сто двадцать восьмая +#define DURATION_1_64 1000*1/16 // Шестьдесят четвёртая +#define DURATION_1_32 1000*1/8 // Тридцать вторая +#define DURATION_1_16 1000*1/4 // Шестнадцатая +#define DURATION_1_8 1000*1/2 // Восьмая +#define DURATION_1_4 1000*1 // Четвертная +#define DURATION_1_2 1000*2 // Половинная +#define DURATION_1 1000*4 // Целая +#define DURATION_2 1000*8 // Бревис +#define DURATION_4 1000*16 // Лонга +#define DURATION_8 1000*32 // Максима + +/* Массив с нотами. Сначала идет значение частоты ноты, а затем ее длительность. + * Длительности звучания ноты или паузы: + * Кностанта Название Длительность в ед. времени + * DURATION_1_256 - Двести пятьдесят шестая - 1/256 + * DURATION_1_128 - Сто двадцать восьмая - 1/128 + * DURATION_1_64 - Шестьдесят четвёртая - 1/64 + * DURATION_1_32 - Тридцать вторая - 1NOTE_H3/32 + * DURATION_1_16 - Шестнадцатая - 1/16 + * DURATION_1_8 - Восьмая - 1/8 + * DURATION_1_4 - Четвертная - 1/4 + * DURATION_1_2 - Половинная - 1/2 + * DURATION_1 - Целая - 1 + * DURATION_2 - Бревис - 2 + * DURATION_4 - Лонга - 4 + * DURATION_8 - Максима - 8 + * + * Например, NOTE_C4, DURATION_1_4 означет ноту C(До) длительностью 1/4. + */ +int badApple[] = +{ + // Такт 1 + NOTE_E4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_E5, DURATION_1_8, + NOTE_D5, DURATION_1_8, + + // Такт 2 + NOTE_H4, DURATION_1_4, + NOTE_E4, DURATION_1_4, + NOTE_H4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + + // Такт 3 + NOTE_E4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_A4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + + // Такт 4 + NOTE_F4, DURATION_1_8, + NOTE_E4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + NOTE_E4, DURATION_1_8, + NOTE_DS4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + + // Такт 5 + NOTE_E4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_E5, DURATION_1_8, + NOTE_D5, DURATION_1_8, + + // Такт 6 + NOTE_H4, DURATION_1_4, + NOTE_E4, DURATION_1_4, + NOTE_H4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + + // Такт 7 + NOTE_E4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_A4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + + // Такт 8 + NOTE_F4, DURATION_1_4, + NOTE_G4, DURATION_1_4, + NOTE_A4, DURATION_1_4, + NOTE_H4, DURATION_1_4, + + // Реприза + // Такт 9 + NOTE_D5, DURATION_1_8, + NOTE_E5, DURATION_1_8, + NOTE_H4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_8, + + // Такт 10 + NOTE_D5, DURATION_1_8, + NOTE_E5, DURATION_1_8, + NOTE_H4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_8, + + // Такт 11 + NOTE_A4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + NOTE_D4, DURATION_1_8, + NOTE_E4, DURATION_1_4, + NOTE_D4, DURATION_1_8, + NOTE_E4, DURATION_1_8, + + // Такт 12 + NOTE_F4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_8, + NOTE_E4, DURATION_1_4, + NOTE_H4, DURATION_1_8, + NOTE_E5, DURATION_1_8, + + // Такт 13 + NOTE_D5, DURATION_1_8, + NOTE_E5, DURATION_1_8, + NOTE_H4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_8, + + // Такт 14 + NOTE_D5, DURATION_1_8, + NOTE_E5, DURATION_1_8, + NOTE_H4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_E5, DURATION_1_8, + NOTE_F5, DURATION_1_8, + + // Такт 15 + NOTE_G5, DURATION_1_8, + NOTE_F5, DURATION_1_8, + NOTE_E5, DURATION_1_8, + NOTE_D5, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_8, + + // Концовка 1 + // Такт 16 + NOTE_A4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + NOTE_D4, DURATION_1_8, + NOTE_E4, DURATION_1_4, + NOTE_H4, DURATION_1_8, + NOTE_E5, DURATION_1_8, + + // Повтор репризы + // Такт 17 + NOTE_D5, DURATION_1_8, + NOTE_E5, DURATION_1_8, + NOTE_H4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_8, + + // Такт 18 + NOTE_D5, DURATION_1_8, + NOTE_E5, DURATION_1_8, + NOTE_H4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_8, + + // Такт 19 + NOTE_A4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + NOTE_D4, DURATION_1_8, + NOTE_E4, DURATION_1_4, + NOTE_D4, DURATION_1_8, + NOTE_E4, DURATION_1_8, + + // Такт 20 + NOTE_F4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_8, + NOTE_E4, DURATION_1_4, + NOTE_H4, DURATION_1_8, + NOTE_E5, DURATION_1_8, + + // Такт 21 + NOTE_D5, DURATION_1_8, + NOTE_E5, DURATION_1_8, + NOTE_H4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_8, + + // Такт 22 + NOTE_D5, DURATION_1_8, + NOTE_E5, DURATION_1_8, + NOTE_H4, DURATION_1_8, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_E5, DURATION_1_8, + NOTE_F5, DURATION_1_8, + + // Такт 23 + NOTE_G5, DURATION_1_8, + NOTE_F5, DURATION_1_8, + NOTE_E5, DURATION_1_8, + NOTE_D5, DURATION_1_8, + NOTE_H4, DURATION_1_4, + NOTE_A4, DURATION_1_8, + NOTE_H4, DURATION_1_8, + + // Концовка 2 + // Такт 23 + NOTE_A4, DURATION_1_8, + NOTE_G4, DURATION_1_8, + NOTE_F4, DURATION_1_8, + NOTE_D4, DURATION_1_8, + NOTE_E4, DURATION_1_4, + NOTE_PAUSE, DURATION_1_4, +}; diff --git a/libraries/Start_mik32_Guide/keywords.txt b/libraries/Start_mik32_Guide/keywords.txt new file mode 100644 index 0000000..56e4b89 --- /dev/null +++ b/libraries/Start_mik32_Guide/keywords.txt @@ -0,0 +1,16 @@ +####################################### +# Syntax Coloring Map For StartGuide +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/libraries/Start_mik32_Guide/library.properties b/libraries/Start_mik32_Guide/library.properties new file mode 100644 index 0000000..a41bde0 --- /dev/null +++ b/libraries/Start_mik32_Guide/library.properties @@ -0,0 +1,10 @@ +name=StartGuide +version=0.0.0 +author=Mikron +maintainer=Mikron +sentence=Collection of examples for a course based on START-MIK32-V1. +paragraph=Collection of examples for a course based on START-MIK32-V1. +category=Uncategorized +url=https://wiki.mik32.ru/ +architectures=MIK32_Amur + diff --git a/libraries/Start_mik32_Guide/src/empty.h b/libraries/Start_mik32_Guide/src/empty.h new file mode 100644 index 0000000..e69de29 diff --git a/libraries/Wire/examples/i2c_master/i2c_master.ino b/libraries/Wire/examples/i2c_master/i2c_master.ino index ef358fc..cee2c74 100644 --- a/libraries/Wire/examples/i2c_master/i2c_master.ino +++ b/libraries/Wire/examples/i2c_master/i2c_master.ino @@ -42,13 +42,12 @@ uint8_t masterGetData(uint8_t *buf, uint8_t dataSize) void setup() { - Serial.begin(115200); + Serial.begin(57600); while (!Serial); Serial.println("I2C master start"); // Initialize the device on the I2C bus as a master Wire.begin(); - Wire.setClock(400000); } void loop() diff --git a/libraries/Wire/examples/i2c_slave/i2c_slave.ino b/libraries/Wire/examples/i2c_slave/i2c_slave.ino index 2b86bda..09ecdf4 100644 --- a/libraries/Wire/examples/i2c_slave/i2c_slave.ino +++ b/libraries/Wire/examples/i2c_slave/i2c_slave.ino @@ -73,7 +73,7 @@ void receiveEvent(int bytesNum) // ----------------------------------------- // void setup() { - Serial.begin(115200); + Serial.begin(57600); while (!Serial); Serial.println("I2C slave start"); diff --git a/platform.txt b/platform.txt index eaee952..d356c9b 100644 --- a/platform.txt +++ b/platform.txt @@ -1,5 +1,5 @@ -name=ELBEAR boards -version=1.0.0 +name=MIK32 Boards +version=0.1.0 # Compiler and tools compiler.prefix=riscv-none-elf- @@ -63,7 +63,7 @@ recipe.size.regex.data= ^(?:\.data|\.bss|\.noinit)\s+([0-9]+).* tools.elbear_uploader.cmd=elbear_uploader tools.elbear_uploader.cmd.windows=elbear_uploader.exe tools.elbear_uploader.path={runtime.tools.elbear_uploader.path} -tools.elbear_uploader.upload.pattern={path}/{cmd} {build.path}/{build.project_name}.hex --com={serial.port} +tools.elbear_uploader.upload.pattern={path}/{cmd} {build.path}/{build.project_name}.hex --com={serial.port} --baudrate={upload.speed} tools.elbear_uploader.upload.params.quiet= # Set elbear_uploader as programmer @@ -82,9 +82,9 @@ tools.mik32_upload.erase.pattern= tools.mik32_upload.erase.params.quiet= # For Tools > Burn Bootloader -tools.mik32_upload.bootloader.pattern={path}/{cmd} {runtime.platform.path}/bootloaders/{bootloader.file} --run-openocd --openocd-exec={runtime.tools.openocd.path}/bin/openocd{cmd.extension} --openocd-interface={path}/openocd-scripts/interface/ftdi/mikron-link.cfg --openocd-target={path}/openocd-scripts/target/mik32.cfg +tools.mik32_upload.bootloader.pattern={path}/{cmd} {runtime.platform.path}/bootloaders/{bootloader.file} --run-openocd --openocd-exec={runtime.tools.openocd.path}/bin/openocd{cmd.extension} --openocd-interface={path}/openocd-scripts/interface/{bootloader.interface} --openocd-target={path}/openocd-scripts/target/mik32.cfg tools.mik32_upload.bootloader.params.quiet= # For Sketch > Upload Using Programmer -tools.mik32_upload.program.pattern={path}/{cmd} {build.path}/{build.project_name}.hex --run-openocd --openocd-exec={runtime.tools.openocd.path}/bin/openocd{cmd.extension} --openocd-interface={path}/openocd-scripts/interface/ftdi/mikron-link.cfg --openocd-target={path}/openocd-scripts/target/mik32.cfg +tools.mik32_upload.program.pattern={path}/{cmd} {build.path}/{build.project_name}.hex --run-openocd --openocd-exec={runtime.tools.openocd.path}/bin/openocd{cmd.extension} --openocd-interface={path}/openocd-scripts/interface/{bootloader.interface} --openocd-target={path}/openocd-scripts/target/mik32.cfg tools.mik32_upload.program.params.quiet= diff --git a/variants/standart/pins_arduino.h b/variants/elbear_ace_uno/pins_arduino.h similarity index 95% rename from variants/standart/pins_arduino.h rename to variants/elbear_ace_uno/pins_arduino.h index 404f7da..9e02c16 100644 --- a/variants/standart/pins_arduino.h +++ b/variants/elbear_ace_uno/pins_arduino.h @@ -65,6 +65,8 @@ uint16_t pinCommonQty(void); volatile uint32_t* portOutputRegister(GPIO_TypeDef* GPIO_x); // the function returns a reference to the STATE address of the GPIO register volatile uint32_t* portInputRegister(GPIO_TypeDef* GPIO_x); +// the function initializes additional MCU pins depending on the specified pin number +void additionalPinsInit(uint32_t PinNumber); // UART // available uarts quantity @@ -109,7 +111,8 @@ static const uint8_t SCL = PIN_WIRE_SCL; #define WIRE_FREQ_1000K 1000000 // interrupts -extern uint8_t interruptInfo[EXTERNAL_NUM_INTERRUPTS][3]; +#define EXTERNAL_INTERRUPTS_QTY 7 +extern uint8_t interruptInfo[EXTERNAL_INTERRUPTS_QTY][3]; // determines the board pin number by interrupt number #define interruptToDigitalPin(interruptNum) (interruptInfo[interruptNum][0]) // determines gpio interrupt line by interrupt number diff --git a/variants/standart/variant.c b/variants/elbear_ace_uno/variant.c similarity index 90% rename from variants/standart/variant.c rename to variants/elbear_ace_uno/variant.c index a54ee4d..1d5e306 100644 --- a/variants/standart/variant.c +++ b/variants/elbear_ace_uno/variant.c @@ -100,6 +100,23 @@ volatile uint32_t* portInputRegister(GPIO_TypeDef* GPIO_x) return &GPIO_x->STATE; } +// the function initializes additional MCU pins depending on the specified pin number +void additionalPinsInit(uint32_t PinNumber) +{ + // if we use pin A5, we need to set SELA45 (1.15) to 1 to switch the output from A4 to A5 + if (PinNumber == A5) + { + HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_15, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA); + HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_15, GPIO_PIN_HIGH); + } + else if(PinNumber == A4) + { + // return the switch to A4 in case A5 was previously read + HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_15, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA); + HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_15, GPIO_PIN_LOW); + } +} + // ---------------------- ADC ---------------------- // // determines the ADC channel number by the board pin number uint32_t analogInputToChannelNumber(uint32_t PinNumber) @@ -207,7 +224,7 @@ HAL_TIMER32_CHANNEL_IndexTypeDef pwmPinToTimerChannel(uint32_t digPinNumber) // ---------------------- interrupts ---------------------- // // interrupt table is stored in ram to improve performance // index = interrupt number. In each row {digitalPinNumber, IntLineValue, IntMuxValue} -uint8_t interruptInfo[EXTERNAL_NUM_INTERRUPTS][3] = +uint8_t interruptInfo[EXTERNAL_INTERRUPTS_QTY][3] = { { 2, GPIO_LINE_2, GPIO_MUX_LINE_2_PORT0_10}, // INT0 { 3, GPIO_LINE_0, GPIO_MUX_LINE_0_PORT0_0}, // INT1 @@ -220,7 +237,7 @@ uint8_t interruptInfo[EXTERNAL_NUM_INTERRUPTS][3] = int8_t digitalPinToGpioIntMux(uint8_t digPinNumber) { - for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++) + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { if (interruptInfo[i][0] == digPinNumber) return interruptInfo[i][2]; @@ -229,7 +246,7 @@ int8_t digitalPinToGpioIntMux(uint8_t digPinNumber) } int8_t digitalPinToGpioIntLine(uint8_t digPinNumber) { - for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++) + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { if (interruptInfo[i][0] == digPinNumber) return interruptInfo[i][1]; @@ -239,7 +256,7 @@ int8_t digitalPinToGpioIntLine(uint8_t digPinNumber) int8_t gpioIntLineToInterrupt(uint32_t gpioIntLine) { - for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++) + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { if (interruptInfo[i][1] == gpioIntLine) return i; @@ -249,7 +266,7 @@ int8_t gpioIntLineToInterrupt(uint32_t gpioIntLine) int8_t digitalPinToInterrupt(uint32_t digPinNumber) { - for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++) + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { if (interruptInfo[i][0] == digPinNumber) return i; diff --git a/variants/start/pins_arduino.h b/variants/start/pins_arduino.h new file mode 100644 index 0000000..4669d9f --- /dev/null +++ b/variants/start/pins_arduino.h @@ -0,0 +1,184 @@ +/* + pins_arduino.h - Pin definition functions for Arduino + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2007 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA +*/ + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include "wiring_constants.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mik32_hal_gpio.h" +#include "mik32_hal_timer32.h" + +#define PORT_PIN_MASK 0xF + +// digital pins +#define P0_0 0 +#define P0_1 1 +#define P0_2 2 +#define P0_3 3 +#define P0_4 4 +#define P0_5 5 +#define P0_6 6 +#define P0_7 7 +#define P0_8 8 +#define P0_9 9 +#define P0_10 10 +#define P0_11 11 +#define P0_12 12 +#define P0_13 13 +#define P0_14 14 +#define P0_15 15 +#define P1_0 16 +#define P1_1 17 +#define P1_2 18 +#define P1_3 19 +#define P1_4 20 +#define P1_5 21 +#define P1_6 22 +#define P1_7 23 +#define P1_8 24 +#define P1_9 25 +#define P1_10 26 +#define P1_11 27 +#define P1_12 28 +#define P1_13 29 +#define P1_14 30 +#define P1_15 31 +#define P2_0 32 +#define P2_1 33 +#define P2_2 34 +#define P2_3 35 +#define P2_4 36 +#define P2_5 37 +#define P2_6 38 +#define P2_7 39 + +// analog pins +#define PIN_A0 (P1_5) +#define PIN_A1 (P1_7) +#define PIN_A2 (P0_2) +#define PIN_A3 (P0_4) +#define PIN_A4 (P0_7) +#define PIN_A5 (P0_9) +#define PIN_A6 (P0_11) +#define PIN_A7 (P0_13) + +static const uint8_t A0 = PIN_A0; +static const uint8_t A1 = PIN_A1; +static const uint8_t A2 = PIN_A2; +static const uint8_t A3 = PIN_A3; +static const uint8_t A4 = PIN_A4; +static const uint8_t A5 = PIN_A5; +static const uint8_t A6 = PIN_A6; +static const uint8_t A7 = PIN_A7; + + +// User led and button +#define LED_BUILTIN0 (P0_3) +#define LED_BUILTIN1 (P1_3) +#define LED_BUILTIN LED_BUILTIN0 +#define BTN_BUILTIN (P0_8) + +// determines the address of the port by the board pin number to which this pin belongs on the MCU +GPIO_TypeDef* digitalPinToPort(uint32_t digPinNumber); +// determines the pin address inside the port by the board pin number +HAL_PinsTypeDef digitalPinToBitMask(uint32_t digPinNumber); +// total number of pins available for initialization +uint16_t pinCommonQty(void); +// the function returns a reference to the OUTPUT address of the GPIO register +volatile uint32_t* portOutputRegister(GPIO_TypeDef* GPIO_x); +// the function returns a reference to the STATE address of the GPIO register +volatile uint32_t* portInputRegister(GPIO_TypeDef* GPIO_x); +// the function is needed for compatibility with other boards +static inline void additionalPinsInit(uint32_t PinNumber) {} + +// UART +// available uarts quantity +#define SERIAL_PORT_QTY 2 + +// ADC +#define MCU_ADC_RESOLUTION 12 // bits +// determines the ADC channel number by the board pin number +uint32_t analogInputToChannelNumber(uint32_t PinNumber); + +// PWM +bool digitalPinHasPWM(uint8_t p); +bool digitalPinPwmIsOn(uint8_t digitalPin); // use only if digitalPinHasPWM() == true +// determines which timer the pin belongs to +TIMER32_TypeDef* pwmPinToTimer(uint32_t digPinNumber); +// determines which timer channel the pin belongs to +HAL_TIMER32_CHANNEL_IndexTypeDef pwmPinToTimerChannel(uint32_t digPinNumber); + +// SPI +#define PIN_SPI_SS (P1_3) +#define PIN_SPI_MOSI (P1_1) +#define PIN_SPI_MISO (P1_0) +#define PIN_SPI_SCK (P1_2) +static const uint8_t SS = PIN_SPI_SS; +static const uint8_t MOSI = PIN_SPI_MOSI; +static const uint8_t MISO = PIN_SPI_MISO; +static const uint8_t SCK = PIN_SPI_SCK; +// functions is needed for compatibility with other boards +static inline void spi_onBegin(void) {} +static inline void spi_onEnd(void) {} + +// I2C +#define PIN_WIRE_SDA (P1_12) +#define PIN_WIRE_SCL (P1_13) +#define I2C_NUM (1) // i2c number 1 +static const uint8_t SDA = PIN_WIRE_SDA; +static const uint8_t SCL = PIN_WIRE_SCL; +// available frequencies +#define WIRE_FREQ_100K 100000 +#define WIRE_FREQ_400K 400000 +#define WIRE_FREQ_1000K 1000000 + +// interrupts +#define EXTERNAL_INTERRUPTS_QTY 8 +extern uint8_t interruptInfo[EXTERNAL_INTERRUPTS_QTY][3]; +// determines the board pin number by interrupt number +#define interruptToDigitalPin(interruptNum) (interruptInfo[interruptNum][0]) +// determines gpio interrupt line by interrupt number +#define interruptToGpioIntLine(interruptNum) ((uint8_t)interruptInfo[interruptNum][1]) +// determines gpio interrupt mux by interrupt number +#define interruptToGpioIntMux(interruptNum) ((uint8_t)interruptInfo[interruptNum][2]) +// determines interrupt number by the board pin number +int8_t digitalPinToInterrupt(uint32_t digPinNumber); +// determines interrupt number by the gpio interrupt line +int8_t gpioIntLineToInterrupt(uint32_t gpioIntLine); +// determines gpio interrupt mux by the board pin number +int8_t digitalPinToGpioIntMux(uint8_t digPinNumber); +// determines gpio interrupt line by the board pin number +int8_t digitalPinToGpioIntLine(uint8_t digPinNumber); + + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/variants/start/variant.c b/variants/start/variant.c new file mode 100644 index 0000000..6d8ece7 --- /dev/null +++ b/variants/start/variant.c @@ -0,0 +1,223 @@ +/** + ******************************************************************************* + * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. + * All rights reserved. + * + * This software component is licensed by WCH under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + */ + +#include "pins_arduino.h" +#include "mik32_hal_adc.h" +#include "wiring_analog.h" +#include "wiring_LL.h" + +/** + * @brief Determines the address of the port by the board pin number to which this pin belongs on the MCU + * @return The address of the port corresponding to the board pin number. Can return 0 if the pin not exists + */ + +GPIO_TypeDef *digitalPinToPort(uint32_t digitalPinNumber) +{ + if (digitalPinNumber < 16u) + { + return GPIO_0; + } + else if ((digitalPinNumber >= 16u) && (digitalPinNumber < 32u)) + { + return GPIO_1; + } + else if ((digitalPinNumber >= 32u) && (digitalPinNumber < 40u)) + { + return GPIO_2; + } + else + { + return NULL; + } +} + +// determines the pin address inside the port by the board pin number +HAL_PinsTypeDef digitalPinToBitMask(uint32_t digitalPinNumber) +{ + return 1 << (digitalPinNumber & 0xF); +} + +uint16_t pinCommonQty(void) +{ + return (uint16_t)40; +} + +// the function returns a reference to the OUTPUT address of the GPIO register +volatile uint32_t *portOutputRegister(GPIO_TypeDef *GPIO_x) +{ + return &GPIO_x->OUTPUT_; +} + +// the function returns a reference to the STATE address of the GPIO register +volatile uint32_t *portInputRegister(GPIO_TypeDef *GPIO_x) +{ + return &GPIO_x->STATE; +} + +// ---------------------- ADC ---------------------- // +// determines the ADC channel number by the board pin number +uint32_t analogInputToChannelNumber(uint32_t PinNumber) +{ + uint32_t adcChannel = 0; + + switch (PinNumber) + { + case PIN_A0: + adcChannel = ADC_CHANNEL0; + break; + case PIN_A1: + adcChannel = ADC_CHANNEL1; + break; + case PIN_A2: + adcChannel = ADC_CHANNEL2; + break; + case PIN_A3: + adcChannel = ADC_CHANNEL3; + break; + case PIN_A4: + adcChannel = ADC_CHANNEL4; + break; + case PIN_A5: + adcChannel = ADC_CHANNEL5; + break; + case PIN_A6: + adcChannel = ADC_CHANNEL6; + break; + case PIN_A7: + adcChannel = ADC_CHANNEL7; + break; + default: + adcChannel = NC; + } + return adcChannel; +} + +// ---------------------- PWM ---------------------- // +// use only if digitalPinHasPWM() == true +#define PWM_PIN_TO_PORT_NUMBER(pin) (((pin) & 16) ? 1 : 0) +// use only if digitalPinHasPWM() == true +static inline uint8_t pwmPinToGpioPinShift(uint8_t digitalPin) +{ + return digitalPin & 3; +} +// use only if digitalPinHasPWM() == true +// return true if digitalPin configured as pwm +bool digitalPinPwmIsOn(uint8_t digitalPin) +{ + uint8_t config = 0; + uint8_t pinShift = pwmPinToGpioPinShift(digitalPin); + + if (PWM_PIN_TO_PORT_NUMBER(digitalPin) == 0) + config = PIN_GET_PAD_CONFIG(PORT_0_CFG, pinShift); + else + config = PIN_GET_PAD_CONFIG(PORT_1_CFG, pinShift); + + if (config == 2) + return true; + else + return false; +} + +bool digitalPinHasPWM(uint8_t p) +{ + return (p < 32) && ((p & 0xF) < 4); +} + +// function is used only if digitalPinHasPWM() is true +TIMER32_TypeDef *pwmPinToTimer(uint32_t digPinNumber) +{ + if (digPinNumber < 16) + { + return TIMER32_1; + } + else if ((digPinNumber >= 16) && (digPinNumber < 32)) + { + return TIMER32_2; + } + else + { + return NULL; + } +} + +// function is used only if digitalPinHasPWM() is true +HAL_TIMER32_CHANNEL_IndexTypeDef pwmPinToTimerChannel(uint32_t digPinNumber) +{ + switch (digPinNumber & 0x3) + { + case 0: + return TIMER32_CHANNEL_0; + case 1: + return TIMER32_CHANNEL_1; + case 2: + return TIMER32_CHANNEL_2; + case 3: + return TIMER32_CHANNEL_3; + default: + return 255; + } +} + +// ---------------------- interrupts ---------------------- // +// interrupt table is stored in ram to improve performance +// index = interrupt number. In each row {digitalPinNumber, IntLineValue, IntMuxValue} +uint8_t interruptInfo[EXTERNAL_INTERRUPTS_QTY][3] = +{ + {BTN_BUILTIN, GPIO_LINE_0, GPIO_MUX_LINE_0_PORT0_8}, // INT0 + {P1_9, GPIO_LINE_1, GPIO_MUX_LINE_1_PORT1_9}, // INT1 + {P0_10, GPIO_LINE_2, GPIO_MUX_LINE_2_PORT0_10}, // INT2 + {P1_15, GPIO_LINE_3, GPIO_MUX_LINE_3_PORT1_15}, // INT3 + {P0_12, GPIO_LINE_4, GPIO_MUX_LINE_4_PORT0_12}, // INT4 + {P0_13, GPIO_LINE_5, GPIO_MUX_LINE_5_PORT0_13}, // INT5 + {P0_14, GPIO_LINE_6, GPIO_MUX_LINE_6_PORT0_14}, // INT6 + {P0_15, GPIO_LINE_7, GPIO_MUX_LINE_7_PORT0_15}, // INT7 +}; + +int8_t digitalPinToGpioIntMux(uint8_t digPinNumber) +{ + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) + { + if (interruptInfo[i][0] == digPinNumber) + return interruptInfo[i][2]; + } + return NOT_AN_INTERRUPT; +} +int8_t digitalPinToGpioIntLine(uint8_t digPinNumber) +{ + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) + { + if (interruptInfo[i][0] == digPinNumber) + return interruptInfo[i][1]; + } + return NOT_AN_INTERRUPT; +} + +int8_t gpioIntLineToInterrupt(uint32_t gpioIntLine) +{ + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) + { + if (interruptInfo[i][1] == gpioIntLine) + return i; + } + return NOT_AN_INTERRUPT; +} + +int8_t digitalPinToInterrupt(uint32_t digPinNumber) +{ + for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) + { + if (interruptInfo[i][0] == digPinNumber) + return i; + } + return NOT_AN_INTERRUPT; +} \ No newline at end of file