STC32通用GPIO中断,库函数配置方式 AI8051U和STC32G已测试没有问题

近来STC的单片机已经出到32位了,并且个人自己打板测试了几个型号,相比之前的51完全不是一个量级,可以通过以下这张图片中的信息来感受一下如今的32位8051单片机的强大,也是很很期待25年的这一新作了!
在这里插入图片描述
配图为AI8052U或叫STC/AI32G144K256 预计今年夏天能用上。

GPIO_INT_LIB.h

#ifndef __GPIO_XINT_H
#define __GPIO_XINT_H
#include "config.h"
//--------------------------------定义变量-----------------------------------
//      7           6          5           4            3           2           1           0     --》
//  10000000    010000000   00100000    00010000    00001000    00000100    00000010    00000001  --》1<<Pin
//    0x80        0x40        0x20        0x10        0x08        0x04        0x02        0x01    --》位 Pin   管脚
#define  P0_ENABLE_IOINT(Pin)	        {P0INTE |= (Pin);}   //1使能
#define  P0_DISENABLE_IOINT(Pin)	    {P0INTE &= ~(Pin);}  //0失能
/*	端口1到7同上方式	*/

//端口中断优先级设置,这种方式看上去简单,但代码量多,不太建议
#define  PO_INT_Priority(n)	 do{ if(n == 0) PINIPH &= ~(0x01), PINIPL &= ~(0x01); \
                                 if(n == 1) PINIPH &= ~(0x01), PINIPL |=  (0x01); \
								 if(n == 2) PINIPH |=  (0x01), PINIPL &= ~(0x01); \
								 if(n == 3) PINIPH |=  (0x01), PINIPL |=  (0x01); \
								}while(0)
/*---------------*/
#define	PxINT_MODE_Fall		0	//下降沿中断
#define	PxINT_MODE_Rise     1	//上升沿中断
#define	PxINT_MODE_LOW		2	//低电平中断
#define	PxINT_MODE_HIGH     3	//高电平中断
//IO中断用户函数
u8 NVIC_PxINT_Init(u8 GPIO_Px, u8 Priority);
u8 GPIO_INT_InitE(u8 GPIO, GPIO_InitTypeDef *GPIOx);
#endif

接着来编写初始化函数

/***********************************************************************************
 * 函 数 名:u8 GPIO_INT_InitE(u8 GPIO, GPIO_InitTypeDef *GPIOx)
 * 功    能:初始化GPIO 端口中断,精确到每个IO口,初始化后立即使能,eg: P0INTE  的7个位对应P0.0到P0.7
 * 参    数:GPIO端口,I/O结构体(管脚和中断模式配置)
 * 返 回 值:无
 * 软件版本:V1.0
 **********************************************************************************/
u8 GPIO_INT_InitE(u8 GPIO_PX, GPIO_InitTypeDef *GPIOx)
{
	if(GPIO_PX > GPIO_P7)	return FAIL;	                //错误
	if(GPIOx->Mode > PxINT_MODE_HIGH)	return FAIL;	//错误
    switch(GPIO_PX)
    {
        case GPIO_P0:
        {
            if(GPIOx->Mode == PxINT_MODE_Fall)		{P0IM1 &= ~(GPIOx->Pin),   P0IM0 &= ~(GPIOx->Pin);}	 //下降沿中断
            if(GPIOx->Mode == PxINT_MODE_Rise)		{P0IM1 &= ~(GPIOx->Pin),   P0IM0 |=  (GPIOx->Pin);}	 //上升沿中断
            if(GPIOx->Mode == PxINT_MODE_LOW)		{P0IM1 |=  (GPIOx->Pin),   P0IM0 &= ~(GPIOx->Pin);}	 //低电平中断
            if(GPIOx->Mode == PxINT_MODE_HIGH)		{P0IM1 |=  (GPIOx->Pin),   P0IM0 |=  (GPIOx->Pin);}	 //高点平中断
            P0_MODE_IO_PU(GPIOx->Pin); //准双向口 内部若上拉,实际可能需要根据选择的中断方式对应配置I/O模式,这里先放到此处
            P0_ENABLE_IOINT(GPIOx->Pin)//使能P0.Pin中断
		}break;
		/* -------------其他端口------------ */
	}
	return SUCCESS;	        //成功
}

/***********************************************************************************
 * 函 数 名: NVIC_PxINT_Init
 * 描    述: PxINT嵌套向量中断控制器初始化.
 * 参    数: Priority: 中断优先级, Priority_0,Priority_1,Priority_2,Priority_3.
 * 返    回: 执行结果 SUCCESS/FAIL.
 * 版    本: V1.0
 **********************************************************************************/
u8 NVIC_PxINT_Init(u8 GPIO_Px, u8 Priority)
{
    if(GPIO_Px > GPIO_P7)	return FAIL;
    if(Priority <= Priority_3)
    {
        if(Priority_0 == Priority) PINIPH &= ~(0x01<<GPIO_Px), PINIPL &= ~(0x01<<GPIO_Px);
        if(Priority_1 == Priority) PINIPH &= ~(0x01<<GPIO_Px), PINIPL |=  (0x01<<GPIO_Px);
		if(Priority_2 == Priority) PINIPH |=  (0x01<<GPIO_Px), PINIPL &= ~(0x01<<GPIO_Px);
		if(Priority_3 == Priority) PINIPH |=  (0x01<<GPIO_Px), PINIPL |=  (0x01<<GPIO_Px);

//        switch(GPIO_Px)  //两种方式都可以,上面的方式代码量小
//        {
//            case GPIO_P0: PO_INT_Priority(Priority); break;
				/*	-------------------   */
//            default: 
//                break;
//        }
    }
    else  return FAIL;
    
	return SUCCESS;
}

最后写测试函数,这里我在发这个文章的时候,也就是25年1月31日,去STC官网看了STC32G的手册 ,发现其中关于下降沿和上升沿模式的注意说明如下:
在这里插入图片描述
其中提到,这两个模式暂不要使用,但笔者测试可用,不知道时芯片本版本还是什么原因,我测试使用的就是STC32G12K128不带其他后缀字母的,暂时没有发现有什么问题

/***********************************************************************************
 * 函 数 名:void GPIO_PxINT_Init()
 * 功    能:IO端口中断,初始化,设置中断IO,以及中断模式、端口优先级等
 * 参    数:无
 * 返 回 值:无
 * 说    明:AI8051U或STC32G支持所有普通I/O可中断,切记需要手动清除中断标志位(详见中断服务函数)
 **********************************************************************************/
void GPIO_PxINT_Init()
{
    GPIO_InitTypeDef  GPIO_PxINT_Structure;

    GPIO_PxINT_Structure.Pin  = GPIO_Pin_0|GPIO_Pin_3;  //要初始化的I/O  eg: GPIO_Pin_0|GPIO_Pin_2;
    GPIO_PxINT_Structure.Mode = PxINT_MODE_Fall;        //初始化的I/O 模式 下降沿触发中断
    GPIO_INT_InitE(GPIO_P0,&GPIO_PxINT_Structure);      //初始化管脚中断模式行 并 >使能< 其管脚中断!!!
//    P0_ENABLE_IOINT(Pinx);                              //  使能P0.Pinx管脚 IO中断,失能:P0_DISENABLE_IOINT(Pin)
    //根据初始化的中断模式选择是否需要开启,内部上下拉电阻
    P0_PULL_UP_ENABLE(GPIO_Pin_0);                      //使能P0.0 口内部上拉电阻!!!

    NVIC_PxINT_Init(GPIO_P0,Priority_0);                //中断优先级配置,对象是端口 PO_INT_Priority(Priority_0);
}

/***********************************************************************************
 * 函 数 名:void Test_GPIO_PxINT()
 * 功    能:STC GPIO中断测试函数,中断服务函数中LED0状态,借用13号中断,或添加支持31以上中断号
 * 参    数:无
 * 返 回 值:无
 * 说    明:AI8051U或STC32G支持所有普通I/O可中断,切记需要手动清除中断标志位(详见中断服务函数)
 **********************************************************************************/
void Test_GPIO_PxINT()
{

    GPIO_LED_Init();
    GPIO_PxINT_Init();          //请前往 STC32_GPIO_ISR.C 中对应的中断服务函数中编写中断服务程序
    Global_IRQ_Enable();

//    OLED_CLS();
//    OLED_P6x8Str(10, 0, "Test P00_INT");

    while(1)
    {
        ;
    }
}

最后想了像还是把中盾服务函数的实现也放出来吧,虽然你说看下手册很容就能够写出来,但是啊,还是展现出来更为直观。
需要注意的是,STC/AI32的GPIO中断是以端口触发的,想要确定具体是哪个管脚则需要软件查询,以下给出简单的查询方式,亦或者自己再细分处理,建立枚举表,通过端口触发后精确到具体的每个I/O上。

//========================================================================
// 函数: void P0xINT_ISR_Handler
// 描述: GPIO P0端口中断函数
// 参数: none.
// 返回: none.
// 版本: V1.0, 2024-11-18
//      如果if判断,将中断服务函数写在其中,不美观,可单独设立一个函数,来写中断服务内容,在进中断后调用
//========================================================================
void P0INT_ISR_Handler (void) interrupt P0INT_VECTOR		//进中断后手动清除标志位
{
    u8 P0x_IRQ;
    P0x_IRQ = P0INTF;       //P0端口中断标志寄存器
    if(P0x_IRQ)
    {
        P0INTF = 0x00;      //清除P0端口中断标志位
        if(P0x_IRQ&GPIO_Pin_0)    /* P0.0中断服务*/
        {
            // TODO: 在此处添加用户代码
            LED_Ctrl(LED0,RVS);
        }

        if(P0x_IRQ&GPIO_Pin_3)    /* P0.3中断服务*/
        {
            // TODO: 在此处添加用户代码
//            LED_Ctrl(LED1,RVS);
        }
/*  还可以继续添加其他管脚的中断服务程序  */
    }
}

完整工程 程序库,后续我会放到个人gitee仓库

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Guard_Byte

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值