forked from Elron_dev/elbear_arduino_bsp
ready to alpha
подготовка к альфа-тестированию
This commit is contained in:
commit
e36b851783
164 files changed
+27352
No files matched your search
@@ -0,0 +1,188 @@
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mik32_hal_adc.h"
|
||||
#include "mik32_hal_gpio.h"
|
||||
#include "mik32_hal_timer32.h"
|
||||
|
||||
extern void ErrorMsgHandler(const char * msg);
|
||||
|
||||
// -------------------------- Analog read -------------------------- //
|
||||
// structure for ADC channel initialization. Only the channel number
|
||||
// changes, everything else is the same
|
||||
static ADC_HandleTypeDef hadc =
|
||||
{
|
||||
.Instance = ANALOG_REG,
|
||||
.Init.EXTClb = ADC_EXTCLB_ADCREF,
|
||||
.Init.EXTRef = ADC_EXTREF_OFF,
|
||||
.Init.Sel = 0
|
||||
};
|
||||
|
||||
// initialize the channel, run a single measurement, wait for the result
|
||||
uint32_t analogRead(uint32_t PinNumber)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
uint32_t adcChannel = analogInputToChannelNumber(PinNumber);
|
||||
if (adcChannel != NC)
|
||||
{
|
||||
// if we use pin A5, we need to set SELA45 (1.15) to 1 to switch the output from A4 to A5
|
||||
if (PinNumber == A5)
|
||||
{
|
||||
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_15, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
|
||||
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_15, GPIO_PIN_HIGH);
|
||||
}
|
||||
else if(PinNumber == A4)
|
||||
{
|
||||
// return the switch to A4 in case A5 was previously read
|
||||
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_15, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
|
||||
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_15, GPIO_PIN_LOW);
|
||||
}
|
||||
// init channel
|
||||
hadc.Init.Sel = adcChannel;
|
||||
HAL_ADC_Init(&hadc);
|
||||
|
||||
// start the conversion twice 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);
|
||||
}
|
||||
else
|
||||
ErrorMsgHandler("analogRead(): invalid analog pin number");
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -------------------------- Analog write -------------------------- //
|
||||
#define PWM_RESOLUTION_DEFAULT 8
|
||||
#define WRITE_VAL_MAX_DEFAULT ((1<<PWM_RESOLUTION_DEFAULT) - 1)
|
||||
#define PWM_TOP_VAL_DEFAULT 32000 // corresponds 1000 Hz
|
||||
#define PWM_FREQUENCY_MAX 1000000 // Hz
|
||||
|
||||
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;
|
||||
|
||||
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:
|
||||
- Set the required operating mode. In the INT_MASK register 0;
|
||||
- Write 0xFFFFFFFF to the INT_CLEAR register;
|
||||
- Set TIM_EN to 1;
|
||||
- If you need interrupts from the timer, set the required interrupt mask in the INT_MASK register.
|
||||
*/
|
||||
void analogWrite(uint32_t PinNumber, uint32_t writeVal)
|
||||
{
|
||||
if (digitalPinHasPWM(PinNumber))
|
||||
{
|
||||
if (writeVal > WriteValMax) writeVal = WriteValMax;
|
||||
|
||||
// initialization of the required timer
|
||||
htimer32.Instance = pwmPinToTimer(PinNumber);
|
||||
htimer32.Top = pwmTopVal;
|
||||
htimer32.State = TIMER32_STATE_DISABLE;
|
||||
htimer32.Clock.Source = TIMER32_SOURCE_PRESCALER;
|
||||
htimer32.Clock.Prescaler = 0; // Prescaler = 1
|
||||
htimer32.InterruptMask = 0;
|
||||
htimer32.CountMode = TIMER32_COUNTMODE_FORWARD;
|
||||
HAL_Timer32_Init(&htimer32);
|
||||
|
||||
// gpio init as timer channel pin
|
||||
HAL_GPIO_PinConfig(digitalPinToPort(PinNumber), digitalPinToBitMask(PinNumber),
|
||||
HAL_GPIO_MODE_TIMER_SERIAL, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
|
||||
|
||||
htimer32_channel.TimerInstance = htimer32.Instance;
|
||||
htimer32_channel.ChannelIndex = pwmPinToTimerChannel(PinNumber);
|
||||
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);
|
||||
// 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
|
||||
}
|
||||
else if(PinNumber == 10) // pin d10 has pwm, but you cannot use it while spi is running
|
||||
ErrorMsgHandler("analogWrite(): D10 cannot be used as PWM pin while SPI is running");
|
||||
else
|
||||
ErrorMsgHandler("analogWrite(): invalid pwm pin number");
|
||||
}
|
||||
|
||||
// Set the resolution of analogWrite parameters
|
||||
void analogWriteResolution(uint8_t resolution)
|
||||
{
|
||||
if ((resolution > 0) && (resolution < 32))
|
||||
WriteValMax = (1 << resolution) - 1;
|
||||
else if (resolution == 32)
|
||||
WriteValMax = UINT32_MAX;
|
||||
else
|
||||
ErrorMsgHandler("analogWriteResolution(): invalid resolution");
|
||||
}
|
||||
|
||||
// Set the frequency of analogWrite
|
||||
void analogWriteFrequency(uint32_t freq)
|
||||
{
|
||||
if ((freq >= 1) && (freq <= PWM_FREQUENCY_MAX))
|
||||
pwmTopVal = F_CPU/freq;
|
||||
else
|
||||
ErrorMsgHandler("analogWriteFrequency(): invalid frequency");
|
||||
}
|
||||
|
||||
/*
|
||||
It is recommended to turn off the timer in the following order:
|
||||
- Write 0 to the INT_MASK register;
|
||||
- Write 0 to the TIM_PRESCALE register;
|
||||
- Write 0 to the INT_CLEAR register;
|
||||
- Set TIM_EN to 0.
|
||||
*/
|
||||
void analogWriteStop(uint32_t PinNumber)
|
||||
{
|
||||
if (pwmIsInited)
|
||||
{
|
||||
// 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);
|
||||
HAL_Timer32_Channel_DeInit(&htimer32_channel);
|
||||
HAL_Timer32_Stop(&htimer32);
|
||||
pwmIsInited = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Reference in new issue
Block a user