Reputation: 35
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) :
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++;
}
}
}
}
Upvotes: 0
Views: 2027
Reputation: 35
After adding "ei();" to my program, it didn't work as expected. I was using "SparkFun FTDI Basic Breakout - 5V" to connect through serial port. I changed my way to connect the PC and the PIC using an RS-232 cable and it worked ! – nico1717 9 mins ago
So I don't really know why but I think that the FTDI board was not sending data from computer to the pic properly (even if the Rx led blinked everytime I sent an info). All is OK now I both transmit and receive info (I still call ei(); in my programm).
Upvotes: 0
Reputation: 2518
Seems like you did not enable global interrupts.
From the tutorial you posted:
ei(); //remember the master switch for interrupt?
This call is missing in your code.
Upvotes: 2