近来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;
}
最后写测试函数
/***********************************************************************************
* 函 数 名: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);
}
/* 还可以继续添加其他管脚的中断服务程序 */
}
}