The ISR executed once even when the event not happened - c

I am using PIC24FJ128GA204 microcontroller in PIC24F Curiosity Development Board.
The ISR is executed at least once even when the event not happened.
Here is the code:
#include <xc.h>
int Random_mode_condition=0;
void __attribute__((__interrupt__, __shadow__)) _INT1Interrupt(void) {
Random_mode_condition = 44;
_INT1IF = 0;
}
void RC9_Switch_Config() {
_TRISC9 = 1; // Switch input
RPINR0bits.INT1R = 25;
IFS1bits.INT1IF=0;//Clear the interrupt flag
IPC5bits.INT1IP1=1;//Choose a priority
INTCON2bits.INT1EP=0;//rising edge
IEC1bits.INT1IE=1;//enable INT1 interrupt
}
int main() {
LATC=0x0000;
RC9_Switch_Config();
while(1){
if(Random_mode_condition==44){ TRISC=0x0000; LATC=0xffff;}
}
return 0;
}
Random_mode_condition will equal 44 then the if statement will be executed.
Please help

Related

time between two edges pic 18f4550

I would like to calculate the time interval between two rising edges of two different signals using the two CCP modules from pic 18f4550.
The idea of ​​calculation is illustrated in the following figures.
The simulation works fine, but my electrical circuit is not. I don't know if there is something wrong with my code. If anyone has an answer or a clue to fix this, I will be grateful! And if you have any questions, please feel free to ask.
#pragma config FOSC = INTOSC_EC
#define _XTAL_FREQ 8000000
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "LCD_8bit_file.h"
#include <string.h>
unsigned long comtage, capt0, x;
char DEPHASAGE[20];
char pulse[20];
float period, dephTempo, deph, phi;
void main()
{
IRCF0 = 1; /* set internal clock to 8MHz */
IRCF1 = 1;
IRCF2 = 1;
LCD_Init();
LCD_String_xy(0, 1, "Dephasage[rad]");
T3CONbits.RD16 = 1;
T3CKPS0 = 0;
T3CKPS1 = 0;
TMR3CS = 0;
TMR3IF = 0;
while (1)
{
CCP2CON = 0b00000101;
CCP1CON = 0b00000101;
PIR2bits.CCP2IF = 0;
PIR1bits.CCP1IF = 0;
TMR3ON = 0;
TMR3 = 0;
if (PIR1bits.CCP1IF == 1) {
TMR3ON = 1;
while (!PIR2bits.CCP2IF);
comtage = TMR3;
dephTempo = (((float)comtage / 30.518) / 65536);
sprintf(pulse,"%.3f ", dephTempo);
LCD_String_xy(0, 0, "Dephasage : ");
LCD_String_xy(2, 9, pulse);
}
}
}
When you test a schematic using a real circuit, other issues will appear, like capacitive and resistive parasitics and that will after the timings. Also, can have jitter noise. If you a have an oscilloscope, try to figure out if there is too much noise. Try do add a pull-down/pull-up on those lines, make sure you have good ground connection. But after looking for your code, you should take an approach similar to CTC: You make fast samples of your input signal and then you check your sampled array, if there is more one than zeros, you caught an edge trigger.
I have a better scenario for your application to implement. But first let's talk about the bad practices in your code.
In your main while loop you setup the CCP modules:
CCP2CON = 0b00000101;
CCP1CON = 0b00000101;
PIR2bits.CCP2IF = 0;
PIR1bits.CCP1IF = 0;
TMR3ON = 0;
TMR3 = 0;
You better do this before the program enters to the infinite while loop.
You handle the timer reads directly while the CCP module captures its value in which the edge you configured it to capture.
comtage = TMR3;
I don't see that you configure the CCP pins as inputs. You have to configure them as inputs by setting the corresponding TRIS bits in order to have them working properly.
So the structure of my recommended scenario would be something like this:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "LCD_8bit_file.h"
#include <string.h>
unsigned long comtage, capt0, x;
char DEPHASAGE[20];
char pulse[20];
float period, dephTempo, deph, phi;
/******************** Utility funcs ********************/
void setupSysClock() {
IRCF0 = 1; /* set internal clock to 8MHz */
IRCF1 = 1;
IRCF2 = 1;
}
void setupCCP1withTMR1() {
CCP1CON = 0b00000101;
PIR1bits.CCP1IF = 0;
TRISCbits.TRISC2 = 1; // set CCP1 pin as input
}
void setupCCP2withTMR3() {
CCP2CON = 0b00000101;
PIR2bits.CCP2IF = 0;
// T3 goes for CCP2 and CCP1, PS 1:1, internal CS
T3CON = (1 << T3CCP2) | (0 << T3CKPS1) | (0 << T3CKPS0) | (1 << T3CCP1) | (0 << TMR3CS);
TMR3 = 0;
// In config bits you must choose RC1 pin for the CCP2 if necessary although it so by default
TRISCbits.TRISC1 = 1 // set CCP2 pin as input
}
void rearm() {
CCP1CON = 0x5
CCP2CON = 0x5
PIR1bits.CCP1IF = 0;
PIR2bits.CCP2IF = 0;
TMR3 = 0;
TMR3ON = 1;
}
void suspend() {
CCP1CON = 0;
CCP2CON = 0;
}
void main()
{
setupSysClock(); // setu internal clock
setupCCP1withTMR1(); // setup CCP1 for capture mode
setupCCP2withTMR3(); // setup CCP1 for capture mode with TMR3
LCD_Init();
LCD_String_xy(0, 1, "Dephasage[rad]");
while (1)
{
while(!CCP2IF); // Wait for the second rising edge
// Event has occured process, first make sure that the CCP1 rised first
if(!CCP1F) {
// An invalid sequence occured ignore and rearm. Note that the sequence of signals is important.
rearm();
continue;
}
/* The sequence is correct let's process the event. Here you will have
two captured value in CCPR1 and CCPR2 registers. First one is the captured value of the T3 when the first rising event occured. Second one is the captured value of the T3 when the second rising event occured. You have to get the delta of the two captured values first. This delta value is the elapsed ticks between the two discrete rising input signals. This is what the capture hardware is made for ;)
Now first we shuld suspend the CCP modules to avoid unwanted captures
while we process the previous value. Because if another capture occures
before we process the previous value, the new capture value will be
overwritten over the old value that we need for computation.
*/
suspend(); // suspend the CCP modules while processing
uint16_t timeDelta = CCPR2 - CCPR1; // Calculate the difference
dephTempo = (((float)timeDelta / 30.518) / 65536);
sprintf(pulse,"%.3f ", dephTempo);
LCD_String_xy(0, 0, "Dephasage : ");
LCD_String_xy(2, 9, pulse);
// Now that we finished processing we can rearm the CCP for new captures
rearm();
}
}
I wrote this code in an editor and haven't compiled in MPLAB. So you must compile and test the code. You can give me a feedback for me to help further.
One important thing to note: If the amount of time between two signals is large, you must either increment the prescaler of Timer3 or you must use a complementary variable for TMR3 register in case it overflows.

Delay within a timer (what is the correct approach)

I'm in a pickle regarding concepts relating to timers. How can I can I operate a "delay" inside a timer? This is the best way I can frame the question knowing full well what I'm trying to do is nonsense. The objective is: I wish to test the pinState condition 2 times (once initially and then 4 seconds later) but this all needs to happen periodically (hence a timer).
The platform is NodeMCU running a WiFi (ESP8266 chip) and coding done inside Arduino IDE.
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
BlynkTimer timer;
char auth[] = "x"; //Auth code sent via Email
char ssid[] = "x"; //Wifi name
char pass[] = "x"; //Wifi Password
int flag=0;
void notifyOnFire()
{
int pinState = digitalRead(D1);
if (pinState==0 && flag==0) {
delay(4000);
int pinStateAgain = digitalRead(D1);
if (pinStateAgain==0) {
Serial.println("Alarm has gone off");
Blynk.notify("House Alarm!!!");
flag=1;
}
}
else if (pinState==1)
{
flag=0;
}
}
void setup()
{
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
pinMode(D1,INPUT_PULLUP);
timer.setInterval(1000L,notifyOnFire);
}
void loop()
{
//Serial.println(WiFi.localIP());
Blynk.run();
timer.run();
}
an easy fix would be to set the periodicity of the timer to be 4000L timer.setInterval(4000L,notifyOnFire); and in notifyOnFire use a static variable and toggle its value whenever notifyOnFire is called
void notifyOnFire()
{
static char state = 0;
if( state == 0)
{
/* Write here the code you need to be executed before the 4 sec delay */
state = 1;
}
else
{
/* Write here the code you need to be executed after the 4 sec delay */
state = 0;
}
}
The nice thing about static variables is that they are initialized only once at compile time and they retain their values after the scope of code changes (In this case function notifyOnFire exits).

USART crashes on PIC18F2550, What can I do?

I'm working in the communication of a PIC18F4550 and the PC with a pair of xBEE S2C. And
I am using xc8 to compile the code.
I send some characters to the PIC from the PC with an Xbee then I send a '/r', and the PIC has to return me the characters that I sent.
It works for 9 iterations, then it crashes. The image shows the
Serial Console (red characters are the response of the PIC).
I´ve tried resetting the EUSART but this doesn´t seem to work. Always fails at the 9th iteration. I´ve read some posts of OERR and I tried a lot of things but nothing has solved my problem.
EDIT: ***NOTE: This Error presents if the transmit interval of the package is
less than 1500 ms. And I need to transmit at least every 300ms.
Someone has an idea of what could it be?
Thanks
#define _XTAL_FREQ 8000000
volatile char bufferRx[60];
volatile char bufferTx[60];
volatile char dum;
int RxFlag,ContRx, ContTx;
void interrupt isr()
{
if(RCSTAbits.OERR)
{
RCSTAbits.CREN = 0;
RCSTAbits.CREN = 1;
}
x = RCREG;
if(x== 13)
{
bufferRx[ContRx] = x;
RxFlag=1;
}
else
{
bufferRx[ContRx] = x;
}
ContRx++;
}
void main(void)
{
//////////////////////////////////////////////////////////////////
//CONFIGURACIONES
//OSCILLATOR
OSCCONbits.IRCF= 0b111;
OSCCONbits.SCS=0b10;
//PORTS
PORTB = 0;
TRISB=1;
TRISC=0b10000000;
//INTERRUPTIONS
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
PIE1bits.RCIE=1;
PIE1bits.TXIE=0;
PIR1bits.RCIF=0;
//RCSTA TXSTA
RCSTAbits.SPEN=1;
RCSTAbits.RX9=0;
RCSTAbits.CREN=1;
TXSTAbits.BRGH=0;
TXSTAbits.SYNC=0;
TXSTAbits.TXEN = 1;
TXSTAbits.TX9=0;
//BAUDRATE BAUDCON
BAUDCONbits.ABDEN = 0;
BAUDCONbits.WUE = 0;
BAUDCONbits.TXCKP = 0;
BAUDCONbits.RXCKP = 0;
BAUDCONbits.BRG16=0;
SPBRG=51;
//////////////////////////////////////////////////////////////////
while(1)
{
while(RCSTAbits.FERR)
{
dum = RCREG;
}
if(RCSTAbits.OERR)
{
RCSTAbits.CREN = 0;
RCSTAbits.CREN = 1;
}
ContTx=0;
if(RxFlag==1)
{
for(int x=0;x<ContRx;x++)
{
bufferTx[x] = bufferRx[x];
TXREG=bufferTx[x];
while(TXSTAbits.TRMT==0);
{
__delay_ms(1);
bufferTx[x]= 00;
bufferRx[x]= 00;
}
ContTx++;
}
RxFlag=0;
ContRx=0;
}
}
}
You are not using the "volatile" keyword anywhere although you are modifying some globals inside the ISR and using them outside.

Atmel studio with Xmega Timer/USART

I'm new in embedded systems developing also in Atmel studio Environment,
I'm using Atxmega128a1 with 32MHz system clk.
I'm trying to send some characters to the PC thought RS232 module at every timer interrupt overflow (0.05s),
so I defined (tc)Timers,USART Drivers on ASF and wrote the below code in main.c file, finally I debugged it without any error but not succeeded to transmit any thing through serial port.
anyone can help me or give me some advices.
#include <asf.h>
volatile int flag=0;
uint8_t received_byte;
uint8_t tx_buf[] = "\n\rHello AVR world ! : ";
uint8_t tx_length = 22;
uint8_t i;
static void my_callback(void)
{
flag =1;
}
int main (void)
{
/* Insert system clock initialization code here (sysclk_init()). */
board_init();
sysclk_init();
static usart_rs232_options_t USART_SERIAL_OPTIONS = {
.baudrate = 9600,
.charlength = 8,
.paritytype = USART_PMODE_DISABLED_gc,
.stopbits = false
};
usart_init_rs232(& USARTF0, &USART_SERIAL_OPTIONS);
//usart_set_baudrate_precalculated(& USARTF0,0x00017700,0x01E84800);
/* Insert application code here, after the board has been initialized. */
if (flag==1)
{
//received_byte = usart_getchar(& USARTF0);
//if (received_byte == '\r') {
for (i = 0; i < tx_length; i++)
{
usart_putchar(& USARTF0, tx_buf[i]);
}
}
else
usart_putchar(& USARTF0, received_byte);
flag=0;
}
I believe you are missing the initialization of the related system clock module:
sysclk_enable_module(SYSCLK_PORT_F, PR_USART0_bm);

PIC endless loop

I am trying to program PIC16F887 and having this interesting problem. I expect from LED to blink one-time and stop forever, however it starts back and never stops although watchdog is disabled. Here is the code. Thanks in advance.
I wrote this in MPLAB v8.84 and programmed using PICkit2 and Hi-Tech C compiler.
#include <htc.h>
#include <pic.h>
#define _XTAL_FREQ 800000
//__CONFIG(0x3FF5);
//functions
void INITgeneral(void);
void ledshow (void);
void main(void) {
INITgeneral();
ledshow();
return;
}
void INITgeneral(void)
{
TRISA = 0;
TRISB = 0;
TRISC = 0;
TRISD = 0;
TRISE = 0;
PORTA = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
PORTE = 0;
}
void ledshow(void)
{
__delay_ms(400);
RD0 = 1;
__delay_ms(400);
RD0 = 0;
}
The built-in simulator is very helpful in finding issues such as this one, well worth learning about.
Under the ‘View’ tab select ‘Disassembly Listing’. Notice that the next instruction after returning from the call to ledshow() is the instruction GOTO 0 which loads the program counter with zero, the reset vector. This is why you are endlessly executing the program.
To stop this behavior replace return in main() with an endless loop while(1){};

Resources