我正在使用pic10f322微控制器开展项目。我做了一个非常基本的通信协议 - 有一个起始脉冲(10 ms),接着是5ms的脉冲数(2个脉冲 - 红灯亮3次,黄灯3次亮 - 绿色4次)。因此,以下代码尝试读取通信协议并打开相应的指示灯。我正在使用TMR0来测量脉冲的长度并对其进行计数。我有一个双色LED(红色和绿色)所以我需要交替两个来创建黄色。我希望使用TMR2作为中断,允许我将黄光与其余代码分开脉冲,这样就不会妨碍我检测启动脉冲的主函数。
我不知道它为什么不起作用。我检查了寄存器(虽然请仔细检查,因为我对某些东西视而不见)。代码编译。我在代码的各个阶段打开灯来检查它,并且灯在每个case语句中打开,包括我将LedColour枚举变量设置为相应颜色的最后一个。当我尝试在中断功能中打开灯时,它从不打开。
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <pic.h>
#include <stdbool.h>
#include <pic10f322.h>
// crystal oscilator
define _XTAL_FREQ 1000000
// CONFIG
#pragma config FOSC = INTOSC // Oscillator Selection bits
#pragma config BOREN = OFF // Brown-out Reset disabled
#pragma config WDTE = OFF // WDT disabled
#pragma config PWRTE = OFF // PWRT disabled
#pragma config MCLRE = OFF // MCLR pin function
#pragma config CP = OFF // Code Protection disabled
#pragma config LVP = ON // Low-voltage programming enabled
#pragma config LPBOR = OFF // Brown-out Reset disabled
#pragma config BORV = LO // Brown-out Reset Voltage, low trip point
#pragma config WRT = OFF // Flash Memory Write protection off
void timer2_isr(void);
#pragma code high_vector=0x08;
void interrupt (void)
{
asm("GOTO timer2_isr");
}
#pragma code
#pragma interrupt timer2_isr
#define RED_LED 0x01
#define GREEN_LED 0x02
#define SetBit(bit) (PORTA |= bit )
#define ClearBit(bit) (PORTA &= ~bit)
#define TestBit(bit) ( PORTA&bit)
int clkval = 0;
int pulsecnt = 0;
enum {
Red,
Green,
Yellow,
Off,
} LedColor = Off;
void timer2_isr (void)
{
PORTA = 0b1101; //This turns a green light on if it enters this function
if (PIR1 == 0x02)
{
PIR1 = 0x00;
}
}
void main(int argc, char** argv)
{
OSCCON = 0x30; //1MHz Clk
TRISA = 0x0C;
ANSELA = 0x00;
PORTA = 0x0C;
OPTION_REG = 0x06;
T2CON = 0x04; //Timer2 Registers Prescaler= 1 - TMR2 PostScaler = 1 - PR2 = 254 - Freq = 980.39 Hz - Period = 0.001020 seconds
PIE1 = 0x02;
PIR1 = 0x00;
TMR0 = 0;
TMR2 = 0;
PR2 = 254;
INTCON = 0xC0;
__delay_ms(2000);
enum {
WaitForStart,
CountPulses,
SelectColor,
} State = WaitForStart;
while (1)
{
switch (State)
{
case WaitForStart: //wait for start pulse
if ( (PORTA & 0x04) != 0x04 )
{
TMR0 = 0;
while ((PORTA & 0x04) != 0x04)
{
clkval = TMR0;
}
if (18 < clkval < 22)
{
State = CountPulses;
pulsecnt = 0;
}
}
break;
case CountPulses: // found start pulse, now count pulses or reset
if ( (PORTA & 0x04) != 0x04 )
{
TMR0 = 0;
while ((PORTA & 0x04) != 0x04)
{
clkval = TMR0;
}
if (8 < clkval < 12)
{
pulsecnt++;
}
}
if ((PORTA & 0x04) == 0x04)
{
clkval = 0;
TMR0 = 0;
while ((PORTA & 0x04) == 0x04 && clkval < 45)
{
clkval = TMR0;
if ((44 < clkval) || (pulsecnt > 4)) //no pulses noticed in over 22ms comparison or if you have surpassed the max number of pulses you are supposed to reach
{
if (pulsecnt > 0)
{
State = SelectColor;
} //if there has been a long delay, and pulses have been detect (so pulsecnt is greater than 0) then move to next case
else
{
State = WaitForStart;
} // if long delay and no pulses have been detected, restart and check for start pulse again
}
}
}
break;
case SelectColor: // if pulses have been detected, this state will be visited after long delay ( >22ms)
if (pulsecnt == 2)
{
LedColor = Red;
//PORTA = 0b1110;
State = WaitForStart;
}
else if (pulsecnt == 3)
{
LedColor = Yellow;
State = WaitForStart;
}
else if (pulsecnt == 4)
{
LedColor = Green;
//PORTA = 0b1101;
State = WaitForStart;
}
else
{
LedColor = Off;
State = WaitForStart;
}
break;
default:
State = WaitForStart;
break;
}
}
}
我使用了“PORTA = 0b1101”,它打开了绿灯。作为测试线来逐步完成代码并确保它达到某些点。现在它是在中断的开始,所以它应该在第一次中断之后打开并保持在righht,这将在大约2.5ms内发生,我认为?或者相对较快,但它永远不会进入中断函数或函数之前使用程序集告诉它转到此函数。
在PIC16中,您需要与配置的其余部分分开启动计时器,如下所示:
T2CONbits.TMR2ON = 1;
另外,检查是否已启用中断:
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;
我建议使用上面的表示法进行初始化;你所拥有的是很难验证的。
PIC 10只有一个中断向量,位于地址0x04
(不是你预期的0x08
)。
尝试这样的事情:
void interrupt myISR(void)
{
........
}