I have a board using a PIC16F15323.
This board is equipped with a relay, a digital input to read, and is configured as i2cbus device slave of another microcontroller.
My board is predominantly in sleep, execpt when timer0 wakes up the micro to read the digital input, or when the host wants to communicate and activates the procedure to set or reset the relay.
My relay is bistable and wants a 5 ms pulse to set or reset its state, so I started the pulse procedure in polling and using timer1 wants to put the board in sleep and finish the pulse procedure at the end of the timer1 period.
The problem is that timer1 doesn't work.
Here is an excerpt of my code :
- Code: Select all
/*
Main application
*/
void main(void)
{
// initialize the device
SYSTEM_Initialize();
// enable first reset pulse to bistable relay
RELAY_OPERATE = 1;
RELAY_STATE = 0;
// Enable the Global Interrupts
INTERRUPT_GlobalInterruptEnable();
// Enable the Peripheral Interrupts
INTERRUPT_PeripheralInterruptEnable();
// operative loop
while (1)
{
if( RELAY_OPERATE )
{
RELAY_OPERATE = 0; // reset flag
//
TMR1_StartTimer(); // handler start relay
}
//
CPUDOZEbits.IDLEN = 0;
Sleep(); // put in sleep
//
Nop();
}
}
void interrupt INTERRUPT_InterruptManager (void)
{
// interrupt handler
if(PIE0bits.TMR0IE == 1 && PIR0bits.TMR0IF == 1)
{
TMR0_ISR();
}
//else
if(INTCONbits.PEIE == 1 && PIE4bits.TMR1IE == 1 && PIR4bits.TMR1IF == 1)
{
TMR1_ISR();
}
//else
if(INTCONbits.PEIE == 1 && PIE3bits.SSP1IE == 1 && PIR3bits.SSP1IF == 1)
{
I2C1_ISR();
}
}
void TMR1_Initialize()
{
//CKPS 1:1; nT1SYNC do_not_synchronize; TMR1ON off; T1RD16 disabled;
T1CON = 0x04;
//T1GE disabled; T1GTM disabled; T1GPOL low; T1GGO done; T1GSPM disabled;
T1GCON = 0x00;
//GSS T1G_pin;
T1GATE = 0x00;
//CS LFINTOSC;
T1CLK = 0x03; // 0x04;
// Clear Interrupt flag before enabling the interrupt
PIR4bits.TMR1IF = 0;
// Enabling TMR1 interrupt.
PIE4bits.TMR1IE = 1;
}
void TMR1_StartTimer(void)
{
if( RELAY_STATE )
{
// start relay set pulse
R_SET_SetHigh();
}
else
{
// start relay reset pulse
R_RESET_SetHigh();
}
// TMR1 stopped
T1CONbits.TMR1ON = 0;
// TMR1 - 0xFF65 to obtain 5mSec;
TMR1L = 0x65;
TMR1H = 0xFF0;
// Clear Interrupt flag before enabling the interrupt
PIR4bits.TMR1IF = 0;
// Start TMR1
T1CONbits.TMR1ON = 1;
}
void TMR1_ISR(void)
{
if( RELAY_STATE )
{
// end relay set pulse
R_SET_SetLow();
}
else
{
// end relay reset pulse
R_RESET_SetLow();
}
// Stop TMR1
T1CONbits.TMR1ON = 0;
// Clear the TMR1 interrupt flag
PIR4bits.TMR1IF = 0;
}
void SYSTEM_Initialize(void)
{
PIN_MANAGER_Initialize();
OSCILLATOR_Initialize();
I2C1_Initialize();
TMR1_Initialize();
TMR0_Initialize();
}
void OSCILLATOR_Initialize(void)
{
// NOSC HFINTOSC; NDIV 1;
OSCCON1 = 0x60;
// CSWHOLD may proceed;
OSCCON3 = 0x00;
// MFOEN disabled; LFOEN disabled; ADOEN disabled; EXTOEN disabled; HFOEN disabled;
OSCEN = 0x00;
// HFFRQ 1_MHz;
OSCFRQ = 0x00;
// MFOR not ready;
OSCSTAT = 0x00;
// HFTUN 0;
OSCTUNE = 0x00;
}
My problem is that when the micro executes the following instructions :
// TMR1 - 0xFF65 to obtain 5mSec;
TMR1L = 0x65;
TMR1H = 0xFF0;
the write operation are not executed, timer1 remains with the previous value, and the period between "TMR1_StartTimer" execution and the "TMR1_ISR" activation is about 2 seconds, that is exactly the period of time needed for counting from 0x0000 and the next roll-over with a clock of 31kHz.
Thanks
Alessandro