SPI master to PIC18F4550 slave synchronization (C18) using NETMF - c

A .NET Micro Framework device (ChipworkX in this case) sends a byte through the SPI interface to a PIC18F. Having PIE1bits.SSPIE enabled, the following code is executed on interrrupt:
void high_isr (void)
{
PIE1bits.SSPIE = 0;
PIR1bits.SSPIF = 0; //Clear interrupt flag.
LATDbits.LATD5 = 1; //Enables LED for high interrupt activity.
while ( !SSPSTATbits.BF ); //Wait until cycle complete
red_byte_array[1] = SSPBUF;
SSPBUF = 0x00;
LATDbits.LATD5 = 0;
PIE1bits.SSPIE = 1;
}
When sending the same byte a few times, the data does not seem to be read consistently. Both master and slave are setup for clock idle low level, and data clocking on rising edge. I don't use the chip select line, because it's direct communictation.
Finally, the master sends data at 100 kHz, while the PIC is operating at 8 MHz.
How do I improve and/or fix this code?

On the PIC16F886/7:
If you are not using the /SS, then the data changes on the rising edge and is sampled on the falling edge, for a SCK idling at 0: CKE = 0, CKP = 0 (or 1), SMP = 0.
The byte moving from the shift register to the buffer register causes BF bit and SSPIF the interrupt, so you don't normally loop about in the interrupt waiting for BF.
There should not be any need to disable SSP interrupts (SSPIE = 0), but you probably need to clear the SSPIF before returning from interrupt.
I would guess you should, on SSP interrupt (SSPIF = 1):
red_byte_array[x] = SSPBUF
SSPIF = 0
You may need to check WCOL and SSPOV for errors.

Given that your PIC only has ( 8 MHz / 100 kHz ) 80 cycles to respond, that Delay1KTCYx() seems rather long.

Related

STM32 maximum interrupt handling frequency

I am trying to implement my own SPI communication from FPGA to STM in which my FPGA serve as MASTER and generate Chip enable and clock for communication. FPGA transmit data at its rising edge and receive data at its falling edge my FPGA code works properly.
In STM side i capture this master clock on interrupts and receive data at its rising edge and transmit at its falling edge but communication not work properly if i increase clock speed from 250khz
According to my understand STM work at 168 Mega hz i set clock setting according to 168Mhz and handling of 1mhz interrupt is not a big problem so can you any guide how i handle this high speed clock in STM
My code is written below
/*
* Project name:
EXTI_interrupt (EXTI interrupt test)
* Copyright:
(c) Mikroelektronika, 2011.
* Revision History:
20111226:
- Initial release;
* Description:
This code demonstrates how to use External Interrupt on PD10.
PD10 is external interrupt pin for click1 socket.
receive data from mosi line in each rising edge.
* Test configuration:
MCU: STM32F407VG
http://www.st.com/st-web-
ui/static/active/en/resource/technical/document/datasheet/DM00037051.pdf
dev.board: EasyMX PRO for STM32
http://www.mikroe.com/easymx-pro/stm32/
Oscillator: HSI-PLL, 140.000MHz
Ext. Modules: -
SW: mikroC PRO for ARM
http://www.mikroe.com/mikroc/arm/
* NOTES:
receive 32 bit data from mosi line in each rising edge
*/
//D10 clk
//D2 ss
//C0 MOSI
//C1 FLAG
int read=0;
int flag_int=0;
int val=0;
int rec_data[32];
int index_rec=0;
int display_index=0;
int flag_dint=0;
void ExtInt() iv IVT_INT_EXTI15_10 ics ICS_AUTO {
EXTI_PR.B10 = 1; // clear flag
flag_int=1; //Flag on interrupt
}
TFT_Init_ILI9340();
void main() {
GPIO_Digital_Input(&GPIOD_BASE, _GPIO_PINMASK_10);
GPIO_Digital_Output(&GPIOD_BASE, _GPIO_PINMASK_13); // Set PORTD as
digital output
GPIO_Digital_Output(&GPIOD_BASE, _GPIO_PINMASK_12); // Set PORTD as
digital output
GPIO_Digital_Output(&GPIOD_BASE, _GPIO_PINMASK_14); // Set PORTD as
digital output
GPIO_Digital_Output(&GPIOD_BASE, _GPIO_PINMASK_15); // Set PORTD as
digital output
GPIO_Digital_Input(&GPIOA_IDR, _GPIO_PINMASK_0); // Set PA0 as
digital input
GPIO_Digital_Input(&GPIOC_IDR, _GPIO_PINMASK_0); // Set PA0 as
digital input
GPIO_Digital_Input(&GPIOC_IDR, _GPIO_PINMASK_2); // Set PA0 as
digital input
GPIO_Digital_Output(&GPIOC_IDR, _GPIO_PINMASK_1); // Set PA0 as
digital input
//interupt register
SYSCFGEN_bit = 1; // Enable clock for alternate pin
functions
SYSCFG_EXTICR3 = 0x00000300; // Map external interrupt on PD10
EXTI_RTSR = 0x00000000; // Set interrupt on Rising edge
(none)
EXTI_FTSR = 0x00000400; // Set Interrupt on Falling edge
(PD10)
EXTI_IMR |= 0x00000400; // Set mask
//NVIC_IntEnable(IVT_INT_EXTI15_10); // Enable External interrupt
while(1)
{
//interrupt is not enable until i push the button
if((GPIOD_ODR.B2==0)&&(flag_dint==0))
{ if (Button(&GPIOA_IDR, 0, 1, 1))
{
Delay_ms(100);
GPIOC_ODR.B1=1; //Status for FPGA
NVIC_IntEnable(IVT_INT_EXTI15_10); // Enable External interrupt
}
}
if(flag_int==1)
{
//functionality on rising edge
flag_int=0;
if(index_rec<31)
{
//display data on led
GPIOD_ODR.B13= GPIOC_IDR.B0;
//save data in an array
rec_data[index_rec]= GPIOC_IDR.B0;
//read data
index_rec=index_rec+1;
}
else
{
flag_dint=1;
NVIC_IntDisable(IVT_INT_EXTI15_10);
}
} // Infinite loop
}
}
Without getting into your code specific, see PeterJ_01's comment, the clock rate problem can be explained by a misunderstanding of throughput in your assumtions.
You assume that given that your STM device has a clock of 168Mhz it can sustain the same throughput of interrupts, which you seem to have conservatively relaxed to 1Mhz.
However the throughput of interrupts it will be able to support is given by the inverse of the time it takes the device to process each interrupt. This time includes both the time the processor takes to enter the service routing (ie detect the interrupt, interrupt the current code and resolve from the vector table where to jump to) plus the time taken to execute the service routine.
Lets be super optimistic and say that entering the routine takes 1 cycle and the routing itself takes 3 (2 for the flags you set and 1 for the jump out of the routine). This gives 4 cycles at 168Mhz is 23.81ns, taking the inverse 42Mhz. This can also be computed by dividing the maximum frequency you would achieve (168Mhz) by the number of cycles spent processing.
Hence our really optimistic bound is 42Mhz, but realistically will be lower. For a more accurate estimate you should test your implementation timings and dig into your device's documentation to see interrupt response times.

how can I make multiple ultrasonic sensors work at the same time using atmega32

I am working on an auto-parking car robot and I am using 8 (hc-sr04) ultrasonic sensors (2 at each side) but the problem is that I am using atmega32 which has limited resources only 3 external interrupts and 3 timers (and even if using interrupts somehow works I might run into risk to have two interrupts triggered at the same time).
I am using this sensor : http://ram-e-shop.com/oscmax/catalog/product_info.php?products_id=907
I've tried using digital I/O pins with polling procedure but it didn't work.
here is the code for polling procedure:
unsigned int read_sonar(){
int dist_in_cm = 0;
init_sonar(); // Setup pins and ports
trigger_sonar(); // send a 10us high pulse
while(!(ECHO_PIN & (1<<ECHO_BIT))){ // while echo pin is still low
USART_Message("echo pin low\r\n");
trig_counter++;
uint32_t max_response_time = SONAR_TIMEOUT;
if (trig_counter > max_response_time){ // SONAR_TIMEOUT
return TRIG_ERROR;
}
}
TCNT1=0; // reset timer
TCCR1B |= (1<<CS10); // start 16 bit timer with no prescaler
TIMSK |= (1<<TOIE1); // enable overflow interrupt on timer1
overFlowCounter=0; // reset overflow counter
sei(); // enable global interrupts
while((ECHO_PIN & (1<<ECHO_BIT))){ // while echo pin is still high
USART_Message("echo pin high\r\n");
if (((overFlowCounter*TIMER_MAX)+TCNT1) > SONAR_TIMEOUT){
USART_Message("timeout");
return ECHO_ERROR; // No echo within sonar range
}
};
TCCR1B = 0x00; // stop 16 bit timer with no prescaler
cli(); // disable global interrupts
no_of_ticks = ((overFlowCounter*TIMER_MAX)+TCNT1); // counter count
dist_in_cm = (no_of_ticks/(CONVERT_TO_CM*CYCLES_PER_US)); // distance in cm
return (dist_in_cm );}
This method doesn't work if I want to read all sensors at the same time, because it gets stuck in the loop for a while.
I also tried using freeRTOS to build a task that checks the state of pins like every 1msec but this won't be a time accurate.
any help?
Assuming that You use internal clock which is 8MHz I would try to handle this inside timer overflow interrupt and would use whole port to connect the sensors.
Use Timer in normal mode or CTC mode (which I find quite intuitive) to ensure periodical interrupts. Set the appropriate period. Remember that the clock has pretty low frequency so don't exaggerate (I think that 0,25 ms will fit).
Connect the sensors to one port, e.g. PORTB. This is a nice situation because ATmega32 has 4 ports with pins numbered from 0-7 and you use 8 sensors so the register for the specific port can cover all of the pins and You can use one read to get states of all of the pins.
Implement the logic:
volatile uint8_t sensors_states;
volatile uint8_t read_flag = 0;
ISR(TIMER0_OVF_vect)
{
sensors_states = PORTB;
read_flag = 1;
}
int main()
{
// Initialize peripherals ...
// You must assume on your own how much time could the pin be held
// in the same state. This is important because the number must not
// be bigger than max value for the type of the array
uint8_t states_time[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint8_t prev_sensors_states = PORTB;
while(1)
{
// Wait until the flag will be set in the ISR
if(read_flag)
{
for(uint8_t i = 0, mask = 0x80 ; i < 8 ; i ++, mask >>= 1)
{
states_time[i]++;
// Compare the previous state and present state on each pin
uint8_t state = mask & sensors_states;
if((mask & prev_sensors_states) != state)
{
// Here you can use the state of the pin and the duration of that state.
// Remember that when 'state' is > 0 it means that previous state of the
// pin was '0' and if if 'state' is == 0 then the previous pin state
// was '1' (negation).
do_something_with_pin_change(states_time[i], state);
states_time[i] = 0;
}
}
// Save the previous states of the pins
prev_sensors_states = sensors_states;
// Clear the flag to await next data update
read_flag = 0;
}
}
}
If You will try to use FreeRTOS You could use ulTaskNotifyTake and vTaskNotifyGiveFromISR, instead of using read_flag, to implement a simple mechanism which will notify a task from the interrupt that the port has been read. The processor will go into idle state for a while and you could then invoke a sleep function to minimize power consumption.
I don't know what You want to do with this data so I've invoked do_something_with_pin_change function to indicate the point where You can use the data.
To sum up for this solution You would only use one interrupt and of course 8 pins.

How to get millisecond resolution from DS3231 RTC

How to get accurate milliseconds?
I need to calculate the delay of sending data from Arduino A to Arduino B. I tried to use DS3231 but I cannot get milliseconds. What should I do to get accurate milliseconds from DS3231?
The comment above is correct, but using millis() when you have a dedicated realtime clock makes no sense. I'll provide you with better instructions.
First thing in any hardware interfacing project is a close reading of the datasheet. The DS3231 datasheeet reveals that there are five possible frequencies of sub-second outputs (see page 13):
32 KHz
1 KHz
1.024 KHz
4.096 KHz
8.192 KHz
These last four options are achieved by various combinations of the RS1 and RS2 control bits.
So, for example, to get exact milliseconds, you'd target option 2, 1KHz. You set RS1 = 0 and RS2 = 0 (see page 13 of the datasheet you provided) and INTCN = 0 (page 9). Then you'd need an ISR to capture interrupts from the !INT/SQW pin of the device to a digital input pin on your Arduino.
volatile uint16_t milliseconds; // volatile important here since we're changing this variable inside an interrupt service routine:
ISR(INT0_vect) // or whatever pin/interrupt you choose
{
++milliseconds;
if(milliseconds == 999) // roll over to zero
milliseconds = 0;
}
OR:
const int RTCpin = 3; // use any digital pin you need.
void setup()
{
pinmode(RTCpin, INPUT);
// Global Enable INT0 interrupt
GICR |= ( 1 < < INT0);
// Signal change triggers interrupt
MCUCR |= ( 1 << ISC00);
MCUCR |= ( 0 << ISC01);
}
If these commands in setup() don't work on your Arduino, google 'Arduino external interrupt INT0'. I've shown you two ways, one with Arduino code and one in C.
Once you have this ISR working and pin3 of the DS3231 connected to a digital input pin of your choosing, that pin will be activated at 1KHz, or every millisecond. Perfect!
// down in main program now you have access to milliseconds, you might want to start off by setting:
// When 1-second RTC changes seconds:
milliseconds = 0; // So you can measure milliseconds since last second.
That's all there is to it. All you need to learn now is how to set the command register using I2C commands and you're all set.
The C code example gains 1ms every second. Should be:
{
if (milliseconds == 999) // roll over to zero
milliseconds = 0;
else
++milliseconds;
}

Different results between step debugging and running program on tiva c

I have a TIVA tm4c123G I have been trying to create a communication between it and my ADXL345 sensor using I2C protocol which I succeeded in writing and reading from the accelerometer the readings of the device address and the register values that I just wrote to which means everything is running fine. However I have tried this in step by step debugging in keil and it works fine but if I run the program it will give zeroes all the way and I have no idea why? Should I add delays between the write and read from registers or whats going wrong in my code?
Here is my code attached
I am using a clock of 80 MHZ for the system and I think this might be the problem however as the code goes too fast to the execution of a next send and there should be some delay? I am not sure I'm only guessing please help thanks !
also my connection for the adxl is
Vcc -> 3.3 volts
GND -> ground
CS -> 3.3 volts
SDO -> ground
SDA -> PB3
SCL -> PB2
#include "tm4c123gh6pm.h"
#include "stdint.h"
void EnableI2CModule0(void);
uint8_t ReadRegister(uint8_t RegisterAddress);
void PLL_Init(void);
void WriteRegister(uint8_t RegisterAddress,uint8_t Data);
volatile uint8_t X_Axis1,X_Axis2,Y_Axis1,Y_Axis2,Z_Axis1,Z_Axis2=0;
int main()
{
volatile long temp;
PLL_Init();
EnableI2CModule0();
temp=ReadRegister(0x00);
WriteRegister(0x2D,0x08);
temp=ReadRegister(0x2D);
WriteRegister(0x31,0x0B);
temp=ReadRegister(0x31);
while(1)
{
X_Axis1=ReadRegister(0x32);
X_Axis2=ReadRegister(0x33);
Y_Axis1=ReadRegister(0x34);
Y_Axis2=ReadRegister(0x35);
Z_Axis1=ReadRegister(0x36);
Z_Axis2=ReadRegister(0x37);
}
}
void PLL_Init(void){
// 0) Use RCC2
SYSCTL_RCC2_R |= 0x80000000; // USERCC2
// 1) bypass PLL while initializing
SYSCTL_RCC2_R |= 0x00000800; // BYPASS2, PLL bypass
// 2) select the crystal value and oscillator source
SYSCTL_RCC_R = (SYSCTL_RCC_R &~0x000007C0) // clear XTAL field, bits 10-6
+ 0x00000540; // 10101, configure for 16 MHz crystal
SYSCTL_RCC2_R &= ~0x00000070; // configure for main oscillator source
// 3) activate PLL by clearing PWRDN
SYSCTL_RCC2_R &= ~0x00002000;
// 4) set the desired system divider
SYSCTL_RCC2_R |= 0x40000000; // use 400 MHz PLL
SYSCTL_RCC2_R = (SYSCTL_RCC2_R&~ 0x1FC00000) // clear system clock divider
+ (4<<22); // configure for 80 MHz clock
// 5) wait for the PLL to lock by polling PLLLRIS
while((SYSCTL_RIS_R&0x00000040)==0){}; // wait for PLLRIS bit
// 6) enable use of PLL by clearing BYPASS
SYSCTL_RCC2_R &= ~0x00000800;
}
void EnableI2CModule0(void)
{
volatile int Delay=0;
SYSCTL_RCGCI2C_R|=0x00000001; //set i2c module 0 clock active
Delay=SYSCTL_RCGCI2C_R; //delay allow clock to stabilize
SYSCTL_RCGCGPIO_R |=0x00000002; //i2c module 0 is portB so activate clock for port B
Delay = SYSCTL_RCGCGPIO_R; //delay allow clock to stabilize
GPIO_PORTB_AFSEL_R|= 0x0000000C; //enable alternate functions for PB2 and PB3
GPIO_PORTB_ODR_R |= 0x00000008; //set PB3 (I2C SDA) for open drain
GPIO_PORTB_DEN_R |= 0xFF; //Enable digital on Port B
GPIO_PORTB_PCTL_R |=0x03;
I2C0_PP_R |= 0x01;
I2C0_MTPR_R |= 0x00000027; //set SCL clock
I2C0_MCR_R |= 0x00000010; //intialize mcr rigester with that value given in datasheet
}
uint8_t ReadRegister(uint8_t RegisterAddress)
{
volatile uint8_t result=0;
I2C0_MSA_R = 0x000000A6; //write operation
I2C0_MDR_R = RegisterAddress; //place data to send mdr register
I2C0_MCS_R = 0x00000007; //stop start run
while((I2C0_MCS_R &= 0x00000040)==1); //poll busy bit
I2C0_MSA_R = 0x000000A7; // read operation
I2C0_MCS_R = 0x00000007; // stop start run
while((I2C0_MCS_R &= 0x00000040)==1); //poll busy bit
result = I2C0_MDR_R;
return result;
}
void WriteRegister(uint8_t RegisterAddress,uint8_t Data)
{
I2C0_MSA_R = 0x000000A6; //write operation
I2C0_MDR_R = RegisterAddress; //place register address to set in mdr register
I2C0_MCS_R = 0x00000003; //burst send ( multiple bytes send )
while((I2C0_MCS_R &= 0x00000040)==1); //poll busy bit
I2C0_MDR_R = Data; //place data to be sent in mdr register
I2C0_MCS_R = 0x00000005; // transmit followed by stop state
while((I2C0_MCS_R &= 0x00000040)==1); //poll busy bit
}
Your WriteRegister and ReadRegister functions do not follow the flowcharts defined in the TM4C123G data sheet. Apart from not checking or handling the MCS ERROR flag, Figure 16-10 Master TRANSMIT of Multiple Data Bytes shows that when writing the MCS register, you should assert specific bits, while you are writing to all bits, You should instead perform a read-modify-write:
I2C0_MCS_R = 0x00000003; //burst send ( multiple bytes send )
should be:
// I2CMCS = ---0-011
uint32_t mcs = I2C0_MCS_R ;
msc &= ~0x00000014; // ---0-0--
mcs |= 0x00000003; // ------11
I2C0_MCS_R = mcs ;
And similarly:
I2C0_MCS_R = 0x00000005; // transmit followed by stop state
should be
// I2CMCS = ---0-101
mcs = I2C0_MCS_R ;
mcs &= ~0x00000012; // ---0--0-
mcs |= 0x00000005; // -----1-1
I2C0_MCS_R = mcs ;
ReadRegister() has a similar issue (although it is unlikely to be an issue in this case):
I2C0_MCS_R = 0x00000007; //stop start run
should strictly be:
// I2CMCS = ---00111
uint32_t mcs = I2C0_MCS_R ;
mcs &= ~0x00000018; // ---00---
mcs |= 0x00000007; // -----111
I2C0_MCS_R = mcs ;
The datasheet recommends for bits 31:5:
Software should not rely on the value of a reserved bit. To provide
compatibility with future products, the value of a reserved bit should
be preserved across a read-modify-write operation.
The above code does that, but in practice should not be necessary on this specific product, but is good practice in any case.
In any event you should add the recommended error handling code. It may be that no error flag is being set, but we don't know that unless you check for it, and doing so will at least assist debugging - rather then stepping the code, you can simply set a break-point on the error handling and then run at full-speed. This will narrow down the number of possibilities.
as #Clifford had explained that i should follow the flow charts and although his answer is completely correct it didn't give me any results (previously gave values in case of stepping into the function gave zeroes afterwards) but , i noticed something in the flow charts that i hadn't noticed before which contradicts with the initialization and configuration section in the data sheet
now as it says in step 11 that you should be polling the bus busy bit in the MCS register but this is wrong and contradicts with the flow charts , the flow charts are more correct as u should check if the bus is busy before sending anything and then check for the master busy bit before reading from the MDR register or moving on to execute and further steps
basically the correct steps in the initialization and configuration should be :
before step 10 poll the bus busy bit in case any other master is sending which can be omitted in case of a single master
after step 10 poll the busy bit before reading or going to any further step to conclude whether the sending has been completed and the master is idle or not
i'm sorry i feel like a complete idiot now for not reading the flow charts carefully but i followed another part which is the initialization and configuration part accepting a fact which wasn't there that both should imply the same thing .
i also found that it works correctly in the tivaware API following the flow charts and not that other section in the datasheet however i didn't want to use the Tivaware API as i am looking forward for problems like this which lead to a better understanding of how things work
thanks again for your help #Clifford cheers!

STM8 interrupt serial receive

I am new to STM8, and trying to use a STM8S103F3, using IAR Embedded Workbench.
Using C, I like to use the registers directly.
I need serial on 14400 baud, 8N2, and getting the UART transmit is easy, as there are numerous good tutorials and examples on the net.
Then the need is to have the UART receive on interrupt, nothing else will do.
That is the problem.
According to iostm8s103f3.h (IAR) there are 5 interrupts on 0x14 vector
UART1_R_IDLE, UART1_R_LBDF, UART1_R_OR, UART1_R_PE, UART1_R_RXNE
According to Silverlight Developer: Registers on the STM8,
Vector 19 (0x13) = UART_RX
According to ST Microelectronics STM8S.h
#define UART1_BaseAddress 0x5230
#define UART1_SR_RXNE ((u8)0x20) /*!< Read Data Register Not Empty mask */
#if defined(STM8S208) ||defined(STM8S207) ||defined(STM8S103) ||defined(STM8S903)
#define UART1 ((UART1_TypeDef *) UART1_BaseAddress)
#endif /* (STM8S208) ||(STM8S207) || (STM8S103) || (STM8S903) */
According to STM8S Reference manual RM0016
The RXNE flag (Rx buffer not empty) is set on the last sampling clock edge,
when the data is transferred from the shift register to the Rx buffer.
It indicates that a data is ready to be read from the SPI_DR register.
Rx buffer not empty (RXNE)
When set, this flag indicates that there is a valid received data in the Rx buffer.
This flag is reset when SPI_DR is read.
Then I wrote:
#pragma vector = UART1_R_RXNE_vector //as iostm8s103f3 is used, that means 0x14
__interrupt void UART1_IRQHandler(void)
{ unsigned character recd;
recd = UART1_SR;
if(1 == UART1_SR_RXNE) recd = UART1_DR;
etc.
No good, I continually get interrupts, UART1_SR_RXNE is set, but UART1_DR
is empty, and no UART receive has happened. I have disabled all other interrupts
I can see that can vector to this, and still no good.
The SPI also sets this flag, presumably the the UART and SPI cannot be used
together.
I sorely need to get this serial receive interrupt going. Please help.
Thank you
The problem was one bit incorrectly set in the UART1 setup.
The complete setup for the UART1 in the STM8S103F3 is now(IAR):
void InitialiseUART()
{
unsigned char tmp = UART1_SR;
tmp = UART1_DR;
// Reset the UART registers to the reset values.
UART1_CR1 = 0;
UART1_CR2 = 0;
UART1_CR4 = 0;
UART1_CR3 = 0;
UART1_CR5 = 0;
UART1_GTR = 0;
UART1_PSCR = 0;
// Set up the port to 14400,n,8,2.
UART1_CR1_M = 0; // 8 Data bits.
UART1_CR1_PCEN = 0; // Disable parity.
UART1_CR3 = 0x20; // 2 stop bits
UART1_BRR2 = 0x07; // Set the baud rate registers to 14400
UART1_BRR1 = 0x45; // based upon a 16 MHz system clock.
// Disable the transmitter and receiver.
UART1_CR2_TEN = 0; // Disable transmit.
UART1_CR2_REN = 0; // Disable receive.
// Set the clock polarity, clock phase and last bit clock pulse.
UART1_CR3_CPOL = 0;
UART1_CR3_CPHA = 0;
UART1_CR3_LBCL = 0;
// Set the Receive Interrupt RM0016 p358,362
UART1_CR2_TIEN = 0; // Transmitter interrupt enable
UART1_CR2_TCIEN = 0; // Transmission complete interrupt enable
UART1_CR2_RIEN = 1; // Receiver interrupt enable
UART1_CR2_ILIEN = 0; // IDLE Line interrupt enable
// Turn on the UART transmit, receive and the UART clock.
UART1_CR2_TEN = 1;
UART1_CR2_REN = 1;
UART1_CR1_PIEN = 0;
UART1_CR4_LBDIEN = 0;
}
//-----------------------------
#pragma vector = UART1_R_RXNE_vector
__interrupt void UART1_IRQHandler(void)
{
byte recd;
recd = UART1_DR;
//send the byte to circular buffer;
}
You forget to add global interrupt flag
asm("rim") ; //Enable global interrupt
It happens at non isolated connections whenever you connect your board's ground with other source's ground (USB<->TTL converter connected to PC etc.), In this case microcontroller is getting noise due to high value SMPS's Y capacitor etc.
Simply connect your RX and TX line's via 1K resistor and put 1nF (can be deceased for high speed) capacitors on these lines and to ground (micro controller side) to suppress noises.

Resources