外部中断
一、ARM Cortex-M4的中断体系
1、定义
中断,意味着中途打断现在干的事情,要处理紧急的事情。二、嵌套向量中断控制寄存器
STM32F4xx中文参考手册中文参考手册.pdf P233~P243
1、NVIC特性
无论是ARM Cortex M0/M3/M4 还是 ARM Cortex-A8/A53/A72/A73等等内核,都有NVIC。
STM32F405xx/07xx 和 STM32F415xx/17xx 具有 82 个可屏蔽(能够通过代码进行开和关中断)中断通道,10个不可屏蔽(无法通过代码关闭该中断)的中断,16 个可编程优先级。
向量意味就是中断源。
向量表,也就是中断源表。
向量表,也就是中断源表。
2、外部中断/事件控制器 (EXTI)
多达 140 个 GPIO(STM32F405xx/07xx 和 STM32F415xx/17xx)通过以下方式连接到 16 个外部中断/事件线:
另外七根 EXTI 线连接方式如下:
● EXTI 线 16 连接到 PVD 输出
● EXTI 线 17 连接到 RTC 闹钟事件
● EXTI 线 18 连接到 USB OTG FS 唤醒事件
● EXTI 线 19 连接到以太网唤醒事件
● EXTI 线 20 连接到 USB OTG HS(在 FS 中配置)唤醒事件
● EXTI 线 21 连接到 RTC 入侵和时间戳事件
● EXTI 线 22 连接到 RTC 唤醒事件
另外七根 EXTI 线连接方式如下:
● EXTI 线 16 连接到 PVD 输出
● EXTI 线 17 连接到 RTC 闹钟事件
● EXTI 线 18 连接到 USB OTG FS 唤醒事件
● EXTI 线 19 连接到以太网唤醒事件
● EXTI 线 20 连接到 USB OTG HS(在 FS 中配置)唤醒事件
● EXTI 线 21 连接到 RTC 入侵和时间戳事件
● EXTI 线 22 连接到 RTC 唤醒事件
3.库函数
a.选择对应的GPIO引脚连接到相应的中断控制线
/** * @brief Selects the GPIO pin used as EXTI Line. * @param EXTI_PortSourceGPIOx : selects the GPIO port to be used as source for * EXTI lines where x can be (A..K) for STM32F42xxx/43xxx devices, (A..I) * for STM32F405xx/407xx and STM32F415xx/417xx devices or (A, B, C, D and H) * for STM32401xx devices. * * @param EXTI_PinSourcex: specifies the EXTI line to be configured. * This parameter can be EXTI_PinSourcex where x can be (0..15, except * for EXTI_PortSourceGPIOI x can be (0..11) for STM32F405xx/407xx * and STM32F405xx/407xx devices and for EXTI_PortSourceGPIOK x can * be (0..7) for STM32F42xxx/43xxx devices. * * @retval None */ void SYSCFG_EXTILineConfig(uint8_t EXTI_PortSourceGPIOx, uint8_t EXTI_PinSourcex)
b.根据EXTI_InitTypeDef结构体进行外部中断控制线0初始化
/** * @brief Initializes the EXTI peripheral according to the specified * parameters in the EXTI_InitStruct. * @param EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure * that contains the configuration information for the EXTI peripheral. * @retval None */ void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
c.根据NVIC_InitTypeDef结构体对中断向量进行配置
/** * @brief Initializes the NVIC peripheral according to the specified * parameters in the NVIC_InitStruct. * @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig() //执行NVIC_Init前,必须调用NVIC_PriorityGroupConfig * function should be called before. * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains * the configuration information for the specified NVIC peripheral. * @retval None */ void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
#include <stdio.h> #include "stm32f4xx.h" #include "sys.h" GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; void delay(void) { int i=0x500000; while(i--); } int main(void) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOF, ENABLE); /* Enable SYSCFG clock ,使能系统配置时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* Connect EXTI Line0 to PA0 pin,将PA0引脚连接到外部中断控制线0 */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); /* 配置PF9引脚为输出模式 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //第9根引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //设置输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽模式,增加驱动电流 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //设置IO的速度为100MHz,频率越高性能越好,频率越低,功耗越低 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //不需要上拉电阻 GPIO_Init(GPIOF, &GPIO_InitStructure); /* PA0 引脚配置为输入模式 */ GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure EXTI Line0,配置外部中断控制线0 */ EXTI_InitStructure.EXTI_Line = EXTI_Line0; //当前使用外部中断控制线0 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿,也意味着按键松开的时候才触发中断 EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能外部中断控制线0,让外部中断控制线0工作 EXTI_Init(&EXTI_InitStructure); /* Enable and set EXTI Line0 Interrupt to the lowest priority */ NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //允许外部中断控制线0触发中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; //抢占优先级为0xF NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; //响应优先级为0xF NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能 NVIC_Init(&NVIC_InitStructure); while(1) { } } void EXTI0_IRQHandler(void) { //检查当前外部中断控制线0是否触发中断 if(EXTI_GetITStatus(EXTI_Line0) == SET) { //添加用户代码 PFout(9)=0; delay(); PFout(9)=1; delay(); /* Clear the EXTI line 0 pending bit,清空外部中断控制线0标志位,告诉CPU我已经完成当前中断请求,可以继续响应下一次的中断请求 */ EXTI_ClearITPendingBit(EXTI_Line0); } }
#include <stdio.h> #include "stm32f4xx.h" #include "sys.h" GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; void delay(void) { int i=0x500000; while(i--); } int main(void) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOF, ENABLE); /* Enable SYSCFG clock ,使能系统配置时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* Connect EXTI Line0 to PA0 pin,将PA0引脚连接到外部中断控制线0 */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); /* 配置PF9引脚为输出模式 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //第9根引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //设置输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽模式,增加驱动电流 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //设置IO的速度为100MHz,频率越高性能越好,频率越低,功耗越低 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //不需要上拉电阻 GPIO_Init(GPIOF, &GPIO_InitStructure); /* PA0 引脚配置为输入模式 */ GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure EXTI Line0,配置外部中断控制线0 */ EXTI_InitStructure.EXTI_Line = EXTI_Line0; //当前使用外部中断控制线0 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿,也意味着按键松开的时候才触发中断 EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能外部中断控制线0,让外部中断控制线0工作 EXTI_Init(&EXTI_InitStructure); /* Enable and set EXTI Line0 Interrupt to the lowest priority */ NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //允许外部中断控制线0触发中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; //抢占优先级为0xF NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; //响应优先级为0xF NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能 NVIC_Init(&NVIC_InitStructure); while(1) { } } void EXTI0_IRQHandler(void) { //检查当前外部中断控制线0是否触发中断 if(EXTI_GetITStatus(EXTI_Line0) == SET) { //添加用户代码 PFout(9)=0; delay(); PFout(9)=1; delay(); /* Clear the EXTI line 0 pending bit,清空外部中断控制线0标志位,告诉CPU我已经完成当前中断请求,可以继续响应下一次的中断请求 */ EXTI_ClearITPendingBit(EXTI_Line0); } }
4、中断优先级
中断优先级的一个意义:出现多个中断同时触发,但是不能同时处理,所以先后顺序之分,要根据实际上的运行环境优先处理重要的中断。
a.概述
STM32对中断进行分组,共5组,组0~4。同时,对每个中断设置一个抢占优先级和一个响应优先级级。
STM32对中断进行分组,共5组,组0~4。同时,对每个中断设置一个抢占优先级和一个响应优先级级。
函数原型如下:
/** * @brief Configures the priority grouping: pre-emption priority and subpriority. * @param NVIC_PriorityGroup: specifies the priority grouping bits length. * This parameter can be one of the following values: * @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority //没有抢占优先级 * 4 bits for subpriority //4位设置响应优先级 * @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority //1位抢占优先级,能设置2个中断抢占优先级 * 3 bits for subpriority //3位设置响应优先级 * @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority //2位抢占优先级,能设置4个中断抢占优先级 * 2 bits for subpriority //2位设置响应优先级 * @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority //3位抢占优先级,能设置8个中断抢占优先级 * 1 bits for subpriority //1位设置响应优先级 * @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority //4位抢占优先级,能设置16个中断抢占优先级 * 0 bits for subpriority //没有响应优先级 * @note When the NVIC_PriorityGroup_0 is selected, IRQ pre-emption is no more possible. * The pending IRQ priority will be managed only by the subpriority. * @retval None */ void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
只要开机初始化一次就可以了。
b.抢占优先级与响应优先级区别
b.抢占优先级与响应优先级区别
1)高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。
2)抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
3)抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
4)无论是抢占优先级还是响应优先级,优先级数值越小,就代表优先级越高。
2)抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。
3)抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。
4)无论是抢占优先级还是响应优先级,优先级数值越小,就代表优先级越高。
如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;
例:假定设置中断优先级组为2,然后设置中断3(RTC中断)的抢占优先级为2,响应优先级为1。
中断6(外部中断0)的抢占优先级为3,响应优先级为0。中断7(外部中断1)的抢占优先级为2,响应优先级为0。
中断7>中断3>中断6。
exti0234
中断6(外部中断0)的抢占优先级为3,响应优先级为0。中断7(外部中断1)的抢占优先级为2,响应优先级为0。
中断7>中断3>中断6。
#include <stdio.h> #include "stm32f4xx.h" #include "sys.h" GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; __IO uint32_t TimingDelay; void delay(void) { int i=0x5000000; while(i--); } void TimingDelay_Decrement(void)//滴答时钟的中断函数 { if (TimingDelay != 0) { TimingDelay--; } } void Delay(__IO uint32_t nTime)//延时函数 { TimingDelay = nTime; while(TimingDelay != 0); } int main(void) { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF, ENABLE); /* Enable SYSCFG clock ,使能系统配置时钟*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* Connect EXTI Line0 to PA0 pin,将PA0引脚连接到外部中断控制线0 */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); /* Connect EXTI Line2 to PE2 pin,将PE2引脚连接到外部中断控制线2 */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource2); /* Connect EXTI Line3 to PE3 pin,将PE3引脚连接到外部中断控制线3 */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource3); /* Connect EXTI Line4 to PE4 pin,将PE4引脚连接到外部中断控制线4 */ SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource4); /* PA0 引脚配置为输入模式 */ GPIO_InitStructure.GPIO_Pin =GPIO_Pin_0 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); /* PE2 PE3 PE4 引脚配置为输入模式 */ GPIO_InitStructure.GPIO_Pin =GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOE, &GPIO_InitStructure); /* Configure PF9 PF10 in output pushpull mode,配置PF9 PF10引脚为输出模式 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; //第9根和10根引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //设置输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽模式,增加驱动电流 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //设置IO的速度为100MHz,频率越高性能越好,频率越低,功耗越低 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //不需要上拉电阻 GPIO_Init(GPIOF, &GPIO_InitStructure); /* Configure PE13 PE14 in output pushpull mode,配置PE13 PE14引脚为输出模式 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14; //第13根和14根引脚 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; //设置输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽模式,增加驱动电流 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //设置IO的速度为100MHz,频率越高性能越好,频率越低,功耗越低 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //不需要上拉电阻 GPIO_Init(GPIOE, &GPIO_InitStructure); /* Configure EXTI Line0 2 3 4,配置外部中断控制线0 2 3 4*/ EXTI_InitStructure.EXTI_Line = EXTI_Line0|EXTI_Line2|EXTI_Line3|EXTI_Line4; //当前使用外部中断控制线0 2 3 4 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //上升沿,也意味着按键松开的时候才触发中断 EXTI_InitStructure.EXTI_LineCmd = ENABLE; //使能外部中断控制线0 2 3 4 ,让外部中断控制线0 2 3 4工作 EXTI_Init(&EXTI_InitStructure); //配置中断优先级的分组 //配置支持4个抢占优先级,支持4个响应优先级 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; //允许外部中断控制线0触发中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03; //抢占优先级为0x3,最低优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //响应优先级为0x3,最低优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能 NVIC_Init(&NVIC_InitStructure); //中断优先级数值越大,优先级就越小 //数值0,优先级是最高 NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn; //允许外部中断控制线2触发中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; //抢占优先级为0x3,最低优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02; //响应优先级为0x3,最低优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能 NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn; //允许外部中断控制线3触发中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01; //抢占优先级为0x3,最低优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01; //响应优先级为0x3,最低优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能 NVIC_Init(&NVIC_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn; //允许外部中断控制线4触发中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03; //抢占优先级为0x3,最低优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; //响应优先级为0x3,最低优先级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能 NVIC_Init(&NVIC_InitStructure); PFout(9)=1; PFout(10)=1; PEout(13)=1; PEout(14)=1; if(SysTick_Config(SystemCoreClock / 1000)) //1ms中断一次 { /* Capture error */ while (1);//写初值成功---则进入while死循环-等待滴答时钟的中断到来 } while(1) { } } void EXTI0_IRQHandler(void) { //检查当前外部中断控制线0是否触发中断 if(EXTI_GetITStatus(EXTI_Line0) == SET) { //添加用户代码 PFout(9)=0; Delay(1000);//delay(); PFout(9)=1; delay(); /* Clear the EXTI line 0 pending bit,清空外部中断控制线0标志位,告诉CPU我已经完成当前中断请求,可以继续响应下一次的中断请求 */ EXTI_ClearITPendingBit(EXTI_Line0); } } void EXTI2_IRQHandler(void) { //检查当前外部中断控制线2是否触发中断 if(EXTI_GetITStatus(EXTI_Line2) == SET) { //添加用户代码 PFout(10)=0; delay(); PFout(10)=1; delay(); /* 清空外部中断控制线2标志位,告诉CPU我已经完成当前中断请求,可以继续响应下一次的中断请求 */ EXTI_ClearITPendingBit(EXTI_Line2); } } void EXTI3_IRQHandler(void) { //检查当前外部中断控制线3是否触发中断 if(EXTI_GetITStatus(EXTI_Line3) == SET) { //添加用户代码 PEout(13)=0; delay(); PEout(13)=1; delay(); /* 清空外部中断控制线3标志位,告诉CPU我已经完成当前中断请求,可以继续响应下一次的中断请求 */ EXTI_ClearITPendingBit(EXTI_Line3); } } void EXTI4_IRQHandler(void) { //检查当前外部中断控制线4是否触发中断 if(EXTI_GetITStatus(EXTI_Line4) == SET) { //添加用户代码 PEout(14)=0; delay(); PEout(14)=1; delay(); /* 清空外部中断控制线4标志位,告诉CPU我已经完成当前中断请求,可以继续响应下一次的中断请求 */ EXTI_ClearITPendingBit(EXTI_Line4); } }
c.注意事项
1)一般情况下,系统代码执行过程中,只设置一次中断优先级分组,比如分组2,设置好分组之后一般不会再改变分组。
随意改变分组会导致中断管理混乱,程序出现意想不到的执行结果。
2)中断优先级设置步骤
.系统运行后先设置中断优先级分组。调用函数:
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
整个系统执行过程中,只设置一次中断分组。
.针对每个中断,设置对应的抢占优先级和响应优先级:
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);
整个系统执行过程中,只设置一次中断分组。
.针对每个中断,设置对应的抢占优先级和响应优先级:
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct);
.如果需要挂起/解挂,查看中断当前激活状态,分别调用相关函数即可。
启动文件startup_stm32f40_41xxx.s看汇编代码
系统时钟SysTick,Cortex M3与M4权威指南.pdf P313
定时器TIM,STM32F4xx中文参考手册.pdf P392
系统时钟SysTick,Cortex M3与M4权威指南.pdf P313
定时器TIM,STM32F4xx中文参考手册.pdf P392
https://www.cnblogs.com/worldsing/p/3433529.html