完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
你好,我正在尝试使用运动反馈*(正交编码器接口)来获得DC电机的速度。我正在模拟proteus中的应用程序,我用XC8编译器编写了MplabX的代码。我做了:配置了QEI模块,当POSCNT增加到一定数量(240)时,它产生一个中断,这是每个革命的脉冲数(我的马达模型每转240个脉冲)。n)因此,240个POSCNT增量应该意味着1次旋转——每当QEI产生一个中断(一次革命就完成)时,通过一个配置的TMR0增加一个速度变量,以中断0.06秒,并在其中使用计数器来跟踪1秒的时间周期。每1秒,我得到速度变量的值,因此得到每秒旋转的值。然后,我把这个数乘以60,得到RPM,然后重置速度变量,以便再次得到它。我是MPLAB新手,试图调试我的代码,但我使用了一些测试LED,发现我的代码由于某种原因没有进入TMR0中断。我提到,我第一次实现了TMR0中断,它工作良好后,我已经配置了QEI中断,并启用优先中断,现在我有这个问题(Un控制器只处理QEI中断,忽略TMR0溢出中断)。我认为我在“组态”功能上做了一些错事,但是我搞不清楚是什么。我尝试将TMR0溢出INT设置为高优先级,QEI为低优先级。请帮助我识别此代码有什么问题。谢谢大家的阅读!这是CODECONFIG位设置:我还上传了Proteus中的示意图。
以上来自于百度翻译 以下为原文 Hello, I'm trying to get the speed of a DC motor using the Motion Feedback*(Quadrature Encoder Interface). I'm simulating the application in Proteus and I wrote the code in MplabX with XC8 compiler. What I did: - configured QEI module to generate an interrupt when the POSCNT gets incremented to a certain number(240) which is the number of pulses per revolution(my motor's model has 240 pulses per revolution) so 240 increments of POSCNT should mean 1 revolution - everytime the QEI generated an interrupt(one revolution is complete) increment a speed variable by one - configured TMR0 to give an interrupt of 0.06 seconds and in it used a counter to keep track of 1 second time period. Every 1 second I get the value of the speed variable and so I get the value of rotations per second. Then I multiply this number with 60 to get RPM and then I reset the speed variable to be able to get it again. I'm new to MPLAB and tried to debug my code but I used some test LEDs and found out that my code for some reason does not enter the TMR0 interrupt. I mention that I have first implemented the TMR0 interrupt and it worked fine after that I have configured the QEI interrupt and enabled priority interrupts now I have this problem(the ucontroller only processes QEI interrupt and ignores the TMR0 overflow interrupt). I think I'm doing something wrong in the 'configINTS' function but I cannot figure out what. I have tried setting TMR0 overflow int as high priority and QEI as low priority. Please help me identify what's wrong with this code. Thank you for reading! This is the code #include #include #include "header.h" #include #include #define FCY 6250000 int speed = 0; // initially speed is 0 float actualspeed; int cnt = 0; // counter used to get speed unsigned char stringSpeed[100]; void init_XLCD(void); //Initialize LCD display void DelayFor18TCY( void ); //18 cycles delay void DelayPORXLCD (void); // Delay of 15ms void DelayXLCD (void); // Delay of 5ms void configTMR0(void); void configINTS(void); void configQEI(void); void main() { OSCCON = 0x7F; // 8Mhz internal oscillator init_XLCD(); //Call the Initialize LCD display function TRISC &= ~(1<<0); // test LED(ignore) for timer interrupt TRISC &= ~(1<<1); // test LED for QEI interrupt configINTS(); configQEI(); configTMR0(); // will give an interrupt every 0.15 seconds while(1) { sprintf(stringSpeed, " %.3g", actualspeed ); // convert speed to string putrsXLCD(stringSpeed); // and display it on LCD WriteCmdXLCD(0x01); } } void init_XLCD(void) //Initialize LCD display { OpenXLCD(FOUR_BIT&LINES_5X7); //configure LCD in 4-bit Data Interface mode //and 5x7 characters, multiple line display while(BusyXLCD()); //Check if the LCD controller is not busy //before writing some commands WriteCmdXLCD(0x06); //Move cursor right, don't shift display WriteCmdXLCD(0x0C); //Turn display on without cursor } void DelayFor18TCY( void ) //18 cycles delay { Delay10TCYx(20); } void DelayPORXLCD (void) //Delay of 15ms { Delay1KTCYx(30); } void DelayXLCD (void) //Delay of 5ms { Delay1KTCYx(10); } void configINTS(void) { INTCONbits.GIE = 1; // enable all interrupts INTCONbits.PEIE = 1; // enable all unmasked peripheral interrupts RCONbits.IPEN = 1; // enable priority level on interrupts INTCON |= (1 << 5); // enable TMR0 overflow interrupt INTCON2 |= (1 << 2); // TMR0 overflow interrupt = high PIE3bits.IC2QEIE = 1; // enable QEI interrupt(when POSCNT == MAXCNT) IPR3bits.IC2QEIP = 0; // QEI interrupt priority = low } void configTMR0(void) { T0CONbits.TMR0ON = 1; // enables timer0 T0CONbits.T016BIT = 0; // timer0 is a 16bit timer/counter T0CONbits.T0CS = 0; // timer0 clock source = internal clock(FOSC/4) T0CONbits.PSA = 0; // timer0 clock input comes from prescaler output T0CONbits.T0PS2 = 0; T0CONbits.T0PS1 = 0; T0CONbits.T0PS0 = 0; // PRESCALER SET TO 2 } void configQEI(void) { ANSEL0 = 0x00; // QEI set as digital TRISA |= 0x1C; // QEA, QEB and INDEX set as inputs; QEICONbits.QEIM2 = 0; // disable the QEICONbits.QEIM1 = 0; // QEIM QEICONbits.QEIM0 = 0; // module QEICONbits.VELM = 1; // velocity mode disabled QEICONbits.UPDOWN = 1; // forward direction(!!!!!!!!!!!!!) QEICONbits.QEIM2 = 1; // QEI enabled in 4x Update mode QEICONbits.QEIM1 = 1; // position counter reset on period match QEICONbits.QEIM0 = 0; // POSCNT = MAXCNT POSCNTH = 0; // reset the position counter POSCNTL = 0; MAXCNTH = 0; // 240 pulses per revolution MAXCNTL = 240; } void interrupt ISR_QEI() { if(IC2QEIE && IC2QEIF) // if POSCNT = MAXCNT do this LATCbits.LATC1 ^= 1; // test interrupt execution { speed = speed + 1; // increment speed POSCNTH = 0; // reset the position counter POSCNTL = 0; } IC2QEIF = 0; } void interrupt ISR_TMR0() // interrupt every 0.06 seconds { if(TMR0IE && TMR0IF) { cnt = cnt+1; if(cnt == 15) // 1 second has passed { LATCbits.LATC0 ^= 1; // test interrupt execution actualspeed = speed * 60; // get speed in RPM speed = 0; cnt = 0; } } TMR0IF = 0; } Config bits settings: // PIC18F2431 Configuration Bit Settings // 'C' source line config statements #include // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. // CONFIG1H #pragma config OSC = XT // Oscillator Selection bits (XT oscillator) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled) #pragma config IESO = ON // Internal External Oscillator Switchover bit (Internal External Switchover mode enabled) // CONFIG2L #pragma config PWRTEN = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled) // BORV = No Setting // CONFIG2H #pragma config WDTEN = OFF // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit)) #pragma config WDPS = 32768 // Watchdog Timer Postscale Select bits (1:32768) #pragma config WINEN = OFF // Watchdog Timer Window Enable bit (WDT window disabled) // CONFIG3L #pragma config PWMPIN = OFF // PWM output pins Reset state control (PWM outputs disabled upon Reset (default)) #pragma config LPOL = HIGH // Low-Side Transistors Polarity (PWM0, 2, 4 and 6 are active-high) #pragma config HPOL = HIGH // High-Side Transistors Polarity (PWM1, 3, 5 and 7 are active-high) #pragma config T1OSCMX = ON // Timer1 Oscillator MUX (Low-power Timer1 operation when microcontroller is in Sleep mode) // CONFIG3H #pragma config MCLRE = OFF // MCLR Pin Enable bit (Disabled) // CONFIG4L #pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset) #pragma config LVP = OFF // Low-Voltage ICSP Enable bit (Low-voltage ICSP enabled) // CONFIG5L #pragma config CP0 = OFF // Code Protection bit (Block 0 (000200-000FFFh) not code-protected) #pragma config CP1 = OFF // Code Protection bit (Block 1 (001000-001FFF) not code-protected) #pragma config CP2 = OFF // Code Protection bit (Block 2 (002000-002FFFh) not code-protected) #pragma config CP3 = OFF // Code Protection bit (Block 3 (003000-003FFFh) not code-protected) // CONFIG5H #pragma config CPB = OFF // Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code-protected) #pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected) // CONFIG6L #pragma config WRT0 = OFF // Write Protection bit (Block 0 (000200-000FFFh) not write-protected) #pragma config WRT1 = OFF // Write Protection bit (Block 1 (001000-001FFF) not write-protected) #pragma config WRT2 = OFF // Write Protection bit (Block 2 (002000-002FFFh) not write-protected) #pragma config WRT3 = OFF // Write Protection bit (Block 3 (003000-003FFFh) not write-protected) // CONFIG6H #pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected) #pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write-protected) #pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected) // CONFIG7L #pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 (000200-000FFFh) not protected from table reads executed in other blocks) #pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 (001000-001FFF) not protected from table reads executed in other blocks) #pragma config EBTR2 = OFF // Table Read Protection bit (Block 2 (002000-002FFFh) not protected from table reads executed in other blocks) #pragma config EBTR3 = OFF // Table Read Protection bit (Block 3 (003000-003FFFh) not protected from table reads executed in other blocks) // CONFIG7H #pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from table reads executed in other blocks) #define _XTAL_FREQ 8000000 I have also uploaded the schematic in Proteus. Attached Image(s) |
|
相关推荐
2个回答
|
|
我认为你需要指定哪个ISR是高优先级的,哪个是低的,这个PIC不使用IVT,因此你需要使用高优先级和低优先级优先级。请参阅XC8指南中的5.5.1节。
以上来自于百度翻译 以下为原文 I think you need to specify which ISR is for high priority and which is low, this pic does not use an IVT and therefore you need to use the high-priority & low_priority qualifiers. See section 5.9.1 in the XC8 guide. |
|
|
|
你好。谢谢你的回复,很抱歉我迟到了:D.I已经做了你说的,并添加了“高/低”优先级标识符。现在,我的中断似乎都被正确地生成了。然而,我并不理解:根据PIC的数据表,QEI中断可以由“周期匹配”(POSCNT=Max CNT)触发。当发生这种情况时,中断会被处理一次,但是如果我不重置软件中的位置计数器(无论是在连续循环中还是在ISR本身),中断将不会被再次触发。但是,微控制器的数据表清楚地指明,当QEIM & lt;2:0&Gt位设置为110(或010)(数据表@ QEICON寄存器中的页162)时,“位置计数器”在周期匹配(POSCNT=Max CNT)上复位。那么为什么POSCNT不能重置它自己,而我必须自己去做呢?做这件事并不打扰我,我只想知道我错过了什么。
以上来自于百度翻译 以下为原文 Hello. Thank you for your reply and sorry for my late one :D. I have done what you said and added the "high/low" priority identifiers. Now both my interrupts seem to be generated properly. I do not understand something however: According to the PIC's datasheet the QEI interrupt can be triggered by 'period match' (POSCNT = MAXCNT). The interrupt gets processed once when this happens however if I do not reset the position counter in software somewhere(either in continous while loop or in the ISR itself) the interrupt will not be triggered again. But the microcontroller's datasheet clearly specifies that the 'position counter is reset on period match(POSCNT=MAXCNT) when QEIM<2:0> bits are set to 110(or 010)(page 162 in the datasheet @QEICON register). So why isn't the POSCNT resetting on it's own and I have to do that myself? It doesn't bother me to do it I just want to understand what am I missing. |
|
|
|
只有小组成员才能发言,加入小组>>
5158 浏览 9 评论
1997 浏览 8 评论
1926 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3169 浏览 3 评论
请问电源和晶体值之间有什么关系吗?PIC在正常条件下运行4MHz需要多少电压?
2222 浏览 5 评论
723浏览 1评论
606浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
494浏览 1评论
PIC Kit3出现目标设备ID(00000000)与预期的设备ID(02c20000)不匹配。是什么原因
620浏览 0评论
519浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-19 11:28 , Processed in 1.209102 second(s), Total 84, Slave 66 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号