mirror of
https://github.com/WeActStudio/ArduinoCore-AT32F4.git
synced 2026-05-21 09:22:01 +00:00
295 lines
7.6 KiB
C
295 lines
7.6 KiB
C
|
|
/*
|
|||
|
|
* MIT License
|
|||
|
|
* Copyright (c) 2017 - 2022 _VIFEXTech
|
|||
|
|
*
|
|||
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|||
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|||
|
|
* in the Software without restriction, including without limitation the rights
|
|||
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|||
|
|
* furnished to do so, subject to the following conditions:
|
|||
|
|
*
|
|||
|
|
* The above copyright notice and this permission notice shall be included in all
|
|||
|
|
* copies or substantial portions of the Software.
|
|||
|
|
*
|
|||
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|||
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|||
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||
|
|
* SOFTWARE.
|
|||
|
|
*/
|
|||
|
|
#include "Arduino.h"
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 配置引脚输入输出模式
|
|||
|
|
* @param pin: 引脚编号
|
|||
|
|
* @param PinMode_x: 模式
|
|||
|
|
* @retval 无
|
|||
|
|
*/
|
|||
|
|
void pinMode(uint8_t pin, PinMode_TypeDef mode)
|
|||
|
|
{
|
|||
|
|
if(!IS_PIN(pin))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if(mode == INPUT_ANALOG_DMA)
|
|||
|
|
{
|
|||
|
|
if(!IS_ADC_PIN(pin))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
pinMode(pin, INPUT_ANALOG);
|
|||
|
|
ADC_DMA_Register(PIN_MAP[pin].ADC_Channel);
|
|||
|
|
}
|
|||
|
|
else if(mode == PWM)
|
|||
|
|
{
|
|||
|
|
PWM_Init(pin, PWM_RESOLUTION_DEFAULT, PWM_FREQUENCY_DEFAULT);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
GPIOx_Init(
|
|||
|
|
PIN_MAP[pin].GPIOx,
|
|||
|
|
PIN_MAP[pin].GPIO_Pin_x,
|
|||
|
|
mode,
|
|||
|
|
GPIO_DRIVE_DEFAULT
|
|||
|
|
);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 将数字HIGH(1)或LOW(0)值写入数字引脚
|
|||
|
|
* @param pin:引脚编号
|
|||
|
|
* @param value: 写入值
|
|||
|
|
* @retval 无
|
|||
|
|
*/
|
|||
|
|
void digitalWrite(uint8_t pin, uint8_t value)
|
|||
|
|
{
|
|||
|
|
if(!IS_PIN(pin))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
value ? digitalWrite_HIGH(pin) : digitalWrite_LOW(pin);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 读取引脚电平
|
|||
|
|
* @param pin: 引脚编号
|
|||
|
|
* @retval 引脚电平
|
|||
|
|
*/
|
|||
|
|
uint8_t digitalRead(uint8_t pin)
|
|||
|
|
{
|
|||
|
|
if(!IS_PIN(pin))
|
|||
|
|
{
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return digitalRead_FAST(pin);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 将模拟值(PWM占空比)写入引脚
|
|||
|
|
* @param pin: 引脚编号
|
|||
|
|
* @param value: PWM占空比
|
|||
|
|
* @retval 无
|
|||
|
|
*/
|
|||
|
|
void analogWrite(uint8_t pin, uint16_t value)
|
|||
|
|
{
|
|||
|
|
if(!IS_PWM_PIN(pin))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
PWM_Write(pin, value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 从指定的模拟引脚读取值
|
|||
|
|
* @param pin: 引脚编号
|
|||
|
|
* @retval ADC值:0~4095
|
|||
|
|
*/
|
|||
|
|
uint16_t analogRead(uint8_t pin)
|
|||
|
|
{
|
|||
|
|
if(!IS_ADC_PIN(pin))
|
|||
|
|
{
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return ADCx_GetValue(PIN_MAP[pin].ADCx, PIN_MAP[pin].ADC_Channel);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 从指定的引脚读取值(DMA方式)
|
|||
|
|
* @param pin: 引脚编号
|
|||
|
|
* @retval ADC值:0~4095
|
|||
|
|
*/
|
|||
|
|
uint16_t analogRead_DMA(uint8_t pin)
|
|||
|
|
{
|
|||
|
|
if(!IS_ADC_PIN(pin))
|
|||
|
|
{
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return ADC_DMA_GetValue(PIN_MAP[pin].ADC_Channel);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 一次移出一个字节的数据,从最左端或最小(最右边)开始
|
|||
|
|
* @param dataPin: 输出每个位的 pin
|
|||
|
|
* @param clockPin: 将 dataPin 设置为正确值后要切换的 pin (int)
|
|||
|
|
* @param bitOrder: MSBFIRST / LSBFIRST
|
|||
|
|
* @param value: 要移出的数据(字节)
|
|||
|
|
* @retval 无
|
|||
|
|
*/
|
|||
|
|
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t value)
|
|||
|
|
{
|
|||
|
|
uint8_t i;
|
|||
|
|
if(!(IS_PIN(dataPin) && IS_PIN(clockPin)))
|
|||
|
|
{
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
digitalWrite_LOW(clockPin);
|
|||
|
|
for (i = 0; i < 8; i++)
|
|||
|
|
{
|
|||
|
|
int bit = bitOrder == LSBFIRST ? i : (7 - i);
|
|||
|
|
digitalWrite(dataPin, (value >> bit) & 0x1);
|
|||
|
|
togglePin(clockPin);
|
|||
|
|
togglePin(clockPin);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 一次将一个字节的数据移位,从最左端或最小 (最右边) 开始
|
|||
|
|
* @param dataPin: 输入每个位的 pin
|
|||
|
|
* @param clockPin: 要切换到的 pin 信号从dataPin读取
|
|||
|
|
* @param bitOrder: MSBFIRST/LSBFIRST
|
|||
|
|
* @retval 读取的值 (字节)
|
|||
|
|
*/
|
|||
|
|
uint32_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint32_t bitOrder)
|
|||
|
|
{
|
|||
|
|
uint8_t value = 0;
|
|||
|
|
uint8_t i;
|
|||
|
|
|
|||
|
|
if(!(IS_PIN(dataPin) && IS_PIN(clockPin)))
|
|||
|
|
{
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (i = 0; i < 8; ++i)
|
|||
|
|
{
|
|||
|
|
digitalWrite_HIGH(clockPin);
|
|||
|
|
if (bitOrder == LSBFIRST )
|
|||
|
|
{
|
|||
|
|
value |= digitalRead(dataPin) << i;
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
value |= digitalRead(dataPin) << (7 - i);
|
|||
|
|
}
|
|||
|
|
digitalWrite_LOW(clockPin);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 在引脚上读取脉冲
|
|||
|
|
* @param pin: 要读取脉冲的引脚编号
|
|||
|
|
* @param value: 脉冲类型:高或低
|
|||
|
|
* @param timeout: 等待脉冲开始的微秒数
|
|||
|
|
* @retval 脉冲的长度(以微秒计)或0, 如果没有脉冲在超时之前开始
|
|||
|
|
*/
|
|||
|
|
uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout)
|
|||
|
|
{
|
|||
|
|
// cache the IDR address and bit of the pin in order to speed up the
|
|||
|
|
// pulse width measuring loop and achieve finer resolution. calling
|
|||
|
|
// digitalRead() instead yields much coarser resolution.
|
|||
|
|
|
|||
|
|
volatile uint32_t *idr = portInputRegister(digitalPinToPort(pin));
|
|||
|
|
const uint32_t bit = digitalPinToBitMask(pin);
|
|||
|
|
const uint32_t stateMask = (state ? bit : 0);
|
|||
|
|
|
|||
|
|
uint32_t width = 0; // keep initialization out of time critical area
|
|||
|
|
|
|||
|
|
// convert the timeout from microseconds to a number of times through
|
|||
|
|
// the initial loop; it takes 16 clock cycles per iteration.
|
|||
|
|
uint32_t numloops = 0;
|
|||
|
|
uint32_t maxloops = timeout * ( F_CPU / 16000000);
|
|||
|
|
volatile uint32_t dummyWidth = 0;
|
|||
|
|
|
|||
|
|
if(!IS_PIN(pin))
|
|||
|
|
return 0;
|
|||
|
|
|
|||
|
|
// wait for any previous pulse to end
|
|||
|
|
while ((*idr & bit) == stateMask)
|
|||
|
|
{
|
|||
|
|
if (numloops++ == maxloops)
|
|||
|
|
{
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
dummyWidth++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// wait for the pulse to start
|
|||
|
|
while ((*idr & bit) != stateMask)
|
|||
|
|
{
|
|||
|
|
if (numloops++ == maxloops)
|
|||
|
|
{
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
dummyWidth++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// wait for the pulse to stop
|
|||
|
|
while ((*idr & bit) == stateMask)
|
|||
|
|
{
|
|||
|
|
if (numloops++ == maxloops)
|
|||
|
|
{
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
width++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Excluding time taking up by the interrupts, it needs 16 clock cycles to look through the last while loop
|
|||
|
|
// 5 is added as a fiddle factor to correct for interrupts etc. But ultimately this would only be accurate if it was done ona hardware timer
|
|||
|
|
|
|||
|
|
return (uint32_t)( ( (unsigned long long)(width + 5) * (unsigned long long) 16000000.0) / (unsigned long long)F_CPU );
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 将一个数字(整形)从一个范围重新映射到另一个区域
|
|||
|
|
* @param x: 要映射的数字
|
|||
|
|
* @param in_min: 值的当前范围的下界
|
|||
|
|
* @param in_max: 值的当前范围的上界
|
|||
|
|
* @param out_min: 值的目标范围的下界
|
|||
|
|
* @param out_max: 值目标范围的上界
|
|||
|
|
* @retval 映射的值(long)
|
|||
|
|
*/
|
|||
|
|
long map(long x, long in_min, long in_max, long out_min, long out_max)
|
|||
|
|
{
|
|||
|
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 将一个数字(浮点型)从一个范围重新映射到另一个区域
|
|||
|
|
* @param x: 要映射的数字
|
|||
|
|
* @param in_min: 值的当前范围的下界
|
|||
|
|
* @param in_max: 值的当前范围的上界
|
|||
|
|
* @param out_min: 值的目标范围的下界
|
|||
|
|
* @param out_max: 值目标范围的上界
|
|||
|
|
* @retval 映射的值(double)
|
|||
|
|
*/
|
|||
|
|
float fmap(float x, float in_min, float in_max, float out_min, float out_max)
|
|||
|
|
{
|
|||
|
|
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void yield(void)
|
|||
|
|
{
|
|||
|
|
}
|