【发布时间】:2020-12-24 00:37:07
【问题描述】:
我正在尝试对 STM32 微控制器的编程有一个基本的了解。我正在尝试使用按钮的外部中断来切换 LED 的状态,方法是设置所有适当的寄存器(没有外部库/定义)。我似乎无法让中断例程工作,控制永远不会传递给处理程序。
这是我用来将 PC-13(根据 Nucleo-G070RB 板连接了一个按钮)设置为外部中断的方法:
RCC_APBENR2 |= 0b1 << 0; // Enable SYSCFGEN
RCC_IOPENR |= 0b1 << 2; // Enable PORTC
EXTI_RTSR1 |= 0b1 << 13; // Enable interrupt on rising edge at EXTI line 13
EXTI_EXTICR4 |= 0x2 << 8; // Set PC-13 as GPIO pin for interrupt
EXTI_IMR1 |= 0x1 << 13; // Unmask EXTI line 13
NVIC_ISER |= 0b1 << 7; // Enable interrupts for EXTI4_15
我不确定我错过了什么。
这是完整的代码:
#include <stdint.h>
#include <stdio.h>
#define RCC_IOPENR *((uint32_t volatile *) 0x40021034)
#define RCC_APBENR2 *((uint32_t volatile *) 0x40021040)
#define GPIOA_MODER *((uint32_t volatile *) 0x50000000)
#define GPIOA_IDR *((uint32_t volatile *) 0x50000010)
#define GPIOA_ODR *((uint32_t volatile *) 0x50000014)
#define GPIOC_MODER *((uint32_t volatile *) 0x50000800)
#define GPIOC_IDR *((uint32_t volatile *) 0x50000810)
#define GPIOC_ODR *((uint32_t volatile *) 0x50000814)
#define NVIC_ISER *((uint32_t volatile *) 0xE000E100)
#define EXTI_RTSR1 *((uint32_t volatile *) 0x40021800)
#define EXTI_EXTICR1 *((uint32_t volatile *) (0x40021800 + 0x060 + 0x4 * 0))
#define EXTI_EXTICR2 *((uint32_t volatile *) (0x40021800 + 0x060 + 0x4 * 1))
#define EXTI_EXTICR3 *((uint32_t volatile *) (0x40021800 + 0x060 + 0x4 * 2))
#define EXTI_EXTICR4 *((uint32_t volatile *) (0x40021800 + 0x060 + 0x4 * 3))
#define EXTI_IMR1 *((uint32_t volatile *) (0x40021800 + 0x080))
#define EXTI_RPR1 *((uint32_t volatile *) (0x40021800 + 0x00C))
void button_init();
extern void initialise_monitor_handles();
uint8_t volatile g_button_pressed = 0;
int main(void) {
//asm volatile ("cpsie i");
initialise_monitor_handles();
//printf("Hello World!\n");
RCC_IOPENR |= 0b1 << 0; // Enable PORTA
GPIOA_MODER &= ~(0b11 << (2*5)); // Clear MODE bits for 5th pin (PA-5)
GPIOA_MODER |= 0b1 << (2*5); // Set MODE bits for 5th pin (PA-5) to 01 (set output)
GPIOC_MODER &= ~(0b11 << (2*13)); // Clear MODE bits for 13th pin (PC-13) (set input)
button_init();
while(1) {
if (g_button_pressed) {
GPIOA_ODR ^= 0b1 << 5;
printf("Button pressed\n");
g_button_pressed = 0;
}
}
}
void button_init() {
RCC_APBENR2 |= 0b1 << 0; // Enable SYSCFGEN
RCC_IOPENR |= 0b1 << 2; // Enable PORTC
EXTI_RTSR1 |= 0b1 << 13; // Enable interrupt on rising edge at EXTI line 13
EXTI_EXTICR4 |= 0x2 << 8; // Set PC-13 as GPIO pin for interrupt
EXTI_IMR1 |= 0x1 << 13; // Unmask EXTI line 13
NVIC_ISER |= 0b1 << 7; // Enable interrupts for EXTI4_15
}
void EXTI4_15_IRQHandler(void) {
g_button_pressed = 1;
printf("Button pressed\n");
EXTI_RPR1 |= 0xFFFF << 0;
}
我正在使用带有默认编译器的 STM32CubeIDE,并使用 OpenOCD 通过半主机进行打印。
所以,我的问题是,我是错过了一步还是做错了什么?
【问题讨论】:
-
external 应该是最难的之一,您是否首先尝试了 systick 计时器,这是不通过 nvic 的东西? swi/svc 处理程序。然后说一个在内核外部但不在芯片之外的定时器中断?了解基础知识,然后将其提升到外部引脚?
-
与任何中断处理程序开发一样,您是否进行了轮询?从外围开始,朝着核心方向努力?一路了解中断状态和清除中断?一次一层?
-
加载到中断向量表中的中断处理程序的地址在哪里?
-
不要重新发明轮子并使用 CMSIS stm32 标头。那里已经定义了所有寄存器。
-
@P__J__ ,我在哪里可以找到 CMSIS STM32 标头?我刚刚从 STM32CubeMX 生成的项目中复制了它们 - 有没有更好的地方来获取它们?