I am trying to upload a simple UART testing program to a PIC24F Curiosity Board using MPLAB X and validate data transmission using TeraTerm. This evaluation board uses a PIC24FJ128GA204 microcontroller. I have made sure to set the serial port configuration on TeraTerm as it is defined in the program.
For data transmission, I am using a USB to RS-232 UART cable connected to my desktop. I have double checked my cable connections and they are as defined in the program. I am not using the +5 Vcc on the cable and I have connected the cable to ground, but I have tried connected and disconnected ground.
Currently no data will be transmitted, although I have noticed that when I program the board, sometimes TeraTerm will display some random values, which I am not sure if that implies there is a connection capable of data transmission or it is just random noise.
Currently, my UART initialization is as follows:
#include <xc.h>
#define U_ENABLE 0x8008 // enable UART, BREGH=1, 1 stop, 8 data bits, no parity, RTS/CTS flow control
#define U_TX 0x0400 // enable transmission, clear all flags
#define _XTAL_FREQ 8000000 //set to internal oscillator frequency
//** UART2 RS232 asynchronous communication demonstration
void initialize_UART(void) {
U1BRG = 104; // initialize the baud rate generator to 104, an equivalent value of 9524
U1MODE = U_ENABLE; // initialize the UART module
U1STA = U_TX; // enable the receiver
//****CONFIGURING FOR UART****
//MICROCONTROLLER PIN || UART WIRE
//RP0/RB0 = U1RX
//RP1/RB1 = U1CTS (Clear to send)
//RP2/RB2 = U1TX
//RP3/RB3 = UR1RTS ()
// Unlock Registers (per MCU data sheet)
asm volatile ("MOV #OSCCON, w1 \n"
"MOV #0x46, w2 \n"
"MOV #0x57, w3 \n"
"MOV.b w2, [w1] \n"
"MOV.b w3, [w1] \n"
"BCLR OSCCON, #6") ;
// Configure Input Functions (Table 11-3 in Datasheet)
// Assign U1RX To Pin RP0
//RPINR
RPINR18bits.U1RXR = 0;
// Assign U1CTS To Pin RP1
RPINR18bits.U1CTSR = 1;
// Configure Output Functions (Table 11-4 in Datasheet)
// Assign U1TX To Pin RP2
RPOR1bits.RP2R = 3;
// Assign U1RTS To Pin RP3
RPOR1bits.RP3R = 4;
// Lock Registers
asm volatile ("MOV #OSCCON, w1 \n"
"MOV #0x46, w2 \n"
"MOV #0x57, w3 \n"
"MOV.b w2, [w1] \n"
"MOV.b w3, [w1] \n"
"BSET OSCCON, #6") ;
}
My function for sending data through UART:
char UART_send_char(char a)
{
while (PORTBbits.RB1 == 1); //wait for clear to send
while (U1STAbits.UTXBF); //wait while Tx buffer is full
U1TXREG = a;
return a;
}
How I am testing the function in main():
int main(void)
{
TRISA = 0;
// init the UART1 serial port
initialize_UART();
// main loop
while (1)
{
PORTAbits.RA10 = 1; //for debugging purposes
UART_send_char('>');
}
}
This program should continuously send the character ">" to the TeraTerm console, but instead I receive nothing. RA10 is connected to an LED, which does light up so I know the program has entered the main loop, but no data is being sent. I have the configuration bits set to the internal oscillator which operates at 8 MHz and have disabled the PLL. BREGH is set to 1, so I have used the respective formula for the Baud Rate Generator given in the datasheet on page 247 with an Fcy value of 8 MHz/2.
I am new to programming MCUs and have spent some hours trying to fix this to no avail, so any help would be much appreciated.
Here is a complete single file application that runs on the DM240004 PIC24F Curiosity Development Board using a MikroElektronical USB UART click.
/*
* https://github.com/dsoze1138/24FJ128GA204_DM240004
*
* File: main.c
* Author: dan1138
* Target: PIC24FJ128GA204
* Compiler: XC16 v1.60
* IDE: MPLABX v5.45
*
* Created on November 24, 2020, 12:02 PM
*
* PIC24FJ128GA204
* +----------------+ +--------------+ +-----------+ +--------------+
* J4_MOSI <> 1 : RB9/RP9 : LED2 <> 12 : RA10 : J4_SDA <> 23 : RB2/RP2 : X2-32KHZ <> 34 : RA4/SOSCO :
* RGB_G <> 2 : RC6/RP22 : <> 13 : RA7 : J4_SCL <> 24 : RB3/RP3 : LED1 <> 35 : RA9 :
* RGB_B <> 3 : RC7/RP23 : <> 14 : RB14/RP14 : POT <> 25 : RC0/RP16 : J4_CS <> 36 : RC3/RP19 :
* S2 <> 4 : RC8/RP24 : <> 15 : RB15/RP15 : <> 26 : RC1/RP17 : J4_SCK <> 37 : RC4/RP20 :
* S1 <> 5 : RC9/RP25 : GND -> 16 : AVSS : <> 27 : RC2/RP18 : RGB_R <> 38 : RC5/RP21 :
* 3v3 <> 6 : VBAT : 3v3 -> 17 : AVDD : 3v3 -> 28 : VDD : GND -> 39 : VSS :
* 10uF -> 7 : VCAP : ICD_VPP -> 18 : MCLR : GND -> 29 : VSS : 3v3 -> 40 : VDD :
* <> 8 : RB10/RP11/PGD2 : J4_AN <> 19 : RA0/AN0 : <> 30 : RA2/OSCI : J4_RX <> 41 : RB5/RP5/PGD3 :
* <> 9 : RB11/RP11/PGC2 : J4_RST <> 20 : RA1/AN1 : <> 31 : RA3/OSCO : J4_TX <> 42 : RB6/RP6/PGC3 :
* <> 10 : RB12/RP12 : ICD_PGD <> 21 : RB0/RP0/PGD1 : <> 32 : RA8 : <> 43 : RB7/RP7 :
* <> 11 : RB13/RP13 : ICD_PGC <> 22 : RB1/RP1/PGC1 : X2-32KHZ <> 33 : RB4/SOSCI : J4_MISO <> 44 : RB8/RP8 :
* +----------------+ +--------------+ +-----------+ +--------------+
* TQFP-44
*
* Description:
*
* Bare metal initialization of the DM240004 Curiosity Board
*
* Setup the system oscillator for 32MHz using the internal FRC and the 4x PLL.
* Turn on the 32.768KHz secondary oscillator.
* Use UART1 and printf to send a message as 9600 baud.
* Flash LED2 on for 500 milliseconds then off for 500 milliseconds.
*
*/
// CONFIG4
#pragma config DSWDTPS = DSWDTPS1F // Deep Sleep Watchdog Timer Postscale Select bits (1:68719476736 (25.7 Days))
#pragma config DSWDTOSC = LPRC // DSWDT Reference Clock Select (DSWDT uses LPRC as reference clock)
#pragma config DSBOREN = OFF // Deep Sleep BOR Enable bit (DSBOR Disabled)
#pragma config DSWDTEN = OFF // Deep Sleep Watchdog Timer Enable (DSWDT Disabled)
#pragma config DSSWEN = OFF // DSEN Bit Enable (Deep Sleep operation is always disabled)
#pragma config PLLDIV = PLL4X // USB 96 MHz PLL Prescaler Select bits (4x PLL selected)
#pragma config I2C1SEL = DISABLE // Alternate I2C1 enable bit (I2C1 uses SCL1 and SDA1 pins)
#pragma config IOL1WAY = OFF // PPS IOLOCK Set Only Once Enable bit (The IOLOCK bit can be set and cleared using the unlock sequence)
// CONFIG3
#pragma config WPFP = WPFP127 // Write Protection Flash Page Segment Boundary (Page 127 (0x1FC00))
#pragma config SOSCSEL = ON // SOSC Selection bits (SOSC circuit selected)
#pragma config WDTWIN = PS25_0 // Window Mode Watchdog Timer Window Width Select (Watch Dog Timer Window Width is 25 percent)
#pragma config PLLSS = PLL_FRC // PLL Secondary Selection Configuration bit (PLL is fed by the on-chip Fast RC (FRC) oscillator)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset Disabled)
#pragma config WPDIS = WPDIS // Segment Write Protection Disable (Disabled)
#pragma config WPCFG = WPCFGDIS // Write Protect Configuration Page Select (Disabled)
#pragma config WPEND = WPENDMEM // Segment Write Protection End Page Select (Write Protect from WPFP to the last page of memory)
// CONFIG2
#pragma config POSCMD = NONE // Primary Oscillator Select (Primary Oscillator Disabled)
#pragma config WDTCLK = LPRC // WDT Clock Source Select bits (WDT uses LPRC)
#pragma config OSCIOFCN = ON // OSCO Pin Configuration (OSCO/CLKO/RA3 functions as port I/O (RA3))
#pragma config FCKSM = CSECMD // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Clock switching is enabled, Fail-Safe Clock Monitor is disabled)
#pragma config FNOSC = FRC // Initial Oscillator Select (Fast RC Oscillator (FRC))
#pragma config ALTCMPI = CxINC_RB // Alternate Comparator Input bit (C1INC is on RB13, C2INC is on RB9 and C3INC is on RA0)
#pragma config WDTCMX = WDTCLK // WDT Clock Source Select bits (WDT clock source is determined by the WDTCLK Configuration bits)
#pragma config IESO = OFF // Internal External Switchover (Disabled)
// CONFIG1
#pragma config WDTPS = PS32768 // Watchdog Timer Postscaler Select (1:32,768)
#pragma config FWPSA = PR128 // WDT Prescaler Ratio Select (1:128)
#pragma config WINDIS = OFF // Windowed WDT Disable (Standard Watchdog Timer)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT disabled in hardware; SWDTEN bit disabled)
#pragma config ICS = PGx1 // Emulator Pin Placement Select bits (Emulator functions are shared with PGEC1/PGED1)
#pragma config LPCFG = OFF // Low power regulator control (Disabled - regardless of RETEN)
#pragma config GWRP = OFF // General Segment Write Protect (Write to program memory allowed)
#pragma config GCP = OFF // General Segment Code Protect (Code protection is disabled)
#pragma config JTAGEN = OFF // JTAG Port Enable (Disabled)
/*
* Defines for system oscillator frequency.
* Make sure that the PIC initialization selects this frequency.
*/
#define FSYS (32000000ul)
#define FCY (FSYS/2ul)
/*
* Target specific Special Function Register definitions
*/
#include <xc.h>
/*
* Standard header files
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
/*
* Initialize this PIC
*/
void PIC_Init(void)
{
uint16_t ClockSwitchTimeout;
/*
* Disable all interrupt sources
*/
__builtin_disi(0x3FFF); /* disable interrupts for 16383 cycles */
IEC0 = 0;
IEC1 = 0;
IEC2 = 0;
IEC3 = 0;
IEC4 = 0;
IEC5 = 0;
IEC6 = 0;
IEC7 = 0;
__builtin_disi(0x0000); /* enable interrupts */
INTCON1bits.NSTDIS = 1; /* Disable interrupt nesting */
/*
* At Power On Reset the configuration words set the system clock
* to use the FRC oscillator. At this point we need to enable the
* PLL to get the system clock running at 32MHz.
*
* Clock switching on the 24FJ family with the PLL can be a bit tricky.
*
* First we need to check if the configuration words enabled clock
* switching at all, then turn off the PLL, then setup the PLL and
* finally enable it. Sounds simple, I know. Make sure you verify this
* clock setup on the real hardware.
*/
if(!OSCCONbits.CLKLOCK) /* if primary oscillator switching is unlocked */
{
/* Select primary oscillator as FRC */
__builtin_write_OSCCONH(0b000);
/* Request switch primary to new selection */
__builtin_write_OSCCONL(OSCCON | (1 << _OSCCON_OSWEN_POSITION));
/* wait, with timeout, for clock switch to complete */
for(ClockSwitchTimeout=10000; --ClockSwitchTimeout && OSCCONbits.OSWEN;);
CLKDIV = 0x0000; /* set for FRC clock 8MHZ operations */
/* Select primary oscillator as FRCPLL */
__builtin_write_OSCCONH(0b001);
/* Request switch primary to new selection */
__builtin_write_OSCCONL(OSCCON | (1 << _OSCCON_OSWEN_POSITION));
/* ALERT: This may be required only when the 96MHz PLL is used */
CLKDIVbits.PLLEN = 1;
/* wait, with timeout, for clock switch to complete */
for(ClockSwitchTimeout=10000; --ClockSwitchTimeout && OSCCONbits.OSWEN;);
/* wait, with timeout, for the PLL to lock */
for(ClockSwitchTimeout=10000; --ClockSwitchTimeout && !OSCCONbits.LOCK;);
/* at this point the system oscillator should be 32MHz */
}
/* Turn on Secondary Oscillation Amplifier */
__builtin_write_OSCCONL(OSCCON | (1 << _OSCCON_SOSCEN_POSITION));
/* Turn off all analog inputs */
ANSA = 0;
ANSB = 0;
ANSC = 0;
}
/*
* WARNING: Not a portable function.
* Maximum delay 16384 instruction cycles.
* At 16 MIPS this is 1024 microseconds.
*
* Minimum 1MHz instruction cycle clock.
*/
void delay_us(unsigned short delay)
{
if (delay > (uint16_t)(16383.0 / (FCY/1E6)))
{
asm(" repeat #16383\n"
" clrwdt \n"
::);
}
else
{
asm(" repeat %0 \n"
" clrwdt \n"
:: "r" (delay*(uint16_t)(FCY/1000000ul)-1));
}
}
/*
* WARNING: Not a portable function.
* Maximum 16MHz instruction cycle clock.
* Minimum 8Khz instruction cycle clock.
*/
void delay_ms(unsigned long delay)
{
if(delay)
{
asm("1: repeat %0 \n"
" clrwdt \n"
" sub %1,#1 \n"
" subb %d1,#0 \n"
" bra nz,1b \n"
:: "r" (FCY/1000ul-6ul), "C" (delay));
}
}
/*
* Initialize the UART
*/
void UART_Init(void)
{
/**
Set the UART1 module to run at 9600 baud with RB6 as TX out and RB5 as RX in.
*/
TRISBbits.TRISB6 = 0;
LATBbits.LATB6 = 1;
__builtin_write_OSCCONL(OSCCON & ~_OSCCON_IOLOCK_MASK); // unlock PPS
RPINR18bits.U1RXR = 0x0005; //RB5->UART1:U1RX
RPOR3bits.RP6R = 0x0003; //RB6->UART1:U1TX
__builtin_write_OSCCONL(OSCCON | _OSCCON_IOLOCK_MASK); // lock PPS
// STSEL 1; IREN disabled; PDSEL 8N; UARTEN enabled; RTSMD disabled; USIDL disabled; WAKE disabled; ABAUD disabled; LPBACK disabled; BRGH enabled; URXINV disabled; UEN TX_RX;
// Data Bits = 8; Parity = None; Stop Bits = 1;
U1MODE = (0x8008 & ~(1<<15)); // disabling UARTEN bit
// UTXISEL0 TX_ONE_CHAR; UTXINV disabled; URXEN disabled; OERR NO_ERROR_cleared; URXISEL RX_ONE_CHAR; UTXBRK COMPLETED; UTXEN disabled; ADDEN disabled;
U1STA = 0x00;
// BaudRate = 9600; Frequency = 16000000 Hz; U1BRG 416;
U1BRG = 0x1A0;
// ADMADDR 0; ADMMASK 0;
U1ADMD = 0x00;
// T0PD 1 ETU; PTRCL T0; TXRPT Retransmits the error byte once; CONV Direct; SCEN disabled;
U1SCCON = 0x00;
// TXRPTIF disabled; TXRPTIE disabled; WTCIF disabled; WTCIE disabled; PARIE disabled; GTCIF disabled; GTCIE disabled; RXRPTIE disabled; RXRPTIF disabled;
U1SCINT = 0x00;
// GTC 0;
U1GTC = 0x00;
// WTCL 0;
U1WTCL = 0x00;
// WTCH 0;
U1WTCH = 0x00;
U1MODEbits.UARTEN = 1; // enabling UART ON bit
U1STAbits.UTXEN = 1;
}
uint8_t UART1_Read(void)
{
while(!(U1STAbits.URXDA == 1));
if ((U1STAbits.OERR == 1))
{
U1STAbits.OERR = 0;
}
return U1RXREG;
}
void UART1_Write(uint8_t txData)
{
while(U1STAbits.UTXBF == 1);
U1TXREG = txData; // Write the data byte to the USART.
}
bool UART1_IsRxReady(void)
{
return U1STAbits.URXDA;
}
bool UART1_IsTxReady(void)
{
return ((!U1STAbits.UTXBF) && U1STAbits.UTXEN );
}
bool UART1_IsTxDone(void)
{
return U1STAbits.TRMT;
}
int __attribute__((__section__(".libc.write"))) write(int handle, void *buffer, unsigned int len)
{
unsigned int i;
for (i = len; i; --i)
{
UART1_Write(*(char*)buffer++);
}
return(len);
}
/*
* Main Application
*/
int main(void)
{
/*
* Application initialization
*/
PIC_Init();
UART_Init();
/* Set RA10 for output to drive LED2 */
LATAbits.LATA10 = 0;
TRISAbits.TRISA10 = 0;
printf("\r\nPIC24FJ128GA204 built on " __DATE__ " at " __TIME__ " Start\r\n");
/*
* Application process loop
*/
for(;;)
{
LATAbits.LATA10 ^= 1;
delay_ms(500);
}
return 0;
}
I suspect that your problem may be trying to implement hardware handshaking with the RTS/CTS signaling.
Try to get the serial data transmit from the PIC to the PC working at a slow baud rate first.
And another thing is that RB0 and RB1 are used to program (and debug) the PIC24FJ128GA204. The onboard In-Circuit-Serial-Programmer can interfere with using these pins for other functions. In a debug session they cannot be used by the application at all.
Related
I have trouble with a PIC24FJ64GP202 to work as an spi slave.
I have simplified the code to the minimum possible in order to find the problem.
In this simple code, an spi master (it is an ATSAMD51N19A) will send 0x55 to a spi slave (it is a PIC24FJ64GP202) once per second at 1MHz.
I can see the signal waveforms on the slave pins so the transmission is fine (please see the attached image but please note that the sample code does not implement the spi2 that communicates with the GLCD because this part of the code works fine and I want to target the problem: making it work as a slave SPI to enventually receive commands from another microcontroller).
The problem is with the spi slave. I can confirm that the pins receives the signal (CSn, spi1 clk, SDI but when I debug the code, the spi interrupt will not fire with the PIC24FJ64GP202 that is configured in slave mode.
Here is the pinout for the spi slave (PIC24FJ64GP202):
CSn (SS): RB2, pin 6
Spi1 clk: RB3, pin 7
SDI: RB4, pin 11
SDO: RB5, pin 14
Any idea why the interrupt will not fire and why the SPI1BUFL and SPI1BUFH are always 0 eventhough the master sends 0x55 with a 1MHz clk once per second ?
Here is the slave simplified code (in one main.c file):
// FSEC
#pragma config BWRP = OFF //Boot Segment Write-Protect bit->Boot Segment may be written
#pragma config BSS = DISABLED //Boot Segment Code-Protect Level bits->No Protection (other than BWRP)
#pragma config BSEN = OFF //Boot Segment Control bit->No Boot Segment
#pragma config GWRP = OFF //General Segment Write-Protect bit->General Segment may be written
#pragma config GSS = DISABLED //General Segment Code-Protect Level bits->No Protection (other than GWRP)
#pragma config CWRP = OFF //Configuration Segment Write-Protect bit->Configuration Segment may be written
#pragma config CSS = DISABLED //Configuration Segment Code-Protect Level bits->No Protection (other than CWRP)
#pragma config AIVTDIS = OFF //Alternate Interrupt Vector Table bit->Disabled AIVT
// FBSLIM
#pragma config BSLIM = 8191 //Boot Segment Flash Page Address Limit bits->8191
// FOSCSEL
#pragma config FNOSC = FRC //Oscillator Source Selection->FRC
#pragma config PLLMODE = PLL96DIV2 //PLL Mode Selection->96 MHz PLL. Oscillator input is divided by 2 (8 MHz input)
#pragma config IESO = OFF //Two-speed Oscillator Start-up Enable bit->Start up with user-selected oscillator source
// FOSC
#pragma config POSCMD = NONE //Primary Oscillator Mode Select bits->Primary Oscillator disabled
#pragma config OSCIOFCN = OFF //OSC2 Pin Function bit->OSC2 is clock output
#pragma config SOSCSEL = OFF //SOSC Selection Configuration bits->Digital (SCLKI) mode
#pragma config PLLSS = PLL_FRC //PLL Secondary Selection Configuration bit->PLL is fed by the on-chip Fast RC (FRC) oscillator
#pragma config IOL1WAY = ON //Peripheral pin select configuration bit->Allow only one reconfiguration
#pragma config FCKSM = CSECMD //Clock Switching Mode bits->Clock switching is enabled,Fail-safe Clock Monitor is disabled
// FWDT
#pragma config WDTPS = PS32768 //Watchdog Timer Postscaler bits->1:32768
#pragma config FWPSA = PR128 //Watchdog Timer Prescaler bit->1:128
#pragma config FWDTEN = OFF //Watchdog Timer Enable bits->WDT and SWDTEN disabled
#pragma config WINDIS = OFF //Watchdog Timer Window Enable bit->Watchdog Timer in Non-Window mode
#pragma config WDTWIN = WIN25 //Watchdog Timer Window Select bits->WDT Window is 25% of WDT period
#pragma config WDTCMX = WDTCLK //WDT MUX Source Select bits->WDT clock source is determined by the WDTCLK Configuration bits
#pragma config WDTCLK = LPRC //WDT Clock Source Select bits->WDT uses LPRC
// FPOR
#pragma config BOREN = ON //Brown Out Enable bit->Brown-out Reset is Enabled
#pragma config LPREGEN = OFF //Low power regulator control->Low Voltage and Low Power Regulator are not available
#pragma config LPBOREN = ENABLE //Downside Voltage Protection Enable bit->Low Power BOR is enabled and active when main BOR is inactive
// FICD
#pragma config ICS = PGD1 //ICD Communication Channel Select bits->Communicate on PGEC1 and PGED1
#pragma config JTAGEN = OFF //JTAG Enable bit->JTAG is disabled
// FDMTIVTL
#pragma config DMTIVTL = 0 //Deadman Timer Interval Low Word->0
// FDMTIVTH
#pragma config DMTIVTH = 0 //Deadman Timer Interval High Word->0
// FDMTCNTL
#pragma config DMTCNTL = 0 //Deadman Timer Instruction Count Low Word->0
// FDMTCNTH
#pragma config DMTCNTH = 0 //Deadman Timer Instruction Count High Word->0
// FMDT
#pragma config DMTDIS = OFF //Deadman Timer Enable Bit->Dead Man Timer is Disabled and can be enabled by software
// FDEVOPT1
#pragma config ALTCMP1 = DISABLE //Alternate Comparator 1 Input Enable bit->C1INC is on RB13 and C3INC is on RA0
#pragma config TMPRPIN = OFF //Tamper Pin Enable bit->TMPRN pin function is disabled
#pragma config SOSCHP = ON //SOSC High Power Enable bit (valid only when SOSCSEL = 1->Enable SOSC high power mode (default)
#pragma config ALTI2C1 = ALTI2C1_OFF //Alternate I2C pin Location->I2C1 Pin mapped to SDA1/SCL1 pins
#pragma config ALTCMP2 = DISABLE //Alternate Comparator 2 Input Enable bit->C2INC is on RA4 and C2IND is on RB4
#pragma config SMB3EN = SMBUS3 //SM Bus Enable->SMBus 3.0 input levels
#ifndef FCY
#define FCY 16000000UL
#endif
#include <xc.h>
#include <libpic30.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
static void CLK_Initialize(void);
static void PPS_Initialize(void);
static void PORT_Initialize(void);
static void SPI1_Initialize(void);
static void INTERRUPT_Initialize(void);
static uint8_t SPI1_exchangeByte(uint8_t data);
static void MSSP1_InterruptHandler(void);
volatile uint8_t sPI_receivedData = 0; /* Data that will be received on the spi bus of the slave */
volatile uint8_t writeData = 1; /* Data that will be transmitted (don't care) */
#define SPI_SS_TRIS TRISBbits.TRISB2
#define SPI_SS_PORT PORTBbits.RB2
#define lcdBackLight_RA2_SetHigh() (_LATA2 = 1)
#define lcdBackLight_RA2_SetLow() (_LATA2 = 0)
#define lcdBackLight_RA2_Toggle() (_LATA2 ^= 1)
#define status0_LED_SetHigh() (_LATB7 = 1)
#define status0_LED_SetLow() (_LATB7 = 0)
#define status0_LED_Toggle() (_LATB7 ^= 1)
#define lcd_FrontPanel_CSn_SetHigh() (_LATB2 = 1)
#define lcd_FrontPanel_CSn_SetLow() (_LATB2 = 0)
#define lcd_FrontPanel_CSn_Toggle() (_LATB2 ^= 1)
#define lcd_FrontPanel_CSn_GetValue() _RB2
#define spi1clk1_GetValue() _RB3
#define spi1SI_GetValue() _RB4
#define status0_SetHigh() (_LATB7 = 1)
#define status0_SetLow() (_LATB7 = 0)
#define status0_Toggle() (_LATB7 ^= 1)
static void CLK_Initialize(void)
{
// CPDIV 1:1; PLLEN disabled; DOZE 1:8; RCDIV FRC; DOZEN disabled; ROI disabled;
CLKDIV = 0x3000;
// STOR disabled; STORPOL Interrupt when STOR is 1; STSIDL disabled; STLPOL Interrupt when STLOCK is 1; STLOCK disabled; STSRC SOSC; STEN disabled; TUN Center frequency;
OSCTUN = 0x00;
// ROEN disabled; ROSWEN disabled; ROSEL FOSC; ROOUT disabled; ROSIDL disabled; ROSLP disabled;
REFOCONL = 0x00;
// RODIV 0;
REFOCONH = 0x00;
// DIV 0;
OSCDIV = 0x00;
// TRIM 0;
OSCFDIV = 0x00;
// AD1MD enabled; T3MD enabled; T1MD enabled; U2MD enabled; T2MD enabled; U1MD enabled; SPI2MD enabled; SPI1MD enabled; I2C1MD enabled;
PMD1 = 0x00;
// RTCCMD enabled; CMPMD enabled; CRCMD enabled; I2C2MD enabled;
PMD3 = 0x00;
// REFOMD enabled; HLVDMD enabled;
PMD4 = 0x00;
// CCP2MD enabled; CCP1MD enabled; CCP4MD enabled; CCP3MD enabled; CCP5MD enabled;
PMD5 = 0x00;
// DMA0MD enabled;
PMD7 = 0x00;
// DMTMD enabled; CLC3MD enabled; CLC4MD enabled; CLC1MD enabled; CLC2MD enabled;
PMD8 = 0x00;
// CF no clock failure; NOSC FRCPLL; SOSCEN disabled; POSCEN disabled; CLKLOCK unlocked; OSWEN Switch is Complete; IOLOCK not-active;
__builtin_write_OSCCONH((uint8_t) (0x01));
__builtin_write_OSCCONL((uint8_t) (0x01));
// Wait for Clock switch to occur
while (OSCCONbits.OSWEN != 0);
while (OSCCONbits.LOCK != 1);
}
static void PPS_Initialize(void)
{
__builtin_write_OSCCONL(OSCCON & 0xbf); // unlock PPS
//SPI1 PPS configuration
RPINR21bits.SS1R = 0x0002; //RB2->SPI1:SSn
RPINR20bits.SCK1R = 0x0003; //RB3->SPI1:SCK1IN
RPINR20bits.SDI1R = 0x0004; //RB4->SPI1:SDI1
RPOR2bits.RP5R = 0x0007; //RB5->SPI1:SDO1
__builtin_write_OSCCONL(OSCCON | 0x40); // lock PPS
}
static void PORT_Initialize(void)
{
TRISAbits.TRISA2 = 0x0000;//lcd backlight
TRISBbits.TRISB7 = 0x0000;//status0
TRISBbits.TRISB5 = 0x0000;//spi1_MISO
TRISBbits.TRISB4 = 0x0001;//spi1_MOSI
TRISBbits.TRISB3 = 0x0001;//spi1_SCK
TRISBbits.TRISB2 = 0x0001;//lcd_FrontPanel_CSn
/****************************************************************************
* Setting the Analog/Digital Configuration SFR(s)
***************************************************************************/
ANSA = 0x0000;//all digital IO
ANSB = 0x0000;
}
static void SPI1_Initialize(void)
{
IEC0bits.SPI1IE = 0; // disable spi1 interrupt
//config SPI1
SPI1CON1bits.SPIEN = 0; // disable SPI port
SPI1BUFL = 0; // clear SPI buffer Low bits
SPI1BUFH = 0; // clear SPI buffer High bits
SPI1CON1Lbits.ENHBUF = 0; // Clear the ENHBUF bit (SPIxCON1L[0]) if using Standard Buffer mode
IFS0bits.SPI1IF = 0; // clear interrupt flag
// SPI1: SPI 1
// Priority: 1
IPC2bits.SPI1IP = 1; // interrupt priority set to the highest
IEC0bits.SPI1IE = 1; // enable spi1 interrupt
SPI_SS_PORT = 1; //
SPI_SS_TRIS = 1; // set SS as input
IFS0bits.SPI1IF = 0; // clear interrupt flag
IEC0bits.SPI1IE = 1; // enable spi1 interrupt
SPI1STATLbits.SPIROV = 0; // Clear the SPIROV bit
//desired settings
//Write the desired settings to the SPI1CON1L register with MSTEN (SPI1CON1L[5]) = 0.
SPI1CON1bits.MSTEN = 0; // 1 = Master mode; 0 = Slave mode
SPI1CON1Lbits.SPISIDL = 0; // Continue module operation in Idle mode
SPI1CON1bits.DISSDO = 0; // SDOx pin is controlled by the module
SPI1CON1bits.MODE16 = 0; // set in 16-bit mode, clear in 8-bit mode
SPI1CON1bits.SMP = 0; // SMP must be cleared when SPIx is used in Slave mode
SPI1CON1bits.CKP = 1; // CKP and CKE is subject to change ...
SPI1CON1bits.CKE = 0; // ... based on your communication mode.
SPI1CON1bits.SSEN = 1; // SSx pin is used for Slave mode
SPI1CON1Lbits.ENHBUF = 0;
//SPI1CON2 = 0; // non-framed mode
SPI1CON1bits.SPIEN = 1; // enable SPI port, clear status
}
static void INTERRUPT_Initialize(void)
{
INTCON2bits.GIE = 1; /* Enable Global Interrupts */
}
uint32_t gCounter;
int main(void)
{
CLK_Initialize();
PPS_Initialize();
PORT_Initialize();
SPI1_Initialize();
INTERRUPT_Initialize();
gCounter = 0;
status0_LED_SetHigh();
while(1)
{
//just to watch CSn signal coming once per second on the spi slave bus
if(!lcd_FrontPanel_CSn_GetValue())//!cs_1 && clk_1)
{
status0_Toggle();
lcdBackLight_RA2_SetHigh();
gCounter++;
__delay_ms(100);
}
else //if(!cs_1)
{
lcdBackLight_RA2_SetLow();
}
if(sPI_receivedData > 1)
status0_Toggle();
}
}
static uint8_t SPI1_exchangeByte(uint8_t data)
{
SPI1BUFL = data;
while(!IFS0bits.SPI1IF) /* Wait until data is exchanged */
{
;
}
IFS0bits.SPI1IF = 0;
return SPI1BUFL;
}
static void MSSP1_InterruptHandler(void)
{
sPI_receivedData = SPI1_exchangeByte(writeData);
}
//spi1 interrupt never fired. Why? ...SPI1 pins are receiving the data and the clk once per second but interrupt will not fire... Why?
void __attribute__((__interrupt__,__auto_psv__)) _SPI1Interrupt(void)//void __attribute__ (( interrupt, no_auto_psv )) _SPI1Interrupt ( void ) //void __interrupt() INTERRUPT_InterruptManager(void)
{
if(IEC0bits.SPI1IE == 1 && IFS0bits.SPI1IF == 1)
{
MSSP1_InterruptHandler();
}
}
Did not find why the spi slave configuration doesnt work with the PIC24FJ64GP202. We did try a development board Explorer 16 with a PIC24FJ128GA010 and the SPI slave works perfectly with the same above code (except the pinout).
... Still dont know why the PIC24FJ64GP202 gives this issue...
So,
To save the hardware we have for our product, it was possible to switch and use the spi CS pin as an Rx UART instead. The uart works perfectly for our requirements... We were lucky to have that pin configurable in UART on both the ATSAMD51N19 in TX and the PIC24F64GP202 in RX.
I familiarising myself with MPLAB X IDE and staring development with C using a Microchip PIC 12F617.
I have a simple program (copied from elsewhere) to flash a LED: on for 1 second then off for 1 second. It all works but I my calculation of the delay does not match 1 second. Anybody able to tell me where I am going wrong?
Internal osc is selected # 8 MHz
clock to TMR2 is FOSC / 4 is 2 MHz
PR2 default to 255 so interrupt at 2 MHz / 255 is 7843 Hz
TMR2 prescale = 1; postscale set to 16; is 490 Hz
Loop counts 675 is 0.726 Hz so LED should be on/off for 1.38 seconds, yet it isn't
Taking into account time for executing instructions the led on/off should be even longer.
what am I missing?
/*
* File: main.c
* Author: user2439830
* Target: PIC12F617
* Compiler: XC8 v2.05
*
* PIC12F617
* +------v------+
* 5v0 ->:1 VDD VSS 8:<- GND
* <>:2 GP5 GP0 7:<> PGD
* <>:3 GP4 GP1 6:<> PGC
* VPP ->:4 GP3 GP2 5:<>
* +-------------+
* DIP-8
*
* Created on May 20, 2020, 5:51 PM
*/
#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA4/AN3/T1G/OSC2/CLKOUT, I/O function on RA5/T1CKI/OSC1/CLKIN)
#pragma config WDTE = ON // Watchdog Timer Enable bit (WDT enabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select bit (MCLR pin is MCLR function and weak internal pull-up is enabled)
#pragma config CP = OFF // Code Protection bit (Program memory is not code protected)
#pragma config IOSCFS = 8MHZ // Internal Oscillator Frequency Select (8 MHz)
#pragma config BOREN = ON // Brown-out Reset Selection bits (BOR enabled)
#pragma config WRT = OFF // Flash Program Memory Self Write Enable bits (Write protection off)
#include <xc.h>
void t2delay( void );
void main(void)
{
// Note: TRISIO = TRISA; IO direction register
TRISIO = 0; // 0 set corresponding pin in GPIO to output
// 76543210
T2CON = 0b01111000; // postscale=16, prescale=1, timer off
T2CON |= ( 1 << 2 ); //timer2 on TMR2ON set to 1
while (1)
{
// Note: GPIO = PORTA
GPIO = 255;
t2delay();
GPIO = 0;
t2delay();
}
return;
}
// TMR2IF set to when when TMR2 == PR2 (set to 255 on reset)
void t2delay( void )
{
unsigned int i;
for( i = 0; i < 675; i++)
{
while( !TMR2IF );
TMR2IF = 0;
}
}
Your main bug is the watchdog timer is on and your code does not reset it.
I have a real stumper I've been stuck on for a while. I am programming a PIC16F15376 microcontroller Xpress board in C.
I initialize a volatile variable called buttonIntention to 0. When the interrupt service routine occurs, buttonSet(1) is called, effectively setting buttonIntention = 1. [Note: I have also tried just toggling the buttonIntention variable directly, with no get or set functions.] In main(), the while(1) that is constantly polling checks whether the ISR has gone off (which would set buttonIntention = 1) and if the ISR did, the TESTPIN is set high where I can view it on my o-scope.
I have determined that when I pressed a button, the ISR does indeed fire. buttonIntention is then set to 1 within the ISR, because the commented out code at the end of the ISR I tried works fine.
However, my if(buttonIntention) in my while(1) in main() never actually sees buttonIntention set to 1. I thought having this variable as volatile would fix this issue because it is shared between the ISR and main(), and I thought using a uint8_t type on my 8-bit microcontroller would fix any "atomic" issues I have read about but don't really understand... but, there's still something wrong that the if statement never sees a 1.
Any ideas?
Here is my code:
// CONFIG1
#pragma config FEXTOSC = OFF // External Oscillator mode selection bits->Oscillator not enabled
#pragma config RSTOSC = HFINT32 // Power-up default value for COSC bits->HFINTOSC with OSCFRQ= 32 MHz and CDIV = 1:1
#pragma config CLKOUTEN = OFF // Clock Out Enable bit->CLKOUT function is disabled; i/o or oscillator function on OSC2
#pragma config CSWEN = ON // Clock Switch Enable bit->Writing to NOSC and NDIV is allowed
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable bit->FSCM timer enabled
// CONFIG2
#pragma config MCLRE = ON // Master Clear Enable bit->MCLR pin is Master Clear function
#pragma config PWRTE = OFF // Power-up Timer Enable bit->PWRT disabled
#pragma config LPBOREN = OFF // Low-Power BOR enable bit->ULPBOR disabled
#pragma config BOREN = ON // Brown-out reset enable bits->Brown-out Reset Enabled, SBOREN bit is ignored
#pragma config BORV = LO // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices
#pragma config ZCD = ON // Zero-cross detect disable->Zero-cross detect circuit is disabled at POR.
#pragma config PPS1WAY = ON // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset
// CONFIG3
#pragma config WDTCPS = WDTCPS_31 // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS
#pragma config WDTE = OFF // WDT operating mode->WDT Disabled, SWDTEN is ignored
#pragma config WDTCWS = WDTCWS_7 // WDT Window Select bits->window always open (100%); software control; keyed access not required
#pragma config WDTCCS = SC // WDT input clock selector->Software Control
// CONFIG4
#pragma config WRTC = OFF // UserNVM self-write protection bits->Write protection off
//#pragma config SCANE = available // Scanner Enable bit->Scanner module is available for use
#pragma config LVP = ON // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.
// CONFIG5
#pragma config CP = OFF // UserNVM Program memory code protection bit->UserNVM code protection disabled
//#pragma config CPD = OFF // DataNVM code protection bit->DataNVM code protection disabled
// ==========================================================================
// Import Header Files
// ==========================================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xc.h>
#include <math.h>
// ==========================================================================
// Define statements
// ==========================================================================
// Inputs from buttons
#define startButton PORTCbits.RC4
#define profileButton PORTCbits.RC5
#define incrementButton PORTCbits.RC6
#define decrementButton PORTCbits.RC7
#define TESTPIN LATCbits.LATC0
// ==========================================================================
// Global Variables
// ==========================================================================
// ISR Toggle Variables (MUST be declared volatile)
volatile uint8_t buttonIntention = 0;
// ==========================================================================
// General Configuration
// ==========================================================================
// --- --- --- --- --- --- ---
// Configure Inputs and Outputs
// --- --- --- --- --- --- ---
void config_IO(void) {
// --- Set output for 5 gate drivers and LCD rs and en: ---
TRISA = 0; // Set all Port A I/O to output
LATA = 0; // Set all Port A outputs to LOW/0
ANSELA = 0; // Turn Port A analog off (Digital only)
// --- Set output for LCD data: ---
TRISB = 0; // Set all Port B I/O to output
LATB = 0; // Set all Port B outputs to LOW/0
ANSELB = 0; // Turn Port B analog off (Digital only)
// --- Set input from buttons: ---
//TRISC = 0b11111000; // Set Port C 3-7 to input for the buttons
TRISC = 0xF8; // Set Port C 3-7 to input for the buttons
LATC = 0; // Set all Port C outputs LOW
ANSELC = 0; // Turn Port C analog off (Digital only)
}
// --- --- --- --- --- --- ---
// Configure Change Notification for Button Interrupts
// --- --- --- --- --- --- ---
void config_CN(void){
//Clear Interrupt flag
IOCIF = 0;
// Clear all of Port C 0-7 interrupt flags
IOCCF = 0x00;
// Enable interrupts on Positive Edge of the buttons RC3-RC7
IOCCP3 = 1;
IOCCP4 = 1;
IOCCP5 = 1;
IOCCP6 = 1;
IOCCP7 = 1;
IOCIE = 1; //Enable Interrupt
}
// --- --- --- --- --- --- ---
// Configure the oscillator:
// --- --- --- --- --- --- ---
void config_OSC (void) {
// Clear registers
OSCCON1 = 0x00;
OSCCON2 = 0x00;
OSCCON3 = 0x00;
// OSCCON1:
// Use High Freq. Internal Oscillator (HFINTOSC # 1 - 32 MHz)
//OSCCON1bits.NOSC = 0b110;
OSCCON1bits.NOSC = 0x6;
// OSCFRQ:
// Configure HFINTOSC to 32 MHz
// OSCFRQbits.HFFRQ = 0b110;
OSCFRQbits.HFFRQ = 0x6;
// Divide clock by 1
//OSCCON1bits.NDIV = 0b0000;
OSCCON1bits.NDIV = 0x0;
}
// ==========================================================================
// Button Function
// ==========================================================================
void buttonSet(uint8_t setter){
buttonIntention = setter;
}
uint8_t buttonGet(void){
return buttonIntention;
}
// ==========================================================================
// Interrupt service routine
// ==========================================================================
void __interrupt() isr(void)
{
// If button is pressed...
if(IOCIF == 1 && buttonIntention == 0) {
//buttonIntention = 1; // Change state to indicate that button was somehow pressed intentionally or unintentionally
//OR
buttonSet(1);
IOCIF = 0; //Clear Interrupt flag
}
//if(buttonIntention){
//TESTPIN = 1;
//}
}
// ==========================================================================
// Main function
// ==========================================================================
int main(void) {
WDTCON0bits.SWDTEN = 0x0; // Ensure Watchdog Timer is totally disabled
// Register 10-1 INTCON
INTCONbits.PEIE = 1; // Enable peripheral interrupt
INTCONbits.GIE = 1; // Enable global interrupt
// --- Call configuration functions: ---
config_IO();
config_OSC();
config_CN();
// --- Loop forever: ---
while (1) {
if(buttonGet()){
TESTPIN = 1;
}
}
return 0;
}
I don't know this MCU but allow me two shoots in the dark.
It sounds to me strange that you can turn off the W/D with a simple assignment instruction WDTCON0bits.SWDTEN = 0;. Maybe the watchdog resets your MCU.
In spec of PIC16F15376 I read on page 155:
The IOCIF bit is the logical OR of all the IOCAF-IOCEF flags.
Therefore, to clear the IOCIF flag, application firmware must clear
all of the lower level IOCAF-IOCEF register bits.
I think a simple IOCIF=0 won't work as expected.
I made a programm with a PIC18F4431 on MPLABX with XC8. It sends PWM according the value which it receives on the UART (it is DMX, 250000kbits/s). This programm works, it runs with an external clock (quartz of 10MHz).
Configuration bits :
// CONFIG1H
#pragma config OSC = HSPLL // Oscillator Selection bits (HS oscillator, PLL enabled (clock frequency = 4 x FOSC1))
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal External Oscillator Switchover bit (Internal External Switchover mode disabled)
UART configuration :
void Config_UART1 (void)
{
BAUDCTLbits.BRG16 = 0; // Générateur 8 bits
SPBRG = 9; // Vitesse de transmission 250kbits/seconde
TXSTAbits.BRGH = 1; //Haute vitesse
TXSTAbits.SYNC = 0; // Asynchronous mode
RCSTAbits.SPEN = 1; // Serial port enabled
RCSTAbits.RX9 = 1; //Selects 9-bit reception
RCSTAbits.CREN = 1; // Enables receiver
}
To improve my programm, I want to work with the internal clock (8MHz). I change my configuration bits and my UART configuration ; my programm doesn't work : do you know why?
Configuration bits :
// CONFIG1H
#pragma config OSC = IRC // Oscillator Selection bits (Internal oscillator block, CLKO function on RA6 and port function on RA7)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal External Oscillator Switchover bit (Internal External Switchover mode disabled)
Oscillator configuration :
void Config_Oscill (void)
{
OSCCONbits.IDLEN = 0b0; // Run mode enabled; CPU core is clocked in power-managed modes
OSCCONbits.IRCF = 0x7; // 8 MHz (8 MHz source drives clock directly)
OSCCONbits.SCS = 0x02; // Internal oscillator block (RC modes)
}
UART configuration :
void Config_UART1 (void)
{
BAUDCTLbits.BRG16 = 0; // Générateur 8 bits
SPBRG = 1; // Vitesse de transmission 250kbits/seconde
TXSTAbits.BRGH = 1; //Haute vitesse
TXSTAbits.SYNC = 0; // Asynchronous mode
RCSTAbits.SPEN = 1; // Serial port enabled
RCSTAbits.RX9 = 1; //Selects 9-bit reception
RCSTAbits.CREN = 1; // Enables receiver
}
I want to connect two PIC18F starter kits (with PIC18F46J50), using RS232. Since USART1 is already connected to the card reader (integrated), I need to use USART2 (I need to remap RX2/TX2 to RP19/RP20 pins-RD2/RD3).
I already found some demo code for SENDING:
#define _XTAL_FREQ 8000000 //The speed of your internal(or)external oscillator
#include <p18cxxx.h>
#include <usart.h>
int i = 0;
// CONFIG1L
#pragma config WDTEN = OFF // Watchdog Timer (Disabled - Controlled by SWDTEN bit)
#pragma config PLLDIV =3 // PLL Prescaler Selection bits - Divide by 3 (12 MHz oscillator input)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset (Enabled)
#pragma config XINST = OFF // Extended instruction set disabled
// CONFIG1H
#pragma config CPUDIV = OSC1 // CPU System Clock Postscaler (No CPU system clock divide)
#pragma config CP0 = OFF // Code Protect (Program memory is not code-protected)
// CONFIG2L
#pragma config OSC = HSPLL //HS oscillator, PLL enabled, HSPLL used by USB
#pragma config T1DIG = ON // T1OSCEN Enforcement (Secondary Oscillator clock source may be selected)
#pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator (High-power operation)
#pragma config FCMEN = OFF //Fail-Safe Clock Monitor disabled
#pragma config IESO = OFF //Two-Speed Start-up disabled
// CONFIG2H
#pragma config WDTPS = 32768 // Watchdog Postscaler (1:32768)
// CONFIG3L
#pragma config DSWDTOSC = INTOSCREF // DSWDT Clock Select (DSWDT uses INTRC)
#pragma config RTCOSC = T1OSCREF // RTCC Clock Select (RTCC uses T1OSC/T1CKI)
#pragma config DSBOREN = OFF // Zero-Power BOR disabled in Deep Sleep
#pragma config DSWDTEN = OFF // Deep Sleep Watchdog Timer (Disabled)
#pragma config DSWDTPS = 8192 //1:8,192 (8.5 seconds)
// CONFIG3H
#pragma config IOL1WAY =OFF //IOLOCK bit can be set and cleared
#pragma config MSSP7B_EN = MSK7 // MSSP address masking (7 Bit address masking mode)
// CONFIG4L
#pragma config WPFP = PAGE_1 // Write/Erase Protect Page Start/End Location (Write Protect Program Flash Page 0)
#pragma config WPEND = PAGE_0 //Start protection at page 0
#pragma config WPCFG = OFF //Write/Erase last page protect Disabled
// CONFIG4H
#pragma config WPDIS = OFF //WPFP[5:0], WPEND, and WPCFG bits ignored
#define USE_AND_MASKS
unsigned char Txdata[] = "MICROCHIP_USART";
void Delay1Second(void);
void main (void)
{
unsigned char spbrg=0,baudconfig=0,i=0;
// REMAPE ID PORT
PPSCON = 0x00; // unlock peripheral Pin select register
RPOR19 = 0x05; // assign USART2 TX to RP19/RD2
RPINR16 = 0x14; // assign USART2 RX to RP20/RD3
PPSCON = 0x01; // lock peripheral Pin select register
TRISDbits.TRISD2 = 0; // TX2 output
TRISDbits.TRISD3 = 1; // RX2 input
//------USART Setup ----
Close2USART(); //turn off usart if was previously on
spbrg = 51;
Open2USART(USART_TX_INT_OFF &
USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_HIGH, spbrg);
baudconfig = BAUD_8_BIT_RATE & BAUD_AUTO_OFF;
baud2USART (baudconfig);
PORTB = 0x03;
while(1){
//------USART Transmission ----
while(Busy2USART()); //Check if Usart is busy or not
puts2USART((char *)Txdata); //transmit the string
Delay1Second();
Close2USART();
}
}
void Delay1Second()
{
for(i=0;i<100;i++)
{
__delay_ms(10);
}
}
I connected the two boards using two wires (on D2 and D3 pins), and I want to send a string from board1 to board2. I think I need to use interrupts to read, but I haven't found any demo code. Also, I don't know if the configuration pins are ok.
Can somebody show me how to receive the sent text to board no.2?
I will assume that you did the wiring correctly.
You don't need interrupts to receive. It can be useful but it's not required. To receive your string, you just have to do :
gets2USART( str, 10 );
If your string if 10 characters long (including the null terminator).
If you want to receive a string of an arbitrary length, you may write your own gets2USART to read until the null terminator. It is actually quite simple, here is the source code of gets2USART to help you :
void gets2USART(char *buffer, unsigned char len)
{
char i; // Length counter
unsigned char data;
for(i=0;i<len;i++) // Only retrieve len characters
{
while(!DataRdy2USART());// Wait for data to be received
data = getc2USART(); // Get a character from the USART
// and save in the string
*buffer = data;
buffer++; // Increment the string pointer
}
}
Also, here is the source code of puts2USART :
void puts2USART( char *data)
{
do
{ // Transmit a byte
while(Busy2USART());
putc2USART(*data);
} while( *data++ );
}
You can see that there already is a while(Busy2USART());, so you don't need to add one. It is logical, because the UART is byte wise, so it is busy when it sends a byte, and the function needs to check for every byte.
Also, you are closing the UART after use, but actually loop to redo the sending. Since you just closed the UART, that won't work.