why this code using dspic33ep512mu810 chip uart 2 not working - uart

In MPLAB X IDE v5.10, I am using dspic33ep512mu810 microcontroller.
I have following piece of C code:
#include "xc.h"
_FOSCSEL(FNOSC_FRCPLL) //INT OSC with PLL (always keep this setting)
_FOSC(OSCIOFNC_OFF & POSCMD_NONE) //disable external OSC
_FWDT(FWDTEN_OFF) //watchdog timer off
_FICD(JTAGEN_OFF & 0b11); //JTAG debugging off
void UART2TX(char c) {
if (U2STAbits.UTXEN == 0)
U2STAbits.UTXEN = 1; //enable UART TX
while (U2STAbits.UTXBF == 1); //if buffer is full, wait
U2TXREG = c;
}
int main(void) {
//setup internal clock for 80MHz/40MIPS
//7.37/2=3.685*43=158.455/2=79.2275
CLKDIVbits.PLLPRE = 0; // PLLPRE (N2) 0=/2
PLLFBD = 41; //pll multiplier (M) = +2
CLKDIVbits.PLLPOST = 0; // PLLPOST (N1) 0=/2
while (!OSCCONbits.LOCK); //wait for PLL ready
_U2TXIF = 0;
_U2TXIE = 0;
_U2RXIF = 0;
_U2RXIE = 0;
//setup UART
U2BRG = 85; //86#80mhz, 85#79.xxx=115200
U2MODE = 0; //clear mode register
U2MODEbits.BRGH = 1; //use high percison baud generator
U2STA = 0; //clear status register
//DSPIC33EP512MU810T-I/PT, RP96 as TX pin
RPOR7bits.RP96R = 3; //
while (1) {
UART2TX('H');
}
}
I am trying to send out 'H' through UART2 with baud rate 115200, but it is not working.

You had to switch RF0 (RP96) aus output:
TRISFbits.TRISF0 = 0; //make F0 an onput
And you had to switch RFO to digital:
ANSELFbits.ANSF0 = 0; //make F0 digital

Related

PIC16F877A with SIM800L

I am having problem with PIC16F877A uart. I am trying to send AT commands to SIM800L but it is returning error. But when I try it with CP2102 module it works fine. Can anybody tell me if something is wrong with my code?
This code with similar logic is working on LPC2148 but having problem on PIC16F877A.
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS 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 = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#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)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define _XTAL_FREQ 20000000
char buff[50], a = 0;
char b, *p;
int conn=0;
int i;
#define RS RD0
#define RW RD1
#define EN RD2
void lcd_cmd(unsigned char cmd)
{
PORTD = (0xF0 & cmd);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (cmd<<4);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_data(unsigned char data)
{
PORTD = (0xF0 & data);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (data<<4);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_string(char *str)
{
while(*str != '\0')
{
lcd_data(*str++);
}
}
void lcd_init()
{
lcd_cmd(0x02);//return to home
lcd_cmd(0x28);///4bitmode
lcd_cmd(0x0C);///cursor off
lcd_cmd(0x06);///increment cursor
lcd_cmd(0x01);///display clear
}
void uart_init()
{
TXSTAbits.TXEN = 1; ////enable transmission
TXSTAbits.BRGH = 1; ////high speed selection bit
RCSTAbits.CREN = 1; ////continuous receive enable
SPBRG = 129; ////baud rate generation 9600 at 20MHz crystal
TRISCbits.TRISC7 = 1; ////enable receive(input) on RC7
TRISCbits.TRISC6 = 0; ////enable transmit(output) on RC6
RCSTAbits.SPEN = 1; ////enable UART
GIE = 1; ///enable UART related interrupts
PEIE = 1;
RCIE = 1;
}
void gsm_send_char(unsigned char data)
{
TXREG = data;
while(PIR1bits.TXIF ==0);
}
char gsm_receive_char()
{
while(PIR1bits.RCIF == 0);
return (RCREG);
}
void gsm_send_string(char *data)
{
while(*data != '\0')
{
gsm_send_char(*data++);
}
}
__interrupt() void uart(void)
{
if(RCIF == 1)
{
b = RCREG;
buff[a] = b;
a++;
//buff[a]='\0';
GIE = 1;
RCIE = 1;
PEIE = 1;
RCIF = 0;
}
}
void gsm_init()
{
if(conn == 0)
{
a=0;
gsm_send_string("AT\r");
__delay_ms(500);
if(strstr(buff, "OK"))
{
lcd_cmd(0x80);
lcd_string(buff);
//a=0;
memset(buff, 0, sizeof(buff));
}
else
{
lcd_cmd(0x80);
lcd_string("AT ERROR");
}
}
}
void main(void)
{
TRISD = 0x00;
lcd_init();
uart_init();
lcd_cmd(0x80);
lcd_string("GSM");
while(1)
{
gsm_init();
__delay_ms(2000);
}
return;
}
I tried with changing code little bit and checked for any errors and tried to execute command on flag condition now it does not receive anything in the buffer because it does not print anything. Can anybody tell me why?
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS 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 = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = ON // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3/PGM pin has PGM function; low-voltage programming enabled)
#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)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <pic16f877a.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define _XTAL_FREQ 20000000
#define RS RD0
#define RW RD1
#define EN RD2
//#define AT "AT\"
char buff[80], a;
int flag, b, i = 0;
void lcd_cmd(unsigned char cmd)
{
PORTD = (0xF0 & cmd);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (cmd<<4 & 0xf0);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_data(unsigned char data)
{
PORTD = (0xF0 & data);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (data<<4 & 0xf0);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_string(char *str)
{
while(*str != '\0')
{
lcd_data(*str++);
}
}
void lcd_init()
{
lcd_cmd(0x02);//return to home
lcd_cmd(0x28);///4bitmode
lcd_cmd(0x0C);///cursor off
lcd_cmd(0x01);///display clear
lcd_cmd(0x06);///increment cursor
}
void uart_init()
{
SPBRG = 129;
BRGH = 1;
SYNC = 0;
SPEN = 1;
TXEN = 1;
CREN = 1;
GIE = 1;
PEIE = 1;
RCIE = 1;
RCIF = 0;
//TXIE = 1;
TRISC7 = 1;
TRISC6 = 0;
}
void gsm_send_char(unsigned char data)
{
//////////PORTB = 0xff;
TXREG = data;
while(PIR1bits.TXIF == 0);
}
char gsm_receive_char()
{
while(PIR1bits.RCIF == 0);
return RCREG;
}
void gsm_send_string(char *p)
{
while(*p != '\0')
{
gsm_send_char(*p++);
}
}
__interrupt() void isr(void)
{
if(RCIF == 1)
{
a = RCREG;
buff[i] = a;
i++;
if(a == '\r')
{
flag = 1;
}
if(OERR)
{
CREN = 0;
CREN = 1;
}
if(FERR)
{
SPEN = 0;
SPEN = 1;
}
RCIF = 0;
///////PORTB = 0xff;
}
}
void main(void)
{
TRISD = 0x00;
//TRISB = 0x00;
lcd_init();
uart_init();
lcd_cmd(0x80);
lcd_string("GSM TESTING");
while(1)
{
if(flag == 1)
{
i = 0;
gsm_send_string("AT\r\n");
__delay_ms(400);
if(strstr(buff, "OK"))
{
lcd_cmd(0xC0);
lcd_string(buff);
//memset(buff, 0, sizeof(buff));
}
else if(strstr(buff, "ERROR"))
{
lcd_cmd(0xC0);
lcd_string(buff);
// memset(buff, 0, sizeof(buff));
}
flag = 0;
}
}
return;
}
took reference from this link enter link description here
I connected PIC directly to the PC removing SIM800L and ran the code below. It was printing hello when I send hello using putty.
#include <xc.h>
#include <pic16f877a.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define _XTAL_FREQ 20000000
#define RS RD0
#define RW RD1
#define EN RD2
char buff[80], a;
int flag, b, i = 0;
void lcd_cmd(unsigned char cmd)
{
PORTD = (0xF0 & cmd);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (cmd<<4 & 0xf0);
RS = 0;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_data(unsigned char data)
{
PORTD = (0xF0 & data);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
PORTD = (data<<4 & 0xf0);
RS = 1;
RW = 0;
EN = 1;
__delay_ms(5);
EN = 0;
}
void lcd_string(char *str)
{
while(*str != '\0')
{
lcd_data(*str++);
}
}
void lcd_init()
{
lcd_cmd(0x02);//return to home
lcd_cmd(0x28);///4bitmode
lcd_cmd(0x0C);///cursor off
lcd_cmd(0x01);///display clear
lcd_cmd(0x06);///increment cursor
}
void uart_init()
{
SPBRG = 129;
BRGH = 1;
SYNC = 0;
SPEN = 1;
TXEN = 1;
CREN = 1;
GIE = 1;
PEIE = 1;
RCIE = 1;
RCIF = 0;
//TXIE = 1;
TRISC7 = 1;
TRISC6 = 0;
}
void gsm_send_char(char data)
{
TXREG = data;
while(TXIF == 0);
}
char gsm_receive_char()
{
while(PIR1bits.RCIF == 0);
return RCREG;
}
void gsm_send_string(char *p)
{
while(*p != '\0')
{
gsm_send_char(*p++);
}
}
__interrupt() void isr(void)
{
if(RCIF == 1)
{
a = RCREG;
buff[i] = a;
i++;
RCIF = 0;
}
}
void main(void)
{
TRISD = 0x00;
lcd_init();
uart_init();
lcd_cmd(0x80);
lcd_string("GSM TESTING");
while(1)
{
gsm_send_string("AT");
__delay_ms(400);
//i = 0;
if(strstr(buff, "hello"))
{
lcd_cmd(0xC0);
lcd_string(buff);
}
}
return;
}
You need to add the terminating character to the string you receive from the UART before using the strstr() function.
Something like this should work:
a=0;
gsm_send_string("AT\r");
__delay_ms(500);
buff[sizeof(buff)-1] = '\0'; // Terminate UART buffer with NULL char
if(strstr(buff, "OK"))
{
lcd_cmd(0x80);
lcd_string(buff);
//a=0;
memset(buff, 0, sizeof(buff));
}
else
{
lcd_cmd(0x80);
lcd_string("AT ERROR");
}
Depending on the compiler you are using you might also need to change the way you check for a pattern within a string. In my opinion, it would be better to do:
if(strstr(buff,"OK") != NULL)

dsPic33E : UART without DMA example not working

I am using dsPic33EP512GM604. I have designed a test circuit to test UART Communication.
I have downloaded a sample code from Microchip website and modified accordingly for my device and circuit designed.
I am facing two issues while debugging.
PLL settings not working. Everytime it gets stuck at " while( OSCCONbits.COSC != 0b011 ); ". Hence I commented the clock configuration and Using simple Internal Oscillator FRC.
UART communication is not working. I m using RPI25 as an RX while RP20 as TX on my circuit.
Here is the final code I am using :
/*******************************************************************************/
#include <xc.h>
#include <stdint.h>
#if __XC16_VERSION < 1011
#warning "Please upgrade to XC16 v1.11 or newer."
#endif
//-----------------------------------------------------------------------------
#pragma config ICS = PGD3 // ICD Communication Channel Select bits (Communicate on PGEC1 and PGED1)
#pragma config JTAGEN = OFF // JTAG Enable bit (JTAG is disabled)
// FPOR
#pragma config BOREN = ON // Brown-out Reset (BOR) Detection Enable bit (BOR is enabled)
#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 = OFF // 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 (XT Crystal Oscillator Mode)
#pragma config OSCIOFNC = OFF // OSC2 Pin Function bit (OSC2 is clock output)
#pragma config IOL1WAY = OFF // Peripheral pin select configuration (Allow multiple reconfigurations)
#pragma config FCKSM = CSDCMD // Clock Switching Mode bits (Clock switching is enabled,Fail-safe Clock Monitor is disabled)
// FOSCSEL
#pragma config FNOSC = FRC // Oscillator Source Selection (Internal Fast RC (FRC))
#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 with 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)
// *****************************************************************************
#define TRUE 1
#define FALSE 0
#define DELAY_105uS asm volatile ("REPEAT, #4201"); Nop();// 105uS delay
// *****************************************************************************
#define FCY 60000000
#define BAUDRATE 9600
#define BRGVAL ( (FCY / BAUDRATE) / 16 ) - 1
uint8_t s3flag, s4flag, s5flag, S6Flag;
/*****************************************************************************/
void __attribute__ ( (interrupt, no_auto_psv) ) _U1RXInterrupt( void )
{
LATA = U1RXREG;
U1TXREG = LATA;
IFS0bits.U1RXIF = 0;
}
/******************************************************************************/
void __attribute__ ( (interrupt, no_auto_psv) ) _U1TXInterrupt( void )
{
IFS0bits.U1TXIF = 0;
}
/******************************************************************************/
void InitClock( void )
{
PLLFBD = 58; // M = 60
CLKDIVbits.PLLPOST = 0; // N1 = 2
CLKDIVbits.PLLPRE = 0; // N2 = 2
OSCTUN = 0;
RCONbits.SWDTEN = 0;
// Clock switch to incorporate PLL
__builtin_write_OSCCONH( 0x03 ); // Initiate Clock Switch to
// External oscillator with PLL (NOSC=0b011)
__builtin_write_OSCCONL( OSCCON || 0x01 ); // Start clock switching
while( OSCCONbits.COSC != 0b011 );
// Wait for Clock switch to occur
while( OSCCONbits.LOCK != 1 )
{ };
}
/******************************************************************************/
void InitUART2( void )
{
// configure U1MODE
U1MODEbits.UARTEN = 0; // Bit15 TX, RX DISABLED, ENABLE at end of func
//U1MODEbits.notimplemented;// Bit14
U1MODEbits.USIDL = 0; // Bit13 Continue in Idle
U1MODEbits.IREN = 0; // Bit12 No IR translation
U1MODEbits.RTSMD = 0; // Bit11 Simplex Mode
//U1MODEbits.notimplemented;// Bit10
U1MODEbits.UEN = 0; // Bits8,9 TX,RX enabled, CTS,RTS not
U1MODEbits.WAKE = 0; // Bit7 No Wake up (since we don't sleep here)
U1MODEbits.LPBACK = 0; // Bit6 No Loop Back
U1MODEbits.ABAUD = 0; // Bit5 No Autobaud (would require sending '55')
U1MODEbits.BRGH = 0; // Bit3 16 clocks per bit period
U1MODEbits.PDSEL = 0; // Bits1,2 8bit, No Parity
U1MODEbits.STSEL = 0; // Bit0 One Stop Bit
U1BRG = BRGVAL; // 60Mhz osc, 9600 Baud
// Load all values in for U1STA SFR
U1STAbits.UTXISEL1 = 0; //Bit15 Int when Char is transferred (1/2 config!)
U1STAbits.UTXINV = 0; //Bit14 N/A, IRDA config
U1STAbits.UTXISEL0 = 0; //Bit13 Other half of Bit15
//U1STAbits.notimplemented = 0;//Bit12
U1STAbits.UTXBRK = 0; //Bit11 Disabled
U1STAbits.UTXEN = 0; //Bit10 TX pins controlled by periph
U1STAbits.UTXBF = 0; //Bit9 *Read Only Bit*
U1STAbits.TRMT = 0; //Bit8 *Read Only bit*
U1STAbits.URXISEL = 0; //Bits6,7 Int. on character recieved
U1STAbits.ADDEN = 0; //Bit5 Address Detect Disabled
U1STAbits.RIDLE = 0; //Bit4 *Read Only Bit*
U1STAbits.PERR = 0; //Bit3 *Read Only Bit*
U1STAbits.FERR = 0; //Bit2 *Read Only Bit*
U1STAbits.OERR = 0; //Bit1 *Read Only Bit*
U1STAbits.URXDA = 0; //Bit0 *Read Only Bit*
IPC7 = 0x4400; // Mid Range Interrupt Priority level, no urgent reason
IFS0bits.U1TXIF = 0; // Clear the Transmit Interrupt Flag
IEC0bits.U1TXIE = 1; // Enable Transmit Interrupts
IFS0bits.U1RXIF = 0; // Clear the Recieve Interrupt Flag
IEC0bits.U1RXIE = 1; // Enable Recieve Interrupts
// RPOR1bits.RP36R = 1; //RB4 as U1TX
// RPINR18bits.U1RXR = 24; //RA8 as U1RX
RPOR0bits.RP20R = 1; // dsPic33EP512GM604 => RP20 as U1TX
_U1RXR = 19; // dsPic33EP512GM604 => RPI25 as U1RX
U1MODEbits.UARTEN = 1; // And turn the peripheral on
U1STAbits.UTXEN = 1;
}
/******************************************************************************/
void InitPorts( void )
{
ANSELA = 0;
// TRISAbits.TRISA9 = 1;
// TRISAbits.TRISA4 = 0;
TRISAbits.TRISA10 = 0; //Output
}
/******************************************************************************
int main( void )
{
char recChar = 'a';
int i = 0;
// int count = 0;
// InitClock(); // This is the PLL settings
InitUART2(); // Initialize UART2 for 9600,8,N,1 TX/RX
InitPorts(); // LEDs outputs, Switches Inputs
/* Wait at least 105 microseconds (1/9600) before sending first char */
DELAY_105uS;
while( 1 )
{
PORTAbits.RA10 = 0;
for (i = 0; i < 1000; i++){
DELAY_105uS;
}
U1TXREG = recChar;
recChar++;
if (recChar == 122){
recChar = 48;
}
if (U1STAbits.OERR == 1){
U1STAbits.OERR = 0;
continue;
}
PORTAbits.RA10 = 0;
for (i = 0; i < 1000; i++){
DELAY_105uS;
}
}
}
/*******************************************************************************
I have tested the Circuit by adding LED at RA10 and its working. So, I guess there might be error in my code.
Got the Issues. Now its working
Edit the Test Code as follow :
void InitClock( void )
{
// Configure PLL prescaler, PLL postscaler, PLL divisor
PLLFBD = 63; // M=65
CLKDIVbits.PLLPOST = 0; // N2=2
CLKDIVbits.PLLPRE = 0; // N1=2
// Initiate Clock Switch to FRC oscillator with PLL (NOSC=0b001)
__builtin_write_OSCCONH(0x01);
__builtin_write_OSCCONL(OSCCON | 0x01);
// Wait for Clock switch to occur
while (OSCCONbits.COSC!= 0b001);
// Wait for PLL to lock
while (OSCCONbits.LOCK!= 1);
}
void InitUART2( void )
{
// configure U1MODE
U1MODEbits.UARTEN = 0; // Bit15 TX, RX DISABLED, ENABLE at end of func
//U1MODEbits.notimplemented;// Bit10
U1MODEbits.UEN = 0; // Bits8,9 TX,RX enabled, CTS,RTS not
U1MODEbits.ABAUD = 0; // Bit5 No Autobaud (would require sending '55')
U1MODEbits.BRGH = 0; // Bit3 16 clocks per bit period
U1MODEbits.PDSEL = 0; // Bits1,2 8bit, No Parity
U1MODEbits.STSEL = 0; // Bit0 One Stop Bit
// Load a value into Baud Rate Generator.
U1BRG = BRGVAL; // 60Mhz osc, 9600 Baud
// Load all values in for U1STA SFR
U1STAbits.UTXISEL1 = 0; //Bit15 Int when Char is transferred (1/2 config!)
U1STAbits.UTXISEL0 = 0; //Bit13 Other half of Bit15
U1STAbits.UTXBRK = 0; //Bit11 Disabled
U1STAbits.UTXEN = 0; //Bit10 TX pins controlled by periph
U1STAbits.URXISEL = 0; //Bits6,7 Int. on character recieved
IPC7 = 0x4400; // Mid Range Interrupt Priority level, no urgent reason
IFS0bits.U1TXIF = 0; // Clear the Transmit Interrupt Flag
IEC0bits.U1TXIE = 1; // Enable Transmit Interrupts
IFS0bits.U1RXIF = 0; // Clear the Recieve Interrupt Flag
IEC0bits.U1RXIE = 1; // Enable Recieve Interrupts
RPOR0bits.RP20R = 1; // dsPic33EP512GM604 => RP20 as U1TX
_U1RXR = 0x19; // dsPic33EP512GM604 => RPI25 as U1RX
U1MODEbits.UARTEN = 1; // And turn the peripheral on
U1STAbits.UTXEN = 1;
}
Applying these changes made my code working.

I'm looking for sample code to service the USCI (UART) on an MSP430 via DMA not interrupts

I have code that works "ok" for reading the USCI (UART) via interrupts, but the TI SimpliciTI stack is a CPU hog and it drops UART bytes when servicing the radio.
I assume DMA is the way to go, but I couldn't find a full example of DMA using USCI as input.
Here's what I ended up doing. It works!
struct {
#ifndef USE_DMA
volatile uint8_t rx_head ;
#endif
volatile uint8_t rx_tail ;
uint8_t rx_buffer[128];
} uart = { 0,0};
void UART_Init(void)
{
#ifndef USE_DMA
uart.rx_head = 0;
#endif
uart.rx_tail = 0;
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
PMAPPWD = 0x02D52; // Get write-access to port mapping regs
P1MAP5 = PM_UCA0RXD; // Map UCA0RXD output to P1.5
P1MAP6 = PM_UCA0TXD; // Map UCA0TXD output to P1.6
PMAPPWD = 0; // Lock port mapping registers
P1DIR |= BIT6; // Set P1.6 as TX output
P1SEL |= BIT5 + BIT6; // Select P1.5 & P1.6 to UART function
UCA0CTL1 = UCSWRST; // **Put state machine in reset**
#ifdef UART_9600
UCA0CTL1 |= UCSSEL_1; // CLK = ACLK
UCA0BR0 = 0x03; // 32kHz/9600=3.41 (see User's Guide)
UCA0BR1 = 0x00; //
UCA0MCTL = UCBRS_3+UCBRF_0; // Modulation UCBRSx=3, UCBRFx=0
#elif defined(UART_9600_SMCLK)
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 0xE2; // 12MHz/12500
UCA0BR1 = 0x04; //
UCA0MCTL = UCBRS_2+UCBRF_0; // Modulation UCBRSx=3, UCBRFx=0
#elif defined(UART_115200)
UCA0CTL1 |= UCSSEL_2; // SMCLK
UCA0BR0 = 104; // 12MHz/115200
UCA0BR1 = 0; //
UCA0MCTL = UCBRS_1 + UCBRF_0; // Modulation UCBRSx=1, UCBRFx=0
#else
#error Please select one of the supported baudrates.
#endif
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
#ifdef USE_DMA
memset(uart.rx_buffer,0,sizeof(uart.rx_buffer));
DMACTL0 = DMA0TSEL_16; // USCIA0 RX trigger
DMA0SAL = (uint16_t) &UCA0RXBUF; // Source address
DMA0DAL = (uint16_t) uart.rx_buffer; // Destination address
DMA0SZ = sizeof(uart.rx_buffer); // Block size. this counts down to 0, then reloads.
DMA0CTL = DMADSTINCR_3 + DMASBDB + DMADT_4 + DMALEVEL;
DMA0CTL |= DMAEN;
#else
UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt
#endif
}
int UART_GetChar(void)
{
#ifdef USE_DMA
if (DMA0SZ + uart.rx_tail != sizeof(uart.rx_buffer))
#else
if ( uart.rx_head != uart.rx_tail )
#endif
{
int c;
c = uart.rx_buffer[uart.rx_tail];
uint8_t next = uart.rx_tail + 1;
if (next >= sizeof(uart.rx_buffer)) next = 0;
uart.rx_tail = next;
return c;
}
return -1;
}

pic18f45550 usb problem

I am trying to build a very simple USB communication device using pic 18f4550
with default mikroelectronica example with no change (only change with hardware that I don't have couple of 100nf attached with vusb so I replaced them with 470uf
and I didn't put any pf with my crystal oscillator)
The hardware:
The code is working very will with Proteus simulation:
unsigned char k;
unsigned char userWR_buffer[64];
const char *text = "MIKROElektronika Compilers ER \r\n";
//**************************************************************************************************
// Main Interrupt Routine
//**************************************************************************************************
void interrupt()
{
HID_InterruptProc();
}
//**************************************************************************************************
//**************************************************************************************************
// Initialization Routine
//**************************************************************************************************
void Init_Main()
{
//--------------------------------------
// Disable all interrupts
//--------------------------------------
INTCON = 0; // Disable GIE, PEIE, TMR0IE,INT0IE,RBIE
INTCON2 = 0xF5;
INTCON3 = 0xC0;
RCON.IPEN = 0; // Disable Priority Levels on interrupts
PIE1 = 0;
PIE2 = 0;
PIR1 = 0;
PIR2 = 0;
ADCON1 |= 0x0F; // Configure all ports with analog function as digital
CMCON |= 7; // Disable comparators
//--------------------------------------
// Ports Configuration
//--------------------------------------
TRISA = 0xFF;
TRISB = 0xFF;
TRISC = 0xFF;
TRISD = 0;
TRISE = 0x07;
LATA = 0;
LATB = 0;
LATC = 0;
LATD = 0;
LATE = 0;
//--------------------------------------
// Clear user RAM
// Banks [00 .. 07] ( 8 x 256 = 2048 Bytes )
//--------------------------------------
}
//**************************************************************************************************
//**************************************************************************************************
// Main Program Routine
//**************************************************************************************************
void main() {
char i;
Init_Main();
HID_Enable(&userWR_buffer, &userWR_buffer);
Delay_ms(1000);
Delay_ms(1000);
while(1) {
Delay_ms(1000);
i=0;
while(text[i]) {
userWR_buffer[0]= text[i++];
while (!HID_Write(&userWR_buffer, 1));
}
}
Delay_ms(1000);
HID_Disable();
}
//**************************************************************************************************
I didn't put any pf with my crystal oscillator
I don't think this will work. Check with an oscilloscope what happens on your crystal. Your device has simply no clock input so it never executes anything.

ARM LPC1768 UART0 configuration, wrong baud rate

My baud rate should be 115200, but it is 892.9
void UART0_Init(int pclk, int baudrate)
{
unsigned long int DLest;
//unsigned long int pclk;
unsigned int temp;
// Turn on power to UART0
SC->PCONP |= PCUART0_POWERON;
// Set PINSEL0 so that P0.2 = TXD0, P0.3 = RXD0
PINCON->PINSEL0 = (PINCON->PINSEL0 & ~0xf0) | (1 << 4) | (1 << 6);
UART0->LCR = 0x83; // 8 bits, no Parity, 1 Stop bit, DLAB=1
DLest = (pclk / 16) / baudrate; // Set baud rate
UART0->DLM = DLest / 256;
UART0->DLL = DLest % 256;
// UART0->FDR =
UART0->IER = 0x7; //enable RBR (b0), THRE(b1), RLS(b2)
UART0->LCR = 0x03; // 8 bits, no Parity, 1 Stop bit DLAB = 0
UART0->FCR = 0x07; // Enable and reset TX and RX FIFO
}
void prvSetupHardware( void )
{
/* Disable peripherals power. */
SC->PCONP = 0;
/* Enable GPIO power. */
SC->PCONP = PCONP_PCGPIO;
/* Disable TPIU. */
PINCON->PINSEL10 = 0;
if ( SC->PLL0STAT & ( 1 << 25 ) )
{
/* Enable PLL, disconnected. */
SC->PLL0CON = 1;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
}
/* Disable PLL, disconnected. */
SC->PLL0CON = 0;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
/* Enable main OSC. */
SC->SCS |= 0x20;
while( !( SC->SCS & 0x40 ) );
/* select main OSC, 12MHz, as the PLL clock source. */
SC->CLKSRCSEL = 0x1;
SC->PCLKSEL0 = 0xAAAAAAAA; /* PCLK is 1/2 CCLK */
SC->PCLKSEL1 = 0xAAAAAAAA;
/*Fcc0 = 400MHz, M = 50, N = 3*/
SC->PLL0CFG = 0x20031;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
/* Enable PLL, disconnected. */
SC->PLL0CON = 1;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
/* Set clock divider. */
/*Clock = 100MHz, Fcc0 = 400MHz*/
SC->CCLKCFG = 0x03;//divided by 4.
/* Configure flash accelerator. */
SC->FLASHCFG = 0x403a;
/* Check lock bit status. */
while( ( ( SC->PLL0STAT & ( 1 << 26 ) ) == 0 ) );
/* Enable and connect. */
SC->PLL0CON = 3;
SC->PLL0FEED = PLLFEED_FEED1;
SC->PLL0FEED = PLLFEED_FEED2;
while( ( ( SC->PLL0STAT & ( 1 << 25 ) ) == 0 ) );
/* Configure the clock for the USB. */
if( SC->PLL1STAT & ( 1 << 9 ) )
{
/* Enable PLL, disconnected. */
SC->PLL1CON = 1;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
}
/* Disable PLL, disconnected. */
SC->PLL1CON = 0;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
SC->PLL1CFG = 0x23;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
/* Enable PLL, disconnected. */
SC->PLL1CON = 1;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
while( ( ( SC->PLL1STAT & ( 1 << 10 ) ) == 0 ) );
/* Enable and connect. */
SC->PLL1CON = 3;
SC->PLL1FEED = PLLFEED_FEED1;
SC->PLL1FEED = PLLFEED_FEED2;
while( ( ( SC->PLL1STAT & ( 1 << 9 ) ) == 0 ) );
/* Configure the LEDs. */
vParTestInitialise();
/*pclk = 100MHZ/2, baud = 115200 */
UART0_Init(100000000/2, 115200);
/* Set the sleep mode to highest level sleep*/
SC->PCON = 0x0;
SCB->SCR = 0x0;
/*set push button interrupt */
PINCON->PINSEL4 |= 0x00100000;
SC->EXTMODE =0;
NVIC_SetPriority( EINT0_IRQn, configUIButton1_INTERRUPT_PRIORITY );
NVIC_EnableIRQ( EINT0_IRQn );
NVIC_SetPriority( UART0_IRQn, configUIButton1_INTERRUPT_PRIORITY + 1 );
NVIC_EnableIRQ( UART0_IRQn );
}
I have confirmed that my cclk is running at 100MHz.
I replace the UART init code with code from an example project by Kunil (uart_interrupt_demo):
void uart_init(int baudrate) {
int errorStatus = -1; //< Failure
long int SystemFrequency = 100000000;
// UART clock (FCCO / PCLK_UART0)
unsigned int uClk = SystemFrequency / 4;
unsigned int calcBaudrate = 0;
unsigned int temp = 0;
unsigned int mulFracDiv, dividerAddFracDiv;
unsigned int divider = 0;
unsigned int mulFracDivOptimal = 1;
unsigned int dividerAddOptimal = 0;
unsigned int dividerOptimal = 0;
unsigned int relativeError = 0;
unsigned int relativeOptimalError = 100000;
// Turn on power to UART0
SC->PCONP |= PCUART0_POWERON;
// Change P0.2 and P0.3 mode to TXD0 and RXD0
PINCON->PINSEL0 = (1 << 4) | (1 << 6);
// Set 8N1 mode
UART0->LCR = 0x83;
// Set the baud rate
uClk = uClk >> 4; /* div by 16 */
/*
* The formula is :
* BaudRate= uClk * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * DLL)
*/
/*
* The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions:
* 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15
*/
for (mulFracDiv = 1; mulFracDiv <= 15; mulFracDiv++) {
for (dividerAddFracDiv = 0; dividerAddFracDiv <= 15; dividerAddFracDiv++) {
temp = (mulFracDiv * uClk) / (mulFracDiv + dividerAddFracDiv);
divider = temp / baudrate;
if ((temp % baudrate) > (baudrate / 2))
divider++;
if (divider > 2 && divider < 65536) {
calcBaudrate = temp / divider;
if (calcBaudrate <= baudrate) {
relativeError = baudrate - calcBaudrate;
} else {
relativeError = calcBaudrate - baudrate;
}
if (relativeError < relativeOptimalError) {
mulFracDivOptimal = mulFracDiv;
dividerAddOptimal = dividerAddFracDiv;
dividerOptimal = divider;
relativeOptimalError = relativeError;
if (relativeError == 0)
break;
}
}
}
if (relativeError == 0)
break;
}
if (relativeOptimalError
< ((baudrate * UART_ACCEPTED_BAUDRATE_ERROR) / 100)) {
UART0->LCR |= DLAB_ENABLE;
UART0->DLM = (unsigned char) ((dividerOptimal >> 8) & 0xFF);
UART0->DLL = (unsigned char) dividerOptimal;
UART0->LCR &= ~DLAB_ENABLE;
UART0->FDR = ((mulFracDivOptimal << 4) & 0xF0) | (dividerAddOptimal
& 0x0F);
errorStatus = 0; //< Success
}
// Enable TX and RX FIFO
UART0->FCR |= FIFO_ENABLE;
// Set FIFO to trigger when at least 14 characters available
UART0->FCR |= (3 << 6);
// Enable UART RX interrupt (for LPC17xx UART)
UART0->IER = RBR_IRQ_ENABLE;
// Enable the UART interrupt (for Cortex-CM3 NVIC)
NVIC_EnableIRQ(UART0_IRQn);
}
And it works!
I have to go through and see what i had wrong. I suspect the order of register settings was off.
Have a look at the Errata sheet.
You can't set SC->PCLKSEL0 after you fired up the main PLL, so the divider stays at CCLK/4.
Just move the line
/* Setup the peripheral bus to be the same as the PLL output (64 MHz). */
SC->PCLKSEL0 = 0x05555555;
a few lines up, before you enable the PLL.
Suspect that clk for UART is further divided from the cclk. You need to check the datasheet and update accordingly.
I wanted a simplified driver for my LPC1768 UART1 port so I have written a baud rate calculator application based on CMSIS code.
You provide the Peripheral Clock Frequency and Desired Baud Rate and it will generate the DLL, Fractional Multiplier & Divider and finally recalculates with the computed values to indicate the Baud rate achievable.
I have tested it with a peripheral clock of 25MHz and baud rates of 115200 & 9600 with success. It does not calculate DLM which is generally 0 for bauds above 4800.
It is available at a freeware download site.
http://sabercathost.com/6y6
I have a reputation to maintain and to that end the application I uploaded does not contain a virus.
HTH
Mark
As requested by Drew I've appended the CMSIS function I used in my code below.
/*********************************************************************//**
* #brief Determines best dividers to get a target clock rate
* #param[in] UARTx Pointer to selected UART peripheral, should be:
* - LPC_UART0: UART0 peripheral
* - LPC_UART1: UART1 peripheral
* - LPC_UART2: UART2 peripheral
* - LPC_UART3: UART3 peripheral
* #param[in] baudrate Desired UART baud rate.
* #return Error status, could be:
* - SUCCESS
* - ERROR
**********************************************************************/
static Status uart_set_divisors(LPC_UART_TypeDef *UARTx, uint32_t baudrate)
{
Status errorStatus = ERROR;
uint32_t uClk;
uint32_t d, m, bestd, bestm, tmp;
uint64_t best_divisor, divisor;
uint32_t current_error, best_error;
uint32_t recalcbaud;
/* get UART block clock */
if (UARTx == LPC_UART0)
{
uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART0);
}
else if (UARTx == (LPC_UART_TypeDef *)LPC_UART1)
{
uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART1);
}
else if (UARTx == LPC_UART2)
{
uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART2);
}
else if (UARTx == LPC_UART3)
{
uClk = CLKPWR_GetPCLK (CLKPWR_PCLKSEL_UART3);
}
/* In the Uart IP block, baud rate is calculated using FDR and DLL-DLM registers
* The formula is :
* BaudRate= uClk * (mulFracDiv/(mulFracDiv+dividerAddFracDiv) / (16 * (DLL)
* It involves floating point calculations. That's the reason the formulae are adjusted with
* Multiply and divide method.*/
/* The value of mulFracDiv and dividerAddFracDiv should comply to the following expressions:
* 0 < mulFracDiv <= 15, 0 <= dividerAddFracDiv <= 15 */
best_error = 0xFFFFFFFF; /* Worst case */
bestd = 0;
bestm = 0;
best_divisor = 0;
for (m = 1 ; m <= 15 ;m++)
{
for (d = 0 ; d < m ; d++)
{
divisor = ((uint64_t)uClk<<28)*m/(baudrate*(m+d));
current_error = divisor & 0xFFFFFFFF;
tmp = divisor>>32;
/* Adjust error */
if(current_error > ((uint32_t)1<<31)){
current_error = -current_error;
tmp++;
}
if(tmp<1 || tmp>65536) /* Out of range */
continue;
if( current_error < best_error){
best_error = current_error;
best_divisor = tmp;
bestd = d;
bestm = m;
if(best_error == 0) break;
}
} /* end of inner for loop */
if (best_error == 0)
break;
} /* end of outer for loop */
if(best_divisor == 0) return ERROR; /* can not find best match */
recalcbaud = (uClk>>4) * bestm/(best_divisor * (bestm + bestd));
/* reuse best_error to evaluate baud error*/
if(baudrate>recalcbaud) best_error = baudrate - recalcbaud;
else best_error = recalcbaud -baudrate;
best_error = best_error * 100 / baudrate;
if (best_error < UART_ACCEPTED_BAUDRATE_ERROR)
{
if (((LPC_UART1_TypeDef *)UARTx) == LPC_UART1)
{
((LPC_UART1_TypeDef *)UARTx)->LCR |= UART_LCR_DLAB_EN;
((LPC_UART1_TypeDef *)UARTx)->/*DLIER.*/DLM = UART_LOAD_DLM(best_divisor);
((LPC_UART1_TypeDef *)UARTx)->/*RBTHDLR.*/DLL = UART_LOAD_DLL(best_divisor);
/* Then reset DLAB bit */
((LPC_UART1_TypeDef *)UARTx)->LCR &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
((LPC_UART1_TypeDef *)UARTx)->FDR = (UART_FDR_MULVAL(bestm) \
| UART_FDR_DIVADDVAL(bestd)) & UART_FDR_BITMASK;
}
else
{
UARTx->LCR |= UART_LCR_DLAB_EN;
UARTx->/*DLIER.*/DLM = UART_LOAD_DLM(best_divisor);
UARTx->/*RBTHDLR.*/DLL = UART_LOAD_DLL(best_divisor);
/* Then reset DLAB bit */
UARTx->LCR &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
UARTx->FDR = (UART_FDR_MULVAL(bestm) \
| UART_FDR_DIVADDVAL(bestd)) & UART_FDR_BITMASK;
}
errorStatus = SUCCESS;
}
return errorStatus;
}