Обновление до версии 0.3.0

- обновлен elbear_fw_bootloader - добавлена проверка контрольной суммы каждой строки hex файла.
- в модуль работы с АЦП добавлена функция analogReadResolution(). Функция analogRead() теперь возвращает усредненное по 10 измерениям значение.
- общая функция обработки прерываний перенесена в память RAM. Обработчики прерываний модулей External Interrupts и Advanced I/O (функция tone()) так же перенесены в память RAM для увеличения скорости выполнения кода.
- в пакет добавлены библиотеки EEPROM, Servo, SoftSerial, NeoPixel, MFRC522 адаптированные для работы с платой Elbear Ace-Uno.
- добавлено описание особенностей работы с пакетом
This commit is contained in:
klassents authored and KLASSENTS committed 2025-02-04 14:24:50 +07:00
1 parent 2044614aba
commit 7261b03ea1
114 files changed
+11064 -666

No files matched your search

+57 -35
View File
@@ -8,9 +8,13 @@ extern "C" {
#include "mik32_hal_gpio.h"
#include "mik32_hal_timer32.h"
extern void ErrorMsgHandler(const char * msg);
// -------------------------- Analog read -------------------------- //
#define ADC_SAMPLES_QTY 10 // samples quantity for averaging adc results
#define ADC_DEFAULT_RESOLUTION 10 // resolution for arduino compatibility
uint8_t currentResolution = ADC_DEFAULT_RESOLUTION; // resolution used for output results
// structure for ADC channel initialization. Only the channel number
// changes, everything else is the same
static ADC_HandleTypeDef hadc =
@@ -21,6 +25,16 @@ static ADC_HandleTypeDef hadc =
.Init.Sel = 0
};
void analogReadResolution(uint8_t resolution)
{
// resolution limits
if (resolution > 32) resolution = 32;
if (resolution < 1) resolution = 1;
// save new resolution
currentResolution = resolution;
}
// initialize the channel, run a single measurement, wait for the result
uint32_t analogRead(uint32_t PinNumber)
{
@@ -44,11 +58,31 @@ uint32_t analogRead(uint32_t PinNumber)
hadc.Init.Sel = adcChannel;
HAL_ADC_Init(&hadc);
// start the conversion twice in case another channel was polled before
// start the dummy conversion in case another channel was polled before
HAL_ADC_SINGLE_AND_SET_CH(hadc.Instance, adcChannel);
value = HAL_ADC_WaitAndGetValue(&hadc);
HAL_ADC_Single(&hadc);
value = HAL_ADC_WaitAndGetValue(&hadc);
HAL_ADC_WaitAndGetValue(&hadc);
// accumulate results
uint32_t acc = 0;
for (uint8_t i = 0; i<ADC_SAMPLES_QTY; i++)
{
HAL_ADC_Single(&hadc);
acc += HAL_ADC_WaitAndGetValue(&hadc);
}
// get value by averaging with MCU_ADC_RESOLUTION
value = acc/ADC_SAMPLES_QTY;
// map value to selected resolution
if (currentResolution > MCU_ADC_RESOLUTION)
{
// extra least significant bits are padded with zeros
value = (value << (currentResolution - MCU_ADC_RESOLUTION));
}
else
{
// extra least significant bits read from the ADC are discarded
value = (value >> (MCU_ADC_RESOLUTION - currentResolution));
}
}
else
ErrorMsgHandler("analogRead(): invalid analog pin number");
@@ -68,25 +102,8 @@ static TIMER32_HandleTypeDef htimer32;
static TIMER32_CHANNEL_HandleTypeDef htimer32_channel;
static uint32_t WriteValMax = WRITE_VAL_MAX_DEFAULT;
static uint32_t pwmTopVal = PWM_TOP_VAL_DEFAULT;
static bool pwmIsInited = false;
static uint8_t pwmIsInited = 0;
HAL_StatusTypeDef Timer32_Channel_Init(TIMER32_CHANNEL_HandleTypeDef *timerChannel)
{
if (timerChannel->TimerInstance == TIMER32_0)
return HAL_ERROR;
// gpio init removed from standard function
timerChannel->Instance = (TIMER32_CHANNEL_TypeDef *)&(timerChannel->TimerInstance->CHANNELS[timerChannel->ChannelIndex]);
HAL_Timer32_Channel_PWM_Invert_Set(timerChannel, timerChannel->PWM_Invert);
HAL_Timer32_Channel_Mode_Set(timerChannel, timerChannel->Mode);
HAL_Timer32_Channel_CaptureEdge_Set(timerChannel, timerChannel->CaptureEdge);
HAL_Timer32_Channel_OCR_Set(timerChannel, timerChannel->OCR);
HAL_Timer32_Channel_ICR_Clear(timerChannel);
HAL_Timer32_Channel_Noise_Set(timerChannel, timerChannel->Noise);
return HAL_OK;
}
/*
It is recommended to enable the timer in the following order:
@@ -120,15 +137,15 @@ void analogWrite(uint32_t PinNumber, uint32_t writeVal)
htimer32_channel.PWM_Invert = TIMER32_CHANNEL_NON_INVERTED_PWM;
htimer32_channel.Mode = TIMER32_CHANNEL_MODE_PWM;
htimer32_channel.CaptureEdge = TIMER32_CHANNEL_CAPTUREEDGE_RISING;
// cast to uint64_t to avoid overflow when multiplying
htimer32_channel.OCR = (uint32_t) (((uint64_t)pwmTopVal * writeVal) / WriteValMax);
htimer32_channel.Noise = TIMER32_CHANNEL_FILTER_OFF;
Timer32_Channel_Init(&htimer32_channel);
HAL_Timer32_Channel_Init(&htimer32_channel);
// start timer with initialized channel
HAL_Timer32_Channel_Enable(&htimer32_channel);
HAL_Timer32_Value_Clear(&htimer32);
HAL_Timer32_Start(&htimer32);
pwmIsInited = true; // if at least one channel is working, say that the module is initialized
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");
@@ -165,21 +182,26 @@ It is recommended to turn off the timer in the following order:
*/
void analogWriteStop(uint32_t PinNumber)
{
if (pwmIsInited)
if ((pwmIsInited > 0) && (digitalPinPwmIsOn(PinNumber)))
{
// load the timer address and channel number corresponding to the specified pin
htimer32.Instance = pwmPinToTimer(PinNumber);
htimer32_channel.TimerInstance = htimer32.Instance;
htimer32_channel.ChannelIndex = pwmPinToTimerChannel(PinNumber);
// in the initChannel function they do it inside, but in deinit they don't. We do it outside
htimer32_channel.Instance = (TIMER32_CHANNEL_TypeDef *)&(htimer32_channel.TimerInstance->CHANNELS[htimer32_channel.ChannelIndex]);
// и все чистим/отключаем
HAL_Timer32_InterruptMask_Clear(&htimer32, 0xFFFFFFFF);
HAL_Timer32_Prescaler_Set(&htimer32, 0);
HAL_Timer32_InterruptFlags_ClearMask(&htimer32, 0xFFFFFFFF);
// deinit channel
HAL_Timer32_Channel_DeInit(&htimer32_channel);
HAL_Timer32_Stop(&htimer32);
pwmIsInited = false;
pwmIsInited--; // decrease inited channels qty
// stop timer if no inited channels left
if (pwmIsInited == 0)
{
HAL_Timer32_Stop(&htimer32);
HAL_Timer32_Deinit(&htimer32);
}
// config pin as input when timer channel off
HAL_GPIO_PinConfig(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber),
HAL_GPIO_MODE_GPIO_INPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
}
}