You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

IoT Nano 33使用CMSIS配置TCC定时器中断时串口断开求助

基于ARM Cortex M0+的CMSIS中断配置排查与实现指南

一、开发板断连问题排查

  • 时钟配置检查:CMSIS代码中不要随意修改系统时钟(Arduino默认已完成可靠初始化),若手动配置时钟,必须保证USB/调试接口的时钟源正确(多数Cortex M0+开发板依赖48MHz USB时钟)。
  • 中断配置错误排查:
    • Cortex M0+仅支持2位优先级(分组固定为0,[7:6]为抢占优先级,[5:0]为子优先级),不要修改SCB->AIRCR寄存器改变优先级分组。
    • ISR函数必须强制清除对应中断标志位,否则会无限触发中断导致系统挂死。
  • 调试接口保护:确认代码未将SWD/JTAG引脚(如SAMD21的PA14/SWDCLK、PA15/SWDIO)配置为普通GPIO,否则会直接导致调试连接失效。
  • 开发板恢复:若无法重连,通过BOOT引脚进入ISP模式,重新烧录Arduino引导程序后再测试CMSIS代码。

二、CMSIS中断配置实现

1. Cortex M0+默认ISR说明

启动文件(如startup_<device>.s)中定义了默认中断服务函数表,未自定义的ISR会跳转到Default_Handler,该函数为死循环:

void Default_Handler(void) {
  while(1);
}

若中断触发但未定义对应ISR,系统会直接挂死,导致开发板无响应。

2. GPIO中断配置(以SAMD21 PA0上升沿触发为例)

#include "samd21.h" // 根据你的开发板替换对应CMSIS头文件

// GPIO中断ISR
void EIC_0_Handler(void) {
  // 清除PA0对应的EXTINT0中断标志
  EIC->INTFLAG.reg = EIC_INTFLAG_EXTINT0;
  // 执行自定义逻辑:翻转PA13引脚状态
  PORT->Group[0].OUTTGL.reg = PORT_PA13;
}

void GPIO_Interrupt_Init(void) {
  // 使能EIC时钟
  MCLK->APBAMASK.reg |= MCLK_APBAMASK_EIC;
  GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
  
  // 配置PA0为输入上拉
  PORT->Group[0].DIRCLR.reg = PORT_PA0;
  PORT->Group[0].PINCFG[0].reg |= PORT_PINCFG_PULLEN | PORT_PINCFG_INEN | PORT_PINCFG_PMUXEN;
  PORT->Group[0].OUTSET.reg = PORT_PA0;
  
  // 将PA0复用为EIC EXTINT0
  PORT->Group[0].PMUX[0].reg = PORT_PMUX_PMUXE_E;
  
  // 配置EIC上升沿触发
  EIC->CONFIG[0].reg = EIC_CONFIG_SENSE0_RISE;
  // 使能EXTINT0中断
  EIC->INTENSET.reg = EIC_INTENSET_EXTINT0;
  
  // NVIC配置:设置优先级(0-3,0最高),使能中断
  NVIC_SetPriority(EIC_IRQn, 2);
  NVIC_EnableIRQ(EIC_IRQn);
  
  // 使能EIC模块
  EIC->CTRL.reg |= EIC_CTRL_ENABLE;
}

3. TCCx定时器中断配置(以SAMD21 TCC0为例)

// TCC0溢出中断ISR
void TCC0_Handler(void) {
  // 清除溢出中断标志
  if(TCC0->INTFLAG.reg & TCC_INTFLAG_OVF) {
    TCC0->INTFLAG.reg = TCC_INTFLAG_OVF;
    // 自定义逻辑:翻转PA13引脚
    PORT->Group[0].OUTTGL.reg = PORT_PA13;
  }
}

void TCC0_Interrupt_Init(void) {
  // 使能TCC0时钟
  MCLK->APBCMASK.reg |= MCLK_APBCMASK_TCC0;
  GCLK->PCHCTRL[TCC0_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
  
  // 配置TCC0为16位计数模式,预分频1024
  TCC0->CTRLA.reg = TCC_CTRLA_PRESCALER_DIV1024 | TCC_CTRLA_MODE_COUNT16;
  // 设置周期值:48MHz/1024/50=937,对应50Hz中断
  TCC0->PER.reg = 937;
  
  // 使能溢出中断
  TCC0->INTENSET.reg = TCC_INTENSET_OVF;
  
  // NVIC配置
  NVIC_SetPriority(TCC0_IRQn, 1);
  NVIC_EnableIRQ(TCC0_IRQn);
}

// TCC0启停函数
void TCC0_Start(void) {
  TCC0->CTRLA.reg |= TCC_CTRLA_ENABLE;
}

void TCC0_Stop(void) {
  TCC0->CTRLA.reg &= ~TCC_CTRLA_ENABLE;
  // 等待模块禁用完成
  while(TCC0->SYNCBUSY.reg & TCC_SYNCBUSY_ENABLE);
}

4. 主函数示例

int main(void) {
  // 初始化系统时钟(开发板提供的默认初始化函数)
  SystemInit();
  
  // 配置PA13为输出(用于测试)
  PORT->Group[0].DIRSET.reg = PORT_PA13;
  PORT->Group[0].OUTCLR.reg = PORT_PA13;
  
  // 初始化GPIO与定时器中断
  GPIO_Interrupt_Init();
  TCC0_Interrupt_Init();
  // 启动定时器
  TCC0_Start();
  
  while(1) {
    // 主循环逻辑
  }
}

三、核心注意事项

  • 中断标志必须清除:所有ISR中必须手动清除对应中断标志,否则会持续触发中断导致系统崩溃。
  • 优先级范围限制:Cortex M0+仅支持0-3共4级中断优先级,不要设置超出范围的值。
  • 外设时钟必使能:所有外设(EIC、TCCx)必须先使能GCLK和APB总线时钟,否则外设无法工作。

内容的提问来源于stack exchange,提问作者Daiyan Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 07:43:18