support linux system

This commit is contained in:
ZYQ-FEIYUE
2022-08-09 22:38:26 +08:00
parent ef453b4ba6
commit d2816d24b5
130 changed files with 22 additions and 24 deletions

View File

@@ -0,0 +1,294 @@
/*
* 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)
{
}

255
cores/arduino/libcore/adc.c Normal file
View File

@@ -0,0 +1,255 @@
/*
* 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 "adc.h"
#include <stdbool.h>
#define ADC_DMA_REGMAX 18
#define IS_ADC_CHANNEL(channel) (channel <= ADC_CHANNEL_17)
/*引脚注册个数*/
static uint8_t ADC_DMA_RegCnt = 0;
/*ADC通道注册列表*/
static uint8_t ADC_DMA_RegChannelList[ADC_DMA_REGMAX] = {0};
/*ADC DMA缓存数组*/
static uint16_t ADC_DMA_ConvertedValue[ADC_DMA_REGMAX] = {0};
/**
* @brief 搜索注册列表找出ADC通道对应的索引号
* @param ADC_Channel:ADC通道号
* @retval ADC通道注册列表对应索引号-1:未找到对应通道号
*/
static int16_t ADC_DMA_SearchChannel(uint16_t ADC_Channel)
{
uint8_t index;
for(index = 0; index < ADC_DMA_RegCnt; index++)
{
if(ADC_Channel == ADC_DMA_RegChannelList[index])
{
return index;
}
}
return -1;
}
/**
* @brief ADC 配置
* @param ADCx: ADC地址
* @retval 无
*/
void ADCx_Init(adc_type* ADCx)
{
adc_base_config_type adc_base_struct;
if(ADCx == ADC1)
{
crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
}
else if(ADCx == ADC2)
{
crm_periph_clock_enable(CRM_ADC2_PERIPH_CLOCK, TRUE);
}
#ifdef ADC3
else if(ADCx == ADC3)
{
crm_periph_clock_enable(CRM_ADC3_PERIPH_CLOCK, TRUE);
}
#endif
else
{
return;
}
crm_adc_clock_div_set(CRM_ADC_DIV_8);
adc_combine_mode_select(ADC_INDEPENDENT_MODE);
adc_base_default_para_init(&adc_base_struct);
adc_base_struct.sequence_mode = FALSE;
adc_base_struct.repeat_mode = FALSE;
adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
adc_base_struct.ordinary_channel_length = 1;
adc_base_config(ADCx, &adc_base_struct);
if (ADCx != ADC3)
adc_ordinary_conversion_trigger_set(ADCx, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
else
adc_ordinary_conversion_trigger_set(ADCx, ADC3_ORDINARY_TRIG_SOFTWARE, TRUE);
adc_enable(ADCx, TRUE);
adc_calibration_init(ADCx);
while(adc_calibration_init_status_get(ADCx));
adc_calibration_start(ADCx);
while(adc_calibration_status_get(ADCx));
}
/**
* @brief 获取 ADC 值
* @param ADCx: ADC地址
* @param ADC_Channel: ADC通道
* @retval 无
*/
uint16_t ADCx_GetValue(adc_type* ADCx, uint16_t ADC_Channel)
{
adc_ordinary_channel_set(ADCx, (adc_channel_select_type)ADC_Channel, 1, ADC_SAMPLETIME_41_5);
adc_ordinary_software_trigger_enable(ADCx, TRUE);
while(!adc_flag_get(ADCx, ADC_CCE_FLAG));
return adc_ordinary_conversion_data_get(ADCx);
}
/**
* @brief 注册需要DMA搬运的ADC通道
* @param ADC_Channel:ADC通道号
* @retval 见ADC_DMA_Res_Type
*/
ADC_DMA_Res_Type ADC_DMA_Register(uint8_t ADC_Channel)
{
/*初始化ADC通道列表*/
static bool isInit = false;
if(!isInit)
{
uint8_t i;
for(i = 0; i < ADC_DMA_REGMAX; i++)
{
ADC_DMA_RegChannelList[i] = 0xFF;
}
isInit = true;
}
/*是否是合法ADC通道*/
if(!IS_ADC_CHANNEL(ADC_Channel))
return ADC_DMA_RES_NOT_ADC_CHANNEL;
/*是否已在引脚列表重复注册*/
if(ADC_DMA_SearchChannel(ADC_Channel) != -1)
return ADC_DMA_RES_DUPLICATE_REGISTRATION;
/*是否超出最大注册个数*/
if(ADC_DMA_RegCnt >= ADC_DMA_REGMAX)
return ADC_DMA_RES_MAX_NUM_OF_REGISTRATIONS_EXCEEDED;
/*写入注册列表*/
ADC_DMA_RegChannelList[ADC_DMA_RegCnt] = ADC_Channel;
/*注册个数+1*/
ADC_DMA_RegCnt++;
return ADC_DMA_RES_OK;
}
/**
* @brief 获取已注册的ADC DMA通道数量
* @param 无
* @retval ADC DMA通道数量
*/
uint8_t ADC_DMA_GetRegisterCount(void)
{
return ADC_DMA_RegCnt;
}
/**
* @brief ADC DMA 配置
* @param 无
* @retval 无
*/
void ADC_DMA_Init(void)
{
dma_init_type dma_init_structure;
adc_base_config_type adc_base_struct;
uint8_t index;
crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
dma_reset(DMA1_CHANNEL1);
dma_default_para_init(&dma_init_structure);
dma_init_structure.buffer_size = ADC_DMA_RegCnt;
dma_init_structure.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
dma_init_structure.memory_base_addr = (uint32_t)ADC_DMA_ConvertedValue;
dma_init_structure.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
dma_init_structure.memory_inc_enable = TRUE;
dma_init_structure.peripheral_base_addr = (uint32_t) (&(ADC1->odt));
dma_init_structure.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
dma_init_structure.peripheral_inc_enable = FALSE;
dma_init_structure.priority = DMA_PRIORITY_HIGH;
dma_init_structure.loop_mode_enable = TRUE;
dma_init(DMA1_CHANNEL1, &dma_init_structure);
adc_combine_mode_select(ADC_INDEPENDENT_MODE);
adc_base_default_para_init(&adc_base_struct);
adc_base_struct.sequence_mode = FALSE;
adc_base_struct.repeat_mode = FALSE;
adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
adc_base_struct.ordinary_channel_length = 1;
adc_base_config(ADC1, &adc_base_struct);
adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
crm_adc_clock_div_set(CRM_ADC_DIV_8);
for(index = 0; index < ADC_DMA_RegCnt; index++)
{
adc_ordinary_channel_set(
ADC1,
ADC_DMA_RegChannelList[index],
index + 1,
ADC_SAMPLETIME_41_5
);
if(ADC_DMA_RegChannelList[index] == ADC_CHANNEL_16)
{
adc_tempersensor_vintrv_enable(true);
}
}
adc_dma_mode_enable(ADC1, TRUE);
adc_enable(ADC1, TRUE);
adc_calibration_init(ADC1);
while(adc_calibration_init_status_get(ADC1));
adc_calibration_start(ADC1);
while(adc_calibration_status_get(ADC1));
}
/**
* @brief 获取DMA搬运的ADC值
* @param ADC_Channel:ADC通道号
* @retval ADC值
*/
uint16_t ADC_DMA_GetValue(uint8_t ADC_Channel)
{
int16_t index;
if(!IS_ADC_CHANNEL(ADC_Channel))
return 0;
index = ADC_DMA_SearchChannel(ADC_Channel);
if(index == -1)
return 0;
return ADC_DMA_ConvertedValue[index];
}

View File

@@ -0,0 +1,51 @@
/*
* 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.
*/
#ifndef __ADC_H
#define __ADC_H
#include "mcu_type.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
ADC_DMA_RES_OK = 0,
ADC_DMA_RES_NOT_ADC_CHANNEL = -1,
ADC_DMA_RES_DUPLICATE_REGISTRATION = -2,
ADC_DMA_RES_MAX_NUM_OF_REGISTRATIONS_EXCEEDED = -3,
} ADC_DMA_Res_Type;
void ADCx_Init(adc_type* ADCx);
uint16_t ADCx_GetValue(adc_type* ADCx, uint16_t ADC_Channel);
void ADC_DMA_Init(void);
ADC_DMA_Res_Type ADC_DMA_Register(uint8_t ADC_Channel);
uint16_t ADC_DMA_GetValue(uint8_t ADC_Channel);
uint8_t ADC_DMA_GetRegisterCount(void);
#ifdef __cplusplus
}
#endif
#endif /* __ADC_H */

View File

@@ -0,0 +1,105 @@
/**
**************************************************************************
* @file at32f403a_407_clock.c
* @version v2.0.9
* @date 2022-04-25
* @brief system clock config program
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* includes ------------------------------------------------------------------*/
#include "at32f403a_407_clock.h"
/**
* @brief system clock config program
* @note the system clock is configured as follow:
* - system clock = hext / 2 * pll_mult
* - system clock source = pll (hext)
* - hext = 8000000
* - sclk = 240000000
* - ahbdiv = 1
* - ahbclk = 240000000
* - apb2div = 2
* - apb2clk = 120000000
* - apb1div = 2
* - apb1clk = 120000000
* - pll_mult = 60
* - pll_range = GT72MHZ (greater than 72 mhz)
* @param none
* @retval none
*/
void system_clock_config(void)
{
/* reset crm */
crm_reset();
#if F_PLL_CLOCK_SOURCE != 0
crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE);
/* wait till hext is ready */
while(crm_hext_stable_wait() == ERROR)
{
}
#endif
/* config pll clock resource */
crm_pll_config(F_PLL_CLOCK_SOURCE, F_PLL_MULT, F_PLL_OUTPUT_RANGE);
#if F_PLL_CLOCK_SOURCE == 2
/* config hext division */
crm_hext_clock_div_set(F_HEXT_DIV);
#elif F_PLL_CLOCK_SOURCE == 1
crm_hick_divider_select(F_HSI_DIV);
#endif
/* enable pll */
crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);
/* wait till pll is ready */
while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
{
}
/* config ahbclk */
crm_ahb_div_set(CRM_AHB_DIV_1);
/* config apb2clk */
crm_apb2_div_set(CRM_APB2_DIV_2);
/* config apb1clk */
crm_apb1_div_set(CRM_APB1_DIV_2);
/* enable auto step mode */
crm_auto_step_mode_enable(TRUE);
/* select pll as system clock source */
crm_sysclk_switch(CRM_SCLK_PLL);
/* wait till pll is used as system clock source */
while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
{
}
/* disable auto step mode */
crm_auto_step_mode_enable(FALSE);
/* update system_core_clock global variable */
system_core_clock_update();
}

View File

@@ -0,0 +1,46 @@
/**
**************************************************************************
* @file at32f403a_407_clock.h
* @version v2.0.9
* @date 2022-04-25
* @brief header file of clock program
**************************************************************************
* Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* define to prevent recursive inclusion -------------------------------------*/
#ifndef __AT32F403A_407_CLOCK_H
#define __AT32F403A_407_CLOCK_H
#ifdef __cplusplus
extern "C" {
#endif
/* includes ------------------------------------------------------------------*/
#include "at32f403a_407.h"
/* exported functions ------------------------------------------------------- */
void system_clock_config(void);
#ifdef __cplusplus
}
#endif
#endif /* __AT32F403A_407_CLOCK_H */

View File

@@ -0,0 +1,112 @@
/*
* 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.
*/
#ifndef __MCU_CONFIG_H
#define __MCU_CONFIG_H
/*=========================
MCU configuration
*=========================*/
/* System tick */
#define SYSTICK_TICK_FREQ 1000 // Hz
#define SYSTICK_PRIORITY 0
/* Hardware Serial */
#define SERIAL_RX_BUFFER_SIZE 128
#define SERIAL_PREEMPTIONPRIORITY_DEFAULT 1
#define SERIAL_SUBPRIORITY_DEFAULT 3
#define SERIAL_CONFIG_DEFAULT SERIAL_8N1
#define SERIAL_1_ENABLE 1
#if SERIAL_1_ENABLE
# define SERIAL_1_USART USART1
# define SERIAL_1_IRQ_HANDLER_DEF() void USART1_IRQHandler(void)
#endif
#define SERIAL_2_ENABLE 1
#if SERIAL_2_ENABLE
# define SERIAL_2_USART USART2
# define SERIAL_2_IRQ_HANDLER_DEF() void USART2_IRQHandler(void)
#endif
#define SERIAL_3_ENABLE 1
#if SERIAL_3_ENABLE
# define SERIAL_3_USART USART3
# define SERIAL_3_IRQ_HANDLER_DEF() void USART3_IRQHandler(void)
#endif
/* Wire (Software I2C) */
#define WIRE_USE_FULL_SPEED_I2C 0
#define WIRE_SDA_PIN PB7
#define WIRE_SCL_PIN PB6
#define WIRE_DELAY 0
#define WIRE_BEGIN_TIMEOUT 100 // ms
#define WIRE_BUFF_SIZE 32
/* SPI Class */
#define SPI_CLASS_AVR_COMPATIBILITY_MODE 1
#define SPI_CLASS_PIN_DEFINE_ENABLE 1
#define SPI_CLASS_1_ENABLE 1
#if SPI_CLASS_1_ENABLE
# define SPI_CLASS_1_SPI SPI1
#endif
#define SPI_CLASS_2_ENABLE 1
#if SPI_CLASS_2_ENABLE
# define SPI_CLASS_2_SPI SPI2
#endif
#define SPI_CLASS_3_ENABLE 1
#if SPI_CLASS_3_ENABLE
# define SPI_CLASS_3_SPI SPI3
#endif
/* WString */
#define WSTRING_MEM_INCLUDE <stdlib.h>
#define WSTRING_MEM_REALLOC realloc
#define WSTRING_MEM_FREE free
/* Print */
#define PRINT_PRINTF_BUFFER_LENGTH 128
/* GPIO */
#define GPIO_DRIVE_DEFAULT GPIO_DRIVE_STRENGTH_STRONGER
/* External Interrupt */
#define EXTI_PREEMPTIONPRIORITY_DEFAULT 2
#define EXTI_SUBPRIORITY_DEFAULT 1
/* Timer Interrupt */
#define TIMER_PREEMPTIONPRIORITY_DEFAULT 0
#define TIMER_SUBPRIORITY_DEFAULT 3
/* Tone */
#define TONE_TIMER_DEFAULT TIM1
#define TONE_PREEMPTIONPRIORITY_DEFAULT 0
#define TONE_SUBPRIORITY_DEFAULT 1
/* PWM */
#define PWM_RESOLUTION_DEFAULT 1000
#define PWM_FREQUENCY_DEFAULT 10000
#endif

View File

@@ -0,0 +1,121 @@
/*
* 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 "delay.h"
#ifndef SYSTICK_TICK_FREQ
# define SYSTICK_TICK_FREQ 1000 // Hz
#endif
#define SYSTICK_TICK_INTERVAL (1000 / SYSTICK_TICK_FREQ)
#define SYSTICK_LOAD_VALUE (system_core_clock / SYSTICK_TICK_FREQ)
#define SYSTICK_MILLIS (SystemTickCount * SYSTICK_TICK_INTERVAL)
static volatile uint32_t SystemTickCount = 0;
/**
* @brief 系统滴答定时器初始化定时1ms
* @param 无
* @retval 无
*/
void Delay_Init(void)
{
system_core_clock_update();
SysTick_Config(SYSTICK_LOAD_VALUE);
NVIC_SetPriority(SysTick_IRQn, SYSTICK_PRIORITY);
}
/**
* @brief 系统滴答定时器中断入口
* @param 无
* @retval 无
*/
void SysTick_Handler(void)
{
SystemTickCount++;
}
/**
* @brief 获取单片机自上电以来经过的毫秒数
* @param 无
* @retval 当前系统时钟毫秒数
*/
uint32_t millis(void)
{
return SYSTICK_MILLIS;
}
/**
* @brief 获取单片机自上电以来经过的微秒数
* @param 无
* @retval 当前系统时钟微秒数
*/
uint32_t micros(void)
{
return (SYSTICK_MILLIS * 1000 + (SYSTICK_LOAD_VALUE - SysTick->VAL) / CYCLES_PER_MICROSECOND);
}
/**
* @brief 毫秒级延时
* @param ms: 要延时的毫秒数
* @retval 无
*/
void delay_ms(uint32_t ms)
{
uint32_t tickstart = SystemTickCount;
uint32_t wait = ms / SYSTICK_TICK_INTERVAL;
while((SystemTickCount - tickstart) < wait)
{
}
}
/**
* @brief 微秒级延时
* @param us: 要延时的微秒数
* @retval 无
*/
void delay_us(uint32_t us)
{
uint32_t total = 0;
uint32_t target = CYCLES_PER_MICROSECOND * us;
int last = SysTick->VAL;
int now = last;
int diff = 0;
start:
now = SysTick->VAL;
diff = last - now;
if(diff > 0)
{
total += diff;
}
else
{
total += diff + SYSTICK_LOAD_VALUE;
}
if(total > target)
{
return;
}
last = now;
goto start;
}

View File

@@ -0,0 +1,42 @@
/*
* 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.
*/
#ifndef __DELAY_H
#define __DELAY_H
#include "mcu_type.h"
#ifdef __cplusplus
extern "C" {
#endif
void Delay_Init(void);
uint32_t millis(void);
uint32_t micros(void);
void delay_ms(uint32_t ms);
void delay_us(uint32_t us);
#ifdef __cplusplus
}
#endif
#endif /* __DELAY_H */

View File

@@ -0,0 +1,103 @@
/**
******************************************************************************
* File : SRAM/extend_SRAM/EXTEND_SRAM/extend_SRAM.c
* Version: V1.2.7
* Date : 2020-11-10
* Brief : This file contains the function extend_SRAM_test used to extend SRAM size
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "extend_SRAM.h"
#include "at32f403a_407.h"
#define EXTEND_SRAM_224K
/* Copy to Startup file */
#if 0
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
IMPORT extend_SRAM
MOV32 R0, #0x20001000
MOV SP, R0
LDR R0, =extend_SRAM
BLX R0
MOV32 R0, #0x08000000
LDR SP, [R0]
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
#endif
/** @addtogroup AT32F403A_StdPeriph_Examples
* @{
*/
/** @addtogroup SRAM_Extended_SRAM
* @{
*/
/* Private typedef -----------------------------------------------------------*/
#define TEST_RAM_SIZE 0x800
/* Private variables ---------------------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief To extend SRAM size
* @param None
* @retval None
*/
void extend_sram(void)
{
/* Target set_SRAM_96K is selected */
#ifdef EXTEND_SRAM_96K
/* check if RAM has been set to 96K, if not, change EOPB0 */
if(((UOPTB->EOPB0)&0xFF)!=0xFF)
{
/* Unlock Option Bytes Program Erase controller */
FLASH_Unlock();
/* Erase Option Bytes */
FLASH_EraseUserOptionBytes();
/* Change SRAM size to 96KB */
FLASH_ProgramUserOptionByteData((uint32_t)&UOPTB->EOPB0,0xFF);
NVIC_SystemReset();
}
#endif
/* Target set_SRAM_224K is selected */
#ifdef EXTEND_SRAM_224K
/* check if ram has been set to expectant size, if not, change eopb0 */
if(((USD->eopb0) & 0xFF) != 0xFE)
{
flash_unlock();
/* erase user system data bytes */
flash_user_system_data_erase();
/* change sram size */
flash_user_system_data_program((uint32_t)&USD->eopb0, 0xFE);
/* system reset */
nvic_system_reset();
}
#endif
}
/**
* @}
*/
/**
* @}
*/

View File

@@ -0,0 +1,18 @@
/**
******************************************************************************
* File : SRAM/extend_SRAM/EXTEND_SRAM/extend_SRAM.h
* Version: V1.2.7
* Date : 2020-11-10
* Brief : This file contains all the macros used in extend_SRAM.c
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __EXTEND_SRAM_H
#define __EXTEND_SRAM_H
/* Exported functions ------------------------------------------------------- */
void extend_sram(void);
#endif /* __EXTEND_SRAM_H */

View File

@@ -0,0 +1,235 @@
/*
* 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 "exti.h"
#include "gpio.h"
#define EXTI_GetPortSourceGPIOx(Pin) GPIO_GetPortNum(Pin)
#define EXTI_GetPinSourcex(Pin) GPIO_GetPinNum(Pin)
static EXTI_CallbackFunction_t EXTI_Function[16] = {0};
/**
* @brief 获取外部中断的中断通道
* @param Pin: 引脚编号
* @retval 通道编号
*/
static IRQn_Type EXTI_GetIRQn(uint8_t Pin)
{
IRQn_Type EXINTx_IRQn = EXINT0_IRQn;
uint8_t Pinx = GPIO_GetPinNum(Pin);
if(Pinx <= 4)
{
switch(Pinx)
{
case 0:
EXINTx_IRQn = EXINT0_IRQn;
break;
case 1:
EXINTx_IRQn = EXINT1_IRQn;
break;
case 2:
EXINTx_IRQn = EXINT2_IRQn;
break;
case 3:
EXINTx_IRQn = EXINT3_IRQn;
break;
case 4:
EXINTx_IRQn = EXINT4_IRQn;
break;
}
}
else if(Pinx >= 5 && Pinx <= 9)
{
EXINTx_IRQn = EXINT9_5_IRQn;
}
else if(Pinx >= 10 && Pinx <= 15)
{
EXINTx_IRQn = EXINT15_10_IRQn;
}
return EXINTx_IRQn;
}
/**
* @brief 外部中断初始化
* @param Pin: 引脚编号
* @param Function: 回调函数
* @param Trigger_Mode: 触发方式
* @param PreemptionPriority: 抢占优先级
* @param SubPriority: 子优先级
* @retval 无
*/
void EXTIx_Init(
uint8_t Pin,
EXTI_CallbackFunction_t Function,
exint_polarity_config_type line_polarity,
uint8_t PreemptionPriority,
uint8_t SubPriority
)
{
exint_init_type exint_init_struct;
uint8_t Pinx;
if(!IS_PIN(Pin))
return;
Pinx = GPIO_GetPinNum(Pin);
if(Pinx > 15)
return;
EXTI_Function[Pinx] = Function;
crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
gpio_exint_line_config(GPIO_GetPortNum(Pin), (gpio_pins_source_type)Pinx);
exint_default_para_init(&exint_init_struct);
exint_init_struct.line_select = 1 << Pinx;
exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
exint_init_struct.line_polarity = line_polarity;
exint_init_struct.line_enable = TRUE;
exint_init(&exint_init_struct);
nvic_irq_enable(EXTI_GetIRQn(Pin), PreemptionPriority, SubPriority);
}
/**
* @brief 外部中断初始化 (Arduino)
* @param Pin: 引脚编号
* @param function: 回调函数
* @param Trigger_Mode: 触发方式
* @retval 无
*/
void attachInterrupt(uint8_t Pin, EXTI_CallbackFunction_t Function, exint_polarity_config_type line_polarity)
{
EXTIx_Init(
Pin,
Function,
line_polarity,
EXTI_PREEMPTIONPRIORITY_DEFAULT,
EXTI_SUBPRIORITY_DEFAULT
);
}
/**
* @brief 关闭给定的中断 (Arduino)
* @param Pin: 引脚编号
* @retval 无
*/
void detachInterrupt(uint8_t Pin)
{
if(!IS_PIN(Pin))
return;
nvic_irq_disable(EXTI_GetIRQn(Pin));
}
#define EXTIx_IRQHANDLER(n) \
do{\
if(exint_flag_get(EXINT_LINE_##n) != RESET)\
{\
if(EXTI_Function[n]) EXTI_Function[n]();\
exint_flag_clear(EXINT_LINE_##n);\
}\
}while(0)
/**
* @brief 外部中断入口通道0
* @param 无
* @retval 无
*/
void EXTI0_IRQHandler(void)
{
EXTIx_IRQHANDLER(0);
}
/**
* @brief 外部中断入口通道1
* @param 无
* @retval 无
*/
void EXTI1_IRQHandler(void)
{
EXTIx_IRQHANDLER(1);
}
/**
* @brief 外部中断入口通道2
* @param 无
* @retval 无
*/
void EXTI2_IRQHandler(void)
{
EXTIx_IRQHANDLER(2);
}
/**
* @brief 外部中断入口通道3
* @param 无
* @retval 无
*/
void EXTI3_IRQHandler(void)
{
EXTIx_IRQHANDLER(3);
}
/**
* @brief 外部中断入口通道4
* @param 无
* @retval 无
*/
void EXTI4_IRQHandler(void)
{
EXTIx_IRQHANDLER(4);
}
/**
* @brief 外部中断入口通道9~5
* @param 无
* @retval 无
*/
void EXTI9_5_IRQHandler(void)
{
EXTIx_IRQHANDLER(5);
EXTIx_IRQHANDLER(6);
EXTIx_IRQHANDLER(7);
EXTIx_IRQHANDLER(8);
EXTIx_IRQHANDLER(9);
}
/**
* @brief 外部中断入口通道15~10
* @param 无
* @retval 无
*/
void EXTI15_10_IRQHandler(void)
{
EXTIx_IRQHANDLER(10);
EXTIx_IRQHANDLER(11);
EXTIx_IRQHANDLER(12);
EXTIx_IRQHANDLER(13);
EXTIx_IRQHANDLER(14);
EXTIx_IRQHANDLER(15);
}

View File

@@ -0,0 +1,56 @@
/*
* 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.
*/
#ifndef __EXTI_H
#define __EXTI_H
#include "mcu_type.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CHANGE EXINT_TRIGGER_BOTH_EDGE
#define FALLING EXINT_TRIGGER_FALLING_EDGE
#define RISING EXINT_TRIGGER_RISING_EDGE
typedef void(*EXTI_CallbackFunction_t)(void);
void EXTIx_Init(
uint8_t Pin,
EXTI_CallbackFunction_t Function,
exint_polarity_config_type line_polarity,
uint8_t PreemptionPriority,
uint8_t SubPriority
);
void attachInterrupt(
uint8_t Pin,
EXTI_CallbackFunction_t Function,
exint_polarity_config_type polarity_config
);
void detachInterrupt(uint8_t Pin);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,341 @@
/*
* 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 "gpio.h"
const PinInfo_TypeDef PIN_MAP[PIN_MAX] =
{
/*GPIO_Type* GPIOx; //对应GPIOx地址
TIM_Type* TIMx; //对应TIMx地址
ADC_Type* ADCx; //对应ADCx地址
uint16_t GPIO_Pin_x; //对应GPIO_Pin位
uint8_t TimerChannel; //对应定时器通道
uint8_t ADC_CHANNEL;*/ //对应ADC通道
{GPIOA, TIM2, ADC1, GPIO_Pin_0, 1, ADC_CHANNEL_0}, /* PA0 */
{GPIOA, TIM2, ADC1, GPIO_Pin_1, 2, ADC_CHANNEL_1}, /* PA1 */
{GPIOA, TIM2, ADC1, GPIO_Pin_2, 3, ADC_CHANNEL_2}, /* PA2 */
{GPIOA, TIM2, ADC1, GPIO_Pin_3, 4, ADC_CHANNEL_3}, /* PA3 */
{GPIOA, NULL, ADC1, GPIO_Pin_4, 0, ADC_CHANNEL_4}, /* PA4 */
{GPIOA, NULL, ADC1, GPIO_Pin_5, 0, ADC_CHANNEL_5}, /* PA5 */
{GPIOA, TIM3, ADC1, GPIO_Pin_6, 1, ADC_CHANNEL_6}, /* PA6 */
{GPIOA, TIM3, ADC1, GPIO_Pin_7, 2, ADC_CHANNEL_7}, /* PA7 */
{GPIOA, TIM1, NULL, GPIO_Pin_8, 1, ADC_CHANNEL_X}, /* PA8 */
{GPIOA, TIM1, NULL, GPIO_Pin_9, 2, ADC_CHANNEL_X}, /* PA9 */
{GPIOA, TIM1, NULL, GPIO_Pin_10, 3, ADC_CHANNEL_X}, /* PA10 */
{GPIOA, TIM1, NULL, GPIO_Pin_11, 4, ADC_CHANNEL_X}, /* PA11 */
{GPIOA, NULL, NULL, GPIO_Pin_12, 0, ADC_CHANNEL_X}, /* PA12 */
{GPIOA, NULL, NULL, GPIO_Pin_13, 0, ADC_CHANNEL_X}, /* PA13 */
{GPIOA, NULL, NULL, GPIO_Pin_14, 0, ADC_CHANNEL_X}, /* PA14 */
{GPIOA, TIM2, NULL, GPIO_Pin_15, 1, ADC_CHANNEL_X}, /* PA15 */
{GPIOB, TIM3, ADC1, GPIO_Pin_0, 3, ADC_CHANNEL_8}, /* PB0 */
{GPIOB, TIM3, ADC1, GPIO_Pin_1, 4, ADC_CHANNEL_9}, /* PB1 */
{GPIOB, NULL, NULL, GPIO_Pin_2, 0, ADC_CHANNEL_X}, /* PB2 */
{GPIOB, TIM2, NULL, GPIO_Pin_3, 2, ADC_CHANNEL_X}, /* PB3 */
{GPIOB, TIM3, NULL, GPIO_Pin_4, 1, ADC_CHANNEL_X}, /* PB4 */
{GPIOB, TIM3, NULL, GPIO_Pin_5, 2, ADC_CHANNEL_X}, /* PB5 */
{GPIOB, TIM4, NULL, GPIO_Pin_6, 1, ADC_CHANNEL_X}, /* PB6 */
{GPIOB, TIM4, NULL, GPIO_Pin_7, 2, ADC_CHANNEL_X}, /* PB7 */
{GPIOB, TIM4, NULL, GPIO_Pin_8, 3, ADC_CHANNEL_X}, /* PB8 */
{GPIOB, TIM4, NULL, GPIO_Pin_9, 4, ADC_CHANNEL_X}, /* PB9 */
{GPIOB, TIM2, NULL, GPIO_Pin_10, 3, ADC_CHANNEL_X}, /* PB10 */
{GPIOB, TIM2, NULL, GPIO_Pin_11, 4, ADC_CHANNEL_X}, /* PB11 */
{GPIOB, NULL, NULL, GPIO_Pin_12, 0, ADC_CHANNEL_X}, /* PB12 */
{GPIOB, NULL, NULL, GPIO_Pin_13, 0, ADC_CHANNEL_X}, /* PB13 */
#ifdef TMR12
{GPIOB, TIM12, NULL, GPIO_Pin_14, 1, ADC_CHANNEL_X},/* PB14 */
#else
{GPIOB, NULL, NULL, GPIO_Pin_14, 0, ADC_Channel_X},/* PB14 */
#endif /*TMR12*/
{GPIOB, NULL, NULL, GPIO_Pin_15, 0, ADC_CHANNEL_X}, /* PB15 */
{GPIOC, NULL, ADC1, GPIO_Pin_0, 0, ADC_CHANNEL_10},/* PC0 */
{GPIOC, NULL, ADC1, GPIO_Pin_1, 0, ADC_CHANNEL_11},/* PC1 */
{GPIOC, NULL, ADC1, GPIO_Pin_2, 0, ADC_CHANNEL_12},/* PC2 */
{GPIOC, NULL, ADC1, GPIO_Pin_3, 0, ADC_CHANNEL_13},/* PC3 */
{GPIOC, NULL, ADC1, GPIO_Pin_4, 0, ADC_CHANNEL_14},/* PC4 */
{GPIOC, NULL, ADC1, GPIO_Pin_5, 0, ADC_CHANNEL_15},/* PC5 */
{GPIOC, TIM3, NULL, GPIO_Pin_6, 1, ADC_CHANNEL_X}, /* PC6 */
{GPIOC, TIM3, NULL, GPIO_Pin_7, 2, ADC_CHANNEL_X}, /* PC7 */
{GPIOC, TIM3, NULL, GPIO_Pin_8, 3, ADC_CHANNEL_X}, /* PC8 */
{GPIOC, TIM3, NULL, GPIO_Pin_9, 4, ADC_CHANNEL_X}, /* PC9 */
{GPIOC, NULL, NULL, GPIO_Pin_10, 0, ADC_CHANNEL_X}, /* PC10 */
{GPIOC, NULL, NULL, GPIO_Pin_11, 0, ADC_CHANNEL_X}, /* PC11 */
{GPIOC, NULL, NULL, GPIO_Pin_12, 0, ADC_CHANNEL_X}, /* PC12 */
{GPIOC, NULL, NULL, GPIO_Pin_13, 0, ADC_CHANNEL_X}, /* PC13 */
{GPIOC, NULL, NULL, GPIO_Pin_14, 0, ADC_CHANNEL_X}, /* PC14 */
{GPIOC, NULL, NULL, GPIO_Pin_15, 0, ADC_CHANNEL_X}, /* PC15 */
{GPIOD, NULL, NULL, GPIO_Pin_0, 0, ADC_CHANNEL_X}, /* PD0 */
{GPIOD, NULL, NULL, GPIO_Pin_1, 0, ADC_CHANNEL_X}, /* PD1 */
{GPIOD, NULL, NULL, GPIO_Pin_2, 0, ADC_CHANNEL_X}, /* PD2 */
{GPIOD, NULL, NULL, GPIO_Pin_3, 0, ADC_CHANNEL_X}, /* PD3 */
{GPIOD, NULL, NULL, GPIO_Pin_4, 0, ADC_CHANNEL_X}, /* PD4 */
{GPIOD, NULL, NULL, GPIO_Pin_5, 0, ADC_CHANNEL_X}, /* PD5 */
{GPIOD, NULL, NULL, GPIO_Pin_6, 0, ADC_CHANNEL_X}, /* PD6 */
{GPIOD, NULL, NULL, GPIO_Pin_7, 0, ADC_CHANNEL_X}, /* PD7 */
{GPIOD, NULL, NULL, GPIO_Pin_8, 0, ADC_CHANNEL_X}, /* PD8 */
{GPIOD, NULL, NULL, GPIO_Pin_9, 0, ADC_CHANNEL_X}, /* PD9 */
{GPIOD, NULL, NULL, GPIO_Pin_10, 0, ADC_CHANNEL_X}, /* PD10 */
{GPIOD, NULL, NULL, GPIO_Pin_11, 0, ADC_CHANNEL_X}, /* PD11 */
{GPIOD, TIM4, NULL, GPIO_Pin_12, 1, ADC_CHANNEL_X}, /* PD12 */
{GPIOD, TIM4, NULL, GPIO_Pin_13, 2, ADC_CHANNEL_X}, /* PD13 */
{GPIOD, TIM4, NULL, GPIO_Pin_14, 3, ADC_CHANNEL_X}, /* PD14 */
{GPIOD, TIM4, NULL, GPIO_Pin_15, 4, ADC_CHANNEL_X}, /* PD15 */
#ifdef GPIOE
{GPIOE, NULL, NULL, GPIO_Pin_0, 0, ADC_CHANNEL_X}, /* PE0 */
{GPIOE, NULL, NULL, GPIO_Pin_1, 0, ADC_CHANNEL_X}, /* PE1 */
{GPIOE, NULL, NULL, GPIO_Pin_2, 0, ADC_CHANNEL_X}, /* PE2 */
{GPIOE, NULL, NULL, GPIO_Pin_3, 0, ADC_CHANNEL_X}, /* PE3 */
{GPIOE, NULL, NULL, GPIO_Pin_4, 0, ADC_CHANNEL_X}, /* PE4 */
{GPIOE, TIM9, NULL, GPIO_Pin_5, 1, ADC_CHANNEL_X}, /* PE5 */
{GPIOE, TIM9, NULL, GPIO_Pin_6, 2, ADC_CHANNEL_X}, /* PE6 */
{GPIOE, NULL, NULL, GPIO_Pin_7, 0, ADC_CHANNEL_X}, /* PE7 */
{GPIOE, NULL, NULL, GPIO_Pin_8, 0, ADC_CHANNEL_X}, /* PE8 */
{GPIOE, TIM1, NULL, GPIO_Pin_9, 1, ADC_CHANNEL_X}, /* PE9 */
{GPIOE, NULL, NULL, GPIO_Pin_10, 0, ADC_CHANNEL_X}, /* PE10 */
{GPIOE, TIM1, NULL, GPIO_Pin_11, 2, ADC_CHANNEL_X}, /* PE11 */
{GPIOE, NULL, NULL, GPIO_Pin_12, 0, ADC_CHANNEL_X}, /* PE12 */
{GPIOE, TIM1, NULL, GPIO_Pin_13, 3, ADC_CHANNEL_X}, /* PE13 */
{GPIOE, TIM1, NULL, GPIO_Pin_14, 4, ADC_CHANNEL_X}, /* PE14 */
{GPIOE, NULL, NULL, GPIO_Pin_15, 0, ADC_CHANNEL_X}, /* PE15 */
#endif /*GPIOE*/
#ifdef GPIOF
{GPIOF, NULL, NULL, GPIO_Pin_0, 0, ADC_CHANNEL_X}, /* PF0 */
{GPIOF, NULL, NULL, GPIO_Pin_1, 0, ADC_CHANNEL_X}, /* PF1 */
{GPIOF, NULL, NULL, GPIO_Pin_2, 0, ADC_CHANNEL_X}, /* PF2 */
#ifdef ADC3
{GPIOF, NULL, ADC3, GPIO_Pin_3, 0, ADC_CHANNEL_9}, /* PF3 */
{GPIOF, NULL, ADC3, GPIO_Pin_4, 0, ADC_CHANNEL_14},/* PF4 */
{GPIOF, NULL, ADC3, GPIO_Pin_5, 0, ADC_CHANNEL_15},/* PF5 */
{GPIOF, TIM10, ADC3, GPIO_Pin_6, 1, ADC_CHANNEL_4}, /* PF6 */
{GPIOF, TIM11, ADC3, GPIO_Pin_7, 1, ADC_CHANNEL_5}, /* PF7 */
{GPIOF, TIM13, ADC3, GPIO_Pin_8, 1, ADC_CHANNEL_6}, /* PF8 */
{GPIOF, TIM14, ADC3, GPIO_Pin_9, 1, ADC_CHANNEL_7}, /* PF9 */
{GPIOF, NULL, ADC3, GPIO_Pin_10, 0, ADC_CHANNEL_8}, /* PF10 */
#else
{GPIOF, NULL, NULL, GPIO_Pin_3, 0, ADC_CHANNEL_X}, /* PF3 */
{GPIOF, NULL, NULL, GPIO_Pin_4, 0, ADC_CHANNEL_X},/* PF4 */
{GPIOF, NULL, NULL, GPIO_Pin_5, 0, ADC_CHANNEL_X},/* PF5 */
{GPIOF, TIM10, NULL, GPIO_Pin_6, 1, ADC_CHANNEL_X}, /* PF6 */
{GPIOF, TIM11, NULL, GPIO_Pin_7, 1, ADC_CHANNEL_X}, /* PF7 */
{GPIOF, NULL, NULL, GPIO_Pin_8, 0, ADC_CHANNEL_X}, /* PF8 */
{GPIOF, NULL, NULL, GPIO_Pin_9, 0, ADC_CHANNEL_X}, /* PF9 */
{GPIOF, NULL, NULL, GPIO_Pin_10, 0, ADC_CHANNEL_X}, /* PF10 */
#endif /*ADC3*/
{GPIOF, NULL, NULL, GPIO_Pin_11, 0, ADC_CHANNEL_X}, /* PF11 */
{GPIOF, NULL, NULL, GPIO_Pin_12, 0, ADC_CHANNEL_X}, /* PF12 */
{GPIOF, NULL, NULL, GPIO_Pin_13, 0, ADC_CHANNEL_X}, /* PF13 */
{GPIOF, NULL, NULL, GPIO_Pin_14, 0, ADC_CHANNEL_X}, /* PF14 */
{GPIOF, NULL, NULL, GPIO_Pin_15, 0, ADC_CHANNEL_X}, /* PF15 */
#endif /*GPIOF*/
#ifdef GPIOG
{GPIOG, NULL, NULL, GPIO_Pin_0, 0, ADC_CHANNEL_X}, /* PG0 */
{GPIOG, NULL, NULL, GPIO_Pin_1, 0, ADC_CHANNEL_X}, /* PG1 */
{GPIOG, NULL, NULL, GPIO_Pin_2, 0, ADC_CHANNEL_X}, /* PG2 */
{GPIOG, NULL, NULL, GPIO_Pin_3, 0, ADC_CHANNEL_X}, /* PG3 */
{GPIOG, NULL, NULL, GPIO_Pin_4, 0, ADC_CHANNEL_X}, /* PG4 */
{GPIOG, NULL, NULL, GPIO_Pin_5, 0, ADC_CHANNEL_X}, /* PG5 */
{GPIOG, NULL, NULL, GPIO_Pin_6, 0, ADC_CHANNEL_X}, /* PG6 */
{GPIOG, NULL, NULL, GPIO_Pin_7, 0, ADC_CHANNEL_X}, /* PG7 */
{GPIOG, NULL, NULL, GPIO_Pin_8, 0, ADC_CHANNEL_X}, /* PG8 */
{GPIOG, NULL, NULL, GPIO_Pin_9, 0, ADC_CHANNEL_X}, /* PG9 */
{GPIOG, NULL, NULL, GPIO_Pin_10, 0, ADC_CHANNEL_X}, /* PG10 */
{GPIOG, NULL, NULL, GPIO_Pin_11, 0, ADC_CHANNEL_X}, /* PG11 */
{GPIOG, NULL, NULL, GPIO_Pin_12, 0, ADC_CHANNEL_X}, /* PG12 */
{GPIOG, NULL, NULL, GPIO_Pin_13, 0, ADC_CHANNEL_X}, /* PG13 */
{GPIOG, NULL, NULL, GPIO_Pin_14, 0, ADC_CHANNEL_X}, /* PG14 */
{GPIOG, NULL, NULL, GPIO_Pin_15, 0, ADC_CHANNEL_X}, /* PG15 */
#endif /*GPIOG*/
};
/**
* @brief GPIO初始化
* @param GPIOx: GPIO地址
* @param GPIO_Pin_x: GPIO对应位
* @param GPIO_Mode_x: GPIO模式
* @param GPIO_Speed_x: GPIO速度
* @retval 无
*/
void GPIOx_Init(
gpio_type* GPIOx,
uint16_t GPIO_Pin_x,
PinMode_TypeDef Mode,
gpio_drive_type GPIO_Drive_x
)
{
gpio_init_type gpio_init_struct;
crm_periph_clock_type CRM_GPIOx_PERIPH_CLOCK;
if(GPIOx == GPIOA) CRM_GPIOx_PERIPH_CLOCK = CRM_GPIOA_PERIPH_CLOCK;
else if(GPIOx == GPIOB)CRM_GPIOx_PERIPH_CLOCK = CRM_GPIOB_PERIPH_CLOCK;
else if(GPIOx == GPIOC)CRM_GPIOx_PERIPH_CLOCK = CRM_GPIOC_PERIPH_CLOCK;
else if(GPIOx == GPIOD)CRM_GPIOx_PERIPH_CLOCK = CRM_GPIOD_PERIPH_CLOCK;
#ifdef GPIOE
else if(GPIOx == GPIOE)CRM_GPIOx_PERIPH_CLOCK = CRM_GPIOE_PERIPH_CLOCK;
#endif /*GPIOE*/
#ifdef GPIOF
else if(GPIOx == GPIOF)CRM_GPIOx_PERIPH_CLOCK = CRM_GPIOF_PERIPH_CLOCK;
#endif /*GPIOF*/
#ifdef GPIOG
else if(GPIOx == GPIOG)CRM_GPIOx_PERIPH_CLOCK = CRM_GPIOG_PERIPH_CLOCK;
#endif /*GPIOG*/
else return;
gpio_default_para_init(&gpio_init_struct);
gpio_init_struct.gpio_pins = GPIO_Pin_x;
gpio_init_struct.gpio_drive_strength = GPIO_Drive_x;
if(Mode == INPUT)
{
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
}
else if(Mode == INPUT_PULLUP)
{
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_init_struct.gpio_pull = GPIO_PULL_UP;
}
else if(Mode == INPUT_PULLDOWN)
{
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
}
else if(Mode == INPUT_ANALOG)
{
gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
}
else if(Mode == OUTPUT)
{
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
}
else if(Mode == OUTPUT_OPEN_DRAIN)
{
gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
}
else if(Mode == OUTPUT_AF_PP)
{
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
}
else if(Mode == OUTPUT_AF_OD)
{
gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
}
else
{
return;
}
crm_periph_clock_enable(CRM_GPIOx_PERIPH_CLOCK, TRUE);
gpio_init(GPIOx, &gpio_init_struct);
}
/**
* @brief 禁用JTAG引脚
* @param 无
* @retval 无
*/
void GPIO_JTAG_Disable(void)
{
// RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_AFIO, ENABLE);
// GPIO_PinsRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
}
/**
* @brief 获取当前引脚对应的GPIOx编号
* @param Pin: 引脚编号
* @retval 无
*/
uint8_t GPIO_GetPortNum(uint8_t Pin)
{
uint8_t retval = 0xFF;
uint8_t index;
gpio_type* GPIOx = PIN_MAP[Pin].GPIOx;
gpio_type* GPIO_Map[] =
{
GPIOA,
GPIOB,
GPIOC,
GPIOD,
#ifdef GPIOE
GPIOE,
#endif
#ifdef GPIOF
GPIOF,
#endif
#ifdef GPIOG
GPIOG
#endif
};
for(index = 0; index < sizeof(GPIO_Map) / sizeof(GPIO_Map[0]); index++)
{
if(GPIOx == GPIO_Map[index])
{
retval = index;
break;
}
}
return retval;
}
/**
* @brief 获取当前引脚对应的 PinSource
* @param GPIO_Pin_x: GPIO对应位
* @retval 无
*/
uint8_t GPIO_GetPinSource(uint16_t GPIO_Pin_x)
{
uint8_t PinSource = 0;
while(GPIO_Pin_x > 1)
{
GPIO_Pin_x >>= 1;
PinSource++;
}
return PinSource;
}
/**
* @brief 获取当前引脚对应的编号
* @param Pin: 引脚编号
* @retval 无
*/
uint8_t GPIO_GetPinNum(uint8_t Pin)
{
return GPIO_GetPinSource(PIN_MAP[Pin].GPIO_Pin_x);
}

View File

@@ -0,0 +1,121 @@
/*
* 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.
*/
#ifndef __GPIO_H
#define __GPIO_H
#include "mcu_type.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef NULL
# define NULL ((void*)0)
#endif
#define ADC_CHANNEL_X ((uint8_t)0xFF)
#define IS_PIN(Pin) (Pin < PIN_MAX)
#define IS_ADC_PIN(Pin) (IS_PIN(Pin) && PIN_MAP[Pin].ADCx != NULL && PIN_MAP[Pin].ADC_Channel != ADC_CHANNEL_X)
#define IS_PWM_PIN(Pin) (IS_PIN(Pin) && PIN_MAP[Pin].TIMx != NULL && PIN_MAP[Pin].TimerChannel != 0)
#define GPIO_HIGH(GPIOX,GPIO_PIN_X) ((GPIOX)->scr = (GPIO_PIN_X))
#define GPIO_LOW(GPIOX,GPIO_PIN_X) ((GPIOX)->clr = (GPIO_PIN_X))
#define GPIO_READ(GPIOX,GPIO_PIN_X) (((GPIOX)->idt & (GPIO_PIN_X))!=0)
#define GPIO_TOGGLE(GPIOX,GPIO_PIN_X) ((GPIOX)->odt ^= (GPIO_PIN_X))
#define portInputRegister(Port) (&(Port->idt))
#define portOutputRegister(Port) (&(Port->odt))
#define analogInPinToBit(Pin) (Pin)
#define digitalPinToInterrupt(Pin) (Pin)
#define digitalPinToPort(Pin) (PIN_MAP[Pin].GPIOx)
#define digitalPinToBitMask(Pin) (PIN_MAP[Pin].GPIO_Pin_x)
#define digitalWrite_HIGH(Pin) GPIO_HIGH (PIN_MAP[Pin].GPIOx, PIN_MAP[Pin].GPIO_Pin_x)
#define digitalWrite_LOW(Pin) GPIO_LOW (PIN_MAP[Pin].GPIOx, PIN_MAP[Pin].GPIO_Pin_x)
#define digitalRead_FAST(Pin) GPIO_READ (PIN_MAP[Pin].GPIOx, PIN_MAP[Pin].GPIO_Pin_x)
#define togglePin(Pin) GPIO_TOGGLE(PIN_MAP[Pin].GPIOx, PIN_MAP[Pin].GPIO_Pin_x)
#define LED_BUILTIN PC13
typedef enum
{
PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9, PA10, PA11, PA12, PA13, PA14, PA15,
PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15,
PC0, PC1, PC2, PC3, PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, PC13, PC14, PC15,
PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9, PD10, PD11, PD12, PD13, PD14, PD15,
#ifdef GPIOE
PE0, PE1, PE2, PE3, PE4, PE5, PE6, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15,
#endif
#ifdef GPIOF
PF0, PF1, PF2, PF3, PF4, PF5, PF6, PF7, PF8, PF9, PF10, PF11, PF12, PF13, PF14, PF15,
#endif
#ifdef GPIOG
PG0, PG1, PG2, PG3, PG4, PG5, PG6, PG7, PG8, PG9, PG10, PG11, PG12, PG13, PG14, PG15,
#endif
PIN_MAX
} Pin_TypeDef;
typedef struct
{
gpio_type* GPIOx;
tmr_type* TIMx;
adc_type* ADCx;
uint16_t GPIO_Pin_x;
uint8_t TimerChannel;
uint8_t ADC_Channel;
} PinInfo_TypeDef;
typedef enum
{
INPUT,
INPUT_PULLUP,
INPUT_PULLDOWN,
INPUT_ANALOG,
INPUT_ANALOG_DMA,
OUTPUT,
OUTPUT_OPEN_DRAIN,
OUTPUT_AF_OD,
OUTPUT_AF_PP,
PWM
} PinMode_TypeDef;
extern const PinInfo_TypeDef PIN_MAP[PIN_MAX];
void GPIOx_Init(
gpio_type* GPIOx,
uint16_t GPIO_Pin_x,
PinMode_TypeDef Mode,
gpio_drive_type GPIO_Drive_x
);
void GPIO_JTAG_Disable(void);
uint8_t GPIO_GetPortNum(uint8_t Pin);
uint8_t GPIO_GetPinNum(uint8_t Pin);
uint8_t GPIO_GetPinSource(uint16_t GPIO_Pin_x);
#ifdef __cplusplus
}// extern "C"
#endif
#endif

158
cores/arduino/libcore/i2c.c Normal file
View File

@@ -0,0 +1,158 @@
/*
* MIT License
* Copyright (c) 2019 _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"
#include "i2c.h"
void I2Cx_Init(i2c_type *I2Cx, uint32_t baudRate)
{
if(I2Cx == I2C1)
{
crm_periph_clock_enable(CRM_I2C1_PERIPH_CLOCK, TRUE);
pinMode(PB6, OUTPUT_AF_OD);
pinMode(PB7, OUTPUT_AF_OD);
}
#ifdef CRM_I2C2_PERIPH_CLOCK
else if(I2Cx == I2C2)
{
crm_periph_clock_enable(CRM_I2C2_PERIPH_CLOCK, TRUE);
pinMode(PB10, OUTPUT_AF_OD);
pinMode(PB11, OUTPUT_AF_OD);
}
#endif
#ifdef CRM_I2C3_PERIPH_CLOCK
else if(I2Cx == I2C3)
{
crm_periph_clock_enable(CRM_I2C3_PERIPH_CLOCK, TRUE);
pinMode(PA8, OUTPUT_AF_OD);
pinMode(PC9, OUTPUT_AF_OD);
}
#endif
else
{
return;
}
/* reset i2c peripheral */
i2c_reset(I2Cx);
/* i2c peripheral initialization */
i2c_init(I2Cx, I2C_FSMODE_DUTY_2_1, baudRate);
i2c_own_address1_set(I2Cx, I2C_ADDRESS_MODE_7BIT, 0);
i2c_ack_enable(I2Cx, TRUE);
i2c_master_receive_ack_set(I2Cx, I2C_MASTER_ACK_CURRENT);
/* i2c peripheral enable */
i2c_enable(I2Cx, TRUE);
}
void I2Cx_ClearADDRFlag(i2c_type* I2Cx)
{
__IO uint32_t tmpreg;
tmpreg = I2Cx->sts1;
tmpreg = I2Cx->sts2;
}
void I2Cx_Read(i2c_type *I2Cx, uint8_t slaveAddr, uint8_t regAddr, void *buf, uint32_t length)
{
uint8_t *dat = (uint8_t *)buf;
/* enable ack */
i2c_ack_enable(I2Cx, TRUE);
/* generate start condtion */
i2c_start_generate(I2Cx);
while(!i2c_flag_get(I2Cx, I2C_STARTF_FLAG));
while(I2Cx->ctrl1 & I2C_CTRL1_STARTGEN);
i2c_7bit_address_send(I2Cx, (slaveAddr << 1), I2C_DIRECTION_TRANSMIT);
while(!i2c_flag_get(I2Cx, I2C_ADDR7F_FLAG));
I2Cx_ClearADDRFlag(I2Cx);
i2c_data_send(I2Cx, regAddr);
while(!i2c_flag_get(I2Cx, I2C_TDC_FLAG));
i2c_flag_clear(I2Cx, I2C_TDC_FLAG);
i2c_start_generate(I2Cx);
while(!i2c_flag_get(I2Cx, I2C_STARTF_FLAG));
i2c_7bit_address_send(I2Cx, (slaveAddr << 1), I2C_DIRECTION_RECEIVE);
while(!i2c_flag_get(I2Cx, I2C_ADDR7F_FLAG));
I2Cx_ClearADDRFlag(I2Cx);
while(length --)
{
if(!length)
{
i2c_ack_enable(I2Cx, FALSE);
i2c_stop_generate(I2Cx);
}
while(!i2c_flag_get(I2Cx, I2C_RDBF_FLAG));
*dat++ = i2c_data_receive(I2Cx);
}
while(I2Cx->ctrl1 & I2C_CTRL1_STOPGEN);
}
void I2Cx_Write(i2c_type *I2Cx, uint8_t slaveAddr, uint8_t regAddr, void *buf, uint32_t length)
{
uint8_t *dat = (uint8_t *)buf;
i2c_start_generate(I2Cx);
while(!i2c_flag_get(I2Cx, I2C_STARTF_FLAG));
i2c_7bit_address_send(I2Cx, (slaveAddr << 1), I2C_DIRECTION_TRANSMIT);
while(!i2c_flag_get(I2Cx, I2C_ADDR7F_FLAG));
I2Cx_ClearADDRFlag(I2Cx);
i2c_data_send(I2Cx, regAddr);
while(!i2c_flag_get(I2Cx, I2C_TDC_FLAG));
i2c_flag_clear(I2Cx, I2C_TDC_FLAG);
while(length --)
{
i2c_data_send(I2Cx, *dat++);
while(!i2c_flag_get(I2Cx, I2C_TDC_FLAG));
i2c_flag_clear(I2Cx, I2C_TDC_FLAG);
}
i2c_stop_generate(I2Cx);
while(I2Cx->ctrl1 & I2C_CTRL1_STOPGEN);
// while(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_TDE));
// while(!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTFF));
}
uint8_t I2Cx_ReadReg(i2c_type *I2Cx, uint8_t slaveAddr, uint8_t regAddr)
{
uint8_t retval = 0;
I2Cx_Read(I2Cx, slaveAddr, regAddr, &retval, sizeof(uint8_t));
return retval;
}
void I2Cx_WriteReg(i2c_type *I2Cx, uint8_t slaveAddr, uint8_t regAddr, uint8_t value)
{
I2Cx_Write(I2Cx, slaveAddr, regAddr, &value, sizeof(uint8_t));
}

View File

@@ -0,0 +1,39 @@
/*
* MIT License
* Copyright (c) 2019 _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.
*/
#ifndef __HARDWAREI2C_H
#define __HARDWAREI2C_H
#include <stdint.h>
#include "mcu_type.h"
/* I2C START mask */
#define I2C_CTRL1_STARTGEN ((uint16_t)0x0100)
/* I2C STOP mask */
#define I2C_CTRL1_STOPGEN ((uint16_t)0x0200)
void I2Cx_Init(i2c_type *I2Cx, uint32_t baudRate);
void I2Cx_Read(i2c_type *I2Cx, uint8_t slaveAddr, uint8_t regAddr, void *buf, uint32_t length);
void I2Cx_Write(i2c_type *I2Cx, uint8_t slaveAddr, uint8_t regAddr, void *buf, uint32_t length);
uint8_t I2Cx_ReadReg(i2c_type *I2Cx, uint8_t slaveAddr, uint8_t regAddr);
void I2Cx_WriteReg(i2c_type *I2Cx, uint8_t slaveAddr, uint8_t regAddr, uint8_t value);
#endif

View File

@@ -0,0 +1,33 @@
/*
* 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 "mcu_core.h"
void Core_Init(void)
{
system_clock_config();
nvic_priority_group_config(NVIC_PRIORITY_GROUP_2);
// GPIO_JTAG_Disable();
Delay_Init();
ADCx_Init(ADC1);
}

View File

@@ -0,0 +1,49 @@
/*
* 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.
*/
#ifndef __MCU_CORE_H
#define __MCU_CORE_H
#include "at32f403a_407_clock.h"
#define sei() __set_PRIMASK(0)
#define cli() __set_PRIMASK(1)
#include "adc.h"
#include "delay.h"
#include "exti.h"
#include "gpio.h"
#include "pwm.h"
#include "timer.h"
#include "wdg.h"
#ifdef __cplusplus
extern "C" {
#endif
void Core_Init(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,75 @@
/*
* 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.
*/
#ifndef __MCU_TYPE_H
#define __MCU_TYPE_H
#include "at32f403a_407.h"
#include "at32f403a_407_conf.h"
#include "config/mcu_config.h"
#define __AT32__
#define __AT32F4__
// #define F_CPU system_core_clock
// #define F_CPU 80000000L
#define CYCLES_PER_MICROSECOND (F_CPU / 1000000U)
typedef gpio_type GPIO_TypeDef;
typedef spi_type SPI_TypeDef;
typedef tmr_type TIM_TypeDef;
#define GPIO_Pin_0 GPIO_PINS_0
#define GPIO_Pin_1 GPIO_PINS_1
#define GPIO_Pin_2 GPIO_PINS_2
#define GPIO_Pin_3 GPIO_PINS_3
#define GPIO_Pin_4 GPIO_PINS_4
#define GPIO_Pin_5 GPIO_PINS_5
#define GPIO_Pin_6 GPIO_PINS_6
#define GPIO_Pin_7 GPIO_PINS_7
#define GPIO_Pin_8 GPIO_PINS_8
#define GPIO_Pin_9 GPIO_PINS_9
#define GPIO_Pin_10 GPIO_PINS_10
#define GPIO_Pin_11 GPIO_PINS_11
#define GPIO_Pin_12 GPIO_PINS_12
#define GPIO_Pin_13 GPIO_PINS_13
#define GPIO_Pin_14 GPIO_PINS_14
#define GPIO_Pin_15 GPIO_PINS_15
#define GPIO_Pin_All GPIO_PINS_All
#define TIM1 TMR1
#define TIM2 TMR2
#define TIM3 TMR3
#define TIM4 TMR4
#define TIM5 TMR5
#define TIM6 TMR6
#define TIM7 TMR7
#define TIM8 TMR8
#define TIM9 TMR9
#define TIM10 TMR10
#define TIM11 TMR11
#define TIM12 TMR12
#define TIM13 TMR13
#define TIM14 TMR14
#define TIM15 TMR15
#endif

115
cores/arduino/libcore/pwm.c Normal file
View File

@@ -0,0 +1,115 @@
/*
* 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 "pwm.h"
#include "timer.h"
#include "Arduino.h"
/**
* @brief 定时器输出捕获初始化
* @param TIMx: 定时器地址
* @param arr: 自动重装值
* @param psc: 时钟预分频数
* @param TimerChannel: 定时器通道
* @retval 无
*/
static void TIMx_OCxInit(tmr_type* TIMx, uint32_t arr, uint16_t psc, uint8_t TimerChannel)
{
tmr_output_config_type tmr_output_struct;
Timer_ClockCmd(TIMx, true);
tmr_base_init(TIMx, arr, psc);
tmr_cnt_dir_set(TIMx, TMR_COUNT_UP);
tmr_output_default_para_init(&tmr_output_struct);
tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_B;
tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_LOW;
tmr_output_struct.oc_idle_state = TRUE;
tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
tmr_output_struct.occ_idle_state = FALSE;
tmr_output_struct.oc_output_state = TRUE;
tmr_output_struct.occ_output_state = TRUE;
switch(TimerChannel)
{
case 1:
tmr_output_channel_config(TIMx, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
break;
case 2:
tmr_output_channel_config(TIMx, TMR_SELECT_CHANNEL_2, &tmr_output_struct);
break;
case 3:
tmr_output_channel_config(TIMx, TMR_SELECT_CHANNEL_3, &tmr_output_struct);
break;
case 4:
tmr_output_channel_config(TIMx, TMR_SELECT_CHANNEL_4, &tmr_output_struct);
break;
default:
return;
}
tmr_output_enable(TIMx, TRUE);
tmr_counter_enable(TIMx, TRUE);
}
/**
* @brief PWM输出初始化
* @param Pin:引脚编号
* @param Resolution: PWM分辨率
* @param Frequency: PWM频率
* @retval 引脚对应的定时器通道
*/
uint8_t PWM_Init(uint8_t Pin, uint32_t Resolution, uint32_t Frequency)
{
uint32_t arr, psc;
if(!IS_PWM_PIN(Pin))
{
return 0;
}
if(Resolution == 0 || Frequency == 0 || (Resolution * Frequency) > F_CPU)
{
return 0;
}
pinMode(Pin, OUTPUT_AF_PP);
arr = Resolution;
psc = Timer_GetClockMax(PIN_MAP[Pin].TIMx) / Resolution / Frequency;
Timer_SetEnable(PIN_MAP[Pin].TIMx, false);
TIMx_OCxInit(PIN_MAP[Pin].TIMx, arr - 1, psc - 1, PIN_MAP[Pin].TimerChannel);
return PIN_MAP[Pin].TimerChannel;
}
/**
* @brief 输出PWM信号
* @param Pin: 引脚编号
* @param Value: PWM输出值
* @retval PWM占空比值
*/
void PWM_Write(uint8_t Pin, uint32_t Value)
{
Timer_SetCompare(PIN_MAP[Pin].TIMx, PIN_MAP[Pin].TimerChannel, Value);
}

View File

@@ -0,0 +1,41 @@
/*
* 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.
*/
#ifndef __PWM_H
#define __PWM_H
#include "mcu_type.h"
#ifdef __cplusplus
extern "C" {
#endif
#define pwmWrite(pin, value) PWM_Write(pin, value)
uint8_t PWM_Init(uint8_t Pin, uint32_t Resolution, uint32_t Frequency);
void PWM_Write(uint8_t Pin, uint32_t Value);
#ifdef __cplusplus
}
#endif
#endif

303
cores/arduino/libcore/rtc.c Normal file
View File

@@ -0,0 +1,303 @@
/*
* 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 "rtc.h"
static const uint8_t table_week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; //Monthly correction data sheet.
static const uint8_t mon_table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //Month data table of Pingnian
/**
* @brief RTC Init.
* @param None
* @retval None
*/
void RTC_Init(void)
{
/* enable pwc and bpr clocks */
crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
/* allow access to bpr domain */
pwc_battery_powered_domain_access(TRUE);
/* Check Backup data registers is correct*/
if (bpr_data_read(BPR_DATA1) != 0x5051)
{
/* reset backup domain */
bpr_reset();
/* enable the lick osc */
crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);
/* wait till lick is ready */
while(crm_flag_get(CRM_LICK_STABLE_FLAG) == RESET);
/* select the rtc clock source */
crm_rtc_clock_select(CRM_RTC_CLOCK_LICK);
/* enable rtc clock */
crm_rtc_clock_enable(TRUE);
/* wait for rtc registers update */
rtc_wait_update_finish();
/* wait for the register write to complete */
rtc_wait_config_finish();
/* enable the rtc second */
rtc_interrupt_enable(RTC_TS_INT, TRUE);
/* wait for the register write to complete */
rtc_wait_config_finish();
/* set rtc divider: set rtc period to 1sec */
rtc_divider_set(40000);
/* wait for the register write to complete */
rtc_wait_config_finish();
/* Set the RTC time */
RTC_SetTime(2018, 8, 8, 8, 8, 0);
/* wait for the register write to complete */
rtc_wait_config_finish();
/* Writes data to Backup Register */
bpr_data_write(BPR_DATA1, 0x5051);
}
else
{
/* wait for rtc registers update */
rtc_wait_update_finish();
/* wait for the register write to complete */
rtc_wait_config_finish();
/* Clear RTC pending flag */
rtc_flag_clear(RTC_CFGF_FLAG);
/* wait for the register write to complete */
rtc_wait_config_finish();
}
}
/**
* @brief Judeg the Leap year or Pingnian.
* Month 1 2 3 4 5 6 7 8 9 10 11 12
* Leap year 31 29 31 30 31 30 31 31 30 31 30 31
* Pingnian 31 28 31 30 31 30 31 31 30 31 30 31
* @param year
* @retval 1: Leap year
2: Pingnian
*/
static uint8_t Is_Leap_Year(uint16_t year)
{
if(year % 4 == 0)
{
if(year % 100 == 0)
{
if(year % 400 == 0) return 1;
else return 0;
}
else return 1;
}
else return 0;
}
/**
* @brief Set time. Convert the input clock to a second.
* The time basic : 1970.1.1
* legitimate year: 1970 ~ 2099
* @param syear: Year
* smon : Month
* sday : Day
* hour
* min
* sec
* @retval 0: Set time right.
* 1: Set time failed.
*/
uint8_t RTC_SetTime(uint16_t syear, uint8_t smon, uint8_t sday, uint8_t hour, uint8_t min, uint8_t sec)
{
uint32_t t;
uint32_t seccount = 0;
if(syear < 1970 || syear > 2099)
return 1;
for(t = 1970; t < syear; t++)
{
if(Is_Leap_Year(t))seccount += 31622400;
else seccount += 31536000;
}
smon -= 1;
for(t = 0; t < smon; t++)
{
seccount += (uint8_t)mon_table[t] * 86400;
if(Is_Leap_Year(syear) && t == 1)seccount += 86400;
}
seccount += (uint8_t)(sday - 1) * 86400;
seccount += (uint8_t)hour * 3600;
seccount += (uint8_t)min * 60;
seccount += sec;
/* enable pwc and bpr clocks */
crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
/* allow access to bpr domain */
pwc_battery_powered_domain_access(TRUE);
/* Set the RTC counter value */
rtc_counter_set(seccount);
/* wait for the register write to complete */
rtc_wait_config_finish();
return 0;
}
/**
* @brief Set RTC alarm.
* The time basic : 1970.1.1
* legitimate year: 1970 ~ 2099
* @param syear : Year
* smon : Month
* sday : Day
* hour
* min
* sec
* @retval 0: Set Alarm right.
* 1: Set Alarm failed.
*/
uint8_t RTC_SetAlarm(uint16_t syear, uint8_t smon, uint8_t sday, uint8_t hour, uint8_t min, uint8_t sec)
{
uint16_t t;
uint8_t seccount = 0;
if(syear < 1970 || syear > 2099)
return 1;
for(t = 1970; t < syear; t++)
{
if(Is_Leap_Year(t))seccount += 31622400;
else seccount += 31536000;
}
smon -= 1;
for(t = 0; t < smon; t++)
{
seccount += (uint8_t)mon_table[t] * 86400;
if(Is_Leap_Year(syear) && t == 1)seccount += 86400;
}
seccount += (uint8_t)(sday - 1) * 86400;
seccount += (uint8_t)hour * 3600;
seccount += (uint8_t)min * 60;
seccount += sec;
/* enable pwc and bpr clocks */
crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
/* allow access to bpr domain */
pwc_battery_powered_domain_access(TRUE);
/* Set the RTC counter value */
rtc_alarm_set(seccount);
/* wait for the register write to complete */
rtc_wait_config_finish();
return 0;
}
/**
* @brief Get current time.
* @param None.
* @retval None.
*/
void RTC_GetCalendar(RTC_Calendar_TypeDef* calendar)
{
static RTC_Calendar_TypeDef _calendar;
static uint16_t daycnt = 0;
uint32_t timecount = 0;
uint32_t temp = 0;
uint32_t temp1 = 0;
timecount = rtc_counter_get();
temp = timecount / 86400;
if(daycnt != temp)
{
daycnt = temp;
temp1 = 1970;
while(temp >= 365)
{
if(Is_Leap_Year(temp1))
{
if(temp >= 366)temp -= 366;
else
{
temp1++;
break;
}
}
else temp -= 365;
temp1++;
}
_calendar.year = temp1;
temp1 = 0;
while(temp >= 28)
{
if(Is_Leap_Year(_calendar.year) && temp1 == 1)
{
if(temp >= 29)temp -= 29;
else break;
}
else
{
if(temp >= mon_table[temp1])temp -= mon_table[temp1];
else break;
}
temp1++;
}
_calendar.month = temp1 + 1;
_calendar.day = temp + 1;
}
temp = timecount % 86400;
_calendar.hour = temp / 3600;
_calendar.min = (temp % 3600) / 60;
_calendar.sec = (temp % 3600) % 60;
_calendar.week = RTC_GetWeek(_calendar.year, _calendar.month, _calendar.day);
*calendar = _calendar;
}
/**
* @brief Get current week by Input Leap year\mouth\day.
* @param syear : Year
* smon : Month
* sday : Day
* @retval week number.
*/
uint8_t RTC_GetWeek(uint16_t year, uint8_t month, uint8_t day)
{
uint16_t temp2;
uint8_t yearH, yearL;
yearH = year / 100;
yearL = year % 100;
if (yearH > 19)yearL += 100;
temp2 = yearL + yearL / 4;
temp2 = temp2 % 7;
temp2 = temp2 + day + table_week[month - 1];
if (yearL % 4 == 0 && month < 3)
temp2--;
return(temp2 % 7);
}

View File

@@ -0,0 +1,53 @@
/*
* 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.
*/
#ifndef __RTC_H
#define __RTC_H
#include "mcu_type.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
uint8_t hour;
uint8_t min;
uint8_t sec;
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t week;
} RTC_Calendar_TypeDef;
void RTC_Init(void);
void RTC_GetCalendar(RTC_Calendar_TypeDef* calendar);
uint8_t RTC_SetAlarm(uint16_t syear, uint8_t smon, uint8_t sday, uint8_t hour, uint8_t min, uint8_t sec);
uint8_t RTC_GetWeek(uint16_t year, uint8_t month, uint8_t day);
uint8_t RTC_SetTime(uint16_t syear, uint8_t smon, uint8_t sday, uint8_t hour, uint8_t min, uint8_t sec);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,108 @@
/**
* \file syscalls_at32.c
*
* Implementation of newlib syscall.
*
*/
#include "at32f403a_407.h"
#include "at32f403a_407_conf.h"
#if defined ( __GNUC__ ) /* GCC CS3 */
#include <sys/stat.h>
#endif
#include <errno.h>
#undef errno
extern int errno;
extern size_t uart_debug_write(uint8_t *data, uint32_t size);
// Helper macro to mark unused parameters and prevent compiler warnings.
// Appends _UNUSED to the variable name to prevent accidentally using them.
#ifdef UNUSED
#undef UNUSED
#endif
#ifdef __GNUC__
#define UNUSED(x) x ## _UNUSED __attribute__((__unused__))
#else
#define UNUSED(x) x ## _UNUSED
#endif
__attribute__((weak))
caddr_t _sbrk(int incr)
{
extern char _estack; /* Defined in the linker script */
extern char _Min_Stack_Size; /* Defined in the linker script */
extern char _end; /* Defined by the linker */
static char *heap_end = &_end ;
char *prev_heap_end = heap_end;
if (heap_end + incr > (char *)__get_MSP()) {
/* Heap and stack collision */
errno = ENOMEM;
return (caddr_t) -1;
}
/* Ensure to keep minimum stack size defined in the linker script */
if (heap_end + incr >= (char *)(&_estack - &_Min_Stack_Size)) {
errno = ENOMEM;
return (caddr_t) -1;
}
heap_end += incr ;
return (caddr_t) prev_heap_end ;
}
__attribute__((weak))
int _close(UNUSED(int file))
{
return -1;
}
__attribute__((weak))
int _fstat(UNUSED(int file), struct stat *st)
{
st->st_mode = S_IFCHR ;
return 0;
}
__attribute__((weak))
int _isatty(UNUSED(int file))
{
return 1;
}
__attribute__((weak))
int _lseek(UNUSED(int file), UNUSED(int ptr), UNUSED(int dir))
{
return 0;
}
__attribute__((weak))
int _read(UNUSED(int file), UNUSED(char *ptr), UNUSED(int len))
{
return 0;
}
/* Moved to Print.cpp to support Print::printf()
__attribute__((weak))
int _write(UNUSED(int file), char *ptr, int len)
{
}
*/
__attribute__((weak))
void _exit(UNUSED(int status))
{
for (; ;) ;
}
__attribute__((weak))
int _kill(UNUSED(int pid), UNUSED(int sig))
{
errno = EINVAL;
return -1;
}
__attribute__((weak))
int _getpid(void)
{
return 1;
}

View File

@@ -0,0 +1,608 @@
/*
* 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 "timer.h"
typedef enum
{
TIMER1, TIMER2, TIMER3, TIMER4, TIMER5, TIMER6, TIMER7, TIMER8,
TIMER9, TIMER10, TIMER11, TIMER12, TIMER13, TIMER14, TIMER15,
TIMER_MAX
} TIMER_Type;
static Timer_CallbackFunction_t Timer_CallbackFunction[TIMER_MAX] = { 0 };
/**
* @brief 启动或关闭指定定时器的时钟
* @param TIMx:定时器地址
* @param NewState: ENABLE启动DISABLE关闭
* @retval 无
*/
void Timer_ClockCmd(tmr_type* TIMx, bool Enable)
{
int index;
typedef struct
{
tmr_type* tmr;
crm_periph_clock_type crm_periph_clock;
} crm_tmr_clock_map_t;
# define CLOCK_MAP_DEF(n) {TMR##n, CRM_TMR##n##_PERIPH_CLOCK}
static const crm_tmr_clock_map_t clock_map[] =
{
CLOCK_MAP_DEF(1),
CLOCK_MAP_DEF(2),
CLOCK_MAP_DEF(3),
CLOCK_MAP_DEF(4),
CLOCK_MAP_DEF(5),
CLOCK_MAP_DEF(6),
CLOCK_MAP_DEF(7),
CLOCK_MAP_DEF(8),
CLOCK_MAP_DEF(9),
CLOCK_MAP_DEF(10),
CLOCK_MAP_DEF(11),
CLOCK_MAP_DEF(12),
CLOCK_MAP_DEF(13),
CLOCK_MAP_DEF(14)
};
for(index = 0; index < sizeof(clock_map) / sizeof(crm_tmr_clock_map_t); index++)
{
if(TIMx == clock_map[index].tmr)
{
crm_periph_clock_enable(clock_map[index].crm_periph_clock, Enable ? TRUE : FALSE);
}
}
}
static float Qsqrt(float number)
{
long i;
float x2, y;
const float threehalfs = 1.5f;
x2 = number * 0.5f;
y = number;
i = *(long*)&y;
i = 0x5f3759df - (i >> 1);
y = *(float*)&i;
y = y * (threehalfs - (x2 * y * y));
y = y * (threehalfs - (x2 * y * y));
return 1.0f / y;
}
/**
* @brief 频率因数分解,获取接近的值
* @param freq: 中断频率(Hz)
* @param clock: 定时器时钟
* @param *period: 重装值地址
* @param *prescaler: 时钟分频值地址
* @retval 误差值(Hz)
*/
static bool Timer_FreqFactorization(
uint32_t freq,
uint32_t clock,
uint16_t* factor1,
uint16_t* factor2,
int32_t* error
)
{
uint32_t targetProdect;
uint16_t fct1;
uint16_t fct2;
uint16_t fct1_save = 1;
uint16_t fct2_save = 1;
uint16_t fct_max;
uint16_t max_error = 0xFFFF;
if(freq == 0 || freq > clock)
{
return false;
}
/* 获取目标乘积 */
targetProdect = clock / freq;
/* 从targetProdect的平方根开始计算 */
fct1 = Qsqrt(targetProdect);
/* 计算因数最大值,减少遍历次数 */
fct_max = (targetProdect < 0xFFFF) ? targetProdect : 0xFFFF;
/* 遍历使两因数的乘积足够接近prodect */
for(; fct1 > 1; fct1--)
{
for(fct2 = fct1; fct2 < fct_max; fct2++)
{
/* 求误差 */
int32_t newerr = fct1 * fct2 - targetProdect;
if(newerr < 0)
{
newerr = -newerr;
}
if(newerr < max_error)
{
/* 保存最小误差 */
max_error = (uint16_t)newerr;
fct1_save = fct1;
fct2_save = fct2;
/* 最佳 */
if(max_error == 0)
{
break;
}
}
}
}
*factor1 = fct1_save;
*factor2 = fct2_save;
*error = (freq - clock / (fct1_save * fct2_save));
return true;
}
/**
* @brief 将定时中断时间转换为重装值和时钟分频值
* @param time: 中断时间(微秒)
* @param clock: 定时器时钟
* @param *period: 重装值地址
* @param *prescaler: 时钟分频值地址
* @retval 无
*/
static void Timer_TimeFactorization(
uint32_t time,
uint32_t clock,
uint16_t* factor1,
uint16_t* factor2
)
{
const uint32_t cyclesPerMicros = clock / 1000000U;
const uint32_t prodect = time * cyclesPerMicros;
uint16_t fct1, fct2;
if(prodect < cyclesPerMicros * 30)
{
fct1 = 10;
fct2 = prodect / 10;
}
else if(prodect < 65535 * 1000)
{
fct1 = prodect / 1000;
fct2 = prodect / fct1;
}
else
{
fct1 = prodect / 20000;
fct2 = prodect / fct1;
}
*factor1 = fct1;
*factor2 = fct2;
}
/**
* @brief 定时器使能
* @param TIMx: 定时器地址
* @param Enable: 使能
* @retval 无
*/
void Timer_SetEnable(tmr_type* TIMx, bool Enable)
{
tmr_counter_enable(TIMx, Enable ? TRUE : FALSE);
}
/**
* @brief 定时中断配置
* @param TIMx:定时器地址
* @param Time: 中断时间(微秒)
* @param Function: 定时中断回调函数
* @retval 无
*/
void Timer_SetInterrupt(tmr_type* TIMx, uint32_t Time, Timer_CallbackFunction_t Function)
{
uint16_t period = 0;
uint16_t prescaler = 0;
uint32_t clock = Timer_GetClockMax(TIMx);
if(Time == 0)
{
return;
}
/*将定时中断时间转换为重装值和时钟分频值*/
Timer_TimeFactorization(
Time,
clock,
&period,
&prescaler
);
/*定时中断配置*/
Timer_SetInterruptBase(
TIMx,
period,
prescaler,
Function,
TIMER_PREEMPTIONPRIORITY_DEFAULT,
TIMER_SUBPRIORITY_DEFAULT
);
}
/**
* @brief 更新定时中断频率
* @param TIMx:定时器地址
* @param Freq:中断频率
* @retval true: 设置成功
*/
bool Timer_SetInterruptFreqUpdate(tmr_type* TIMx, uint32_t Freq)
{
uint16_t period, prescaler;
uint32_t clock = Timer_GetClockMax(TIMx);
int32_t error;
if(Freq == 0)
return false;
bool success = Timer_FreqFactorization(
Freq,
clock,
&period,
&prescaler,
&error
);
if(!success)
{
return false;
}
tmr_base_init(TIMx, period - 1, prescaler - 1);
return true;
}
/**
* @brief 获取定时器最大频率
* @param TIMx:定时器地址
* @retval 最大频率
*/
uint32_t Timer_GetClockMax(tmr_type* TIMx)
{
static crm_clocks_freq_type crm_clocks_freq_struct = {0};
if(!crm_clocks_freq_struct.sclk_freq)
{
crm_clocks_freq_get(&crm_clocks_freq_struct);
}
return crm_clocks_freq_struct.apb1_freq * 2;
}
/**
* @brief 获取定时器中断频率
* @param TIMx:定时器地址
* @retval 中断频率
*/
uint32_t Timer_GetClockOut(tmr_type* TIMx)
{
uint32_t clock = Timer_GetClockMax(TIMx);
return (clock / ((TIMx->pr + 1) * (TIMx->div + 1)));
}
/**
* @brief 更新定时中断时间
* @param TIMx:定时器地址
* @param Time: 中断时间(微秒)
* @retval 无
*/
void Timer_SetInterruptTimeUpdate(TIM_TypeDef* TIMx, uint32_t Time)
{
uint16_t period, prescaler;
uint32_t clock = Timer_GetClockMax(TIMx);
Timer_TimeFactorization(
Time,
clock,
&period,
&prescaler
);
tmr_base_init(TIMx, period - 1, prescaler - 1);
}
/**
* @brief 定时中断基本配置
* @param TIMx:定时器地址
* @param Period:重装值
* @param Prescaler:时钟分频值
* @param Function: 定时中断回调函数
* @param PreemptionPriority: 抢占优先级
* @param SubPriority: 子优先级
* @retval 无
*/
void Timer_SetInterruptBase(
tmr_type* TIMx,
uint16_t Period,
uint16_t Prescaler,
Timer_CallbackFunction_t Function,
uint8_t PreemptionPriority,
uint8_t SubPriority
)
{
IRQn_Type TMRx_IRQn = (IRQn_Type)0;
TIMER_Type TIMERx = TIMER1;
#define TMRx_IRQ_DEF(n,x_IRQn)\
do{\
if(TIMx == TIM##n)\
{\
TIMERx = TIMER##n;\
TMRx_IRQn = x_IRQn;\
goto match;\
}\
}\
while(0)
/*如果编译器提示identifier "xxx_IRQn" is undefined
*把未定义的注释掉即可
*/
TMRx_IRQ_DEF(1, TMR1_OVF_TMR10_IRQn);
TMRx_IRQ_DEF(2, TMR2_GLOBAL_IRQn);
TMRx_IRQ_DEF(3, TMR3_GLOBAL_IRQn);
TMRx_IRQ_DEF(4, TMR4_GLOBAL_IRQn);
TMRx_IRQ_DEF(5, TMR5_GLOBAL_IRQn);
TMRx_IRQ_DEF(6, TMR6_GLOBAL_IRQn);
TMRx_IRQ_DEF(7, TMR7_GLOBAL_IRQn);
TMRx_IRQ_DEF(8, TMR8_OVF_TMR13_IRQn);
TMRx_IRQ_DEF(9, TMR1_BRK_TMR9_IRQn);
TMRx_IRQ_DEF(10, TMR1_OVF_TMR10_IRQn);
TMRx_IRQ_DEF(11, TMR1_TRG_HALL_TMR11_IRQn);
TMRx_IRQ_DEF(12, TMR8_BRK_TMR12_IRQn);
TMRx_IRQ_DEF(13, TMR8_OVF_TMR13_IRQn);
TMRx_IRQ_DEF(14, TMR8_TRG_HALL_TMR14_IRQn);
match:
if(TMRx_IRQn == 0)
{
return;
}
Timer_CallbackFunction[TIMERx] = Function;
tmr_reset(TIMx);
Timer_ClockCmd(TIMx, true);
tmr_repetition_counter_set(TIMx, 0);
tmr_cnt_dir_set(TIMx, TMR_COUNT_UP);
tmr_base_init(TIMx, Period - 1, Prescaler - 1);
nvic_irq_enable(TMRx_IRQn, PreemptionPriority, SubPriority);
tmr_flag_clear(TIMx, TMR_OVF_FLAG);
tmr_interrupt_enable(TIMx, TMR_OVF_INT, TRUE);
}
/**
* @brief 设置输出比较值
* @param TIMx: 定时器地址
* @param TimerChannel: 定时器通道
* @param Compare:输出比较值
* @retval 无
*/
void Timer_SetCompare(TIM_TypeDef* TIMx, uint8_t TimerChannel, uint32_t Compare)
{
switch(TimerChannel)
{
case 1:
tmr_channel_value_set(TIMx, TMR_SELECT_CHANNEL_1, Compare);
break;
case 2:
tmr_channel_value_set(TIMx, TMR_SELECT_CHANNEL_2, Compare);
break;
case 3:
tmr_channel_value_set(TIMx, TMR_SELECT_CHANNEL_3, Compare);
break;
case 4:
tmr_channel_value_set(TIMx, TMR_SELECT_CHANNEL_4, Compare);
break;
default:
break;
}
}
/**
* @brief 获取捕获值
* @param TIMx: 定时器地址
* @param TimerChannel: 定时器通道
* @retval 捕获值
*/
uint16_t Timer_GetCompare(TIM_TypeDef* TIMx, uint8_t TimerChannel)
{
uint16_t retval = 0;
switch(TimerChannel)
{
case 1:
retval = tmr_channel_value_get(TIMx, TMR_SELECT_CHANNEL_1);
break;
case 2:
retval = tmr_channel_value_get(TIMx, TMR_SELECT_CHANNEL_2);
break;
case 3:
retval = tmr_channel_value_get(TIMx, TMR_SELECT_CHANNEL_3);
break;
case 4:
retval = tmr_channel_value_get(TIMx, TMR_SELECT_CHANNEL_4);
break;
default:
break;
}
return retval;
}
/**
* @brief 更新定时器时钟预分频数
* @param TIMx: 定时器地址
* @param rescaler: 时钟预分频数
* @retval 无
*/
void Timer_SetPrescaler(tmr_type* TIMx, uint16_t rescaler)
{
TIMx->div = rescaler;
}
/**
* @brief 更新定时器自动重装值
* @param TIMx: 定时器地址
* @param Reload: 自动重装值
* @retval 无
*/
void Timer_SetReload(tmr_type* TIMx, uint16_t Reload)
{
TIMx->pr = Reload;
}
/**
* @brief 应用定时器更改
* @param TIMx: 定时器地址
* @retval 无
*/
void Timer_GenerateUpdate(tmr_type* TIMx)
{
TIMx->swevt_bit.ovfswtr = TRUE;
}
#define TMRx_IRQHANDLER(n) \
do{\
if (tmr_flag_get(TMR##n, TMR_OVF_FLAG) != RESET)\
{\
if(Timer_CallbackFunction[TIMER##n])\
{\
Timer_CallbackFunction[TIMER##n]();\
}\
tmr_flag_clear(TMR##n, TMR_OVF_FLAG);\
}\
}while(0)
/**
* @brief 定时中断入口定时器1、10
* @param 无
* @retval 无
*/
void TMR1_OV_TMR10_IRQHandler(void)
{
TMRx_IRQHANDLER(1);
TMRx_IRQHANDLER(10);
}
/**
* @brief 定时中断入口定时器2
* @param 无
* @retval 无
*/
void TMR2_GLOBAL_IRQHandler(void)
{
TMRx_IRQHANDLER(2);
}
/**
* @brief 定时中断入口定时器3
* @param 无
* @retval 无
*/
void TMR3_GLOBAL_IRQHandler(void)
{
TMRx_IRQHANDLER(3);
}
/**
* @brief 定时中断入口定时器4
* @param 无
* @retval 无
*/
void TMR4_GLOBAL_IRQHandler(void)
{
TMRx_IRQHANDLER(4);
}
/**
* @brief 定时中断入口定时器5
* @param 无
* @retval 无
*/
void TMR5_GLOBAL_IRQHandler(void)
{
TMRx_IRQHANDLER(5);
}
/**
* @brief 定时中断入口定时器6
* @param 无
* @retval 无
*/
void TMR6_GLOBAL_IRQHandler(void)
{
#ifdef TMR6
TMRx_IRQHANDLER(6);
#endif
}
/**
* @brief 定时中断入口定时器7
* @param 无
* @retval 无
*/
void TMR7_GLOBAL_IRQHandler(void)
{
#ifdef TMR7
TMRx_IRQHANDLER(7);
#endif
}
/**
* @brief 定时中断入口定时器8、13
* @param 无
* @retval 无
*/
void TMR8_OV_TMR13_IRQHandler(void)
{
TMRx_IRQHANDLER(8);
#ifdef TMR13
TMRx_IRQHANDLER(13);
#endif
}
/**
* @brief 定时中断入口定时器15
* @param 无
* @retval 无
*/
void TMR15_OV_IRQHandler(void)
{
#ifdef TMR15
TMRx_IRQHANDLER(15);
#endif
}

View File

@@ -0,0 +1,58 @@
/*
* 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.
*/
#ifndef __TIMER_H
#define __TIMER_H
#include <stdbool.h>
#include "mcu_type.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void(*Timer_CallbackFunction_t)(void);
void Timer_SetEnable(tmr_type* TIMx, bool Enable);
void Timer_SetInterrupt(tmr_type* TIMx, uint32_t time, Timer_CallbackFunction_t Function);
void Timer_SetInterruptTimeUpdate(tmr_type* TIMx, uint32_t Time);
bool Timer_SetInterruptFreqUpdate(tmr_type* TIMx, uint32_t Freq);
void Timer_SetInterruptBase(
tmr_type* TIMx,
uint16_t Period, uint16_t Prescaler,
Timer_CallbackFunction_t Function,
uint8_t PreemptionPriority, uint8_t SubPriority
);
void Timer_SetCompare(tmr_type* TIMx, uint8_t TimerChannel, uint32_t Compare);
void Timer_SetPrescaler(tmr_type* TIMx, uint16_t Prescaler);
void Timer_SetReload(tmr_type* TIMx, uint16_t Reload);
void Timer_ClockCmd(tmr_type* TIMx, bool Enable);
uint32_t Timer_GetClockMax(tmr_type* TIMx);
uint32_t Timer_GetClockOut(tmr_type* TIMx);
uint16_t Timer_GetCompare(tmr_type* TIMx, uint8_t TimerChannel);
void Timer_GenerateUpdate(tmr_type* TIMx);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,96 @@
/*
* 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 "wdg.h"
uint32_t WDG_Init(uint32_t timeout)
{
uint32_t reload_value;
uint32_t real_timeout = 0;
uint16_t division;
static const uint8_t div_map[] =
{
WDT_CLK_DIV_4, /*!< wdt clock divider value is 4 */
WDT_CLK_DIV_8, /*!< wdt clock divider value is 8 */
WDT_CLK_DIV_16, /*!< wdt clock divider value is 16 */
WDT_CLK_DIV_32, /*!< wdt clock divider value is 32 */
WDT_CLK_DIV_64, /*!< wdt clock divider value is 64 */
WDT_CLK_DIV_128, /*!< wdt clock divider value is 128 */
WDT_CLK_DIV_256 /*!< wdt clock divider value is 256 */
};
/* set reload value
* lick_freq = 40000
* timeout = reload_value * divider / lick_freq * 1000 (ms)
* timeout / divider * lick_freq / 1000 = reload_value
*/
const uint32_t lick_freq = 40000;
for(int i = 0; i < sizeof(div_map) / sizeof(uint8_t); i++)
{
int div = 4 << i;
reload_value = (uint64_t)timeout * lick_freq / div / 1000;
if(reload_value <= 0xFFF)
{
real_timeout = (uint64_t)reload_value * div * 1000 / lick_freq;
division = div_map[i];
break;
}
}
if(reload_value > 0xFFF)
{
return 0;
}
if(crm_flag_get(CRM_WDT_RESET_FLAG) != RESET)
{
/* reset from wdt */
crm_flag_clear(CRM_WDT_RESET_FLAG);
}
/* disable register write protection */
wdt_register_write_enable(TRUE);
/* set the wdt divider value */
wdt_divider_set(division);
/* Set counter reload value */
wdt_reload_value_set(3000 - 1);
/* Reload IWDG counter */
wdt_counter_reload();
/* Enable IWDG (the LSI oscillator will be enabled by hardware) */
wdt_enable();
return real_timeout;
}
void WDG_ReloadCounter(void)
{
wdt_counter_reload();
}

View File

@@ -0,0 +1,39 @@
/*
* 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.
*/
#ifndef __WDT_H
#define __WDT_H
#include "mcu_type.h"
#ifdef __cplusplus
extern "C" {
#endif
uint32_t WDG_Init(uint32_t timeout);
void WDG_ReloadCounter(void);
#ifdef __cplusplus
}
#endif
#endif