добавлена поддержка платы Start-MIK32

This commit is contained in:
klassents 2024-12-19 14:23:24 +07:00 committed by KLASSENTS
parent 8c82685f37
commit f06650400b
46 changed files with 1813 additions and 163 deletions

View File

@ -1,52 +1,43 @@
# elbear_arduino_bsp # elbear_arduino_bsp
Пакет поддержки платы Elbear Ace-Uno на базе микроконтроллера MIK32 Амур в среде программирования Arduino IDE. Пакет поддержки плат на базе микроконтроллера MIK32 Амур в среде программирования Arduino IDE.
## Установка пакета в ArduinoIDE ## Установка пакета в ArduinoIDE
Для установки пакета в параметрах ArduinoIDE необходимо добавить ссылку `https://elron.tech/files/package_elbear_beta_index.json` в поле "Дополнительные ссылки для Менеджера плат". Для установки пакета в параметрах 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 на платах, входящих в состав пакета, невозможно управлять притяжками цифрового вывода, настроенного на вход, с помощью функции `void digitalWrite(uint32_t PinNumber, uint32_t Val)`. Для включения притяжки к питанию необходимо воспользоваться функцией `void pinMode(PinNumber, INPUT_PULLUP)`.
В отличие от стандартного функционала Arduino, на плате Elbear Ace-Uno невозможно управлять притяжками цифрового вывода, настроенного на вход, с помощью функции `void digitalWrite(uint32_t PinNumber, uint32_t Val)`. Для включения притяжки к питанию необходимо воспользоваться функцией `void pinMode(PinNumber, INPUT_PULLUP)`.
Для инвертирования состояния цифровых выводов доступна функция `void digitalToggle(uint32_t PinNumber)`. Для инвертирования состояния цифровых выводов доступна функция `void digitalToggle(uint32_t PinNumber)`.
### Аналоговые выводы ### Аналоговые выводы
#### АЦП #### АЦП
Встроенный в MIK32 АЦП обладает разрешением 12 бит, однако по умолчанию в Arduino IDE применяется разрешение 10 бит. С помощью функции `void analogReadResolution(uint8_t resolution)` можно изменять разрешение в диапазоне от 1 до 32 бит. Встроенный в MIK32 АЦП обладает разрешением 12 бит, однако по умолчанию в Arduino IDE применяется разрешение 10 бит. С помощью функции `void analogReadResolution(uint8_t resolution)` можно изменять разрешение в диапазоне от 1 до 32 бит.
Функция `uint32_t analogRead(uint32_t PinNumber)` возвращает результаты измерения после усреднения по 10 значениям. Функция `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 МГц. По умолчанию частота сформированного ШИМ-сигнала составляет 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 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)`: Платы, входящих в состав пакета, позволяют использовать прерывания, настраиваемые функцией `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|
Для получения номера прерывания по номеру вывода существует функция `int8_t digitalPinToInterrupt(uint32_t digPinNumber)`. Для получения номера прерывания по номеру вывода существует функция `int8_t digitalPinToInterrupt(uint32_t digPinNumber)`.
В микроконтроллере MIK32 предусмотрен всего один вектор прерывания. Когда срабатывает прерывание от любого источника, общая функция-обработчик последовательно проверяет все возможные источники и, при необходимости, вызывает соответствующие обработчики конкретных модулей. Поэтому важно, чтобы функции, вызываемые при прерываниях, были небольшими и обеспечивали максимально быстрое завершение обработки. Это позволит избежать задержек и снизит риск пропуска последующих прерываний. В микроконтроллере MIK32 предусмотрен всего один вектор прерывания. Когда срабатывает прерывание от любого источника, общая функция-обработчик последовательно проверяет все возможные источники и, при необходимости, вызывает соответствующие обработчики конкретных модулей. Поэтому важно, чтобы функции, вызываемые при прерываниях, были небольшими и обеспечивали максимально быстрое завершение обработки. Это позволит избежать задержек и снизит риск пропуска последующих прерываний.
Общая функция-обработчик прерываний располагается в RAM памяти. Это позволяет устранить задержки, связанные с кэшированием при работе из FLASH памяти. Обработчики прерываний, назначаемые на цифровые выводы с помощью функции `void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)`, и обработчик прерывания для функции `tone()` так же располагаются в памяти RAM. Общая функция-обработчик прерываний располагается в RAM памяти. Это позволяет устранить задержки, связанные с кэшированием при работе из FLASH памяти. Обработчики прерываний, назначаемые на цифровые выводы с помощью функции `void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)`, и обработчик прерывания для функции `tone()` так же располагаются в памяти RAM.
Глобальное разрешение прерываний активируется после завершения функции `setup()`. Если необходимо использовать прерывания внутри самой функции `setup()`, их можно включить вручную, вызвав функцию `interrupts()` перед вызовом функций, работающих с прерываниями. Прерывания используются для приема данных модулями `Serial`, `Wire`, для работы библиотеки `Servo`, функцией `tone()`.
### Serial ### Serial
Для работы доступно два последовательных интерфейса. Нулевой интерфейс доступен на выводах D0, D1, для работы с ним используется экземпляр класса под названием `Serial`. Нулевой интерфейс используется для вывода информации в Монитор порта в Arduino IDE. Для работы доступно два последовательных интерфейса. Нулевой интерфейс используется экземпляром класса `Serial`. Информации в Монитор порта в Arduino IDE поступает через него. Первый интерфейс используется экземпляром класса `Serial1`. Выводы, на которых доступны указанные интерфейсы, перечислены в описании отдельных плат.
Первый интерфейс доступен на выводах D7, D8, используемый экземпляр класса - `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 бита. Доступны следующие макросы для настройки режима работы каждого интерфейса в функции `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) )`, выполняются в прерывании| |[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| |[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()` перед началом работы с памятью| |[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(+)| |[RF24](https://docs.arduino.cc/libraries/rf24/)|Драйвер радиоустройств, библиотека для работы с микросхемами nRF24L01(+)|
|[Bonezegei_ULN2003_Stepper](https://docs.arduino.cc/libraries/bonezegei_uln2003_stepper/)|Библиотека драйвера шагового двигателя, управляемого микросхемой ULN2003| |[Bonezegei_ULN2003_Stepper](https://docs.arduino.cc/libraries/bonezegei_uln2003_stepper/)|Библиотека драйвера шагового двигателя, управляемого микросхемой ULN2003|
|[Ethernet](https://docs.arduino.cc/libraries/ethernet/)|Библиотека, позволяющая использовать Ethernet шилд для подключения к Интернету| |[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 ACE-UNO](https://elron.tech/support/#elbear)
* [Телеграмм-канал компании (обновления по проекту ELBEAR и другим)](https://t.me/elrontech) * [Телеграмм-канал компании (обновления по проекту 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). При возникновении вопросов или выявлении проблем можно оставить заявку [здесь](https://gitflic.ru/project/elron-tech/elbear_arduino_bsp/issue).

View File

@ -9,18 +9,20 @@ aceUno8Mb.upload.tool=elbear_uploader
aceUno8Mb.upload.protocol=elbear_uploader aceUno8Mb.upload.protocol=elbear_uploader
aceUno8Mb.upload.maximum_size=8388608 aceUno8Mb.upload.maximum_size=8388608
aceUno8Mb.upload.maximum_data_size=16384 aceUno8Mb.upload.maximum_data_size=16384
aceUno8Mb.upload.speed=230400
# tool for bootloader update # tool for bootloader update
aceUno8Mb.bootloader.tool=mik32_upload aceUno8Mb.bootloader.tool=mik32_upload
aceUno8Mb.bootloader.tool.default=mik32_upload aceUno8Mb.bootloader.tool.default=mik32_upload
aceUno8Mb.bootloader.file=ace-uno/bootloader.hex aceUno8Mb.bootloader.file=ace-uno/bootloader.hex
aceUno8Mb.bootloader.interface=ftdi/mikron-link.cfg
# build options # build options
aceUno8Mb.build.mcu=MIK32_Amur aceUno8Mb.build.mcu=MIK32_Amur
aceUno8Mb.build.f_cpu=32000000UL aceUno8Mb.build.f_cpu=32000000UL
aceUno8Mb.build.board=ACE_UNO_8MB aceUno8Mb.build.board=ACE_UNO_8MB
aceUno8Mb.build.core=arduino aceUno8Mb.build.core=arduino
aceUno8Mb.build.variant=standart aceUno8Mb.build.variant=elbear_ace_uno
aceUno8Mb.build.extra_flags= aceUno8Mb.build.extra_flags=
aceUno8Mb.build.flags= aceUno8Mb.build.flags=
@ -33,18 +35,20 @@ aceUno16Mb.upload.tool=elbear_uploader
aceUno16Mb.upload.protocol=elbear_uploader aceUno16Mb.upload.protocol=elbear_uploader
aceUno16Mb.upload.maximum_size=16777216 aceUno16Mb.upload.maximum_size=16777216
aceUno16Mb.upload.maximum_data_size=16384 aceUno16Mb.upload.maximum_data_size=16384
aceUno16Mb.upload.speed=230400
# tool for bootloader update # tool for bootloader update
aceUno16Mb.bootloader.tool=mik32_upload aceUno16Mb.bootloader.tool=mik32_upload
aceUno16Mb.bootloader.tool.default=mik32_upload aceUno16Mb.bootloader.tool.default=mik32_upload
aceUno16Mb.bootloader.file=ace-uno/bootloader.hex aceUno16Mb.bootloader.file=ace-uno/bootloader.hex
aceUno16Mb.bootloader.interface=ftdi/mikron-link.cfg
# build options # build options
aceUno16Mb.build.mcu=MIK32_Amur aceUno16Mb.build.mcu=MIK32_Amur
aceUno16Mb.build.f_cpu=32000000UL aceUno16Mb.build.f_cpu=32000000UL
aceUno16Mb.build.board=ACE_UNO_16MB aceUno16Mb.build.board=ACE_UNO_16MB
aceUno16Mb.build.core=arduino aceUno16Mb.build.core=arduino
aceUno16Mb.build.variant=standart aceUno16Mb.build.variant=elbear_ace_uno
aceUno16Mb.build.extra_flags= aceUno16Mb.build.extra_flags=
aceUno16Mb.build.flags= aceUno16Mb.build.flags=
@ -57,17 +61,45 @@ aceUno32Mb.upload.tool=elbear_uploader
aceUno32Mb.upload.protocol=elbear_uploader aceUno32Mb.upload.protocol=elbear_uploader
aceUno32Mb.upload.maximum_size=33554432 aceUno32Mb.upload.maximum_size=33554432
aceUno32Mb.upload.maximum_data_size=16384 aceUno32Mb.upload.maximum_data_size=16384
aceUno32Mb.upload.speed=230400
# tool for bootloader update # tool for bootloader update
aceUno32Mb.bootloader.tool=mik32_upload aceUno32Mb.bootloader.tool=mik32_upload
aceUno32Mb.bootloader.tool.default=mik32_upload aceUno32Mb.bootloader.tool.default=mik32_upload
aceUno32Mb.bootloader.file=ace-uno/bootloader.hex aceUno32Mb.bootloader.file=ace-uno/bootloader.hex
aceUno32Mb.bootloader.interface=ftdi/mikron-link.cfg
# build options # build options
aceUno32Mb.build.mcu=MIK32_Amur aceUno32Mb.build.mcu=MIK32_Amur
aceUno32Mb.build.f_cpu=32000000UL aceUno32Mb.build.f_cpu=32000000UL
aceUno32Mb.build.board=ACE_UNO_32MB aceUno32Mb.build.board=ACE_UNO_32MB
aceUno32Mb.build.core=arduino aceUno32Mb.build.core=arduino
aceUno32Mb.build.variant=standart aceUno32Mb.build.variant=elbear_ace_uno
aceUno32Mb.build.extra_flags= aceUno32Mb.build.extra_flags=
aceUno32Mb.build.flags= 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=

View File

@ -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

View File

@ -27,24 +27,24 @@ void noInterrupts(void)
} }
// we can provide no more than 8 interrupts on gpio at the same time // 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, nothing,
#endif #endif
#if EXTERNAL_NUM_INTERRUPTS > 6 #if EXTERNAL_INTERRUPTS_QTY > 6
nothing, nothing,
#endif #endif
#if EXTERNAL_NUM_INTERRUPTS > 5 #if EXTERNAL_INTERRUPTS_QTY > 5
nothing, nothing,
#endif #endif
#if EXTERNAL_NUM_INTERRUPTS > 4 #if EXTERNAL_INTERRUPTS_QTY > 4
nothing, nothing,
#endif #endif
#if EXTERNAL_NUM_INTERRUPTS > 3 #if EXTERNAL_INTERRUPTS_QTY > 3
nothing, nothing,
#endif #endif
#if EXTERNAL_NUM_INTERRUPTS > 2 #if EXTERNAL_INTERRUPTS_QTY > 2
nothing, nothing,
#endif #endif
nothing, nothing,
@ -54,7 +54,7 @@ static volatile voidFuncPtr intFunc[EXTERNAL_NUM_INTERRUPTS] =
void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode)
{ {
// if the interrupt number does not exceed the total number // 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 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) void detachInterrupt(uint8_t interruptNum)
{ {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) if(interruptNum < EXTERNAL_INTERRUPTS_QTY)
{ {
// disable the interrupt in line // disable the interrupt in line
HAL_GPIO_DeInitInterruptLine(interruptToGpioIntLine(interruptNum)); HAL_GPIO_DeInitInterruptLine(interruptToGpioIntLine(interruptNum));
@ -98,7 +98,7 @@ void detachInterrupt(uint8_t interruptNum)
// disable single interrupt // disable single interrupt
void disableInterrupt(uint8_t interruptNum) void disableInterrupt(uint8_t interruptNum)
{ {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) if(interruptNum < EXTERNAL_INTERRUPTS_QTY)
// disable gpio interrupt line // disable gpio interrupt line
GPIO_IRQ_LINE_DISABLE(interruptToGpioIntLine(interruptNum)); GPIO_IRQ_LINE_DISABLE(interruptToGpioIntLine(interruptNum));
} }
@ -106,7 +106,7 @@ void disableInterrupt(uint8_t interruptNum)
// enable single interrupt // enable single interrupt
void enableInterrupt(uint8_t interruptNum) void enableInterrupt(uint8_t interruptNum)
{ {
if(interruptNum < EXTERNAL_NUM_INTERRUPTS) if(interruptNum < EXTERNAL_INTERRUPTS_QTY)
// enable gpio interrupt line // enable gpio interrupt line
GPIO_IRQ_LINE_ENABLE(interruptToGpioIntLine(interruptNum)); 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) 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 // 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))) if (GPIO_IRQ_LINE_STATE(interruptToGpioIntLine(i)))
intFunc[i](); intFunc[i]();

View File

@ -11,12 +11,37 @@ void __attribute__((weak)) wire_interrupt_handler(void)
} }
void __attribute__((weak)) servo_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) void __attribute__((noinline, section(".ram_text"), optimize("O3"))) trap_handler (void)
{ {
// custom interrupt
ISR();
// gpio interrupt // gpio interrupt
if (EPIC_CHECK_GPIO_IRQ()) if (EPIC_CHECK_GPIO_IRQ())
gpio_interrupt_handler(); gpio_interrupt_handler();

View File

@ -42,18 +42,8 @@ uint32_t analogRead(uint32_t PinNumber)
uint32_t adcChannel = analogInputToChannelNumber(PinNumber); uint32_t adcChannel = analogInputToChannelNumber(PinNumber);
if (adcChannel != NC) 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 additionalPinsInit(PinNumber);
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);
}
// init channel // init channel
hadc.Init.Sel = adcChannel; hadc.Init.Sel = adcChannel;
HAL_ADC_Init(&hadc); HAL_ADC_Init(&hadc);
@ -147,8 +137,6 @@ void analogWrite(uint32_t PinNumber, uint32_t writeVal)
HAL_Timer32_Start(&htimer32); HAL_Timer32_Start(&htimer32);
pwmIsInited++; // increase inited channels qty 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 else
ErrorMsgHandler("analogWrite(): invalid pwm pin number"); ErrorMsgHandler("analogWrite(): invalid pwm pin number");
} }

View File

@ -40,59 +40,30 @@ void pinMode(uint32_t PinNumber, uint32_t PinMode)
// if the pin can use PWM, disable PWM // if the pin can use PWM, disable PWM
analogWriteStop(PinNumber); analogWriteStop(PinNumber);
// adjusting pins // determine the port and the pin number in the port
if (PinNumber == BTN_BUILTIN) 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 case INPUT:
GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT;
GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT; GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE;
GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE; break;
HAL_GPIO_Init(GPIO_2, &GPIO_InitStruct); case INPUT_PULLUP:
} GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_INPUT;
else // other pins GPIO_InitStruct.Pull = HAL_GPIO_PULL_UP;
{ break;
// determine the port and the pin number in the port case OUTPUT:
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;
GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_OUTPUT; GPIO_InitStruct.Mode = HAL_GPIO_MODE_GPIO_OUTPUT;
GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE; GPIO_InitStruct.Pull = HAL_GPIO_PULL_NONE;
HAL_GPIO_Init(GPIO_1, &GPIO_InitStruct); break;
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);
}
} }
// init pin
HAL_GPIO_Init(GPIO_addr, &GPIO_InitStruct);
additionalPinsInit(PinNumber);
} }
// write pin // write pin
@ -108,11 +79,7 @@ void digitalWrite(uint32_t PinNumber, uint32_t Val)
// if the pin can use PWM, disable PWM // if the pin can use PWM, disable PWM
analogWriteStop(PinNumber); analogWriteStop(PinNumber);
// just in case let's move on to the hal library state terms HAL_GPIO_WritePin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber), (Val == HIGH) ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
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);
} }
// read pin // read pin
@ -128,8 +95,7 @@ int digitalRead(uint32_t PinNumber)
analogWriteStop(PinNumber); analogWriteStop(PinNumber);
GPIO_PinState pinState = HAL_GPIO_ReadPin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber)); GPIO_PinState pinState = HAL_GPIO_ReadPin(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber));
int state = (pinState == GPIO_PIN_LOW) ? LOW : HIGH; return (pinState == GPIO_PIN_LOW) ? LOW : HIGH;
return state;
} }
// toggle pin // toggle pin
@ -144,8 +110,7 @@ void digitalToggle(uint32_t PinNumber)
// if the pin can use PWM, disable PWM // if the pin can use PWM, disable PWM
analogWriteStop(PinNumber); 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 #ifdef __cplusplus

View File

@ -11,7 +11,7 @@ extern "C"{
#endif #endif
// available interrupts number // available interrupts number
#define EXTERNAL_NUM_INTERRUPTS 7 #define EXTERNAL_NUM_INTERRUPTS EXTERNAL_INTERRUPTS_QTY
typedef void (*voidFuncPtr)(void); typedef void (*voidFuncPtr)(void);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -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`.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 49 KiB

View File

@ -3,38 +3,41 @@
2. Откройте меню `Файл -> Параметры`. 2. Откройте меню `Файл -> Параметры`.
3. Вставьте данную ссылку в поле "Дополнительные ссылки для Менеджера плат": 3. Вставьте данную ссылку в поле "Дополнительные ссылки для Менеджера плат":
`https://elron.tech/files/package_elbear_beta_index.json` `https://elron.tech/files/package_elbear_beta_index.json`
![Add_board](docs/Add_board.PNG) ![Add_board](Add_board.PNG)
4. Откройте меню `Инструменты -> Плата -> Менеджер плат...`. 4. Откройте меню `Инструменты -> Плата -> Менеджер плат...`.
5. В поиске найдите плату `Elbear Ace-Uno`, выберите нужную версию и нажмите кнопку `Установить`. 5. В поиске найдите пакет `MIK32 Boards (Arduino BSP by Elron)`, выберите нужную версию пакета и нажмите кнопку `Установить`.
![Install_board](docs/Install_board.PNG) ![Install_board](Install_board.PNG)
6. Процесс установки может занять некоторое время. Результаты установки отобразятся в поле `Вывод`, а так же во всплывающих уведомлениях. 6. Процесс установки может занять некоторое время. Результаты установки отобразятся в поле `Вывод`, а так же во всплывающих уведомлениях.
![Installation_process](docs/Installation_process.PNG) ![Installation_process](Installation_process.PNG)
Для загрузки скетчей по USB в ArduinoIDE необходимо, чтобы на плате Elbear Ace-Uno был специальный начальный загрузчик ([elbear_fw_bootloader](https://gitflic.ru/project/elron-tech/elbear_fw_bootloader)). Если он уже есть на плате, можно сразу переходить к работе. Если загрузчика еще нет или необходимо обновить его на плате, ниже описан процесс загрузки. Актуальная версия начального загрузчика входит в состав пакета поддержки, отдельно скачивать его не нужно.
Платы ревизии 1.1.0 готовы к использованию в ArduinoIDE из коробки, так как поставляются с предварительно записанным начальным загрузчиком.
## Запись начального загрузчика через ArduinoIDE ## Запись начального загрузчика через 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`. 2. В ArduinoIDE выберите программатор: `Инструменты -> Программатор -> mik32 uploader`.
3. Для записи начального загрузчика выберите `Инструменты -> Записать Загрузчик`. 3. Для записи начального загрузчика выберите `Инструменты -> Записать Загрузчик`.
![Bootloader](docs/Bootloader.png) ![Bootloader](Bootloader.png)
4. При возникновении проблем с загрузкой ознакомьтесь с разделом `Настройка программатора` в [инструкции](https://elron.tech/wp-content/uploads/2024/05/instrukcija-po-pervomu-zapusku.pdf) по первому запуску платы ELBEAR ACE-UNO. 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. Теперь можно загружать скетчи в плату по USB.
## Начало работы ## Начало работы
1. Подключите плату к ПК по USB. 1. Подключите плату к ПК по USB.
2. Откройте ArduinoIDE и загрузите необходимый скетч. Для начала работы можно воспользоваться готовыми примерами, например - `Файл -> Примеры -> 01.Basics -> Blink`. 2. Откройте ArduinoIDE и загрузите необходимый скетч. Для начала работы можно воспользоваться готовыми примерами, например - `Файл -> Примеры -> 01.Basics -> Blink`.
![Blink_example](docs/Blink_example.png) ![Blink_example](Blink_example.png)
3. Выберите активную плату - `Инструменты -> Плата`. 3. Выберите активную плату - `Инструменты -> Плата`.
![Set_board](docs/Set_board.png) ![Set_board](Set_board.png)
4. Выберите используемый COM порт - `Инструменты -> Порт`. 4. Выберите используемый COM порт - `Инструменты -> Порт`.
![Set_port](docs/Set_port.png) ![Set_port](Set_port.png)
Выбранные плата и порт в ArduinoIDE должны отображаться следующим образом: Выбранные плата и порт в ArduinoIDE должны отображаться следующим образом:
![Selected_board_port](docs/Selected_board_port.png) ![Selected_board_port](Selected_board_port.png)
5. Проверьте скетч, нажав соответствующую кнопку. 5. Проверьте скетч, нажав соответствующую кнопку.
![Build_project](docs/Build_project.png) ![Build_project](Build_project.png)
6. Загрузите полученную прошивку на плату. 6. Загрузите полученную прошивку на плату.
![Flash_project](docs/Flash_project.png) ![Flash_project](Flash_project.png)
7. При необходимости можно открыть терминал и получать сообщения от платы по интерфейсу Serial. Для этого добавьте в скетч работу с интерфейсом и после загрузки прошивки выберите `Инструменты -> Монитор порта`. 7. При необходимости можно открыть терминал и получать сообщения от платы по интерфейсу Serial. Для этого добавьте в скетч работу с интерфейсом и после загрузки прошивки выберите `Инструменты -> Монитор порта`.
![Monitor](docs/Monitor.png) ![Monitor](Monitor.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 64 KiB

BIN
docs/Start_V1_pinout.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@ -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 бод.

View File

@ -1,7 +1,7 @@
#include <NeoPixel.h> #include <NeoPixel.h>
#define PIN 2 #define PIN 2
#define NUMPIXELS 8 #define NUMPIXELS 1
NeoPixel pixels(NUMPIXELS, PIN); NeoPixel pixels(NUMPIXELS, PIN);

View File

@ -1,7 +1,7 @@
#include <NeoPixel.h> #include <NeoPixel.h>
#define PIN 2 #define PIN 2
#define NUMPIXELS 8 #define NUMPIXELS 1
NeoPixel pixels(NUMPIXELS, PIN); NeoPixel pixels(NUMPIXELS, PIN);

View File

@ -24,6 +24,7 @@ setClockDivider KEYWORD2
####################################### #######################################
# Constants (LITERAL1) # Constants (LITERAL1)
####################################### #######################################
SPI_CLOCK_DIV2 LITERAL1
SPI_CLOCK_DIV4 LITERAL1 SPI_CLOCK_DIV4 LITERAL1
SPI_CLOCK_DIV8 LITERAL1 SPI_CLOCK_DIV8 LITERAL1
SPI_CLOCK_DIV16 LITERAL1 SPI_CLOCK_DIV16 LITERAL1

View File

@ -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 // Find the fastest clock that is less than or equal to the
// given clock rate. If nothing is slow enough - use the slowest. // given clock rate. If nothing is slow enough - use the slowest.
// mik32v2 has the set of deviders, that can be calculate as: // 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) 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) if ((F_CPU/(2 << divRegVal)) <= speedMaximum)
// find suitable divider // find suitable divider
break; break;
divRegVal++;
} }
// if break didn't call in cycle, it will be the greatest divRegVal (and divider) // 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) void SPIClass::usingInterrupt(uint8_t interruptNumber)
{ {
if(interruptNumber < EXTERNAL_NUM_INTERRUPTS) if(interruptNumber < EXTERNAL_INTERRUPTS_QTY)
{ {
noInterrupts(); // prevent transactionBegin noInterrupts(); // prevent transactionBegin
interruptMask |= (1 << interruptNumber); // add new interrupt to mask interruptMask |= (1 << interruptNumber); // add new interrupt to mask
@ -107,7 +107,7 @@ void SPIClass::usingInterrupt(uint8_t interruptNumber)
void SPIClass::notUsingInterrupt(uint8_t interruptNumber) void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
{ {
if(interruptNumber < EXTERNAL_NUM_INTERRUPTS) if(interruptNumber < EXTERNAL_INTERRUPTS_QTY)
{ {
noInterrupts(); // prevent transactionBegin noInterrupts(); // prevent transactionBegin
interruptMask &= ~(1<<interruptNumber); // delete interrupt from mask interruptMask &= ~(1<<interruptNumber); // delete interrupt from mask
@ -122,7 +122,7 @@ void SPIClass::beginTransaction(SPISettings settings)
// disable interrupts in use if necessary // disable interrupts in use if necessary
if (spiInUse && (interruptMode > 0)) 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)) if (interruptMask & (1 << i))
// disable every interrupt by it's number // disable every interrupt by it's number
@ -234,7 +234,7 @@ void SPIClass::endTransaction(void)
// enable interrupts in use // enable interrupts in use
if (spiInUse && (interruptMode > 0)) 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)) if (interruptMask & (1 << i))
// enable every interrupt in use by it's number // enable every interrupt in use by it's number
@ -270,10 +270,10 @@ void SPIClass::setClockDivider(uint8_t clockDiv)
if (spiInUse) if (spiInUse)
{ {
// if divider is valid // if divider is valid
if ((clockDiv == SPI_CLOCK_DIV4) || (clockDiv == SPI_CLOCK_DIV8) || if ((clockDiv == SPI_CLOCK_DIV2) || (clockDiv == SPI_CLOCK_DIV4) ||
(clockDiv == SPI_CLOCK_DIV16) || (clockDiv == SPI_CLOCK_DIV32) || (clockDiv == SPI_CLOCK_DIV8) || (clockDiv == SPI_CLOCK_DIV16) ||
(clockDiv == SPI_CLOCK_DIV64) || (clockDiv == SPI_CLOCK_DIV128) || (clockDiv == SPI_CLOCK_DIV32) || (clockDiv == SPI_CLOCK_DIV64) ||
(clockDiv == SPI_CLOCK_DIV256)) (clockDiv == SPI_CLOCK_DIV128) || (clockDiv == SPI_CLOCK_DIV256))
{ {
hspi.Init.BaudRateDiv = clockDiv; hspi.Init.BaudRateDiv = clockDiv;
currentSpeed = F_CPU >> (clockDiv+1); currentSpeed = F_CPU >> (clockDiv+1);

View File

@ -34,6 +34,7 @@
// dividers for setClockDivider() // dividers for setClockDivider()
#define SPI_CLOCK_DIV2 0x00 // 16 MHz
#define SPI_CLOCK_DIV4 0x01 // 8 MHz #define SPI_CLOCK_DIV4 0x01 // 8 MHz
#define SPI_CLOCK_DIV8 0x02 // 4 MHz #define SPI_CLOCK_DIV8 0x02 // 4 MHz
#define SPI_CLOCK_DIV16 0x03 // 2 MHz #define SPI_CLOCK_DIV16 0x03 // 2 MHz

View File

@ -0,0 +1,2 @@
installed.json
.vscode/

View File

@ -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); // Секунда ожидания
}

View File

@ -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
}
}

View File

@ -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); // Выключаем светодиод
}
}

View File

@ -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 мс
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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,
};

View File

@ -0,0 +1,16 @@
#######################################
# Syntax Coloring Map For StartGuide
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
#######################################
# Constants (LITERAL1)
#######################################

View File

@ -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

View File

View File

@ -42,13 +42,12 @@ uint8_t masterGetData(uint8_t *buf, uint8_t dataSize)
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(57600);
while (!Serial); while (!Serial);
Serial.println("I2C master start"); Serial.println("I2C master start");
// Initialize the device on the I2C bus as a master // Initialize the device on the I2C bus as a master
Wire.begin(); Wire.begin();
Wire.setClock(400000);
} }
void loop() void loop()

View File

@ -73,7 +73,7 @@ void receiveEvent(int bytesNum)
// ----------------------------------------- // // ----------------------------------------- //
void setup() void setup()
{ {
Serial.begin(115200); Serial.begin(57600);
while (!Serial); while (!Serial);
Serial.println("I2C slave start"); Serial.println("I2C slave start");

View File

@ -1,5 +1,5 @@
name=ELBEAR boards name=MIK32 Boards
version=1.0.0 version=0.1.0
# Compiler and tools # Compiler and tools
compiler.prefix=riscv-none-elf- 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=elbear_uploader
tools.elbear_uploader.cmd.windows=elbear_uploader.exe tools.elbear_uploader.cmd.windows=elbear_uploader.exe
tools.elbear_uploader.path={runtime.tools.elbear_uploader.path} 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= tools.elbear_uploader.upload.params.quiet=
# Set elbear_uploader as programmer # Set elbear_uploader as programmer
@ -82,9 +82,9 @@ tools.mik32_upload.erase.pattern=
tools.mik32_upload.erase.params.quiet= tools.mik32_upload.erase.params.quiet=
# For Tools > Burn Bootloader # 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= tools.mik32_upload.bootloader.params.quiet=
# For Sketch > Upload Using Programmer # 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= tools.mik32_upload.program.params.quiet=

View File

@ -65,6 +65,8 @@ uint16_t pinCommonQty(void);
volatile uint32_t* portOutputRegister(GPIO_TypeDef* GPIO_x); volatile uint32_t* portOutputRegister(GPIO_TypeDef* GPIO_x);
// the function returns a reference to the STATE address of the GPIO register // the function returns a reference to the STATE address of the GPIO register
volatile uint32_t* portInputRegister(GPIO_TypeDef* GPIO_x); 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 // UART
// available uarts quantity // available uarts quantity
@ -109,7 +111,8 @@ static const uint8_t SCL = PIN_WIRE_SCL;
#define WIRE_FREQ_1000K 1000000 #define WIRE_FREQ_1000K 1000000
// interrupts // 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 // determines the board pin number by interrupt number
#define interruptToDigitalPin(interruptNum) (interruptInfo[interruptNum][0]) #define interruptToDigitalPin(interruptNum) (interruptInfo[interruptNum][0])
// determines gpio interrupt line by interrupt number // determines gpio interrupt line by interrupt number

View File

@ -100,6 +100,23 @@ volatile uint32_t* portInputRegister(GPIO_TypeDef* GPIO_x)
return &GPIO_x->STATE; 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 ---------------------- // // ---------------------- ADC ---------------------- //
// determines the ADC channel number by the board pin number // determines the ADC channel number by the board pin number
uint32_t analogInputToChannelNumber(uint32_t PinNumber) uint32_t analogInputToChannelNumber(uint32_t PinNumber)
@ -207,7 +224,7 @@ HAL_TIMER32_CHANNEL_IndexTypeDef pwmPinToTimerChannel(uint32_t digPinNumber)
// ---------------------- interrupts ---------------------- // // ---------------------- interrupts ---------------------- //
// interrupt table is stored in ram to improve performance // interrupt table is stored in ram to improve performance
// index = interrupt number. In each row {digitalPinNumber, IntLineValue, IntMuxValue} // 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 { 2, GPIO_LINE_2, GPIO_MUX_LINE_2_PORT0_10}, // INT0
{ 3, GPIO_LINE_0, GPIO_MUX_LINE_0_PORT0_0}, // INT1 { 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) 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) if (interruptInfo[i][0] == digPinNumber)
return interruptInfo[i][2]; return interruptInfo[i][2];
@ -229,7 +246,7 @@ int8_t digitalPinToGpioIntMux(uint8_t digPinNumber)
} }
int8_t digitalPinToGpioIntLine(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) if (interruptInfo[i][0] == digPinNumber)
return interruptInfo[i][1]; return interruptInfo[i][1];
@ -239,7 +256,7 @@ int8_t digitalPinToGpioIntLine(uint8_t digPinNumber)
int8_t gpioIntLineToInterrupt(uint32_t gpioIntLine) 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) if (interruptInfo[i][1] == gpioIntLine)
return i; return i;
@ -249,7 +266,7 @@ int8_t gpioIntLineToInterrupt(uint32_t gpioIntLine)
int8_t digitalPinToInterrupt(uint32_t digPinNumber) 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) if (interruptInfo[i][0] == digPinNumber)
return i; return i;

View File

@ -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

223
variants/start/variant.c Normal file
View File

@ -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;
}