最近使用attiny816开发了测速仪。基本上使用5个输入来感知来自霍尔传感器的脉冲(使用中断感知上升的边缘)。在测试中,当我使用简单的晶体管键来模拟霍尔传感器(给出不同频率的矩形波)时,我注意到,经过一段时间后,微控制器慢下来了(是的,像慢动作一样工作)。有时只需要几分钟,有时需要几个小时。
为了找出问题,我创建了一个简单的程序,在触发中断时切换并改变速度值。值得一提的是,在使用内部32k时钟的示例代码上,当更改为20 than时,它正确工作了几个小时(比32k长得多)。在Attiny816和Attiny826上尝试了程序,两者的问题相同。有什么能导致问题的原因吗?下面是测试代码。在每个输入端,不同的中断时间(不同的信号频率) PB5 -每120 is PB4中断一次-每60 is PB3中断一次-每40 is PB2中断一次30 is PB1中断每24 is中断一次。
/*
* Attiny816 VQFN TeST.c
*
* Created: 01/11/2022 10:11:41
* Author :
*/
#define F_CPU 32768UL
#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#define USART0_BAUD_RATE(BAUD_RATE) ((float)(F_CPU * 64 / (16 * (float)BAUD_RATE)) + 0.5)
void USART0_init(void);
void USART0_sendChar(char c);
void USART0_sendString(char *str);
int USART0_printChar(char c, FILE *stream);
void reset_screen(void);
FILE USART_stream = FDEV_SETUP_STREAM(USART0_printChar, NULL, _FDEV_SETUP_WRIT);
uint16_t speed_read(uint8_t wejscie_TACHO);
int main(void)
{
CPU_CCP = CCP_IOREG_gc;
CLKCTRL_MCLKCTRLA = CLKCTRL_CLKSEL_OSCULP32K_gc; /*32.768 kHz */
CPU_CCP = CCP_IOREG_gc;
CLKCTRL_MCLKCTRLB = 0 << CLKCTRL_PEN_bp; /* prescaler DISABLED */
/* --- ALARM LED'S --- */
PORTC.DIRSET = PIN3_bm; // F1 ALARM LED
PORTC.DIRSET = PIN2_bm; // F2 ALARM LED
PORTC.DIRSET = PIN1_bm; // F3 ALARM LED
PORTC.DIRSET = PIN0_bm; // F4 ALARM LED
PORTB.DIRSET = PIN0_bm; // F5 ALARM LED
/* --- USART --- */
USART0_init();
printf( "%cc", 27 );
/* --- TACHO --- */
PORTB.PIN5CTRL = PORT_ISC_INTDISABLE_gc; //TACHO_1_DIS
PORTB.PIN4CTRL = PORT_ISC_INTDISABLE_gc; //TACHO_2_DIS
PORTB.PIN3CTRL = PORT_ISC_INTDISABLE_gc; //TACHO_3_DIS
PORTB.PIN2CTRL = PORT_ISC_INTDISABLE_gc; //TACHO_4_DIS
PORTB.PIN1CTRL = PORT_ISC_INTDISABLE_gc; //TACHO_5_DIS
sei();
/* Replace with your application code */
while (1)
{
printf("\n\r Speed 1 - %u[rpm]", speed_read(1));
printf("\n\r Speed 2 - %u[rpm]", speed_read(2));
printf("\n\r Speed 3 - %u[rpm]", speed_read(3));
printf("\n\r Speed 4 - %u[rpm]", speed_read(4));
printf("\n\r Speed 5 - %u[rpm]", speed_read(5));
USART0_sendString("\n\r");
}
}
ISR( PORTB_PORT_vect )
{
switch ( PORTB_INTFLAGS )
{
case (32): // TACHO_1 - PB5 (2^(5-1) = 32)
////tacho_now[1] = TCA0.SINGLE.CNT;
PORTB.INTFLAGS |= PORT_INT5_bm; /* clear interrupt flag */
break;
case (16): // TACHO_2 - PB4
////tacho_now[2] = TCA0.SINGLE.CNT; // tacho_cnt;
PORTB.INTFLAGS |= PORT_INT4_bm; /* clear interrupt flag */
break;
case (8): // TACHO_3 - PB3
////tacho_now[3] = TCA0.SINGLE.CNT;
PORTB.INTFLAGS |= PORT_INT3_bm; /* clear interrupt flag */
break;
case (4): // TACHO_4 - PB2
//tacho_now[4] = TCA0.SINGLE.CNT;
PORTB.INTFLAGS |= PORT_INT2_bm; /* clear interrupt flag */
break;
case (2): // TACHO_5 - PB1
////tacho_now[5] = TCA0.SINGLE.CNT;
PORTB.INTFLAGS |= PORT_INT1_bm; /* clear interrupt flag */
break;
default:
break;
}
}
void USART0_init(void)
{
PORTMUX.CTRLB = PORTMUX_USART0_ALTERNATE_gc;
PORTA.DIRSET = PIN1_bm; // PA1 - TXD jako wyjscie
USART0.BAUD = (uint16_t)USART0_BAUD_RATE( 1200 ); // set the Baud Rate
USART0.CTRLB |= USART_TXEN_bm; // enable the Transmitter
// Set frame format
USART0.CTRLC = USART_CMODE_ASYNCHRONOUS_gc // Asynchronous Mode
| USART_CHSIZE_8BIT_gc // Character size: 8 bit
| USART_PMODE_DISABLED_gc // No Parity
| USART_SBMODE_1BIT_gc; // 1 stop bit
stdout = &USART_stream;
_delay_ms(250);
}
void USART0_sendChar(char c)
{
while ( !(USART0.STATUS & USART_DREIF_bm) )
{
; // do nothing
}
USART0.TXDATAL = c;
}
void USART0_sendString(char *str)
{
for(size_t i = 0; i < strlen(str); i++)
{
USART0_sendChar(str[i]);
}
}
int USART0_printChar(char c, FILE *stream)
{
USART0_sendChar(c);
return 0;
}
uint16_t speed_read(uint8_t wejscie_TACHO)
{
uint32_t speed = 0;
/* --- disable all TACHO input --- */
PORTB.PIN5CTRL = PORT_ISC_INTDISABLE_gc; //TACHO_1_DIS
PORTB.PIN4CTRL = PORT_ISC_INTDISABLE_gc; //TACHO_2_DIS
PORTB.PIN3CTRL = PORT_ISC_INTDISABLE_gc; //TACHO_3_DIS
PORTB.PIN2CTRL = PORT_ISC_INTDISABLE_gc; //TACHO_4_DIS
PORTB.PIN1CTRL = PORT_ISC_INTDISABLE_gc; //TACHO_5_DIS
//_delay_ms(100);
/* --- enable [wejscie_TACHO] only --- */
switch ( wejscie_TACHO )
{
case (1):
speed = 500;
PORTC.OUTTGL = PIN3_bm;// _delay_ms(200);
PORTB.PIN5CTRL = PORT_ISC_RISING_gc;
break;
case (2):
speed = 1000;
PORTC.OUTTGL = PIN2_bm; //_delay_ms(200);
PORTB.PIN4CTRL = PORT_ISC_RISING_gc;
break;
case (3):
speed = 1500;
PORTC.OUTTGL = PIN1_bm; //_delay_ms(200);
PORTB.PIN3CTRL = PORT_ISC_RISING_gc;
break;
case (4):
speed = 2000;
PORTC.OUTTGL = PIN0_bm; //_delay_ms(200);
PORTB.PIN2CTRL = PORT_ISC_RISING_gc;
break;
case (5):
speed = 2500;
PORTB.OUTTGL = PIN0_bm; //_delay_ms(200);
PORTB.PIN1CTRL = PORT_ISC_RISING_gc;
break;
default:
break;
}
_delay_ms(250);
return speed;
}我试过不同的芯片,测试过电源和输入信号波,看起来都应该是。它看起来就像在中断程序中迷路之后的微控制器。
发布于 2022-11-02 12:49:53
发现问题时,如果两个或多个引脚同时触发中断,则中断处理程序不考虑此问题。
https://stackoverflow.com/questions/74288032
复制相似问题