[APM32E0]

APM32E030 工程模版的新建与GPIO的使用

[复制链接]
561|7
手机看帖
扫描二维码
随时随地手机跟帖
LIZARD925|  楼主 | 2025-6-14 22:09 | 显示全部楼层 |阅读模式
本帖最后由 LIZARD925 于 2025-6-22 00:24 编辑

#技术资源# #申请原创#
APM32E030系列使用记录--GPIO的使用
我将极海官网APME030的例程,根据B站江科大的例程,新建了一个工程模版,在这里介绍一下模板的结构,并说明如何在这个工程模板上进行GPIO的操作,如点灯、按键等,例程已上传附件,仅供参考。

工程模板的介绍:
336056856d0af71665.png
1、DebugConfig
2、library
3、Listings
4、Objects
5、start
6、user
模版分为这六个文件夹,其中DebugConfig、Listings和Objects文件夹是 Keil MDK 5 自动生成的,DebugConfig文件夹用于存储一些调试配置文件,Listings和Objects文件夹用来存储 Keil MDK 5 编译过程的一些中间文件;library文件夹下放的是APM32E030用到的驱动标准库文件,不需要改;start文件下放的是外设寄存器文件、内核寄存器描述文件、时钟文件等,也不需要更改;user文件夹下,存放中断函数与主函数,可根据自己喜好进行添加。

GPIO操作之点亮LED灯:
我们先打开工程模版,新建一个system 的文件夹,放我们的延时函数,延时函数使用 系统嘀嗒定时器 进行实现,文件添加完成后,记得在工程中添加文件的路径
83984684d81bd9645c.png
将延时函数复制过来即可使用,添加进工程后,如图所示
99846684d66fee22c8.png
#include "apm32e030.h"                  // Device header

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  微秒级延时
  * @param  xus 延时时长,范围:0~233015
  * @retval 无
  */
void Delay_us(uint32_t xus)
{
        SysTick->LOAD = 72 * xus;                                //设置定时器重装值
        SysTick->VAL = 0x00;                                        //清空当前计数值
        SysTick->CTRL = 0x00000005;                                //设置时钟源为HCLK,启动定时器
        while(!(SysTick->CTRL & 0x00010000));        //等待计数到0
        SysTick->CTRL = 0x00000004;                                //关闭定时器
}

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  毫秒级延时
  * @param  xms 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_ms(uint32_t xms)
{
        while(xms--)
        {
                Delay_us(1000);
        }
}

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  秒级延时
  * @param  xs 延时时长,范围:0~4294967295
  * @retval 无
  */
void Delay_s(uint32_t xs)
{
        while(xs--)
        {
                Delay_ms(1000);
        }
}
此时我们写一个简单的IO翻转来测试延时函数的准确性,使用逻辑分析仪进行测量,可看到时间和我们设置的时间相差无几,IO的初始化也可参考例程进行更改
62170684d75e661fae.png 61256684d75fcb783a.png
int main (void)
{
        RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB);        //打开GPIOB的时钟

        GPIO_Config_T GPIO_InitStructure;   
        
        GPIO_InitStructure.mode = GPIO_MODE_OUT;            // 输出模式
        GPIO_InitStructure.pin = GPIO_PIN_6;      
        GPIO_InitStructure.speed = GPIO_SPEED_50MHz;        
        GPIO_InitStructure.outtype = GPIO_OUT_TYPE_PP;        //推挽输出
        GPIO_Config(GPIOB,&GPIO_InitStructure);

        while(1)
        {
                Delay_ms(500);
                GPIO_WriteBitValue(GPIOB,GPIO_PIN_6,0);
                Delay_ms(500);
                GPIO_WriteBitValue(GPIOB,GPIO_PIN_6,1);
        }
}
此时可看到延时函数没问题,我们将点灯程序进行封装,添加hardware文件夹,放入led.c\led.h文件,如图所示,硬件原理图在此链接进行下载:
https://www.geehy.com/uploads/tool/APM32E030R%20Micro-EVB%20V1.0.SchDoc.pdf
949706856d5ab6c765.png 766116856d58c29bb5.png
添加好后,我们根据原理图初始化对应的GPIO口,初始化PB6和PB7这个两个引脚,调用后测试无误,为流水灯的现象,具体代码如下:



#include "LED.h"

void LED_init(void)
{
        RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOB);        //打开GPIOB的时钟

        GPIO_Config_T GPIO_InitStructure;   
        
        GPIO_InitStructure.mode = GPIO_MODE_OUT;            // 输出模式
        GPIO_InitStructure.pin = GPIO_PIN_6|GPIO_PIN_7;      
        GPIO_InitStructure.speed = GPIO_SPEED_50MHz;        
        GPIO_InitStructure.outtype = GPIO_OUT_TYPE_PP;        //推挽输出
        GPIO_Config(GPIOB,&GPIO_InitStructure);
        GPIO_SetBit(GPIOB, GPIO_PIN_6|GPIO_PIN_7);                //初始化LED为灭
}

void LED1_on(void)
{
        GPIO_ClearBit(GPIOB,GPIO_PIN_6);  //亮
}

void LED1_off(void)
{
        GPIO_SetBit(GPIOB,GPIO_PIN_6);  //灭
}

void LED2_on(void)
{
        GPIO_ClearBit(GPIOB,GPIO_PIN_7);  //亮
}

void LED2_off(void)
{
        GPIO_SetBit(GPIOB,GPIO_PIN_7);  //灭
}

void LED1_turn(void)
{
        if(GPIO_ReadOutputBit(GPIOB,GPIO_PIN_6)==0)  //电平反转
        {
                GPIO_SetBit(GPIOB,GPIO_PIN_6);
        }
        else
        {
                GPIO_ClearBit(GPIOB,GPIO_PIN_6);
        }
}

void LED2_turn(void)
{
        if(GPIO_ReadOutputBit(GPIOB,GPIO_PIN_7)==0)  //电平反转
        {
                GPIO_SetBit(GPIOB,GPIO_PIN_7);
        }
        else
        {
                GPIO_ClearBit(GPIOB,GPIO_PIN_7);
        }
}

#ifndef __LED_H__
#define __LED_H__

#include "apm32e030.h"                  // Device header
#include "apm32e030_gpio.h"
#include "apm32e030_rcm.h"

void LED_init(void);

void LED1_on(void);
void LED1_off(void);
void LED2_on(void);
void LED2_off(void);
void LED1_turn(void);
void LED2_turn(void);
               
#endif
#include "apm32e030.h"                  // Device header
#include "Delay.h"
#include "LED.h"


int main (void)
{
        LED_init();
        while(1)
        {
                LED1_turn();
                Delay_ms(500);
                LED2_turn();

        }
}

GPIO操作之按键输入
此例程主要验证APM32E030的GPIO输入功能,对于普通的按键检测,只需初始化GPIO为输入模式,并配置引脚上下拉,在while1中一直读取即可,GPIO初始化:
void key_init(void)
{
        RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);        //打开GPIOA的时钟
        GPIO_Config_T GPIO_InitStructure;   
        
        GPIO_InitStructure.mode = GPIO_MODE_IN;                    // 输入模式
        GPIO_InitStructure.pin = GPIO_PIN_0|GPIO_PIN_1;      
        GPIO_InitStructure.speed = GPIO_SPEED_50MHz;        
        GPIO_InitStructure.pupd = GPIO_PUPD_PU;                        //上拉输入
        GPIO_Config(GPIOA,&GPIO_InitStructure);
}
进行按键的消抖与按键状态的读取,使用的都是通用的函数:
uint8_t key_getnum(void)
{
        uint8_t keynum=0;
        if(GPIO_ReadInputBit(GPIOA,GPIO_PIN_0)==0)//判断按键是否按下
        {
                Delay_ms(10);
                while(GPIO_ReadInputBit(GPIOA,GPIO_PIN_0)==0);
                Delay_ms(10);
                keynum=1;        
        }
        if(GPIO_ReadInputBit(GPIOA,GPIO_PIN_1)==0)//判断按键是否按下
        {
                Delay_ms(10);
                while(GPIO_ReadInputBit(GPIOA,GPIO_PIN_1)==0);
                Delay_ms(10);
                keynum=2;
        }
        return keynum;

}
此时只需在主函数中调用读取,进行按键的判断
304866856d8571d6e9.png

GPIO操作之按键中断输入
对于外部中断输入的验证,我们需要打开引脚的复用,并打开 SYSCFG 时钟,配置中断线与触发边沿,并设置中断优先级为15;
用户手册中也有对SYSCFG 的介绍:主要用于管理地址映射和控制中断,具体是指:控制部分 IO 口上的I2C 的超快模式;TMR16,TMR17,USART1 和 ADC 的 DMA 触发源的重映射;存储器到代码起始区的重映射;管理连接到 GPIO 的外部中断
void key_eint_init(void)        //中断按键
{
        RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_GPIOA);        //打开GPIOA的时钟
        RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SYSCFG);
      
        GPIO_Config_T GPIO_InitStructure;   
      
        GPIO_InitStructure.mode = GPIO_MODE_IN;                    // 输入模式
        GPIO_InitStructure.pin = GPIO_PIN_0|GPIO_PIN_1;      
        GPIO_InitStructure.speed = GPIO_SPEED_50MHz;      
        GPIO_InitStructure.pupd = GPIO_PUPD_PU;                        //上拉输入
        GPIO_Config(GPIOA,&GPIO_InitStructure);
      
        SYSCFG_EINTLine(SYSCFG_PORT_GPIOA, SYSCFG_PIN_0);  //跟管脚
        SYSCFG_EINTLine(SYSCFG_PORT_GPIOA, SYSCFG_PIN_1);
      
        EINT_Config_T EXTI_InitStructure;
        EXTI_InitStructure.line = EINT_LINE0|EINT_LINE1;
        EXTI_InitStructure.lineCmd = ENABLE;
        EXTI_InitStructure.mode = EINT_MODE_INTERRUPT;
        EXTI_InitStructure.trigger = EINT_TRIGGER_FALLING;
        EINT_Config(&EXTI_InitStructure);
      
        NVIC_EnableIRQRequest(EINT0_1_IRQn, 0x0f);
}

此时,即可使用中断的方式进行按键的读取,在中断中加入自己的逻辑:
void EINT0_1_IRQHandler(void)
{
        if (EINT_ReadStatusFlag(EINT_LINE0) == SET)
    {
        EINT_ClearStatusFlag(EINT_LINE0);
                LED1_turn();
    }

    if (EINT_ReadStatusFlag(EINT_LINE1) == SET)
    {
        EINT_ClearStatusFlag(EINT_LINE1);
                LED2_turn();
    }
}
外部中断的中断函数具体在此处:

具体的中断可看用户手册:
728686856db2e7738e.png


3-1 APM32E030-LED流水灯.zip

170.65 KB

2-1 APM32E030 工程模板.zip

168.18 KB

3-2 APM32E030-按键控制LED.zip

172.43 KB

使用特权

评论回复
jobszheng| | 2025-6-15 20:40 | 显示全部楼层
这个小芯片可玩性还是蛮高的。

使用特权

评论回复
幻影书记| | 2025-6-18 15:36 | 显示全部楼层
这个延时函数没有必要了吧!
哪程序需要ns级的延时啊?

使用特权

评论回复
雾里闲逛| | 2025-6-18 17:06 | 显示全部楼层
我觉得LED的初始化还是初始化为开漏模式为好。
当关闭LED灯时,直接断开电路。

使用特权

评论回复
梦之一瞥| | 2025-6-28 22:31 | 显示全部楼层
楼主,您这工程模板的层级划分是不是太多了

使用特权

评论回复
DawnFervor| | 2025-6-28 23:20 | 显示全部楼层
我倒是觉得楼主的分层还是挺实用的。
keil的文件夹,官方提供的库文件夹,自己的文件夹。
在编写程序的过程中,只更新自己的文件夹即可。

使用特权

评论回复
FrostShimmer| | 2025-6-29 16:44 | 显示全部楼层
看楼主把LED的控制放到了hardware里面。我挺犹豫的是放到hardware里面,还是放到board.c/.h里面。

使用特权

评论回复
星云狂想曲| | 2025-6-30 20:46 | 显示全部楼层
楼主使用逻辑分析仪来测量这个LED灯的闪烁频率,时间上面准不?
我倒是一直觉得示波器看着并不准呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

15

主题

17

帖子

0

粉丝