Sleep mode(PIC 18f46j50) with internal oscilator - c

I am programming my PIC and i am trying to put it in the deep sleep mode.
I want use Deep Sleep function and the wake up event should be created by WDT interupt. But my problem is, that it is impossible to reach the interrupt. Device will continue sleeping.
#include <xc.h>
// 'C' source line config statements
// CONFIG1L
#pragma config WDTEN = ON // Watchdog Timer (Enabled)
#pragma config PLLDIV = 1 // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
#pragma config STVREN = ON // Stack Overflow/Underflow Reset (Enabled)
#pragma config XINST = OFF // Extended Instruction Set (Enabled)
// 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 = HS // Oscillator (HS, USB-HS)
#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 = ON // Fail-Safe Clock Monitor (Enabled)
#pragma config IESO = ON // Internal External Oscillator Switch Over Mode (Enabled)
// CONFIG2H
#pragma config WDTPS = 32768 // Watchdog Postscaler (1:32768)
// CONFIG3L
#pragma config DSWDTOSC = INTOSCREF// DSWDT Clock Select (DSWDT uses INTRC)
#pragma config RTCOSC = INTOSCREF// RTCC Clock Select (RTCC uses INTRC)
#pragma config DSBOREN = ON // Deep Sleep BOR (Enabled)
#pragma config DSWDTEN = ON // Deep Sleep Watchdog Timer (Enabled)
#pragma config DSWDTPS = 8192 // Deep Sleep Watchdog Postscaler (1:8,192 (8.5 seconds))
// CONFIG3H
#pragma config IOL1WAY = ON // IOLOCK One-Way Set Enable bit (The IOLOCK bit (PPSCON<0>) can be set once)
#pragma config MSSP7B_EN = MSK7 // MSSP address masking (7 Bit address masking mode)
// CONFIG4L
#pragma config WPFP = PAGE_63 // Write/Erase Protect Page Start/End Location (Write Protect Program Flash Page 63)
#pragma config WPEND = PAGE_WPFP// Write/Erase Protect Region Select (valid when WPDIS = 0) (Page WPFP<5:0> through Configuration Words erase/write protected)
#pragma config WPCFG = OFF // Write/Erase Protect Configuration Region (Configuration Words page not erase/write-protected)
// CONFIG4H
#pragma config WPDIS = OFF // Write Protect Disable bit (WPFP<5:0>/WPEND region ignored)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
void sleep_f()
{
//INTCON &= ~0xF8; /* Disable all interrupt sources */
//INTCON3 &= ~0x38;
PIR2bits.OSCFIF = 1;
//RCONbits.IPEN = 0;
// OSCCON = 0b01110000;
OSCCONbits.IDLEN = 0 ; // 0 Sleep mode a 1 idle mod
//WDTCONbits.SWDTEN = 1; /* Enable the regular Watch Dog Time out too */
WDTCONbits.REGSLP = 0;
//DSCONLbits.DSBOR = 1;
//DSCONHbits.RTCWDIS = 0;
DSCONHbits.DSEN = 0; // We run deep slep
Sleep();
}
void main()
{
TRISD6 = 0;
TRISDbits.TRISD4 = 0;
LATD6 = 1;
int i;
while (1){
LATD4 = 0;
int i;
for (i = 0;i < 10000; i++) asm("nop");
LATD4 = 1; // Blink led if everything is OK.
sleep_f();
DSCONLbits.RELEASE = 0;
WDTCONbits.DS = 0;
for (i = 0;i < 30000; i++) asm("nop");
}
}
Do you have any idea what is wrong with my code ?
I am stacked on it already for 3 days.
I would be grateful for any help.

I'm not sure if you realize that the DSWDT period is set to 8192 and the normal WDT to 32768, which means it takes 8.5 seconds and 2.25 minutes to trigger according to the datasheet. I'd set it to a few seconds instead for debugging. When you're sure it's working increase the WDT to the desired period.
Maybe the delay loops are too short to notice any blinking? Does the led blink without the sleep function?
This line doesn't do anything as this bit is read only.
WDTCONbits.DS = 0;
This line
DSCONHbits.DSEN = 0; // We run deep slep
Should be
DSCONHbits.DSEN = 1; // We run deep sleep
The datasheet states that 1 is deep sleep, 0 is sleep. When your device enters normal sleep, the WDT triggers in 2.25 minutes (post scaler of 32768) instead of the DSWDT 8.5 seconds (DSWDT postscaler of 8192).

Related

Measuring and displaying frequency of 10Hz-20kHz square wave using pic16F15243 with precision

I am trying to measure the frequency of a squared signal (10Hz-20kHz), using pic16F15243 and displaying the value in Hz.
The problem is that I cant get accurate measurements the higher the frequency goes (20kHz I get 25kHz).
The code is below:
// CONFIG1
#pragma config FEXTOSC = OFF // External Oscillator Mode Selection bits (Oscillator not enabled)
#pragma config RSTOSC = HFINTOSC_1MHZ// Power-up Default Value for COSC bits (HFINTOSC (1 MHz))
#pragma config CLKOUTEN = OFF // Clock Out Enable bit (CLKOUT function is disabled; I/O function on RA4)
#pragma config VDDAR = HI // VDD Range Analog Calibration Selection bit (Internal analog systems are calibrated for operation between VDD = 2.3V - 5.5V)
// CONFIG2
#pragma config MCLRE = EXTMCLR // Master Clear Enable bit (If LVP = 0, MCLR pin is MCLR; If LVP = 1, RA3 pin function is MCLR)
#pragma config PWRTS = PWRT_OFF // Power-up Timer Selection bits (PWRT is disabled)
#pragma config WDTE = OFF // WDT Operating Mode bits (WDT disabled; SEN is ignored)
#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled)
#pragma config BORV = LO // Brown-out Reset Voltage Selection bit (Brown-out Reset Voltage (VBOR) set to 1.9V)
#pragma config PPS1WAY = OFF // PPSLOCKED One-Way Set Enable bit (The PPSLOCKED bit can be set and cleared as needed (unlocking sequence is required))
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a reset)
// CONFIG3
// CONFIG4
#pragma config BBSIZE = BB512 // Boot Block Size Selection bits (512 words boot block size)
#pragma config BBEN = OFF // Boot Block Enable bit (Boot Block is disabled)
#pragma config SAFEN = OFF // SAF Enable bit (SAF is disabled)
#pragma config WRTAPP = OFF // Application Block Write Protection bit (Application Block is not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block is not write-protected)
#pragma config WRTC = OFF // Configuration Registers Write Protection bit (Configuration Registers are not write-protected)
#pragma config WRTSAF = OFF // Storage Area Flash (SAF) Write Protection bit (SAF is not write-protected)
#pragma config LVP = OFF // Low Voltage Programming Enable bit (High Voltage on MCLR/Vpp must be used for programming)
// CONFIG5
#pragma config CP = OFF // User Program Flash Memory Code Protection bit (User Program Flash Memory code protection is disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <stdio.h>
#define _XTAL_FREQ 32000000
unsigned long value;
void osc_init()
{
OSCENbits.HFOEN = 1; // USE INTERNAL CLOCK
OSCFRQbits.FRQ = 0b101; // 32 MHZ CLOCK
}
void pin_master()
{
TRISAbits.TRISA2 = 1; // RA5 IS INPUT
ANSELAbits.ANSA2 = 0; // RA5 IS digital INPUT
TRISBbits.TRISB7 = 0; // RB7 IS OUTPUT (TX UART)
TRISBbits.TRISB6 = 0;
RB7PPS = 0x05; // RB7 IS MAPPED AS EUSART1 TX1
}
void uart_init()
{
// CONFIGURE BAUD RATE, ENABLE EUART UNIT, ENABLE TRANSMISSION
// CONFIGURE THE DIVIDER AS 4:
SYNC=0;
BRG16=1;
BRGH=1;
// FINETUNE THE MULTIPLIER
SP1BRG = 9;
// CONFIGURE THE EUART CONTROLS
RC1STAbits.CREN = 0; // DISABLE RX
TX1STAbits.TXEN = 1; // ENABLE TX
RC1STAbits.SPEN = 1; // ENABLE EUART UNIT
}
void putch(char data)
{
while( ! TX1IF)
continue;
TX1REG = data;
}
__interrupt() INTERRUPT_Interrupt_Manager (void){
value=(TMR0H<<8)|(TMR0L);
TMR0H=0;
TMR0L=0;
INTF=0;
}
teim_init() {
TMR0IF=0;
TMR0IE=1;
T0CON1 = 0b01000110; //0b01000011
T0CON0 = 0b10010001; //
}
inter_init(){
INTE=1;
INTF=0;
GIE=1;
INTEDG=1;
}
void main(void) {
osc_init();
pin_master();
uart_init();
teim_init();
inter_init();
TMR0H=0;
TMR0L=0;
while(1)
{
value=8*value;
value=1000000/value;
printf("Frequency = %lu\n",value);
__delay_ms(1000);
}
return;
}
I have tried different baud rates with different clock speeds and this was the closest I got.
Any hints on how I can get readings with acceptable accuracy would be appreciated.
You are capturing the number of clock counts between input pulses, and that is necessarily an integer value. At high frequencies the resolution will be very low. The difference between 5 and 6 counts being around 5KHz in this case.
If you wanted say 1% precision at the highest frequency you wanted to measure you would need a clock frequency of fmax x 100, and 1% precision is still pretty poor - you would need very fast clocks to get good precision and given that it is only a 16 bit timer it would limit your lower frequency limit.
A better method for high frequencies is to count the number of pulses over a fixed period of time - then the resolution is determined by the measurement period rather than the timer clock rate. The disadvantage then of course is poor resolution at low frequencies.
A solution that would work for high and low frequencies is to count pulses until the timer count is greater than say 32767 (half full scale - somewhat arbitrarily, but clearly avoiding overflow, and providing a fair degree of precision). Then:
frequency = 125000 x pulse_count / TMR0_COUNT
So for example for 20KHz, TMR0 whould reach 32768 after 5243 pulses; 125000 x 32768 / 5243 = 20000 Hz.
At the lower frequency of 10Hz, the counter will reach 50000 after 4 pulses (so well within the 16-bit range of TMR0), and 125000 * 4 / 50000 = 10Hz.
So here instead of resetting the counter to zero on the input interrupt, you would increment the pulse count then if the counter value is greater than 32767 (or whatever you choose as sufficient precision), you would capture both its value and the pulse count and then reset both to zero.
Something like (illustrative - I have not tested or even compiled this):
static volatile uint32_t timer_counts = 0 ;
static volatile uint32_t pulse_counts = 0 ;
__interrupt() INTERRUPT_Interrupt_Manager (void)
{
static pulse_count = 0 ;
pulse_count++ ;
int tmr_count = (TMR0H<<8)|(TMR0L) ;
if( tmr_count > 0x7FFFu )
{
timer_counts = tmr_count ;
pulse_counts = pulse_count ;
pulse_count = 0 ;
TMR0H=0;
TMR0L=0;
}
INTF=0;
}
Then in main():
for(;;)
{
// Capture timer and pulse counts atomically
INTE = 0 ;
uint32_t tcount = timer_counts ;
uint32_t pcount = pulse_counts ;
INTE = 1 ;
uint32_t f = 125000u * tcount / pcount ;
printf( "Frequency = %lu\n", f ) ;
__delay_ms(1000);
}
There are issues with your code such as the non-atomic access of value and the fact that it was not declared volatile. The above code addresses those issues.
I think your problem is the integer math:
value=8*value;
value=1000000/value;
This is effectively doing
value = 125000/value;
If value is 5 you get 25000; if value is 6 you get 20833. The error in this computation is very large for small values of value.
To reduce this error you need to accumulate pulses for a longer period of time.

SPI Slave using PIC24FJ64GP202

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.

PIC32MK1024MCM064 gets stuck in timer2 ISR

I am beginner exploring PIC32MK1024MCM064 timers. Just want to write simple code with self triggering timer and some main program in the background. So I achieved my code to get into the ISR part, but the code gets stuck in the ISR after first time interrupt event. The code does not come back to the main loop with blinking leds. I investigated the datasheet quite well, but besides clearing the interrupt flag, I don`t know what to do else. I really thank you in advance for any help provided
// DEVCFG3
#pragma config USERID = 0xFFFF // Enter Hexadecimal value (Enter Hexadecimal value)
#pragma config PWMLOCK = OFF // PWM IOxCON lock (PWM IOxCON register writes accesses are not locked or protected)
#pragma config FUSBIDIO2 = ON // USB2 USBID Selection (USBID pin is controlled by the USB2 module)
#pragma config FVBUSIO2 = ON // USB2 VBUSON Selection bit (VBUSON pin is controlled by the USB2 module)
#pragma config PGL1WAY = OFF // Permission Group Lock One Way Configuration bit (Allow multiple reconfigurations)
#pragma config PMDL1WAY = OFF // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = OFF // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
#pragma config FUSBIDIO1 = ON // USB1 USBID Selection (USBID pin is controlled by the USB1 module)
#pragma config FVBUSIO1 = ON // USB2 VBUSON Selection bit (VBUSON pin is controlled by the USB1 module)
// DEVCFG2
#pragma config FPLLIDIV = DIV_1 // System PLL Input Divider (1x Divider)
#pragma config FPLLRNG = RANGE_BYPASS // System PLL Input Range (Bypass)
#pragma config FPLLICLK = PLL_FRC // System PLL Input Clock Selection (FRC is input to the System PLL)
#pragma config FPLLMULT = MUL_2 // System PLL Multiplier (PLL Multiply by 1)
#pragma config FPLLODIV = DIV_2 // System PLL Output Clock Divider (2x Divider)
#pragma config BORSEL = HIGH // Brown-out trip voltage (BOR trip voltage 2.1v (Non-OPAMP deviced operation))
#pragma config UPLLEN = OFF // USB PLL Enable (USB PLL Disabled)
// DEVCFG1
#pragma config FNOSC = FRC // Oscillator Selection Bits (Internal Fast RC (FRC))
#pragma config DMTINTV = WIN_0 // DMT Count Window Interval (Window/Interval value is zero)
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Disable Secondary Oscillator)
#pragma config IESO = OFF // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = OFF // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disabled, FSCM Disabled)
#pragma config WDTPS = PS1 // Watchdog Timer Postscaler (1:1)
#pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
#pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled)
#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%)
#pragma config DMTCNT = DMT31 // Deadman Timer Count Selection (2^31 (2147483648))
#pragma config FDMTEN = OFF // Deadman Timer Enable (Deadman Timer is disabled)
// DEVCFG0
#pragma config DEBUG = OFF // Background Debugger Enable (Debugger is disabled)
#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx3 // ICE/ICD Comm Channel Select (Communicate on PGEC3/PGED3)
#pragma config TRCEN = OFF // Trace Enable (Trace features in the CPU are disabled)
#pragma config BOOTISA = MIPS32 // Boot ISA Selection (Boot code and Exception code is MIPS32)
#pragma config FECCCON = ECC_DECC_DISABLE_ECCON_WRITABLE// Dynamic Flash ECC Configuration Bits (ECC and Dynamic ECC are disabled (ECCCON<1:0> bits are writable))
#pragma config FSLEEP = OFF // Flash Sleep Mode (Flash is powered down when the device is in Sleep mode)
#pragma config DBGPER = PG_ALL // Debug Mode CPU Access Permission (Allow CPU access to all permission regions)
#pragma config SMCLR = MCLR_NORM // Soft Master Clear Enable (MCLR pin generates a normal system Reset)
#pragma config SOSCGAIN = G3 // Secondary Oscillator Gain Control bits (Gain is G3)
#pragma config SOSCBOOST = ON // Secondary Oscillator Boost Kick Start Enable bit (Boost the kick start of the oscillator)
#pragma config POSCGAIN = G3 // Primary Oscillator Coarse Gain Control bits (Gain Level 3 (highest))
#pragma config POSCBOOST = ON // Primary Oscillator Boost Kick Start Enable bit (Boost the kick start of the oscillator)
#pragma config POSCFGAIN = G3 // Primary Oscillator Fine Gain Control bits (Gain is G3)
#pragma config POSCAGCDLY = AGCRNG_x_25ms// AGC Gain Search Step Settling Time Control (Settling time = 25ms x AGCRNG)
#pragma config POSCAGCRNG = ONE_X // AGC Lock Range bit (Range 1x)
#pragma config POSCAGC = Automatic // Primary Oscillator Gain Control bit (Automatic Gain Control for Oscillator)
#pragma config EJTAGBEN = NORMAL // EJTAG Boot Enable (Normal EJTAG functionality)
// DEVCP
#pragma config CP = OFF // Code Protect (Protection Disabled)
// SEQ
#pragma config TSEQ = 0x0 // Boot Flash True Sequence Number (Enter Hexadecimal value)
#pragma config CSEQ = 0xFFFF // Boot Flash Complement Sequence Number (Enter Hexadecimal value)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <xc.h>
#include <toolchain_specifics.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "stdio.h"
#include <sys/attribs.h>
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define CPU_CLOCK_FREQUENCY 8000000
#define _CP0_GET_COUNT() _mfc0 (_CP0_COUNT, _CP0_COUNT_SELECT)
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void delay_ms ( uint32_t delay_ms)
{
uint32_t startCount, endCount;
endCount=((CPU_CLOCK_FREQUENCY/1000)*delay_ms)/2;
startCount=_CP0_GET_COUNT();
while((_CP0_GET_COUNT()-startCount)<endCount);
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Timer2_setup(void){
PB2DIVbits.ON = 0b0; //PB2CLK is disabled
PB2DIVbits.PBDIVRDY = 0b1; //Enabling the PBDIV configuration
PB2DIVbits.PBDIV = 0b0000000; //PBCLKx is SYSCLK divided by 128
PB2DIVbits.PBDIVRDY = 0b0; //Disabling the PBDIV configuration
PB2DIVbits.ON = 0b1; //PB2CLK is enabled
//----------------------------------------------------
T2CONbits.ON = 0b0; //Timer2 is disabled
T2CONbits.TCS = 0b0; //Internal peripheral clock
T2CONbits.T32 = 0b1; //Timer2 is set to 32 bits
T2CONbits.TCKPS = 0b101; //1:256 prescale value
T2CONbits.SIDL = 0b1; //Timer2 does not work in idle mode
TMR2 = 0x0; //Clear counter
PR2 = 124999U; //Timer2 period is set to 1000 milliseconds
//----------------------------------------------------
//Interrupt setup
IEC0bits.T2IE = 0b1; //Enable timer interrupt
IPC2bits.T2IP = 0b001; //Interrupt priority set to 1
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int main ( void )
{
TRISAbits.TRISA7 = 0;
LATAbits.LATA7 = 0;
TRISBbits.TRISB14 = 0;
LATBbits.LATB14 = 0;
TRISBbits.TRISB15 = 0;
LATBbits.LATB15 = 0;
Timer2_setup();
__builtin_enable_interrupts(); // VERY IMPORTANT Built in macro function to globally enable interrupts
T2CONbits.ON = 0b1; //Timer2 is enabled
while (1)
{
LATBbits.LATB14 = 1;
delay_ms(300);
LATBbits.LATB14 = 0;
LATBbits.LATB15 = 1;
delay_ms(300);
LATBbits.LATB15 = 0;
}
return (EXIT_FAILURE);
}
//INTERRUPTS-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void __ISR( _TIMER_2_VECTOR, IPL1SRS) Timer2_Handler (void){
T2CONbits.ON = 0b0; //Timer2 is disabled
TMR2 = 0x0; //Clear counter
LATAbits.LATA7 = 1;
delay_ms(300); //Interrupt indicator
LATAbits.LATA7 = 0;
IFS0bits.T2IF = 0b0; //Clear input change interrupt
T2CONbits.ON = 0b1; //Timer2 is enabled
}
You most definitely shouldn't call delay_ms() in your interrupt handler. I'm fairly sure that this is the reason of your problem. IRQ handlers should be as quick as possible.
Check out https://www.aidanmocke.com/blog/2018/11/15/timers/. This whole blog is great for learning firmware development on PIC32.

Gated Timer on PIC18 sets TMR3IF flag to late & with Fosc/4 it doesn't set it anyway

I have already spent several nights debugging gated timer on PIC18F26K80. I use MPLAB v4.15 and XC8 v2.32. I want to run a long period timer, so I chose Timer 3 gated by Timer 4. I've read Microchip's documentation and tried to find answers anywhere, but I cannot understand:
Why it doesn't set TMR3IF flag (and doesn't fire appropriate interruption) using Fosc/4 as a clock source of Timer 3 (so I use Fosc with prescale 1:4 - it works, but... why Fosc/4 doesn't?)
Why TMR3IF flag fires in TMR3 state 0x0001? It should fire from 0xFFFF to 0x0000 and with PR4 = 0x63 there is no need to step over 0x0000 so fast.
So these 2 points are the most important points, there are some other miracles, but, if you could, help me with these.
/*
* Test file for Gated timer
*/
// PIC18F26K80 Configuration Bit Settings
// 'C' source line config statements
// CONFIG1L
#pragma config RETEN = OFF // VREG Sleep Enable bit (Ultra low-power regulator is Disabled (Controlled by REGSLP bit))
#pragma config INTOSCSEL = HIGH // LF-INTOSC Low-power Enable bit (LF-INTOSC in High-power mode during Sleep)
#pragma config SOSCSEL = DIG // SOSC Power Selection and mode Configuration bits (High Power SOSC circuit selected)
#pragma config XINST = OFF // Extended Instruction Set (Disabled)
// CONFIG1H
#pragma config FOSC = INTIO2 // Oscillator (Internal RC oscillator)
#pragma config PLLCFG = OFF // PLL x4 Enable bit (Disabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor (Disabled)
#pragma config IESO = OFF // Internal External Oscillator Switch Over Mode (Disabled)
// CONFIG2L
#pragma config PWRTEN = OFF // Power Up Timer (Disabled)
#pragma config BOREN = SBORDIS // Brown Out Detect (Enabled in hardware, SBOREN disabled)
#pragma config BORV = 3 // Brown-out Reset Voltage bits (1.8V)
#pragma config BORPWR = ZPBORMV // BORMV Power level (ZPBORMV instead of BORMV is selected)
// CONFIG2H
#pragma config WDTEN = SWDTDIS // Watchdog Timer (WDT enabled in hardware; SWDTEN bit disabled)
#pragma config WDTPS = 1048576 // Watchdog Postscaler (1:1048576)
// CONFIG3H
#pragma config CANMX = PORTB // ECAN Mux bit (ECAN TX and RX pins are located on RB2 and RB3, respectively)
#pragma config MSSPMSK = MSK7 // MSSP address masking (7 Bit address masking mode)
#pragma config MCLRE = ON // Master Clear Enable (MCLR Enabled, RE3 Disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Overflow Reset (Enabled)
#pragma config BBSIZ = BB2K // Boot Block Size (2K word Boot Block size)
// CONFIG5L
#pragma config CP0 = OFF // Code Protect 00800-03FFF (Disabled)
#pragma config CP1 = OFF // Code Protect 04000-07FFF (Disabled)
#pragma config CP2 = OFF // Code Protect 08000-0BFFF (Disabled)
#pragma config CP3 = OFF // Code Protect 0C000-0FFFF (Disabled)
// CONFIG5H
#pragma config CPB = OFF // Code Protect Boot (Disabled)
#pragma config CPD = OFF // Data EE Read Protect (Disabled)
// CONFIG6L
#pragma config WRT0 = OFF // Table Write Protect 00800-03FFF (Disabled)
#pragma config WRT1 = OFF // Table Write Protect 04000-07FFF (Disabled)
#pragma config WRT2 = OFF // Table Write Protect 08000-0BFFF (Disabled)
#pragma config WRT3 = OFF // Table Write Protect 0C000-0FFFF (Disabled)
// CONFIG6H
#pragma config WRTC = OFF // Config. Write Protect (Disabled)
#pragma config WRTB = OFF // Table Write Protect Boot (Disabled)
#pragma config WRTD = OFF // Data EE Write Protect (Disabled)
// CONFIG7L
#pragma config EBTR0 = OFF // Table Read Protect 00800-03FFF (Disabled)
#pragma config EBTR1 = OFF // Table Read Protect 04000-07FFF (Disabled)
#pragma config EBTR2 = OFF // Table Read Protect 08000-0BFFF (Disabled)
#pragma config EBTR3 = OFF // Table Read Protect 0C000-0FFFF (Disabled)
// CONFIG7H
#pragma config EBTRB = OFF // Table Read Protect Boot (Disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <stdint.h>
uint8_t tmr3Lprev = 0x00u;
void interrupt ISR(void){
if(TMR3IF){
if(TMR3L == 0x00u){ //after TMR3IF fires, TMR3L should be 0 (if PR4 is > cca 0x20)
asm("BTG LATA, 2, 0"); //toggles with an output
}else{
LATAbits.LATA6 = 1; // a failure flag
}
asm("BTG LATA, 1, 0"); //toggles with an output
TMR3IF = 0;
}
if(TMR4IF){
if(TMR3L == ++tmr3Lprev){ //TMR3L should increment on every T4 rollover
asm("BTG LATA, 0, 0"); //toggles with an output
}else{
LATAbits.LATA5 = 1; // a failure flag
}
TMR4IF = 0;
}
return;
}
void main(void) {
//Clock setting (clock for system and all modules)
OSCCONbits.IRCF = 0b111;
OSCTUNEbits.PLLEN = 1; //turn on 4x Phase Lock Loop = 64MHz Clock
//sets ports to output
TRISA = 0x00; //A vse prepnout na vystup
LATA = 0x00;
//Timer4 initialization
T4CONbits.T4OUTPS = 0; //postscale, I don't know why, but doesen't effect length of T4 rollover
T4CONbits.T4CKPS1 = 1; //I dont know why, but T4CKPS = 0x11 doesnt set T4CKPS1
PR4 = 0x63; //loop periode
T4CONbits.TMR4ON = 1; //1 = Timer 4 Enabled
//Timer3 initialization
T3CONbits.TMR3CS = 0b01; //Clock source, 1 = system clock = Fosc; 0 = instruction clock = Fosc/4
T3CONbits.T3CKPS = 0b10; // 0b11 = 1:8 Prescale value; 0b10 = 1:4 Prescale value; 0b01 = 1:2 Prescale value; 0b00 = 1:1 Prescale value
T3CONbits.SOSCEN = 0;
T3CONbits.RD16 = 1; //16bits wide register
T3CONbits.TMR3ON = 1; //1 = Timer 3 Enabled
T3GCONbits.TMR3GE = 1; //Timer 3 is gated
T3GCONbits.T3GPOL = 1; //high/low level of timer4 enables Timer3
T3GCONbits.T3GTM = 0; //Toggle mode disabled
T3GCONbits.T3GSPM = 0; //Single pulse mode disabled
T3GCONbits.T3GSS = 0x01; //TMR4 as a source
WRITETIMER3(0x0000ul);
TMR4 = 0x00;
//interrupts handling
PIE2bits.TMR3IE = 1;
PIE4bits.TMR4IE = 1;
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
//the infinite loop
while(1){
}
}
I have spent plenty of time solving this problem (even there: https://www.microchip.com/forums/m1211315.aspx) and my conclusion is, that it is most probably a HW bug. So Timers 1 and 3 with gated control (from Timer 2/4) works properly as a timer (their registers TMR1/3H/L increment well), but they fail in triggering interrupts and setting appropriate PIR flags.
So my resolution for another applications is:
let's use Timers 1/3 as counters of TMR2/4 rollovers (and make a 24bit wide timer), it works well and is useful;
but do not use any (including CCP) ISR function (or PIR values) rising from Timer 1/3 with gated control from Timer 2/4. I simply use ISR rising from Timer 2/4 and test Timer 1/3 state by SW.

Connecting two PIC18F starter kits using USART2

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.

Resources