AT32固件库外设使用,ArduinoAPI接口移植,模块化

目录

  • 一、ArduinoAPI移植
  • 一、通用定时器使用
    • 1.计时
    • 1.
    • 2.ETR外部时钟计数
    • 4.ArduinoAPI - timer
  • 三、ADC
    • 1.ADC初始化(非DMA)
    • 2.ADC_DMA 规则通道扫描
  • 六、USB HID IAP
    • 1.准备好Bootloader和app
    • 2.配置好时钟,一定要打开USB
    • 3.将生成的时钟配置复制到bootloader和app对应位置
    • 4 设置bootloader和app的起始位置
    • 5 使用IAP Programmer下载,地址要设置为app地址

一、ArduinoAPI移植

通过arduinoapi实现封装,实现底层分离,支持arduino生态,
通过固件库模块化外设,由ArduinoAPI调用
参考FastShift的封装方式,由于F403A固件库升级,底层需要重新封装

一、通用定时器使用

1.计时

在这里插入图片描述

在这里插入图片描述
由图可以看出AHB时钟为240M
定时器时钟为240M

时间计算
Tout= ((arr+1)(psc+1))/Tclk;
Tclk:TIM3的输入时钟频率(单位为MHz)。
Tout:TIM3溢出时间(单位为us)。
例:计时1ms,输入时钟频率为240MHz。
  arr = 239,psc = 999。
  Tout = ((arr+1)
(psc+1))/Tclk = ((239+1) *(240+1))/240=1000(us)=1(ms)

void trm3_int_init(u16 arr, u16 psc)
{

/* enable tmr1 clock */
  crm_periph_clock_enable(CRM_TMR3_PERIPH_CLOCK, TRUE);

  tmr_base_init(TMR3, arr, psc);
  tmr_cnt_dir_set(TMR3, TMR_COUNT_UP);
  tmr_interrupt_enable(TMR3, TMR_OVF_INT, TRUE);

  /* tmr1 overflow interrupt nvic init */
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_0);
  nvic_irq_enable(TMR3_GLOBAL_IRQn, 1, 0);

  /* enable tmr3 */
  tmr_counter_enable(TMR3, TRUE);  
}
 
void TMR3_GLOBAL_IRQHandler(void)
{ 		  
  TMR3->ists = 0;;
  lv_tick_inc(1);	     
}

1.

2.ETR外部时钟计数

对于外部脉冲(方波)计数,通用的方法为捕获比较方式,由于项目对于脉冲的精度要求比较高,在快速搭建代码测试过后,发现该方法并不能满足需求,进而寻求计数更为精确的方法----ETR计数。

定时器实际就是一个计数器
可选内部、外部、内部触发输入用作计数时钟
即使用外部触发ETR作为计数器触发源

参考https://blog.csdn.net/u010650845/article/details/81781670

4.ArduinoAPI - timer


void Timer_SetInterrupt(TIM_TypeDef* TIMx, uint32_t Time, Timer_CallbackFunction_t Function)
{
    uint16_t period = 0;
    uint16_t prescaler = 0;
    uint32_t clock = TIMER_GET_CLOCK_MAX(TIMx);

    if(!IS_TMR_ALL_PERIPH(TIMx) || Time == 0)
    {
        return;
    }

    /*将定时中断时间转换为重装值和时钟分频值*/
    Timer_TimeFactorization(
        Time,
        clock,
        &period,
        &prescaler
    );

    /*定时中断配置*/
    Timer_SetInterruptBase(
        TIMx,
        period,
        prescaler,
        Function,
        TIMER_PREEMPTIONPRIORITY_DEFAULT,
        TIMER_SUBPRIORITY_DEFAULT
    );
}

三、ADC

1.ADC初始化(非DMA)


/**
  * @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);
    }
    else if(ADCx == ADC3)
    {
        crm_periph_clock_enable(CRM_ADC3_PERIPH_CLOCK, TRUE);
    }
    else
    {
        return;
    }

	/* select combine mode */
	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);
	adc_resolution_set(ADCx, ADC_RESOLUTION_12B);
	
	adc_ordinary_conversion_trigger_set(ADCx, ADC_ORDINARY_TRIG_TMR1CH1, ADC_ORDINARY_TRIG_EDGE_NONE);
	
	adc_dma_mode_enable(ADCx, FALSE);
	adc_dma_request_repeat_enable(ADCx, FALSE);
	adc_interrupt_enable(ADCx, ADC_OCCO_INT, FALSE);
	
	adc_enable(ADCx, TRUE);
	while(adc_flag_get(ADCx, ADC_RDY_FLAG) == RESET);
	
	/* adc calibration */
	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)
{
#if 0
    adc_ordinary_channel_set(ADCx, (adc_channel_select_type)ADC_Channel, 1, ADC_SAMPLETIME_47_5);

    adc_ordinary_software_trigger_enable(ADCx, TRUE);
    while(!adc_flag_get(ADCx, ADC_OCCE_FLAG));
#endif
    return adc_ordinary_conversion_data_get(ADCx);

}

2.ADC_DMA 规则通道扫描

通道注册API

	pinMode(PWR_FWD_L_Pin, INPUT_ANALOG_DMA);
	pinMode(PWR_FWD_M_Pin, INPUT_ANALOG_DMA);
	pinMode(PWR_RET_L_Pin, INPUT_ANALOG_DMA);
	pinMode(PWR_RET_M_Pin, INPUT_ANALOG_DMA);

pinMode会调用ADC_DMA_Register

/**
  * @brief  注册需要DMA搬运的ADC通道
  * @param  ADC_Channel:ADC通道号
  * @retval 见ADC_DMA_Res_Type
  */
ADC_DMA_Res_Type ADC_DMA_Register(uint8_t ADC_Channel)
{
#if 1
    /*初始化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++;
#endif
    return ADC_DMA_RES_OK;
}

ADC_DMA_Init函数必须放到所有ADC_DMA引脚注册完之后

/**
* @brief  ADC DMA 配置  配置ADC和对应DMA,固定ADC1 如果不需要DMA则使用ADCx_Init函数
  *       需要放到初始化最后,或者所有ADC_DMA引脚注册完之后
  * @param  无
  * @retval 无
  */
void ADC_DMA_Init(void)
{

    uint8_t index;
    dma_init_type dma_init_structure;
    adc_base_config_type adc_base_struct;

    /*CLOCK CONFIG*/
    crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    
	/*INTERUPT COFIG*/
	nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);

    /*DMA CONFIG*/
    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);
	
	dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
	
    dma_channel_enable(DMA1_CHANNEL1, TRUE);


    /*ADC CONFIG*/
	adc_combine_mode_select(ADC_INDEPENDENT_MODE);
    adc_base_default_para_init(&adc_base_struct);

    adc_base_struct.sequence_mode = TRUE;
    adc_base_struct.repeat_mode = TRUE;
    adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
    adc_base_struct.ordinary_channel_length = ADC_DMA_RegCnt;
    adc_base_config(ADC1, &adc_base_struct);


    for(index = 0; index < ADC_DMA_RegCnt; index++)
    {
        adc_ordinary_channel_set(
            ADC1,
            (adc_channel_select_type)ADC_DMA_RegChannelList[index],
            index + 1,
            ADC_SAMPLETIME_41_5
        );
    }

  
    adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, 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));

}

两种方式 :1 DMA完成中断中再次软件触发,实现循环采样,中断频率较高
2 ADC_DMA_GetValue中软件触发,需要获取数据时才开启采集
通过CONFIG_ADC_CIRCLE_ENABLE 进行切换

void DMA1_Channel1_IRQHandler(void)
{
  if(dma_flag_get(DMA1_FDT1_FLAG) != RESET)
  {
    dma_flag_clear(DMA1_FDT1_FLAG);
   
	  
#if (CONFIG_ADC_CIRCLE_ENABLE == 1)
	adc_ordinary_software_trigger_enable(ADC1, TRUE);
#else
	   dma_trans_complete_flag = 1;
#endif
  }
}

/**
  * @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;

#if (CONFIG_ADC_CIRCLE_ENABLE == 0) 
	adc_ordinary_software_trigger_enable(ADC1, TRUE);
	while(dma_trans_complete_flag == 0);
	dma_trans_complete_flag = 0;
#endif
	
    return ADC_DMA_ConvertedValue[index];
}

六、USB HID IAP

1.准备好Bootloader和app

在这里插入图片描述

2.配置好时钟,一定要打开USB

在这里插入图片描述

3.将生成的时钟配置复制到bootloader和app对应位置

设置正确才能正确识别HID设备,并且免驱,否则无法识别usb

void system_clock_config(void)
{
   /* reset crm */
  crm_reset();

  /* enable hext */
  crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE);

   /* wait till hext is ready */
  while(crm_hext_stable_wait() == ERROR)
  {
  }


  /* config pll clock resource */
  crm_pll_config(CRM_PLL_SOURCE_HEXT, CRM_PLL_MULT_15, CRM_PLL_OUTPUT_RANGE_GT72MHZ);

  /* 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();
}

4 设置bootloader和app的起始位置

bootloader
在这里插入图片描述

app
在这里插入图片描述
在这里插入图片描述
保持一致

5 使用IAP Programmer下载,地址要设置为app地址

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/108395.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《Attention Is All You Need》阅读笔记

论文标题 《Attention Is All You Need》 XXX Is All You Need 已经成一个梗了&#xff0c;现在出现了很多叫 XXX Is All You Need 的文章&#xff0c;简直标题党啊&#xff0c;也不写方法&#xff0c;也不写结果&#xff0c;有点理解老师扣论文题目了。 作者 这个作者栏太…

vue源码分析(五)——vue render 函数的使用

文章目录 前言一、render函数1、render函数是什么&#xff1f; 二、render 源码分析1.执行initRender方法2.vm._c 和 vm.$createElement 调用 createElement 方法详解&#xff08;1&#xff09;区别&#xff08;2&#xff09;代码 3、原型上的_render方法&#xff08;1&#xf…

视频特效制作软件 After Effects 2023 mac中文版介绍说明

After Effects 2023 mac是一款专业视频特效和动态图形设计软件。ae2023被广泛应用于电影、电视节目、广告和网络媒体等领域&#xff0c;可以创建各种令人惊叹的视觉效果。 在After Effects 2023中&#xff0c;用户可以使用强大的工具和功能来制作复杂的特效和动画。新版本引入了…

数据库简史:多主数据库架构的由来和华为参天引擎的机遇

注&#xff1a;本文发表后&#xff0c;收到了很多后台反馈&#xff0c;其中关于大型机的早期成就不容省略。微调重发本文&#xff0c;纯属个人观点&#xff0c;错谬之处&#xff0c;仍然期待指正。 2023年10月13日&#xff0c;在北京举办的“2023金融业数据库技术大会"上&…

GPT的广泛应用会对互联网公司造成挑战吗?——探讨GPT在实际使用中的应用和影响

文章目录 前言GPT 技术的背景和发展历程GPT 技术对互联网行业的影响GPT 技术在互联网行业中的应用GPT 技术对于用户隐私和数据安全的威胁GPT 技术对于人类工作岗位的影响加强 AI 伦理和监管加强 AI 安全性和隐私保护推动 AI 创新和发展&#xff0c;避免过度依赖 AIGPT 技术是一…

HIT_OS_LAB1 调试分析 Linux 0.00 引导程序

操作系统实验一 姓名&#xff1a;董帅学号&#xff1a;2021111547班级&#xff1a;21R0312 1.1 实验目的 熟悉实验环境掌握如何手写Bochs虚拟机的配置文件掌握Bochs虚拟机的调试技巧掌握操作系统启动的步骤 1.2 实验内容 1.2.1 掌握如何手写Bochs虚拟机的配置文件 boot: f…

2.MySQL的调控按钮——启动选项和系统变量

2.MySQL的调控按钮——启动选项和系统变量 1.启动选项和配置文件1.1 在命令行上使用选项1.2 配置文件中使用选项1.2.1 配置文件路径1.2.2 配置文件的内容1.2.3 特定 MySQL 版本的专用选项组1.2.4 配置文件的优先级1.2.5 同一个配置文件中多个组的优先级1.2.6 defaults-file 的使…

回归预测 | MATLAB实现BO-BiLSTM贝叶斯优化双向长短期神经网络多输入单输出回归预测

回归预测 | MATLAB实现BO-BiLSTM贝叶斯优化双向长短期神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现BO-BiLSTM贝叶斯优化双向长短期神经网络多输入单输出回归预测效果一览基本介绍模型搭建程序设计参考资料 效果一览 基本介绍 MATLAB实现BO-BiLSTM贝叶斯优化双向长…

mysql源码安装

Linux环境 1、mysql下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/5.7.html#downloads 下载参考&#xff1a; 2、把下载的 MySQL 压缩包上传到 Linux 服务器 3、解压mysql-5.7.39-linux-glibc2.12-x86_64.tar.gz tar -zxvf mysql-5.7.39-linux-glibc2.12-x86…

【Linux】解决缓存锁问题:无法获得锁 /var/lib/dpkg/lock-frontend

今天在运行apt-get update更新软件包后&#xff0c;突然发现安装新的软件出现了这个报错&#xff1a;正在等待缓存锁&#xff1a;无法获得锁 /var/lib/dpkg/lock-frontend。锁正由进程 1855&#xff08;unattended-upgr&#xff09;持有。如图。 这个错误通常是由于其他进程正在…

Word批量删除文档属性和个人信息方法图解

投标文件中设计敏感信息&#xff0c;在投标前必须删除&#xff0c;Word批量删除文档属性和个人信息方法图解&#xff1a; 右键word文件属性--详细信息&#xff0c;可以查看如下信息&#xff1b; 删除上述信息的办法&#xff1a; 1.打开word文件---文件 2.检查文档、检查文档 检…

竞赛 深度学习卫星遥感图像检测与识别 -opencv python 目标检测

文章目录 0 前言1 课题背景2 实现效果3 Yolov5算法4 数据处理和训练5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **深度学习卫星遥感图像检测与识别 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐…

Linux操作系统 - 从概念上认识进程

目录 前置知识 冯诺依曼和现代计算机结构 操作系统的理解 进程的概念 进程和PCB 查看进程信息的指令 - ps 进程的一些特性 进程标识符 - PID 进程状态 进程状态的概念 Linux下的进程状态 父子进程 子进程的创建 - fork 僵尸进程 孤儿进程 进程切换 CPU上下文切…

分享54个ASP.NET源码总有一个是你想要的

分享54个ASP.NET源码总有一个是你想要的 链接&#xff1a;https://pan.baidu.com/s/1khPzxtOFP0wUHpg7TBDitg?pwd8888 提取码&#xff1a;8888 项目名称 (ASP.Net)基于三层架构的企业信息管理系统 asp .net mvc编写的房产管理系统 asp.net core mvc 病人管理后台 asp.ne…

【表面缺陷检测】钢轨表面缺陷检测数据集介绍(2类,含xml标签文件)

一、介绍 钢轨表面缺陷检测是指通过使用各种技术手段和设备&#xff0c;对钢轨表面进行检查和测量&#xff0c;以确定是否存在裂纹、掉块、剥离、锈蚀等缺陷的过程。这些缺陷可能会对铁路运输的安全和稳定性产生影响&#xff0c;因此及时进行检测和修复非常重要。钢轨表面缺陷…

pytorch-fastrcnn识别王者荣耀敌方英雄血条

文章目录 前言效果如下实现训练数据获得训练数据和测试数据yaml文件训练py画框文件的修改py测试py 前言 最近看王者荣耀视频看到了一个别人提供的一个百里自动设计解决方案,使用一个外设放在百里的二技能上,然后拖动外设在屏幕上滑动,当外设检测到有敌方英雄时外设自动松开百里…

05、SpringCloud -- 秒杀按钮、秒杀请求流程(各种请求到后台的判断、减库存、下单数据和次数保存)

目录 秒杀按钮代码实现:vue的JS实现:秒杀请求需求:代码前端后端Seckill-apidomainSeckill-serverWebConfig1、秒杀请求判断controller2、重复下单判断MapperService 接口Impl 实现类controller3、库存判断4、秒杀涉及到的操作_01、减库存_02、创建订单对象并保存_03、用户下…

buuctf_练[CSAWQual 2019]Web_Unagi

[CSAWQual 2019]Web_Unagi 文章目录 [CSAWQual 2019]Web_Unagi掌握知识解题思路关键payload 掌握知识 ​ XXE漏洞利用&#xff0c;xml文件转换编码绕过WAF(UTF-8 --> UTF-16)&#xff0c;xml文件格式的书写 ​ 再遇到上传xml文件被拦截&#xff0c;就尝试修改编码再上传&a…

openpnp - 汇川伺服和冰沙主板的连接

文章目录 openpnp - 汇川伺服和冰沙主板的连接概述笔记X轴伺服X轴步进电机X伺服 - 电源进线X轴伺服 - 步进控制线X轴步进电机 - 步进控制线X轴伺服 - 编码器反馈线X轴步进电机 - 编码器反馈线X伺服 - 主板端来的控制信号线主板端 - 主板端来的控制信号线X伺服控制信号线 - 主板…

驱动作业10.28

驱动程序 #include <linux/init.h> #include <linux/module.h> #include<linux/of.h> #include<linux/of_gpio.h> #include<linux/gpio.h> #include<linux/timer.h> #include <linux/fs.h> #include <linux/io.h> #include &…