PIC Capture mode not triggering interrupt - embedded

I'm trying to use the capture module on a PIC 16LF1827, but the ISR is never entered. I started with a basic falling-edge interrupt (worked), then added in the timer 1 configuration (still working), then disabled the IOC interrupt and configured/enabled the relevant CCP interrupt (ISR is never entered). The code is below: the commented section is the original basic IOC setup.
I've verified with the MPLab debugger that the ISR is not entered, and confirmed this by hooking it up to a logic analyzer and watching RB1.
#include "htc.h"
//config1
//internal osc, no wdt, use power-up timer, enable reset
// no code protection, brown-out-reset enabled, clkout is gpio,
// internal-external switchover off, failsafe clock monitor off
__CONFIG(FOSC_INTOSC & WDTE_OFF & PWRTE_ON
& MCLRE_ON & CP_OFF & CPD_OFF & BOREN_ON
& CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF);
//config2 (following MPLab's complaints when running debugger)
//low-voltage programming off, debug on, brown-out reset at 2.7 v
// stack over/under flow triggers reset, no 4x pll,
// no flash write protection
__CONFIG(LVP_OFF & DEBUG_ON & BORV_27
& STVREN_ON & PLLEN_OFF & WRT_OFF);
void interrupt isr(void){
//bounce pin 1
LATB ^= 0b10;
LATB ^= 0b10;
if(IOCIF && IOCBF0){
IOCBF0 = 0;
IOCIF = 0;
}
if (CCP1IF){
CCP1IF = 0;
}
}
void main(void){
//configure internal oscillator:
//PLL = 0, source = from config 1, frequency = 4 mhz
//0b0: SPLLEN_OFF
OSCCONbits.SPLLEN = 0b0;
//0b00: use config word 1
OSCCONbits.SCS = 0b00;
//0b1101: 4 mhz frequency
OSCCONbits.IRCF = 0b1101;
//configure peripherals
//PORT A: LEDs (output), digital
TRISA = 0x00;
ANSELA = 0;
//PORT B: digital, 0 = input, 1 = output, rest don't care
TRISB = 0b11111101;
ANSELB = 0;
//configure timer 1 (not needed for basic IOC)
//source = instruction clock, prescale = 1:1, disable LP osc, do synchronize (DC)
//0b00: instruction clock
T1CONbits.TMR1CS = 0b00;
//0b00: 1:1
T1CONbits.T1CKPS = 0b00;
//0b0: lp osc off
T1OSCEN = 0b0;
//0b0: synch (ignored)
nT1SYNC = 0b0;
//interrupts
/*
//IOC enabled on falling edge for port B 0
IOCBN0 = 0b00000001;
IOCIE = 1;
*/
//Capture on falling edge for port B 0
//notes in 23.1 of DS: disable interrupt, set operating mode, clear flag, enable interrupt
CCP1IE = 0b0;
//0b100: every falling edge
CCP1CONbits.CCP1M = 0b100;
CCP1IF = 0b0;
CCP1IE = 0b1;
//enable peripheral interrupts, global interrupts
PEIE = 1;
GIE = 1;
//start timer 1
TMR1ON = 1;
while(1){
//Toggle led 0
LATA ^= 0b1;
}
}
I'm using the HI-TECH C compiler (lite), running in MPLab.
Any suggestions would be greatly appreciated. My apologies if I butcher terminology, this is my first project on a PIC.

Your setting for TRISB1 is as an output. According to the datasheet, the capture pin needs to be configured as an input. For the GPIO pins, setting the TRIS bit a 0 is an output, 1 is for an input.
EDIT: Forgive the initial stupid answer as I didn't realize you were using PORTB1 as a GPIO indicator for your scope.
So initially you used PORTB0 as your capture pin correct (using IOC)? The capture module uses a different GPIO port for its input (PORTB3 for CCP1). Did you move the connection to PORTB3 for your capture source?
EDIT: After some more looking through the PIC datasheet I noticed that CCP1's GPIO pin can be moved from PORTB3 to PORTB0 but I don't see any reference to how you set the APFCON0.CCP1SEL bit. That would be something else to check.

Related

Attiny204 Interrupt Flag Not Being Generated

I'm trying to write a (fairly) basic bit of software for and Attiny204, which handles interrupts when a clock input is pulled high.
When I run the code in the debug simulator in Atmel Studio, and set the clock input high, there is no interrupt flag generated. The interrupts do trigger when I manually produce an interrupt flag.
I've tried using different pins, and even, the other port. I can't seem to get the simulator to produce the interrupt flag.
In the past, I have used the AtMega328P in the simulator with equivalent code, and it works fine.
ISR(PORTA_PORT_vect)
{
//In this function we must:
//1. Shift all data up
shiftUp();
//2. Get new 8th bit
bit8 = VPORTA.IN & (1 << 1);
//3. Set Data Output Pin to bit0
if(bit0 == 0)
VPORTA.OUT &= ~(1 << 3);
else
VPORTA.OUT |= (1 << 3);
//4. Calculate new dimValue and dimMilliseconds
calcDim();
calcDelay();
}
int main(void)
{
initVariables();
/*
Below this, we must set the Data Direction (DD) of each pin we assigned.
*/
//Below, set the ISC of the Zero Cross Pin and the Clock Pin to allow interrupts
PORTA_PIN0CTRL |= 0b00000001; //Zero Cross
//PORTA_PIN1CTRL = 0b00000000; //Data In
//PORTA_PIN2CTRL = 0b00000000; //Data Next
//PORTA_PIN3CTRL = 0b00000000; //Triac Control
PORTB_PIN0CTRL |= 0b00000001; //Clock
//VPORTB.INTFLAGS |= 0b00000001;
//Set Port direction.
VPORTA.DIR = 0x30;
VPORTB.DIR = 0x00;
/*
Below this, we must enable interrupts.
*/
sei();
/* Replace with your application code */
while (1)
{
}
}
Why are you writing to VPORTA and VPORTB? The Tiny204 doesn´t have this registers.
You enable interrupts on both edges for Pin 0 of Port A (PIN0CTRL bit 0 is set = BOTHEDGES) and you don´t clear the interrupt flag in your ISR of Port A. Please take a look at the data sheet:
The interrupt request remains active until the interrupt flag is cleared. See the peripheral's INTFLAGSregister for details on how to clear interrupt flags.

Why HM-10 doesn't send an OK if i send AT from an MSP430 Launchpad?

I'm trying to set up an UART communication with a HM-10 chip on a Texas Instruments MSP430 Launchpad, but I ran into a very elementary problem.
What I want to achieve is to send an "AT" through UART to HM-10, and receive an answer for that. By the way this is a code I found here and I slightly modified for my purposes.
#include "msp430g2553.h"
const char string[] = { "AT" };
unsigned int i;
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop the Watch dog
//------------------- Configure the Clocks -------------------//
if (CALBC1_1MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
BCSCTL1 = CALBC1_1MHZ; // Set range
DCOCTL = CALDCO_1MHZ; // Set DCO step + modulation
//---------------- Configuring the LED's ----------------------//
P1DIR |= BIT0 + BIT6; // P1.0 and P1.6 output
P1OUT &= ~BIT0 + BIT6; // P1.0 and P1.6 = 0
//--------- Setting the UART function for P1.1 & P1.2 --------//
P1SEL |= BIT1 + BIT2; // P1.1 UCA0RXD input
P1SEL2 |= BIT1 + BIT2; // P1.2 UCA0TXD output
//------------ Configuring the UART(USCI_A0) ----------------//
UCA0CTL1 |= UCSSEL_2 + UCSWRST; // USCI Clock = SMCLK,USCI_A0 disabled
UCA0BR0 = 104; // 104 From datasheet table-
UCA0BR1 = 0; // -selects baudrate =9600,clk = SMCLK
UCA0MCTL = UCBRS_1; // Modulation value = 1 from datasheet
//UCA0STAT |= UCLISTEN; // loop back mode enabled
UCA0CTL1 &= ~UCSWRST; // Clear UCSWRST to enable USCI_A0
//---------------- Enabling the interrupts ------------------//
IE2 |= UCA0TXIE; // Enable the Transmit interrupt
IE2 |= UCA0RXIE; // Enable the Receive interrupt
_BIS_SR(GIE); // Enable the global interrupt
i = 0;
UCA0TXBUF = string[i]; // Transmit a byte
_BIS_SR(LPM0_bits + GIE); // Going to LPM0
}
//-----------------------------------------------------------------------//
// Transmit and Receive interrupts //
//-----------------------------------------------------------------------//
#pragma vector = USCIAB0TX_VECTOR
__interrupt void TransmitInterrupt(void)
{
P1OUT ^= BIT0;//light up P1.0 Led on Tx
if (i == sizeof string - 1)
{
UC0IE &= ~UCA0TXIE;
}
UCA0TXBUF = string[i++];
}
#pragma vector = USCIAB0RX_VECTOR
__interrupt void ReceiveInterrupt(void)
{
// light up P1.6 LED on RX
if (UCA0RXBUF == 'O')
{
P1OUT ^= BIT6;
}
IFG2 &= ~UCA0RXIFG; // Clear RX flag
}
According to the datasheet I should receive an OK answer for this command.
If there was an 'O' in the RX buffer, I would expect the LED to light up on my board, but that doesn't happen.
Using Code Composer, I also verified with adding a breakpoint to the RX interrupt that there is indeed no RX answer.
I believe this is entirely a software question, that's why I put it here. I'm using the correct rotation of jumpers(http://xanthium.in/Serial-Communication-MSP430-UART-USCI_A) and RX is wired to TX and vica versa.
I would appreciate if you could point out if I was doing anything conceptionally wrong or if I just made a mistake. Thank you!
I see a problem in the interrupt routine TransmitInterrupt(): you should use UCA0TXBUF = string[++i]; because using "i++" you transmit two times the letter "A". The test about sizeof(string) should also be retouched.
Then, I would not trust too much the datasheet. I think that, despite what the datasheet says, every command sent to the modem must be terminated by CR (\r), otherwise how could the modem discern an "AT" from an "AT+RESET"? I am not really sure but the datasheet doesn't seem a high quality one. Anyway, it's a quick test (to add a \r to the end of the string).
Finally, the CTS and RTS signals can play a role too. Some modem wants RTS asserted, other modems don't care, and terminology sometimes is confusing: when datasheet says RTS, does it mean RTS of the modem or RTS of the host? I hope this helps, you should do a few scientific tries.
I think for everyone who is working with HM-10 devices in the future I want to answer this question, because it has I think its own sort of mini-literature, which was first frustrating, but then I kind of liked the challenges it posed to me.
Some of the problems are hardware related, so this post might need to be moved to an embedded engineering section. (Great consequence - you cannot be 100% sure before checking it with a scope)
Know your hardware - HM-10 has tons of versions, and it turned our one needed an extra potential divider because it has a 3.3V logic level high instead of 5V. This website is a fantastic place to start. Though, ours turned out to be an MLT-BT05 which is a clone of a clone. It doesn't have iBeacon capability on its firmware, so if you don't want to power cycling, then you should probably avoid this one.
About the coding bit the most important thing is to check with \n, \r and \n\r, as linuxfan briefly mentioned its importance above, because some of the devices need it. The best place to start is AT and if it works, then use AT+HELP and find the version, usually AT+VERSION command so you can identify with 100% certainty which chip you have.
Currenetly it is prototyped on an Arduino, but I will include working code as soon as its finished on MSP430.
The Arduino code:
#include <SoftwareSerial.h>
SoftwareSerial bluetooth(9, 10); // RX, TX
char commandbuffer[50];
int j = 0;
void setup()
{
memset(commandbuffer, 0, sizeof(commandbuffer));
analogWrite(12, 255);
analogWrite(11, 0);
// Start the hardware serial port
Serial.begin(19200);
bluetooth.begin(9600);
// un REM this to set up a Master and connect to a Slave
Serial.println("BLE CC41A Bluetooth");
Serial.println("----------------------------------");
Serial.println("");
Serial.println("Trying to connect to Slave Bluetooth");
delay(1000);
bluetooth.println("AT"); // just a check
delay(2000);
bluetooth.println("AT+NAMEHIST");
delay(2000);
bluetooth.println("AT+ROLE0");
delay(2000);
bluetooth.println("AT+INQ"); // look for nearby Slave
delay(5000);
bluetooth.println("AT+CONN1"); // connect to it */
}
void loop()
{
bluetooth.listen();
// while there is data coming in, read it
// and send to the hardware serial port:
while (bluetooth.available() > 0) {
char inByte = bluetooth.read();
Serial.write(inByte);
}
// Read user input if available.
if (Serial.available()) {
delay(10); // The DELAY!
char temp = Serial.read();
if (temp == '\n')
{
bluetooth.println(commandbuffer);
Serial.println(commandbuffer);
memset(commandbuffer, 0, sizeof(commandbuffer));
j = 0; // Reset
}
else
{
commandbuffer[j++] = temp;
}
delay(500);
}

PIC32MX795F512H UART communication to RS232

I am currently working for the first time with a PIC microcontroller. In the code I specified exactly which PIC, compiler, etc I am using. Maybe this is of help.
I am trying to set up UART communication on the PIC32 and send a hex code like 0x41 for example to a terminal on my computer through RS232. To convert the signal from the PIC UART to RS232 levels I am using a MAX232EPE.
At the moment I am running into the problem that when I send 0x41 for example from the PIC32 to the terminal or vice versa, the received data doesn't match. I think this being caused by a mistake in my baud rate settings, but I am not sure. Could someone please look over my code and see if someone can see a problem? Did I forget to define something? Did I define something wrong? Did I mis calculate the baud rate?
P.S. I know the data being received doesn't match the data send because i checked in the "watches" in debug mode in mplab and when I echo the data send from the terminal to the PIC32 back to the terminal it doesn't match either.
The Delay and interrupt code can be ignored, they are working as expected, so I really believe the problem has to do with the initial setting of the PIC/buad rate.
I hope this is clear enough, any help is very much appreciated
Thanks,
See code below
/*
The configuration below and in void UART1_Init should set up the UART correctly.
I want to achieve a buadrate of 9600. My external Crystal is 8MHz. So:
FPLLIDIV=2, FPLLMUL=20, FPLLODIV=1, FPBDIV=2, FNOSC=PRIPLL, BRGH = 0, and U1BRG = 259.
This should give me the desired baudrate of 9600.
- ((8MHz / 2) * 20)/2) = 40MHz PBclk.
- U1BRG = (PBclk/(16*Buad rate))-1 so 259
- 16*Buad rate because BRGH = 0
PIC32MX795F512H
MPLAB X IDE V3.26
XC32 Compiler
PICKit3
*/
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <plib.h>
// Give useful names to pins
#define LED1_TRIS TRISDbits.TRISD6
#define LED1 LATDbits.LATD6
#define UART1TX_TRIS TRISDbits.TRISD3
#define UART1RX_TRIS TRISDbits.TRISD2
#define FOSC 8000000 // Crystal frequency = 8 MHz
#define SYS_FREQ (80000000UL) // SYSCLK is 80 MHz
#define GetSystemClock() (FOSC) // For delay
#pragma config FPLLIDIV=DIV_2 // PLL Input Divider Value (Divide by 2)
#pragma config FPLLMUL=MUL_20 // Phase-Locked Loop (PPL) muiltiplier, multiplier of 20
#pragma config FPLLODIV=DIV_1 // Postscaler for PLL, output divided by 1
#pragma config FPBDIV=DIV_2 // 2 = PBCLK is SYSCLK divided by 2 (80MHz/2 = 40MHz)
#pragma config FWDTEN=OFF // Watch Dog Timer (WDT) is not enabled. It can be enabled by software
#pragma config CP=OFF // Code-Protect, 1 = OFF/Disabled
#pragma config BWP=OFF // Boot Flash Write-protect, 1 = OFF/Disabled
#pragma config POSCMOD=XT // Primary oscillator configuration, HS = HS Oscillator mode selection
#pragma config FNOSC=PRIPLL // Oscillator selection, PRIPLL = Primary Oscillator with PLL module
#pragma config OSCIOFNC=OFF // CLKO output disabled
#pragma config FSOSCEN=OFF // Disable secondary Oscillator
int UART_RX_Count; // Counter variable for the UART1 receiver interrupt
int UART_TX_Count; // Counter varible for the UART1 transmitted interrupt
unsigned char RD_SER_NUM; // Variable to store command to read serial number
unsigned char UART_RX_OUTPUT; // Variable to store the UART output
unsigned char i;
void UART1_Init(void){
// UART1 initialization
U1MODEbits.ON = 1; // UART1 is enabled
U1MODEbits.SIDL = 0; // Continue operation in idle mode
U1MODEbits.IREN = 0; // Disable IrDA (IrDA Encoder and Decoder Enable bit)
U1MODEbits.RTSMD = 1; // !U1RTS! pin is in Simplex mode, 0 = !U1RTS! pin is in Flow Control mode
U1MODEbits.UEN = 0; // UxTX and UxRX pins are enabled and used; UxCTS and UxRTS/UxBCLK pins are controlled by corresponding bits in the PORTx register
U1MODEbits.WAKE = 1; // Enable Wake-up on Start bit Detect During Sleep Mode bit
U1MODEbits.LPBACK = 0; // UARTx Loopback Mode Select bit, 0 = disabled, loopback = UxTX output is internally connected to the UxRX input
U1MODEbits.PDSEL = 2; // Parity and Data Selection bits, 10 = 8-bit data, odd parity
U1MODEbits.STSEL = 0; // Stop Selection bit, 0 = 1 stop bit
U1MODEbits.BRGH = 0; // High Baud Rate Enable bit, 0 = Standard Speed mode 16x baud clock enabled
U1MODEbits.RXINV = 1; // Receive Polarity Inversion bit, 1 = UxRX Idle state is 0
U1STAbits.URXEN = 1; // 1 = UART1 receiver is enabled. U1RX pin is controlled by UARTx (if ON = 1)
U1STAbits.UTXEN = 1; // 1 = UART1 transmitter is enabled. U1TX pin is controlled by UARTx (if ON = 1)
U1STAbits.UTXINV = 1; // Transmit Polarity Inversion bit, 1 = UxTX Idle state is 0
U1STAbits.ADM_EN = 0; // 0 = Automatic Address Detect mode is disabled
U1BRG = 259; // Baud Rate Divisor bits (0-15 bits), set baud rate, 9600 # 40 MHz PBclk
__builtin_disable_interrupts(); // Tell CPU to stop paying attention to interrupts
INTCONbits.MVEC = 1; // Multi Vector interrupts
U1STAbits.URXISEL = 0; // 0x = Interrupt flag bit is set when a character is received
U1STAbits.UTXISEL = 1; // 01 = Interrupt flag bit is set when all characters have been transmitted
IPC6bits.U1IP = 5; // Set UART1 priority 5 of 7
IPC6bits.U1IS = 0; // Set UART1 sub priority to 0
IFS0bits.U1RXIF = 0; // Clear UART1 RX interrupt flag
IFS0bits.U1TXIF = 0; // Clear UART1 TX interrupt flag
IEC0bits.U1RXIE = 1; // Enable UART1 RX ISR
__builtin_enable_interrupts(); // Tell CPU to start paying attention to interrupts again
UART_RX_Count = 0; // Set initial UART1 received interrupts count to 0
UART_TX_Count = 0; // Set initial UART1 transmit interrupts count to 0
}
void __ISR(_UART_1_VECTOR, IPL5SRS) UART1_INT(void){
if(INTGetFlag(INT_U1RX)){ // Check if UART1 RX interrupt was triggered
LED1 = ~LED1; // Toggle LED1
UART_RX_Count++; // Add 1 to UART1 RX interrupt occurrence counter
// UART_RX_OUTPUT = U1RXREG; // Read UART1 RX buffer/register
U1TXREG = U1RXREG; // Transmit the received data back
// U1STAbits.OERR = 0; // Clear UART1 buffer overflow
IFS0bits.U1RXIF = 0; // Clear UART1 RX interrupt flag
}else{
if(INTGetFlag(INT_U1TX)){ // Check if UART1 TX interrupt was triggered
UART_TX_Count++; // Add 1 to UART1 TX interrupt occurrence counter
IEC0bits.U1TXIE = 0; // Disable UART1 TX ISR
IFS0bits.U1TXIF = 0; // Clear UART1 TX interrupt flag
}
}
}
// DelayMs creates a delay of given milliseconds using the Core Timer
void DelayMs(WORD delay){
unsigned int int_status;
while( delay-- ){
int_status = INTDisableInterrupts();
OpenCoreTimer(GetSystemClock() / 200);
INTRestoreInterrupts(int_status);
mCTClearIntFlag();
while( !mCTGetIntFlag() );
}
mCTClearIntFlag();
}
int main(){
UART1_Init(); // Call the initializations function of UART1
LED1_TRIS = 0; // Set the LED1 as an output
UART1TX_TRIS = 0; // Set UART1 TX pin as output
UART1RX_TRIS = 1; // Set UART1 RX pin as input
LED1 = 0; // Turn off LED1
while(1){
// DelayMs(1000);
// IEC0bits.U1TXIE = 1; // Enable UART1 TX ISR
// U1TXREG = 0x41; // Send command to U1TXREG
}
return 0;
}
As You are using PIC32MX795F512H, You can use the MPLAB Harmony framework tool for creating your project. So that you need not to play on bit level and stuck in minor error or most probabaly typo error.
Its convinient to generate drivers and all framework properly.
Thanks and regards
Ravi
Using Harmony will actually help you avoid simple errors like the one you have encountered. Especially for the clocks you even have auto calculating functions decreasing your implementation time significantly.

MSP430 G2553 UART Baudrate 9600 16MHz clock Issues

I'm interfacing my G2553 to a standard LCD screen using UART. I got it working like a dream at 1MHz, but need the system to run at 16MHz for certain other peripherals. I got it very close to working at 16MHz but there is what I believe to be a baudrate error, as the screen will show almost what I sent it, but miss a character here or there or get a character incorrect. I'll take you through how I wrote my code to see if I made any errors.
The screen expects a baudrate of 9600, so I went to the table in my user guide:
So UCBRx = 1666
and UCBRSx = 6.
The expected % errors on this are actually better than what I was using at the 1MHz clock so I thought this would be OK.
This means UCBR0 = 130 and UCBR1 = 6 (This is just the HEX value of UCBRx spread over two 8-bit registers) and UCBRSx = 6.
Now to enter these I looked at what the user guide tells us about the UART modulation register:
(was going to make this pretty but I don't have the reputation to post images)
So my initialisation code ended up being:
if (CALBC1_16MHZ==0xFF) // If calibration constant erased
{
while(1); // do not load, trap CPU!!
}
DCOCTL = 0; // Select lowest DCOx and MODx settings
//setup DCO to 16MHZ
BCSCTL1 = CALBC1_16MHZ;
DCOCTL = CALDCO_16MHZ;
P1SEL |= BIT1 + BIT2 ; // P1.1 = RXD, P1.2=TXD
P1SEL2 |= BIT1 + BIT2;
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 130; // 16MHz 9600
UCA0BR1 = 6; // 16MHz 9600
UCA0MCTL = UCBRS2 + UCBRS1; // modulation is 110b or 6
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
However as I stated above this is almost there, for example if I try to display the string "Initialising..." which worked for my 1MHz 9600 baudrate settings, with 16MHz at these settings it might display "Initiali ng..." - something close but obviously some error in there that I don't want.
Thank you for any help you can provide on this.
According to the baud rate calculator at http://mspgcc.sourceforge.net/baudrate.html, UCA0MCTL is supposed to be 0x5B

No interrupts being triggered in UART Receive on PIC18F2680

I have been working with this code for days and cannot figure out why my interrupts are not being triggered. I know data is coming through successfully because I used a probe on a logic analyzer, also my baud rate is correct as I can transmit with UART successfully.
At this point I'm lost, I've read the datasheet over and over and can't figure out my problem. I will try to include only the relative code but enough that you can see how things work in my project.
Please let me know if you see issues with this code.
Thank you!
Code snippets from main.c:
// USART RX interrupt priority
IPR1bits.RCIP = 0;
IPR1bits.TXIP = 0;
// configure the hardware USART device
OpenUSART(USART_TX_INT_OFF & USART_RX_INT_ON & USART_ASYNCH_MODE & USART_EIGHT_BIT &
USART_CONT_RX & USART_BRGH_LOW, 14);
Code snippets from interrupts.c
//----------------------------------------------------------------------------
// Low priority interrupt routine
// this parcels out interrupts to individual handlers
#pragma code
#pragma interruptlow InterruptHandlerLow
// This works the same way as the "High" interrupt handler
void InterruptHandlerLow() {
// check to see if we have an interrupt on USART RX
if (PIR1bits.RCIF) {
PIR1bits.RCIF = 0; //clear interrupt flag
uart_recv_int_handler();
}
// check to see if we have an interrupt on USART TX
if (PIR1bits.TXIF && PIE1bits.TXIE) {
// cannot clear TXIF, this is unique to USART TX
// so just call the handler
uart_tx_int_handler();
}
}
UART RX Interrupt Handler snippet:
void uart_recv_int_handler() {
int msgLen;
//if (DataRdyUSART()) {
uc_ptr->buffer[uc_ptr->buflen] = RCREG;
//uc_ptr->buffer[uc_ptr->buflen] = ReadUSART();
uc_ptr->buflen++;
}
}
Did you
- Set trisC6/7 correctly?
- if you have a part with analog inputs multiplexed on those pins, did you disable them?
- Is your BRG value validated for this part and these oscillator settings?
See also
http://www.piclist.com/techref/microchip/rs232.htm
I migrated to dspic, but I used to do the serial receive under interrupt. This I had in the interrupt (serialin1 is a power of two circular buffer, lastserialin1 the pointer into it, and ser1bufinmask is size of buffer-1)
if (PIR1bits.RCIF == 1) /* check if RC interrupt (receive USART) must be serviced
{
while (PIR1bits.RCIF == 1) /* flag becomes zero if buffer/fifo is empty */
{
lastserialin1=(lastserialin1+1)&ser1bufinmask;
serialin1[lastserialin1]=RCREG;
}
}
To initialize the uart I had:
// Configure USART
TXSTA = 0x20; // transmit enable
RCSTA = 0x90; // spen en cren
RCONbits.IPEN = 1; /* Interrupt Priority Enable Bit. Enable priority levels on interrupts */
INTCONbits.GIE = 1; /* Set GIE. Enables all high priority unmasked interrupts */
INTCONbits.GIEL = 1; /* Set GIEL. Enables all low priority unmasked interrupts */
TRISCbits.TRISC6 = 0; // page 237
TRISCbits.TRISC7 = 1; // page 237
Open1USART (
USART_TX_INT_OFF
&
USART_RX_INT_ON &
USART_ASYNCH_MODE &
USART_EIGHT_BIT & // 8-bit transmit/receive
USART_CONT_RX & // Continuous reception
// USART_BRGH_HIGH, 155); // High baud rate, 155 eq 19k2
USART_BRGH_HIGH, brgval); // High baud rate, 25 eq 115k2
IPR1bits.RCIP = 0;
PIR1bits.RCIF = 0;
with brgval calculated using
#define GetInstructionClock() (GetSystemClock()/4)
#define GetPeripheralClock() GetInstructionClock()
// See if we can use the high baud rate setting
#if ((GetPeripheralClock()+2*BAUD_RATE)/BAUD_RATE/4 - 1) <= 255
#define BRGVAL ((GetPeripheralClock()+2*BAUD_RATE)/BAUD_RATE/4 - 1)
#define BRGHVAL (1)
#else // Use the low baud rate setting
#define BRGVAL ((GetPeripheralClock()+8*BAUD_RATE)/BAUD_RATE/16 - 1)
#define BRGHVAL (0)
#endif