Following this tutorial, I wanted to send and receive data from PIC18f4520 to my computer. Sending data to the computer using serial port is working fine for me. I'm now trying to receive data from my computer using the serial port. I'm sending data from a C# app which has been created by my teacher (it's working fine for other students) so this can't be the problem.
To receive data, I need to do it using interrupts. I changed USART_RX_INT_OFF to USART_RX_INT_ON and enabled the peripheral interrupt.
Using the debugging tool, I noticed that my program was never entering is the interrupt (I must use the high-priority one).
What my program does basically (this is working fine) :
- I'm gathering analog data from pin RA5 using ADC
- Sending HIGH or LOW to pin RE2 to light a bulb or to turn it off
- Using pin RA1 to control a servo motor
- Using an LCD screen to print information on it
Init_Interruptions() is supposed to init the interrupts ADC_Init() is supposed to init ADC
Here is my code, I tried to add as much comments as possible in order to be clear. Let me know if you can help me, this would be really appreciated.
#include <stdio.h>
#include <stdlib.h>
#include "p18f4520.h"
#include <stdio.h>
#include <stdlib.h>
#include <plib/adc.h>
#include <plib/usart.h>
#include <plib/portb.h>
#include <plib/delays.h>
#include <plib/timers.h>
#include <plib/pwm.h>
#include <string.h>
#include <xc.h>
#include <stdlib.h>
#include "config.h"
#include "hd44780/hd44780.h"
#define delay1S for(uint8_t i = 0 ; i < 20 ; i++) __delay_ms(50)
int counter;
unsigned char textTx[10];
unsigned char JourMSG[]= "jour";
unsigned char NuitMSG[]= "nuit";
/*char chaine[10]= "";
char buffer[10];
char * s1, * s2;
unsigned int i, j;*/
//Servo motor signal sending functions
void turn_middle() { //0°
PORTAbits.RA1 = 1;
__delay_us(1500);
PORTAbits.RA1 = 0;
__delay_us(18500);
}
void turn_left() { //-90°
PORTAbits.RA1 = 1;
__delay_us(1000);
PORTAbits.RA1 = 0;
__delay_us(19000);
}
void turn_right() { //90°
PORTAbits.RA1 = 1;
__delay_us(2000);
PORTAbits.RA1 = 0;
__delay_us(18000);
}
//////////////////////////////////////
//Delay functions
void DelayxmSecond(unsigned int tempo_ms)
{
for(int i=0;i<tempo_ms;i++)
__delay_ms(1);
}
void DelayxSecond(unsigned int tempo_s)
{
for(int j=0;j<tempo_s;j++)
DelayxmSecond(1000);
}
////////////////////////////////////////
void Init_Timer1(void)
{
OpenTimer1(TIMER_INT_ON & T1_16BIT_RW & T1_SOURCE_EXT & T1_PS_1_1 & T1_OSC1EN_ON & T1_SYNC_EXT_ON);
IPR1bits.TMR1IP=0;
WriteTimer1(32768);
}
void Init_Interruptions(void)
{
PIR1bits.RCIF = 0; //reset RX pin flag
IPR1bits.RCIP = 1; //high priority
PIE1bits.RCIE = 1; //Enable RX interrupt
INTCONbits.PEIE = 1; //Enable pheripheral interrupt (serial port is a pheripheral)
RCONbits.IPEN = 1;
INTCONbits.GIEH = 1;
INTCONbits.GIEL = 1;
}
void interrupt high_priority Int_haute()
{
//check if the interrupt is caused by RX pin
if(PIR1bits.RCIF == 1)
{
INTCONbits.GIEH = 0;
getsUSART(textTx,10);
PIR1bits.RCIF = 0; // clear rx flag
INTCONbits.GIEH = 1;
}
}
void interrupt low_priority Int_basse() //Not doing anything here
{
INTCONbits.GIEL = 0;
INTCONbits.GIEL = 1;
}
void ADC_Init() //ADC init
{
ADCON1bits.VCFG1 = 0; //-Vref VSS
ADCON1bits.VCFG0 = 0; //+Vref VDD
ADCON1bits.PCFG3 = 1110;
ADCON1bits.PCFG2 = 1110;
ADCON1bits.PCFG1 = 1110;
ADCON1bits.PCFG0 = 1110;
ADCON0bits.CHS3 = 0000;
ADCON0bits.CHS2 = 0000;
ADCON0bits.CHS1 = 0000;
ADCON0bits.CHS0 = 0000;
ADCON0bits.GODONE = 0;
ADCON0bits.ADON = 1;
ADCON2bits.ADFM = 0;
ADCON2bits.ACQT2 = 101;
ADCON2bits.ACQT1 = 101;
ADCON2bits.ACQT0 = 101;
ADCON2bits.ADCS2 = 010;
ADCON2bits.ADCS2 = 010;
ADCON2bits.ADCS2 = 010;
ADCON0bits.ADON = 1; //TURN ON AD MODULE
ADCON1 = 0xC0; //All pins as Analog Input
//With reference voltages VDD and VSS
}
void main(){
TRISCbits.TRISC7 = 1;
TRISCbits.TRISC6 = 0;
OpenUSART( USART_TX_INT_OFF &USART_RX_INT_ON &USART_ASYNCH_MODE &USART_EIGHT_BIT &USART_BRGH_HIGH,12 );
Init_Interruptions();
//Set LCD pins to output
TRISD=0x00;
//PIC2DEMPLUS related stuffs. Not needed on board without LCD power control and with R/W wired to ground
LATDbits.LD7 = 1; // LCD power on
__delay_ms(50); // LCD power up delay
LATDbits.LD5 = 0; // R/W set to W
//LCD init
LCDinit(LCD_INIT_CURSOR_DISABLED);
__delay_ms(2);
ADC_Init();
TRISAbits.TRISA5 = 1; // configure RA5 as analog input
ADCON0 = 0b01100000; // Set channel select to AN5
ADCON1 = 0b00001011; // Configure RA5/AN5 as analogue
ADCON2 = 0b10101010; // Right justified result
// configure voltage reference
//ADCON1bits.VCFG1 = 0; // -ve ref = Vss
//ADCON1bits.VCFG0 = 1; // +ve ref = Vdd
// select ADC input channel
ADCON0bits.CHS = 100; // input = AN5
ADCON2bits.ACQT = 100; // input = AN5
ADCON2bits.ADCS = 100; // input = AN5
ADCON2bits.ADFM = 1;
ADCON0bits.ADON = 1; // turn on ADC module
TRISAbits.TRISA1 = 0; //RA1 output -> SERVOMOTOR
TRISEbits.TRISE2 = 0; //RB1 output -> BULB
PORTBbits.RB1 = 1;
int compteur=0;
int modejour=1; //Starting with day mode
unsigned int N;
while(1)
{
ADCON0bits.GO_DONE = 1; //LAUNCH CONVERSION
while(ADCON0bits.GO_DONE != 0);
LCDpos(0,3);
N=(ADRESH<<8)+ADRESL;
putsUSART(textTx);
if(N>800 && modejour==0)
{
LCDpos(0,3);
LCDprintConst("PLEIN JOUR");
putsUSART(JourMSG);
PORTEbits.RE2 = 0;
modejour=1;
compteur=0;
while(compteur<20)
{
turn_right();
compteur++;
}
}
if(N<800 && modejour==1)
{
LCDpos(0,3);
LCDprintConst("MODE NUIT ");
putsUSART(NuitMSG);
PORTEbits.RE2 = 1;
modejour=0;
compteur=0;
while(compteur<20)
{
turn_left();
compteur++;
}
}
}
}
ADCON2bits.ADCS2 = 010;
are octal values, it that what you actually want? – user3629249Int_haute()
function, callinggetsUSART()
with a second parameter of 10 will cause the code to stay in that interrupt for a minimum of 10 'char' times. That is a VERY long time to be sitting in an interrupt.getsUSART()
performs polling rather than interrupt driven I/O. Suggest removing the interrupt code, then calling:char DataRdyUSART( void );
on a regular basis. keep a status of how many bytes are currently in the input buffer. And when that buffer is full, invoking the code to process the buffer. – user3629249char DataRdyUSART( void );
can be invoked from within themain() while()
loop and if returns true, then call getsUSART() to get one(1) char which the code appends to the input buffer. When the input buffer is full, then process the data and indicate buffer is again empty. – user3629249