PIC32MX795F512H UART communication to RS232 - uart

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.

Related

What is wrong with this PIC16F877A HCSR04 example?

I am working on distance sensor with PIC16F877A.
I am using MPLAB IDE AND XC8 compiler.
My goal is to gradually turn on the right leds at certain distance levels, but the leds are blinking unstable. What am I doing wrong? distance/5
When it measures 5 cm, it is 5/5 and the result is 1 and 1 led is on.
When it measures 10 cm, it is 10/5 and the result is 2 and 2 leds are on.
When you measure 15 cm, it is 15/5 and the result is 3 and 3 LEDs are on.
When you measure 20 cm, it is 20/5 and the result is 4 and 4 leds are on.
If the distance is less than 5 cm or above 20 cm, no led lights are on
https://i.stack.imgur.com/fFKQg.png
#include <xc.h>
#include <pic16f877a.h>
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define _XTAL_FREQ 4000000
#define trigger RC2
#define echo RC3
int calc_distance();
int calc_distance()
{
int distance=0;
trigger=1;
__delay_us(10);
trigger=0;
while(!echo); // normally the echo pin is logic 0. If we toggle the zero and throw it into the while, it returns idle until the echo arrives (until the signal becomes logic 1).
TMR1ON=1;//In the upper loop, while returning the command empty, echo comes and exits the upper loop and timer1 is activated.
while(echo);
TMR1ON=0;//
distance=TMR1/58;
return distance;
}
void main(void)
{
int dist=0; // Create Distance Variable
TRISB = 0x00; // Set PORTB To Be Output Port (All The 8 Pins)
PORTB = 0x00; // Set PORTB To Be LOW For initial State
TRISC2 = 0; // Set RC2 To Be Output Pin ( Trigger )
RC2 = 0;
TRISC3 = 1; // Set RC3 To Be Input Pin ( Echo )
//--[ Configure Timer Module To Operate in Timer Mode ]--
// Clear The Pre-Scaler Select Bits
T1CKPS0=0;
T1CKPS1=0;
TMR1CS=0;// Choose The Local Clock As Clock Source
while(1)
{
calc_distance();
dist = calc_distance()/5;
if(dist==1)
{PORTB = 0x01; __delay_ms(50);}
if(dist==2)
{PORTB = 0x03; __delay_ms(50);}
if(dist==3)
{PORTB = 0x07; __delay_ms(50);}
if(dist==4)
{PORTB = 0x0F; __delay_ms(50);}
else
{PORTB = 0x00; __delay_ms(50);}
}
return;
}

STM8 UART polling receive is mangles

I'm trying to connect to an STM8 using uart. The STM seems to transmit data OK, but what it receives seems to be mostly junk, and often seems to receive 2 bytes at once. Here's the code:
#include "../stm8.h"
//
// Setup the system clock to run at 16MHz using the internal oscillator.
//
void InitialiseSystemClock()
{
CLK_ICKR = 0; // Reset the Internal Clock Register.
CLK_ICKR |= CLK_ICKR_HSIEN ; // Enable the HSI.
CLK_ECKR = 0; // Disable the external clock.
while ((CLK_ICKR & CLK_ICKR_HSIRDY) == 0); // Wait for the HSI to be ready for use.
CLK_CKDIVR = 0; // Ensure the clocks are running at full speed.
CLK_PCKENR1 = 0xff; // Enable all peripheral clocks.
CLK_PCKENR2 = 0xff; // Ditto.
CLK_CCOR = 0; // Turn off CCO.
CLK_HSITRIMR = 0; // Turn off any HSIU trimming.
CLK_SWIMCCR = 0; // Set SWIM to run at clock / 2.
CLK_SWR = 0xe1; // Use HSI as the clock source.
CLK_SWCR = 0; // Reset the clock switch control register.
CLK_SWCR |= CLK_SWCR_SWEN; // Enable switching.
while ((CLK_SWCR & CLK_SWCR_SWBSY) != 0); // Pause while the clock switch is busy.
}
//
// Setup the UART to run at 115200 baud, no parity, one stop bit, 8 data bits.
//
// Important: This relies upon the system clock being set to run at 16 MHz.
//
void init_uart()
{
//
// Clear the Idle Line Detected bit in the status register by a read
// to the UART1_SR register followed by a Read to the UART1_DR register.
//
//unsigned char tmp = UART1_SR;
//tmp = UART1_DR;
//UART1_SR = 0xC0; // mcarter set to default value
//
// 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;
//
// Now setup the port to 115200,n,8,1.
//
// clear certain bits
UART1_CR1 &= ~UART1_CR1_M ; // 8 Data bits.
UART1_CR1 &= ~UART1_CR1_PCEN; // Disable parity
// stop bits
UART1_CR3 &= 0b11001111; // unmask the stop bit to default (1 stop bit)
//UART1_CR3 |= 0b00100000; // two stop bits
//UART1_CR3 |= 0b00110000; // 1.5 stop bits
//UART1_CR3 &= ~UART1_CR3_STOP; // 1 stop bit.
#if 1 //115200 baud
//UART1_BRR2 = 0x0a; // given in original example
UART1_BRR2 = 0x0b; // Set the baud rate registers to 115200 baud
UART1_BRR1 = 0x08; // based upon a 16 MHz system clock.
#else // 9600 baud, but seems to be worse than 115200
UART1_BRR2 = 0x03;
UART1_BRR1 = 0x69;
#endif
//
// Disable the transmitter and receiver.
//
//UART1_CR2_TEN = 0; // Disable transmit.
//UART1_CR2_REN = 0; // Disable receive.
//
// Set the clock polarity, lock phase and last bit clock pulse.
//
UART1_CR3 |= UART1_CR3_CPOL;
UART1_CR3 |= UART1_CR3_CPHA;
//UART1_CR3 |= UART1_CR3_LBCL; // this seems to cause problems
UART1_CR2 |= UART1_CR2_TEN; // enable transmit
UART1_CR2 |= UART1_CR2_REN; // enable receive
UART1_CR3 |= UART1_CR3_CLKEN; // unable uart clock
}
char uart_getc()
{
while((UART1_SR & UART1_SR_RXNE)==0); // Block until char rec'd
//char c = UART1_DR;
//return c;
return UART1_DR;
}
void uart_putc(char c)
{
while((UART1_SR & UART1_SR_TXE)==0); // Wait for transmission complete
UART1_DR = c; // transmit char
}
void UARTPrintf(char *message)
{
char *ch = message;
while (*ch)
uart_putc(*ch++);
}
void main()
{
disable_interrupts();
InitialiseSystemClock();
init_uart();
enable_interrupts();
UARTPrintf("Uart example: you type, I echo\n\r");
while (1)
{
//continue;
char c = uart_getc();
uart_putc(c);
//UARTPrintf("Hello from my microcontroller....\n\r");
//for (long counter = 0; counter < 2500000; counter++);
}
}
Relevant declaration headers are:
#define UART1_SR *(uchar*)(0x5230)
#define UART1_DR *(uchar*)(0x5231)
#define UART1_BRR1 *(uchar*)(0x5232)
#define UART1_BRR2 *(uchar*)(0x5233)
#define UART1_CR1 *(uchar*)(0x5234)
#define UART1_CR2 *(uchar*)(0x5235)
#define UART1_CR3 *(uchar*)(0x5236)
#define UART1_CR4 *(uchar*)(0x5237)
#define UART1_CR5 *(uchar*)(0x5238)
#define UART1_GTR *(uchar*)(0x5239)
#define UART1_PSCR *(uchar*)(0x523A)
#define UART1_CR1_M (1<<4)
#define UART1_CR1_PCEN (1<<2)
#define UART1_CR2_TEN (1<<3)
#define UART1_CR2_REN (1<<2)
#define UART1_CR3_STOP 4
#define UART1_CR3_CPOL (1<<2)
#define UART1_CR3_CPHA (1<<1)
#define UART1_CR3_LBCL (1<<0)
#define UART1_CR3_CLKEN (1<<3)
#define UART1_SR_TXE (1<<7)
#define UART1_SR_TC (1<<6)
#define UART1_SR_RXNE (1<<5)
I'm not really sure about stop bits, and all that. It's just "regular" serial communication.
I found that if I uncommented the line
//UART1_CR3 |= UART1_CR3_LBCL; // this seems to cause problems
then the stm8 prints out a continuous stream of junk. But with it commented out, the mcu seems to correctly know that there has been a transmission. There doesn't seem to be any pattern as to what it sees, though.
Hmm. The offending line seems to be
UART1_CR3 |= UART1_CR3_CLKEN;
It's purpose seem to be to "enable the SCLK pin". I don't really understand what's going on here, but according to a pinout diagram, one of the purposes of pin PD4 is UART1_CK. So you can attach a UART clock to the STM8 and this enables it?? And thereby causes problems if a clock isn't attached. It doesn't make that much sense, really; I didn't know uarts could have external clocks.
Anyway, commenting out the line seems to have fixed things.

dsPIC33EP128MC202 UART receiver doesn't work

I wrote the code for UART communication. TX is working fine, but RX is not working. I have searched a lot but found no solution.
I am transmitting character x to PC with time interval, and I am able see the data. But when transmits data pic is not receiving any thing.
Below are pins used for uart
//PGEC1/AN4/C1IN1+/RPI34/RB2 for receiver
RPINR18bits.U1RXR = 34;
//RP36/RB4 for transmitting data
RPOR1bits.RP36R = 1;
I am able transmit data to pc but PIC doesn't receive any charector from pc.
Thanks in advance
Here is my code.
DSPIC33EP128MC202
/*
* File: newmainXC16.c
* Author:
*
* Created on 27 December, 2017, 4:21 PM
*/
// FICD
#pragma config ICS = PGD3 // ICD Communication Channel Select bits (Communicate on PGEC3 and PGED3)
#pragma config JTAGEN = OFF // JTAG Enable bit (JTAG is disabled)
// FPOR
#pragma config ALTI2C1 = OFF // Alternate I2C1 pins (I2C1 mapped to SDA1/SCL1 pins)
#pragma config ALTI2C2 = OFF // Alternate I2C2 pins (I2C2 mapped to SDA2/SCL2 pins)
#pragma config WDTWIN = WIN25 // Watchdog Window Select bits (WDT Window is 25% of WDT period)
// FWDT
#pragma config WDTPOST = PS32768 // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128 // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON // PLL Lock Enable bit (Clock switch to PLL source will wait until the PLL lock signal is valid.)
#pragma config WINDIS = OFF // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable bit (Watchdog timer enabled/disabled by user software)
// FOSC
#pragma config POSCMD = NONE // Primary Oscillator Mode Select bits (Primary Oscillator disabled)
#pragma config OSCIOFNC = ON // OSC2 Pin Function bit (OSC2 is clock output)
#pragma config IOL1WAY = ON // Peripheral pin select configuration (Allow only one reconfiguration)
#pragma config FCKSM = CSDCMD // Clock Switching Mode bits (Both Clock switching and Fail-safe Clock Monitor are disabled)
// FOSCSEL
#pragma config FNOSC = FRCPLL // Oscillator Source Selection (Fast RC Oscillator with divide-by-N with PLL module (FRCPLL) )
#pragma config PWMLOCK = ON // PWM Lock Enable bit (Certain PWM registers may only be written after key sequence)
#pragma config IESO = ON // Two-speed Oscillator Start-up Enable bit (Start up device with FRC, then switch to user-selected oscillator source)
// FGS
#pragma config GWRP = OFF // General Segment Write-Protect bit (General Segment may be written)
#pragma config GCP = OFF // General Segment Code-Protect bit (General Segment Code protect is Disabled)
#include "xc.h"
#include <stdint.h>
#include <p33EP128MC202.h>
#define FP 60000000
#define BAUDRATE 115200
#define BRGVAL ((FP/BAUDRATE)/16)-1
#define DELAY_100uS asm volatile ("REPEAT, #5400"); Nop(); // 100uS delay
int main(void)
{
uint8_t c;
int i,j,a,b;
// Configure Oscillator to operate the device at 60Mhz
// Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
// Fosc= 8M*60/(2*2)=120Mhz for 8M input clock == 8*60/4 = 120/2 = 60
CLKDIVbits.PLLPOST=0; // PLLPOST (N1) 0=/2
while(!OSCCONbits.LOCK); // wait for PLL ready
PLLFBD = 58; // M=60
CLKDIVbits.PLLPOST = 0; // N1=2
CLKDIVbits.PLLPRE = 0; // N2=2
OSCTUN = 0; // Tune FRC oscillator, if FRC is used
/*Initialize the Ports */
TRISA = 0x00;
LATA = 0x0000;
PORTA = 0x0000;
ANSELAbits.ANSA1 = 0;
ANSELAbits.ANSA0 = 0;
__builtin_write_OSCCONL(OSCCON & ~(1<<6));
RPINR18bits.U1RXR = 34;
RPOR1bits.RP36R = 1;
__builtin_write_OSCCONL(OSCCON | (1<<6));
U1MODEbits.STSEL = 0;
U1MODEbits.PDSEL = 0;
U1MODEbits.ABAUD = 0;
U1MODEbits.BRGH = 0;
U1BRG = 30;
U1MODEbits.UARTEN = 1;
IEC0bits.U1TXIE = 0;
U1STAbits.UTXEN = 1;
U1STAbits.URXISEL = 0;
DELAY_100uS;
DELAY_100uS;
DELAY_100uS;
U1TXREG = 'X';
char ReceivedChar;
while(1){
//If data is received send data to TX
if(U1STAbits.URXDA == 1) {
ReceivedChar = U1RXREG + 2;
U1TXREG = 10;
U1TXREG = 13;
}
for(i=0;i<1000;i++){
a = a + 1;
for(j=0;j<2000;j++){
b = b + 1;
}
}
//LED Blink code for programme check
if(c == 0){
c = 1;
}else{
c = 0;
}
LATAbits.LATA0 = c;
LATAbits.LATA1 = c;
U1TXREG = 'x';
U1TXREG = 10;
U1TXREG = 13;
}
}
void __attribute__((interrupt, no_auto_psv)) _U1TXInterrupt( void )
{
IFS0bits.U1TXIF = 0; // Clear TX Interrupt flag
}
void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt( void )
{
IFS0bits.U1RXIF = 0; // Clear RX Interrupt flag
//cntr++;
U1TXREG='a';
U1TXREG = 10;
U1TXREG = 13;
}
I looked into the code, It works fine for me.
Please check the connection with your peripherals and their pins. If there is an extra connection to that pin remove it and try it again.
RB2 should be an an Input.
TRISB = 0x04;

PIC32MX dma not triggered by adc

I’m trying to make a little application on the pic32mx795f512l but I can’t get it to work.
What I want to achieve is that adc continuously gets the current analog value from channel 0 with the highest possible rate. If the 16 Word buffer is filled, it should trigger the dma to save this buffer in ram. The dma should trigger an Interrupt if the ram buffer is full. So i could start the calculation in the main loop.
My problem now is that the dma is not triggered at all. When I enable the interrupt on the adc the main loop isn't running.
Does anyone know what I did wrong?
Here is my source code:
/*** DEVCFG0 ***/
#pragma config DEBUG = OFF
#pragma config ICESEL = ICS_PGx2
#pragma config PWP = 0xff
#pragma config BWP = OFF
#pragma config CP = OFF
/*** DEVCFG1 ***/
#pragma config FNOSC = PRIPLL
#pragma config FSOSCEN = ON
#pragma config IESO = ON
#pragma config POSCMOD = XT
#pragma config OSCIOFNC = OFF
#pragma config FPBDIV = DIV_8
#pragma config FCKSM = CSDCMD
#pragma config WDTPS = PS1048576
#pragma config FWDTEN = ON
/*** DEVCFG2 ***/
#pragma config FPLLIDIV = DIV_2
#pragma config FPLLMUL = MUL_20
#pragma config FPLLODIV = DIV_1
#pragma config UPLLIDIV = DIV_2
#pragma config UPLLEN = ON
/*** DEVCFG3 ***/
#pragma config USERID = 0xffff
#pragma config FSRSSEL = PRIORITY_7
#pragma config FMIIEN = ON
#pragma config FETHIO = ON
#pragma config FCANIO = ON
#pragma config FUSBIDIO = ON
#pragma config FVBUSONIO = ON
int adcValues[128];
void __ISR(_ADC_VECTOR, IPL7SRS) ADCHandler(void) // interrupt every 8 samples
{
IFS1bits.AD1IF = 0; // clear interrupt flag
}
void __ISR(_DMA0_VECTOR, ipl5) _IntHandlerSysDmaCh0(void)
{
int dmaFlags=DCH0INT&0xff; // read the interrupt flags
/*
perform application specific operations in response to any interrupt flag set
*/
DCH0INTCLR=0x000000ff; // clear the DMA channel interrupt flags
IFS1CLR = 0x00010000; // Be sure to clear the DMA0 interrupt flags
}
unsigned int __attribute__((always_inline)) _VirtToPhys(const void* p) {
return (int) p < 0 ? ((int) p & 0x1fffffffL) : (unsigned int) ((unsigned char*) p + 0x40000000L);
}
void initADC(void) {
AD1PCFG = 0xFFFB; // PORTB = Digital; RB2 = analog
AD1CON1 = 0x0000; // SAMP bit = 0 ends sampling
// and starts converting
// turn ADC on | unsigned 32-bit int output | auto-convert after sample finished |
// don?t stop conversions at interrupt | auto-sample after conversion finished
AD1CON1 = (1 << 15) | (4 << 8) | (7 << 5) | (0 << 4) | (1 << 2);
IPC6bits.AD1IP = 7; // INT priority level 7, for shadow register set
IFS1bits.AD1IF = 0; // clear interrupt flag
IEC1bits.AD1IE = 1; // enable interrupts
AD1CHS = 0x00020000; // Connect RB2/AN2 as CH0 input
AD1CON1SET = 0x8000; // turn on the ADC
}
void initDMA(void) {
IEC1CLR=0x00010000; // disable DMA channel 0 interrupts
IFS1CLR=0x00010000; // clear any existing DMA channel 0 interrupt flag
DMACONSET=0x00008000; // enable the DMA controller
DCH0CON=0x03; // channel off, priority 3, no chaining
DCH0ECON=0;
DCH0ECONbits.CHSIRQ=_ADC_IRQ; // This should map the AD1 ? ADC1 Convert Done Interrupt to start the dma IRQ no. 33 Vector no. 27
// program the transfer
DCH0SSA=_VirtToPhys(&ADC1BUF0); // transfer source physical address
DCH0DSA=_VirtToPhys(adcValues); // transfer destination physical address
DCH0SSIZ=16; // source size 16 bytes
DCH0DSIZ=128; // destination size NUM_SAMPS bytes
DCH0CSIZ=16; // 16 bytes transferred per event
DCH0INTCLR=0x00ff00ff; // clear existing events, disable all interrupts
//DCH0INTSET=0x00090000; // enable Block Complete and error interrupts
DCH0INTbits.CHDDIF=1; //1 = Channel Destination Pointer has reached end of destination (CHDPTR = CHDSIZ)
IPC9CLR=0x0000001f; // clear the DMA channel 0 priority and sub-priority
IPC9SET=0x00000016; // set IPL 5, sub-priority 2
IEC1SET=0x00010000; // enable DMA channel 0 interrupt
DCH0CONSET=0x80; // turn channel on
}
void main(){
INTDisableInterrupts(); // disable interrupts before configuring ADC
initADC();
initDMA();
INTEnableSystemMultiVectoredInt(); // enable interrupts at CPU
while(1);
}
It seems to me that the issue is that you have two different sources that are trying to consume the interrupt vector from the ADC, both the DMA channel and an ISR.
From my experience this means that only one of the two will get the interrupt vector, and it tends to be the ISR.
I recommend that you remove the ISR for the ADC. Especially since it seems that you are only reseting the interrupt flag, but it should be possible to configure the ADC to automatically reset the flag and interrupt every number of samples (I've been able to do this on the PIC32mx256f128B)

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