完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
首先呢,我得承认做为菜鸟,一直不是很明白M3的“中断组优先级”及“中断优先级”这两个概念。在本项目中,有如下定义:
使用工具为Keil char a,b,c,d,e[10],*P; int f,g,h,i,j;...............................................等等,有N多的全局变量及指针。 然后是相关的配置: /******************************************************************************************/ //PWM配置动作 /******************************************************************************************/ SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM); // 使能PWM模块 SysCtlPWMClockSet(SYSCTL_PWMDIV_1); // PWM时钟配置:不分频 GPIOPinTypePWM(SINA_PORT,SINA_PIN);// PG2配置为PWM0功能 GPIOPinTypePWM(SINB_PORT,SINB_PIN);// PD1配置为PWM1功能 GPIOPinTypePWM(SINC_PORT,SINC_PIN);// PH0配置为PWM1功能 GPIOPinTypePWM(SIND_PORT,SIND_PIN);// PH1配置为PWM1功能 PWMGenConfigure(PWM_BASE, PWM_GEN_0,PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);// 配置PWM发生器0:加减计数,不同步 PWMGenConfigure(PWM_BASE, PWM_GEN_1,PWM_GEN_MODE_UP_DOWN | PWM_GEN_MODE_NO_SYNC);// 配置PWM发生器1:加减计数,不同步 PWMGenPeriodSet(PWM_BASE, PWM_GEN_0, 1040); // 设置PWM发生器0的周期 PWMGenPeriodSet(PWM_BASE, PWM_GEN_1, 1040); // 设置PWM发生器1的周期 PWMPulseWidthSet(PWM_BASE, PWM_OUT_0, 64); // 设置PWM0输出的脉冲宽度 PWMPulseWidthSet(PWM_BASE, PWM_OUT_1, 64); // 设置PWM1输出的脉冲宽度 PWMPulseWidthSet(PWM_BASE, PWM_OUT_2, 64); // 设置PWM2输出的脉冲宽度 PWMPulseWidthSet(PWM_BASE, PWM_OUT_3, 64); // 设置PWM3输出的脉冲宽度 PWMSyncUpdate(PWM_BASE,PWM_GEN_0_BIT | PWM_GEN_1_BIT);//配置PWM发生器0、1同步 PWMOutputState(PWM_BASE,PWM_OUT_0_BIT|PWM_OUT_1_BIT|PWM_OUT_2_BIT|PWM_OUT_3_BIT,true);// 使能PWM0、1、2、3的输出 IntPrioritySet(INT_PWM0, 0<< 5); 注意这个优先级设置为0,后面会改为1 IntPrioritySet(INT_PWM1, 1<< 5); 注意这个优先级设置为1,后面会改为2 PWMGenEnable(PWM_BASE, PWM_GEN_0); // 使能PWM发生器0,开始产生PWM方波 PWMGenEnable(PWM_BASE, PWM_GEN_1); // 使能PWM发生器1,开始产生PWM方波 PWMGenIntTrigEnable(PWM_BASE,PWM_GEN_0,PWM_INT_CNT_ZERO);//使能PWM发生器0归零触发中断 PWMGenIntTrigEnable(PWM_BASE,PWM_GEN_1,PWM_INT_CNT_ZERO);//使能PWM发生器1归零触发中断 PWMIntEnable(PWM_BASE, PWM_INT_GEN_0 | PWM_INT_GEN_1);//使能PWM发生器0、1中断 // PWMIntEnable(PWM_BASE, PWM_INT_GEN_1);//使能PWM发生器0中断 IntEnable(INT_PWM0);//使能PWM发生器0中断 IntEnable(INT_PWM1);//使能PWM发生器1中断 IntMasterEnable();//使能总中断 /******************************************************************************************/ //UART配置动作 /******************************************************************************************/ SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1); // 使能UART模块 SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); // 使能RX/TX所在的GPIO端口 GPIOPinTypeUART(GPIO_PORTD_BASE, // 配置RX/TX所在管脚为 GPIO_PIN_2 | GPIO_PIN_3); // UART收发功能 UARTConfigSet(UART1_BASE, // 配置UART端口 9600, // 波特率 UART_CONFIG_WLEN_8 | // 数据位:8 UART_CONFIG_STOP_ONE | // 停止位:1 UART_CONFIG_PAR_NONE); // 校验位:无 UARTFIFOLevelSet(UART1_BASE, // 设置发送和接收FIFO深度 UART_FIFO_TX2_8, // 发送FIFO为2/8深度(4B) UART_FIFO_RX6_8); // 接收FIFO为6/8深度(12B)取值有1/8、2/8 、4/8 6/8、 7/8 IntPrioritySet(INT_UART1, 2 << 5);注意这个优先级设置为2,后面会改为3 UARtintEnable(UART1_BASE, UART_INT_RX | UART_INT_RT); // 使能接收和接收超时中断UART_INT_TX| IntEnable(INT_UART1); // 使能UART总中断 IntMasterEnable(); // 使能处理器中断 UARTEnable(UART1_BASE); 到此,配置了相关中断处理函数(IRQ)后,在main()里面,PWM0,PWM1,UART等程序运行一切都正常。 后来又增加了I2C模块,并配置相关中断及中断处理函数: /******************************************************************************************/ //I2C配置动作 /******************************************************************************************/ I2CM_DeviceInitSet(>Device, 0, 0, 0, (void *)0, 0); SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C1); // 使能I2C1模块 SysCtlPeripheralEnable(I2CSCL_PERIPH); // 使能SCL所在的GPIO模块 GPIOPinTypeI2C(I2CSCL_PORT, I2CSCL_PIN); // 配置相关管脚为SCL功能 SysCtlPeripheralEnable(I2CSDA_PERIPH); // 使能SDA所在的GPIO模块 GPIOPinTypeI2C(I2CSDA_PORT, I2CSDA_PIN); // 配置相关管脚为SDA功能 IntPrioritySet(INT_I2C1, 0 << 5);注意这个优先级设置为0,并把上面的PWM0,PWM1,UART的优先级做向后顺延。意图是设I2C为最高优先级 IntEnable(INT_I2C1); // 使能I2C1中断 I2CMasterInit(I2C1_MASTER_BASE, true); // I2C主机模块初始化,100kbps I2CMasterIntEnable(I2C1_MASTER_BASE); // 使能I2C主模块中断 IntMasterEnable(); // 使能处理器中断 I2CMasterEnable(I2C1_MASTER_BASE); // 使能I2C主机 于是可悲的事情发生了,程序跑起来后,开始正常,不一会就会精神错乱。程序开始处定义的全局变量、指针就会莫名其妙的乱了,完全不是应该有的样子。 关于NVIC,仅仅是在M3的默认状态增加了 IntPrioritySet(INT_I2C1, 0 << 5);这一改变优先级的库函数。 本菜鸟试图找原因,却始终不明白原因。怀疑堆栈溢出,或者LR错误,又或者中断设置及嵌套存在问题。 请各位大侠们帮忙诊断一下病因。不胜感激。 |
|
相关推荐
5 个讨论
|
|
阿兵888824 发表于 2020-8-20 15:15 Dong : 看了半天没发现你要证实什么。如果怀疑堆栈溢出的话,可以将堆栈值设大一点。 关于M3的NVIC,中断优先级与中断级优先级的说明可参考Register 14: Interrupt 0-3 Priority (PRI0), offset 0x400中描述 |
|
|
|
|
|
thyy***k 发表于 2020-8-20 15:21 看来是我描述的不清楚了,I2C呢,接了一个DS1302时钟。PWM驱动电机。UART做控制台。起初没添加相关DS1302的I2C中断时,控制台与电机运行都一切正常。 关闭PWM中断输出。仅仅使用UART控制台中断和I2C的中断在UART上输出时间也是正常的。 如果PWM和I2C一旦同时工作(运行在可中断状态)。电机运行,时钟读取并从UART输出时间一开始也正常,但很快时间就不能正确的从DS1302中读出。 利用硬件调试,发现指向DS1302的I2C从地址的指针,还有一些全局变量等出现了异常。从而不能从DS1302中读出正确的时间。 程序中有如下语句: typedef struct [ unsigned char ucSLA; // 从机地址(这是7位纯地址,不含读写控制位) unsigned char ulAddr; // 数据地址 unsigned char uiLen; // 数据地址长度(取值1、2或4) char *pcData; // 指向收发数据缓冲区的指针 unsigned cahr uiSize; // 收发数据长度 ] tI2CM_DEVICE; tI2CM_DEVICE C_DS1302; C_DS1302.ucSLA=0xa0;(在这里将I2C从机地址初始化为0xa0) main()[ while(1)[ .......................................................... I2CM_DeviceDataSet(&C_DS1302, 0x00+i, &h, 1); ................................................... ] ] 当时间输出正常时,每当程序运行到I2CM_DeviceDataSet(),观察C_DS1302.ucSLA=0xa0. 而当不能正常读出时间时,观察C_DS1302.ucSLA=0xXX XX表示处于不定,为任意值。 此变量的改变仅是特例,还有其它的变量会改变为不正常状态。 将KEIL的断点设置在C_DS1302.ucSLA改变时。每次C_DS1302.ucSLA由0xa0变为其它值时程序都停止在PWM0_ISR的中断服务函数入口处。(此种状态为I2C中断优先级为0,PWM0中断优先级为1)。如设置PWM1中断优先级为1,PWM0中断优先级设置为2。则每次C_DS1302.ucSLA由0xa0变为其它值时程序停止在PWM1_ISR的中断服务入口处。 至此,严重怀疑程序错乱是由中断引起的。本人菜鸟级别,再无从下手。 在没有更好办法的情况下,现已将硬件中断I2C模式改为软件模拟I2C从而不再使用I2C中断。程序运行及测试全部正常。 可心中的疑惑却没有答案。 |
|
|
|
|
|
阿兵888824 发表于 2020-8-20 15:32 Dong : "当时间输出正常时,每当程序运行到I2CM_DeviceDataSet(),观察C_DS1302.ucSLA=0xa0. 而当不能正常读出时间时,观察C_DS1302.ucSLA=0xXX XX表示处于不定,为任意值。" 你的C_DS1302是什么性质的变量呀?是局部还是全局呀? 看你那样描述,应该是中断嵌套过多导致的栈溢出 |
|
|
|
|
|
thyy***k 发表于 2020-8-20 15:43 十分感谢JSW-P J的热心帮助。 C_DS1302全局静态变量。 本来程序已经测试好了(采用软件模拟I2C),不打算纠结这个问题了。可是还是过不了自己这关。还是决定把中断方式的I2C加进去测试一下。又Google了一下Keil怎么设置栈的大小。将栈则默认的0x100修改为0x200。重新编译和测试,竟然就完全好了。再改回0x100,就又回到“精神错乱”的状态。看来问题就在于栈的大小设置了。 遥想当年,用KEIL加汇编方式做51的时候。那个SP是一点一点的计算,从没发生过这样的问题。 后来用Keil加C,一直采用默认,也一直没发生问题,慢慢的就忽略了堆栈。直到这次问题发生。 在通往大侠的路上,菜鸟的路还很漫长。。。。。 |
|
|
|
|
|
只有小组成员才能发言,加入小组>>
NA555DR VCC最低电压需要在5V供电,为什么用3.3V供电搭了个单稳态触发器也使用正常?
692 浏览 3 评论
MSP430F249TPMR出现高温存储后失效了的情况,怎么解决?
605 浏览 1 评论
对于多级放大电路板,在PCB布局中,电源摆放的位置应该注意什么?
1064 浏览 1 评论
755 浏览 0 评论
普中科技F28335开发板每次上电复位后数码管都会显示,如何熄灭它?
529 浏览 1 评论
请问下tpa3220实际测试引脚功能和官方资料不符,哪位大佬可以帮忙解答下
171浏览 20评论
请教下关于TAS5825PEVM评估模块原理图中不太明白的地方,寻求答疑
133浏览 14评论
在使用3254进行录音的时候出现一个奇怪的现象,右声道有吱吱声,请教一下,是否是什么寄存器设置存在问题?
129浏览 13评论
TLV320芯片内部自带数字滤波功能,请问linein进来的模拟信号是否是先经过ADC的超采样?
125浏览 12评论
GD32F303RCT6配置PA4 ADC引脚,将PA2代替key功能,PA2连接时无法实现预期功能,为什么?
62浏览 10评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-28 03:43 , Processed in 1.075644 second(s), Total 71, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号