在FSMC中,INT2~3和INTR引脚是三个外部中断,可高电平触发(EXTI没有的功能)、上升沿或下降沿触发。中断引脚分别是PG6、PG7和PF10。不打开相应的FSMC Bank(FSMC_PCRx_PBKEN=0)也能触发中断。其中上升/下降沿可通过软件对标志位写1来触发。
下面的程序通过改变各中断引脚内部所接的上下拉电阻来改变引脚电平,进而触发相应的中断。
#include <stdio.h>
#include <stm32f10x.h>
int fputc(int ch, FILE *fp)
{
if (fp == stdout)
{
if (ch == '\n')
{
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, '\r');
}
while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, ch);
}
return ch;
}
int main(void)
{
GPIO_InitTypeDef gpio;
USART_InitTypeDef usart;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG | RCC_APB2Periph_USART1, ENABLE);
gpio.GPIO_Mode = GPIO_Mode_AF_PP;
gpio.GPIO_Pin = GPIO_Pin_9;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio);
gpio.GPIO_Mode = GPIO_Mode_IPD; // 接内部下拉电阻
gpio.GPIO_Pin = GPIO_Pin_10; // PF10为INTR引脚
GPIO_Init(GPIOF, &gpio);
gpio.GPIO_Mode = GPIO_Mode_IPD; // 接内部下拉电阻
gpio.GPIO_Pin = GPIO_Pin_7; // PG7为INT3引脚
GPIO_Init(GPIOG, &gpio);
USART_StructInit(&usart);
usart.USART_BaudRate = 115200;
USART_Init(USART1, &usart);
USART_Cmd(USART1, ENABLE);
printf("FSMC Interrupt Test\n");
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
NVIC_EnableIRQ(USART1_IRQn);
FSMC_ITConfig(FSMC_Bank3_NAND, FSMC_IT_RisingEdge | FSMC_IT_FallingEdge, ENABLE);
FSMC_ITConfig(FSMC_Bank4_PCCARD, FSMC_IT_RisingEdge | FSMC_IT_FallingEdge, ENABLE);
NVIC_EnableIRQ(FSMC_IRQn);
// FSMC的Bank3~4不启用也能触发中断
// 外部存储芯片的ready/busy引脚应该全部接到NWAIT上, 不应该接到INT引脚上, 否则无法使用FSMC的WAIT引脚等待功能
// ready/busy引脚通常为开漏输出, 所以只要有一个芯片拉低了NWAIT, PD6就为低电平
while (1)
__WFI();
}
void FSMC_IRQHandler(void)
{
if (FSMC_GetITStatus(FSMC_Bank3_NAND, FSMC_IT_RisingEdge) == SET)
{
FSMC_ClearITPendingBit(FSMC_Bank3_NAND, FSMC_IT_RisingEdge);
printf("Interrupt rising edge in Bank 3!\n");
}
if (FSMC_GetITStatus(FSMC_Bank3_NAND, FSMC_IT_FallingEdge) == SET)
{
FSMC_ClearITPendingBit(FSMC_Bank3_NAND, FSMC_IT_FallingEdge);
printf("Interrupt falling edge in Bank 3!\n");
}
if (FSMC_GetITStatus(FSMC_Bank4_PCCARD, FSMC_IT_RisingEdge) == SET)
{
FSMC_ClearITPendingBit(FSMC_Bank4_PCCARD, FSMC_IT_RisingEdge);
printf("Interrupt rising edge in Bank 4!\n");
}
if (FSMC_GetITStatus(FSMC_Bank4_PCCARD, FSMC_IT_FallingEdge) == SET)
{
FSMC_ClearITPendingBit(FSMC_Bank4_PCCARD, FSMC_IT_FallingEdge);
printf("Interrupt falling edge in Bank 4!\n");
}
}
void USART1_IRQHandler(void)
{
uint8_t data = USART_ReceiveData(USART1);
printf("[Key %c] ", data);
switch (data)
{
case 'a':
// 改变PG7上所接的内部上/下拉电阻
printf("PG7=%d\n", GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_7));
GPIOG->ODR ^= GPIO_ODR_ODR7;
break;
case 'b':
// 高电平中断会反复触发, 所以放在这里
if (FSMC_GetFlagStatus(FSMC_Bank3_NAND, FSMC_FLAG_Level) == SET)
{
FSMC_ClearFlag(FSMC_Bank3_NAND, FSMC_FLAG_Level);
printf("Interrupt high-level occurred in Bank 3!\n");
}
else
printf("\n");
break;
case 'c':
// 改变PF10上所接的内部上/下拉电阻
printf("PF10=%d\n", GPIO_ReadInputDataBit(GPIOF, GPIO_Pin_10));
GPIOF->ODR ^= GPIO_ODR_ODR10;
break;
case 'd':
if (FSMC_GetFlagStatus(FSMC_Bank4_PCCARD, FSMC_FLAG_Level) == SET)
{
FSMC_ClearFlag(FSMC_Bank4_PCCARD, FSMC_FLAG_Level);
printf("Interrupt high-level occurred in Bank 4!\n");
}
else
printf("\n");
break;
case 'e':
if (FSMC_GetFlagStatus(FSMC_Bank2_NAND, FSMC_FLAG_FEMPT) == SET)
printf("FSMC Bank2 FIFO empty!\n");
if (FSMC_GetFlagStatus(FSMC_Bank3_NAND, FSMC_FLAG_FEMPT) == SET)
printf("FSMC Bank3 FIFO empty!\n");
if (FSMC_GetFlagStatus(FSMC_Bank4_PCCARD, FSMC_FLAG_FEMPT) == SET)
printf("FSMC Bank4 FIFO empty!\n");
break;
case 'f':
// 可软件触发中断
FSMC_Bank3->SR3 |= FSMC_SR3_IRS; // rising
break;
case 'g':
FSMC_Bank3->SR3 |= FSMC_SR3_IFS; // falling
break;
case 'h':
FSMC_Bank4->SR4 |= FSMC_SR4_IRS;
break;
case 'i':
FSMC_Bank4->SR4 |= FSMC_SR4_IFS;
break;
default:
printf("\n");
}
// 注意: 高电平中断ILS不可通过对标志位写1触发
}
程序运行结果:
FSMC Interrupt Test
Interrupt rising edge in Bank 3!
Interrupt falling edge in Bank 3!
Interrupt rising edge in Bank 4!
Interrupt falling edge in Bank 4!
[Key b] Interrupt high-level occurred in Bank 3!
[Key b]
[Key b]
[Key b]
[Key a] PG7=0
Interrupt rising edge in Bank 3!
[Key b] Interrupt high-level occurred in Bank 3!
[Key b] Interrupt high-level occurred in Bank 3!
[Key b] Interrupt high-level occurred in Bank 3!
[Key b] Interrupt high-level occurred in Bank 3!
[Key a] PG7=1
Interrupt falling edge in Bank 3!
[Key b] Interrupt high-level occurred in Bank 3!
[Key b]
[Key b]
[Key b]
[Key d] Interrupt high-level occurred in Bank 4!
[Key d]
[Key d]
[Key d]
[Key c] PF10=0
Interrupt rising edge in Bank 4!
[Key d] Interrupt high-level occurred in Bank 4!
[Key d] Interrupt high-level occurred in Bank 4!
[Key d] Interrupt high-level occurred in Bank 4!
[Key d] Interrupt high-level occurred in Bank 4!
[Key c] PF10=1
Interrupt falling edge in Bank 4!
[Key d] Interrupt high-level occurred in Bank 4!
[Key d]
[Key d]
[Key d]
[Key c] PF10=0
Interrupt rising edge in Bank 4!
[Key d] Interrupt high-level occurred in Bank 4!
[Key d] Interrupt high-level occurred in Bank 4!
[Key d] Interrupt high-level occurred in Bank 4!
[Key d] Interrupt high-level occurred in Bank 4!
[Key e] FSMC Bank2 FIFO empty!
FSMC Bank3 FIFO empty!
FSMC Bank4 FIFO empty!
[Key f] Interrupt rising edge in Bank 3!
[Key g] Interrupt falling edge in Bank 3!
[Key f] Interrupt rising edge in Bank 3!
[Key g] Interrupt falling edge in Bank 3!
[Key h] Interrupt rising edge in Bank 4!
[Key h] Interrupt rising edge in Bank 4!
[Key h] Interrupt rising edge in Bank 4!
[Key i] Interrupt falling edge in Bank 4!
[Key i] Interrupt falling edge in Bank 4!
[Key i] Interrupt falling edge in Bank 4!
程序最开始运行时标志位FSMC_SRx_IFS、FSMC_SRx_IRS、FSMC_SRx_ILS的状态是不定的,也可能都默认置位了,也可能部分置位,或者全部为0,所以打开FSMC中断前最好清除一下所有的标志位,防止误判:
FSMC_ClearFlag(FSMC_Bank3_NAND, FSMC_FLAG_Level);
FSMC_ClearFlag(FSMC_Bank3_NAND, FSMC_FLAG_RisingEdge);
FSMC_ClearFlag(FSMC_Bank3_NAND, FSMC_FLAG_FallingEdge);
FSMC_ClearFlag(FSMC_Bank4_PCCARD, FSMC_FLAG_Level);
FSMC_ClearFlag(FSMC_Bank4_PCCARD, FSMC_FLAG_RisingEdge);
FSMC_ClearFlag(FSMC_Bank4_PCCARD, FSMC_FLAG_FallingEdge);
FSMC_ITConfig(FSMC_Bank3_NAND, FSMC_IT_RisingEdge | FSMC_IT_FallingEdge, ENABLE);
FSMC_ITConfig(FSMC_Bank4_PCCARD, FSMC_IT_RisingEdge | FSMC_IT_FallingEdge, ENABLE);
NVIC_EnableIRQ(FSMC_IRQn);