Attiny816外部中断问题



最近使用attiny816开发转速表。基本上使用5个输入来感测来自霍尔传感器的脉冲(使用中断来感测上升沿(。在测试过程中,当我使用简单的晶体管键来模拟霍尔传感器(给出不同频率的矩形波(时,我注意到微控制器在一段时间后会变慢(是的,像慢动作一样工作(。有时需要几分钟,有时需要几个小时。

为了找到这个问题,我创建了一个简单的程序,当中断被触发时切换led并改变速度值。值得一提的是,在使用内部32k时钟的示例代码中,当更改为20MHz时,它可以正常工作几个小时(比32k上长得多(。在Attiny816和Attiny826上尝试了程序,两者都有相同的问题。有什么想法可以引起这个问题吗?下面的测试代码。在每个输入上,中断之间有不同的时间(不同的信号频率(PB5-每120ms中断一次PB4-每60ms中断一次PB3-每40ms中断一次PB2-每30ms中断一次PB1-每隔24毫秒中断一次

/*
* 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("nr Speed 1 - %u[rpm]", speed_read(1));
printf("nr Speed 2 - %u[rpm]", speed_read(2));
printf("nr Speed 3 - %u[rpm]", speed_read(3));
printf("nr Speed 4 - %u[rpm]", speed_read(4));
printf("nr Speed 5 - %u[rpm]", speed_read(5));
USART0_sendString("nr");
}
}
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;
}

我试过不同的芯片,测试过电源和输入信号波,看起来都是应该的。它看起来像是微控制器在中断程序中丢失。

发现问题,如果两个或多个引脚同时触发中断,则中断处理程序不考虑。

最新更新