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){};
Related
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.
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
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.
I am working on RGB LED project and that's controlled by a PIC12F1572. The software that I am using is MPLAB IDE with the HiTech C compiler. The plan is to use serial communication to send LED RGB combination data commands to the PIC to be stored in a variable that will make it perform the LED blink and glowing I have been able to establish UART communication.Every function or step I code is right by syntax and works on linux command line terminal if I compile..
And it fails if I try to simulate using register injection in MPLAB.I wanted to run it in simulation also (anyone knows how register injection actuallly works in MPLAB?)
The problem I face together when I try to debug . it compiles but doesn't work
here is my code :
Any idea or hint about the problem will be highly appreciated.
I personally fee that placing the code [hierarchical way] may be wrong
Thanks!
#include <xc.h>
#include "mcc.h"
#include "LED.h"
#include "tmr0.h"
#include "interrupt_manager.h"
void SetLedColor(uint16_t R_color, uint16_t G_color, uint16_t B_color);
void main(void)
{
uint8_t data, i, j;
uint16_t R_value, G_value, B_value;
uint8_t value;
uint8_t RX_Buffer[FRAMESIZE] ,RGB_data[6] ,HEX_data[6];
// initialize the device
SYSTEM_Initialize();
INTERRUPT_GlobalInterruptEnable(); // Enable the Global Interrupts
INTERRUPT_PeripheralInterruptEnable(); // Enable the Peripheral Interrupts
while (1)
{
// EUSART_Write(0x61);
while (!RCIF)
{
data = EUSART_Read(); // Read received character
for (i = 0; i < FRAMESIZE; i++)
{
RX_Buffer[i] = data;
}
EUSART_Write(data);
}
//check if any data is received
for (j = 0; j = 5; j++) // get the RGB value in the separate array
{
RGB_data[j] = RX_Buffer[j + 3];
HEX_data[value] = RGB_data[j] / 16;
}
if (RX_Buffer[0] == 'R' && RX_Buffer[FRAMESIZE - 1] == '\n')
{
//ASCII to HEX separate values
// uint32_t number = (uint32_t)strtol(HEX_data, NULL, 16);
// R_value = number >>16;
// G_value = (number & 0xffff) >> 8;
// B_value = (number & 0x0000FF);
R_value = (uint16_t) atoh(HEX_data[0], HEX_data[1]);
G_value = (uint16_t) atoh(HEX_data[2], HEX_data[3]);
B_value = (uint16_t) atoh(HEX_data[4], HEX_data[5]);
}
SetLedColor(R_value, G_value, B_value);
}
}
void SetLedColor(uint16_t R_color, uint16_t G_color, uint16_t B_color)
{
if (R_color == 0xFF)
{
LATAbits.LATA2 = 1;
}
else
{
LATAbits.LATA2 = 0;
}
if (G_color == 0xFF)
{
LATAbits.LATA4 = 1;
}
else
{
LATAbits.LATA4 = 0;
}
if (B_color == 0xFF)
{
LATAbits.LATA5 = 1;
}
else
{
LATAbits.LATA5 = 0;
}
}
So till the receiving the UART frame and echoed back and from the storing data make LED blink , I am able to succeed and this is what I wanted for primary step here by hierarchical way
#include "mcc_generated_files/mcc.h"
#include <stdlib.h>
#include <stdio.h>
#include "atoh.h"
#include "LED.h"
#define _XTAL_FREQ 16000000
#define FRAMESIZE 19
void main(void)
{
uint8_t data,i,j,got_char;
uint8_t R_value, G_value ,B_value;
uint8_t value;
uint8_t RX_Buffer[FRAMESIZE];
uint8_t RGB_data[6] ,HEX_data[6];
// initialize the device
SYSTEM_Initialize();
INTERRUPT_GlobalInterruptEnable(); // Enable the Global Interrupts
INTERRUPT_PeripheralInterruptEnable(); // Enable the Peripheral Interrupts
while (1)
{
if (EUSART_DataReady)
{
for (i = 0; i<FRAMESIZE; i++)
{
RX_Buffer[i] = EUSART_Read();
if (RX_Buffer[i] == '\n')
break;
}
RX_Buffer[i] = '\n'; //append '\n' at the end of stoaring array for detection of frame
RX_Buffer[i+1] = '\0'; // End of an array
EUSART_WriteAnArrayOfBytes(RX_Buffer);
if(RX_Buffer[0]=='R' && RX_Buffer[FRAMESIZE-2] == '\n') //check for correct frame
{
LATAbits.LATA2 = 1;
__delay_ms(2000);
LATAbits.LATA2 = 0;
__delay_ms(1000);
}
}
}
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);