2024电赛H,一些思路和源码

一、设备

        主控:MSPM0G3507

        电机驱动:TB6612

        循迹:感为八路

        电机:310电机

二、遇见的一些问题:

2.1 锁芯片

        TI这个就很烦,我同批次买了两块最小系统板,一块被锁一块不会,被锁的那块按网上的步骤也解锁不了,只能按RST和BSL烧录,也没法步进调试,给我们代码编写过程带来了很大的不便。

2.2 串口总是会卡死

        这道题最合理的方式就是得得到角度,然后进行角度PID确保路线,我们赛前买了个正点原子的IMU九轴模块,他是使用串口来通信的,TI这颗芯片不知道为什么总是会串口接收卡死,而且时会时不会,该做的清中断,等待发数据都做了,并且把接收中断优先级提升到最高,还是会出现这些情况,用STM32就不会,我们吭哧吭哧调试了两天,最后还是放弃了,还是吃了资料太少的亏。

        有考虑过用MPU6050模块,他用I2C通信,最后能稳定的读数据了,但是又有零漂,没接触过,一时半会找不到办法解决,最后我们放弃角度PID的方案了,后文讲讲我们的方案。

2.3 编码器

        我这颗芯片64Pin只有一个硬件编码器,所以只能采取中断的办法来获取编码器的值,值得注意的是,这种方法编码器倍频是2,STM32硬件的那种是4,部分代码如下:(在中断服务函数里)

 // 中断服务函数:外部中断模拟编码器信号、按键外部中断
void GROUP1_IRQHandler(void)//Group1的中断服务函数
{
    /* 获取中断信号 */
    gpio_interrup = DL_GPIO_getEnabledInterruptStatus(GPIOA, ENCODERA_E1A_PIN | ENCODERA_E1B_PIN | ENCODERB_E2A_PIN | ENCODERB_E2B_PIN);
    //encoderA
    if((gpio_interrup & ENCODERA_E1A_PIN) == ENCODERA_E1A_PIN)
    {
        if(!DL_GPIO_readPins(GPIOA, ENCODERA_E1B_PIN))
            g_encoder1_count--;
        else
            g_encoder1_count++;
    }
    else if((gpio_interrup & ENCODERA_E1B_PIN) == ENCODERA_E1B_PIN)
    {
        if(!DL_GPIO_readPins(GPIOA, ENCODERA_E1A_PIN))
            g_encoder1_count++;
        else
            g_encoder1_count--;
    }
    //encoderB
    if((gpio_interrup & ENCODERB_E2A_PIN) == ENCODERB_E2A_PIN)
    {
        if(!DL_GPIO_readPins(GPIOA, ENCODERB_E2B_PIN))
            g_encoder2_count--;
        else
            g_encoder2_count++;
    }
    else if((gpio_interrup & ENCODERB_E2B_PIN) == ENCODERB_E2B_PIN)
    {
        if(!DL_GPIO_readPins(GPIOA, ENCODERB_E2A_PIN))
            g_encoder2_count++;
        else
            g_encoder2_count--;
    }
DL_GPIO_clearInterruptStatus(GPIOA,ENCODERA_E1A_PIN|ENCODERA_E1B_PIN|ENCODERB_E2A_PIN|ENCODERB_E2B_PIN;
}

三、方案:

        我们采用速度PID + 红外循迹PID(可看我主页2022电赛C那篇文章)+ 两轮差速PID来控制小车。

        速度PID:控制小车转速是为了能快速稳定的达到你预期的速度

        红外循迹PID:为了控制小车能稳定的在黑线投影上

        两轮差速PID:为了控制小车在空白地图可以直线行驶,因为两个轮子多少有一些转速差异,会导致小车偏移,这是为了弥补没有角度的缺陷。

四、演示视频:

题目1:

1

题目2:

2

题目3:

3

题目4:

4

五、总结

        我们前期花了两天看角度串口,那两天啥也没搞出来,所以实际上这个方案只花了一天半吧,所以速度都没敢提高,而且由于没有角度,走直线还是不太稳定,容易偏移,希望这篇文章能对备战2026年省赛的师弟师妹有帮助!

        需要源码可以留下你的邮箱,电赛时间很赶,代码写的很烂说实话,全局变量满天飞。

        底板原理图有需要也可以发给你,基本上串口屏,OLED屏,舵机,openmv这些电赛常见外设我都有在上面画好了。

        如果有用的话,希望大家帮我点个赞啦,谢谢!

<think>好的,用户的问题是关于MSPM0G3507微控制器在中断处理中卡死的原因解决方法。我需要结合之前的知识可能的硬件特性来分析。 首先,用户提到的MSP430的低功耗模式可能与中断卡死有关,特别是在进入低功耗模式时,如果配置不当,可能导致CPU无法响应中断。比如,之前的引用提到SCG0、SCG1等位的设置会影响时钟模块的工作状态。如果中断服务程序(ISR)执行时所需的时钟被关闭,可能导致中断无法正确退出,从而卡死。 接下来,可能的原因可能包括中断标志未清除。当中断触发后,如果程序没有清除相应的标志位,会导致中断重复触发,不断进入ISR,导致主程序无法继续执行。另外,中断优先级冲突也可能是一个问题,比如高优先级中断打断了低优先级中断的处理,导致资源竞争或死锁。 堆栈溢出也是一个常见问题。如果中断服务程序中使用了大量局部变量或递归调用,可能导致堆栈空间不足,破坏程序运行环境,进而卡死。此外,硬件外设配置错误,比如未正确配置外设的中断使能或状态寄存器,可能使中断无法正常触发或处理。 在低功耗模式下,如果系统在进入睡眠前未正确配置唤醒源,或者中断唤醒条件不满足,可能导致CPU无法唤醒,停留在低功耗状态。此外,静干扰或源不稳定等硬件问题也可能导致中断逻辑异常。 针对这些可能的原因,解决方法包括检查中断标志位是否在ISR中正确清除,确保中断优先级设置合理,避免嵌套中断导致的冲突。同时,检查堆栈大小是否足够,优化ISR的代码以减少堆栈使用。验证外设的配置是否正确,包括中断使能位时钟源的配置。在进入低功耗模式前,确认唤醒源已正确设置,并确保中断能有效唤醒CPU。此外,检查硬件路是否有干扰或源问题,必要时添加滤波容或稳压路。 还需要参考TI的官方文档示例代码,确认配置步骤是否符合要求。例如,MSPM0系列可能有特定的中断处理机制或寄存器配置需要注意。如果用户之前的问题涉及低功耗模式,可能需要结合之前的建议,确保在低功耗模式下中断的正确处理。</think>### MSPM0G3507中断卡死原因及解决方案分析 #### 一、常见原因分析 1. **中断标志未清除** 中断服务程序(ISR)未正确清除外设中断标志,导致反复触发中断。例如: ```c void ADC_ISR(void) { // 未执行ADC_IFG = 0x00 导致中断循环触发 } ``` 2. **低功耗模式配置冲突**[^1] 在进入LPM3/LPM4等低功耗模式时,若未正确保留中断唤醒源: - 未配置SCG0/SCG1位导致时钟关闭 - ACLK/MCLK未保持活动状态 - 唤醒信号未正确映射到中断控制器 3. **堆栈溢出** 中断嵌套或局部变量过多导致堆栈越界,典型表现为: - 中断返回后PC指针异常 - 关键寄存器值被覆盖 4. **硬件外设冲突** 多外设共享中断向量时未正确分配优先级,例如: ```c // 错误示例:ADCTIMER使用相同优先级 NVIC_SetPriority(ADC_IRQn, 1); NVIC_SetPriority(TIMER0_IRQn, 1); ``` #### 二、验证与解决方法 1. **中断标志排查步骤** - 在ISR入口添加断点,观察是否重复进入 - 检查外设状态寄存器: $$ \text{IFG} \& \text{IE} \neq 0 \Rightarrow \text{未清除标志} $$ - 使用TI官方驱动库的清除函数: ```c ADC_clearInterruptStatus(ADC_BASE, ADC_INT_CH7); ``` 2. **低功耗模式配置要点** | 模式 | SCG1 | SCG0 | OscOff | CPUOff | 可用时钟 | |---|---|---|---|---|---| | Active | 0 | 0 | 0 | 0 | All | | LPM3 | 1 | 1 | 0 | 1 | ACLK | - 确保在__WFI()前启用唤醒中断: ```c Power_setPerformanceLevel(PRF_LEVEL_0); PCM_enableWakeupOnPin(PCM_WAKEUP_PIN_LOW, PIN_ID(0,5)); ``` 3. **堆栈深度优化** - 通过.map文件检查堆栈使用: ```text .stack 0x20000500 0x400 ``` - 推荐ISR堆栈余量 > 20% 4. **硬件调试技巧** - 使用XDS110调试器捕获异常现场: ```c __asm(" BKPT #0"); // 在卡死前插入断点 ``` - 检查NVIC寄存器: $$ \text{NMI\_FAULT} = ISER[0] \& IABR[0] $$ #### 三、典型修复案例 某ADC采样项目卡死问题: 1. 现象:ADC中断执行3次后卡死 2. 排查: - 发现DMA未关闭导致内存覆盖 - ADC校准寄存器未锁定 3. 修复代码: ```c void ADC_ISR(void) { ADC_disableConversion(ADC_BASE); DMA_disableChannel(DMA_CH0); ADC_clearInterrupt(ADC_INT_CH7); __bic_SR_register_on_exit(LPM3_bits); // 正确退出低功耗 } ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值