最近使用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;
}
我试过不同的芯片,测试过电源和输入信号波,看起来都是应该的。它看起来像是微控制器在中断程序中丢失。
发现问题,如果两个或多个引脚同时触发中断,则中断处理程序不考虑。