I'm relatively new to programming PIC18 micro-controllers and I keep getting a compile error 195 when I try to get my code to compile. The PIC I'm using is a PIC18F46k80, and the application I'm trying to program it for is for a piece of hardware with the PIC already embedded, so I can't change the Pin configuration (I didn't design the hardware). I'm trying to get my PIC to perform a slightly modified SPI protocol via bit-banging as the correct pins for the internal peripheral haven't been connect. I keep running into this compile error whenever I try to set RA6 or RA5, even though (I think) I've configured the pins to make them writable (not providing the internal clock). Specifically I get the error when trying to set LATA6 = x or LATA5 = x. In MPLAB X every issue of me writing LATA6 or LATA5 is highlighted. Can someone help me with writing/setting these pins?
Any instance of the follow code will cause an issue:
LATA5 = 0;
//or
LAT6 = 0;
//or
LAT6 = 1;
I can send through the entire file including headers and config files if needed :) Cheers for any help.
Here is the entire code:
#include "mcc_generated_files/mcc.h"
#include <stdio.h>
#include<stdlib.h>
#include<xc.h>
//Define words for transfer//
uint8_t FR1IByte = 0x01;
int FR1DBytes = 0x900000;
uint8_t CSRIByte = 0x00;
uint8_t CSRCH0 = 0x10;
uint8_t CSRCH1 = 0x20;
uint8_t CSRCH2 = 0x40;
uint8_t CFTWIByte = 0x04;
uint32_t CFTWCH0 = 0x42680000;
uint32_t CFTWCH1 = 0x1F400000;
uint32_t CFTWCH2 = 0x3E800000;
//Functions to perform SPI//
void SPItransfer8( uint8_t byte)
{
// local variable declaration
int i;
for (i = 0; i <8; i++){ //compares MSB with mask. If it matches, it will transfer a 1//
if(byte & 0x80)
{
LATC5 = 1;
}
else
{
LATC5 = 0;
}
// Pulses clock for transfer of data//
LATA6 = 1;
LATA6 = 0;
// Logical shift left so that next byte can be read//
byte <<= 1;
}
}
void SPItransfer24( int bytes)
{
// local variable declaration
int i;
for (i = 0; i <24; i++);
{ //compares MSB with mask. If it matches, it will transfer a 1//
if(bytes & 0x800000)
{
LATC5 = 1;
}
else
{
LATC5 = 0;
}
// Pulses clock for transfer of data//
LATA6 = 1;
LATA6 = 0;
// Logical shift left so that next byte can be read//
bytes <<= 1;
}
}
void SPItransfer32( uint32_t bytes)
{
// local variable declaration
int i;
for (i = 0; i <32; i++);
{ //compares MSB with mask. If it matches, it will transfer a 1//
if(bytes & 0x80000000)
{
LATC5 = 1;
}
else
{
LATC5 = 0;
}
// Pulses clock for transfer of data//
LATA6 = 1;
LATA6 = 0;
// Logical shift left so that next byte can be read//
bytes <<= 1;
}
}
void main(void)
{
TRISE = 0x03;
TRISA = 0b1001111;
// Initialize the device//
SYSTEM_Initialize();
// Perform master reset on DDS to set the device to its default state (Active high on E2)//
LATE1 = 1;
LATE1 = 0;
// Delay to allow the system to load (PLL takes time to lock) //
__delay_ms(10)
//Set RA5 to low to prevent power down//
LATA5 = 0;
//Set RA6 to low for SPI clock//
LATA6 = 0;
//Transfers the Function Register 1 Information Byte//
SPItransfer8(FR1IByte);
//Transfers the Function Register 1 Data Bytes//
SPItransfer24(FR1DBytes);
//Transfers the Channel Select Register Information Byte//
SPItransfer8(CSRIByte);
//Transfers the Channel Select Register Data Byte for CH0
SPItransfer8(CSRCH0);
//Transfers the Channel Frequency Tuning Word Information Byte//
SPItransfer8(CFTWIByte);
//Transfers the Channel 0 Frequency Tuning Word//
SPItransfer32(CFTWCH0);
//Transfers the Channel Select Register Information Byte//
SPItransfer8(CSRIByte);
//Transfers the Channel Select Register Data Byte for CH1
SPItransfer8(CSRCH1);
//Transfers the Channel Frequency Tuning Word Information Byte//
SPItransfer8(CFTWIByte);
//Transfers the Channel 1 Frequency Tuning Word//
SPItransfer32(CFTWCH1);
//Transfers the Channel Select Register Information Byte//
SPItransfer8(CSRIByte);
//Transfers the Channel Select Register Data Byte for CH2
SPItransfer8(CSRCH2);
//Transfers the Channel Frequency Tuning Word Information Byte//
SPItransfer8(CFTWIByte);
//Transfers the Channel 2 Frequency Tuning Word//
SPItransfer32(CFTWCH2);
//Toggle I/O_Update to load data into DDS//
PORTEbits.RE2 = 1;
PORTEbits.RE2 = 0;
//Loop holding RA6 low to prevent further data transmission//
while (1)
{
PORTAbits.RA6 = 0;
}
}
Here are the MCC generated config files:
// 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->Digital (SCLKI) mode
#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 = OFF // Watchdog Timer->WDT disabled 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 = OFF // Master Clear Enable->MCLR Disabled, RE3 Enabled
// 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
The error is actually in the line just above LATA5 = 0;. The macro __delay_ms is defined in pic18.h as:
_delay((unsigned long)((x)*(_XTAL_FREQ/4000000.0)))
and requires a statement terminator. You are missing a semicolon. Change the line to:
__delay_ms(10);
Related
I am having a lot of trouble when it comes to flash erasing on the dsPIC33EP64GP503 and I am hoping someone on here will be able help.
I am wanting to store a data struct in the flash program memory of the device. I am having trouble when it comes to erasing the flash though. I need to erase it and re-write it when the data changes.
I am padding the rest of the page with 0s so it can be safely erased.
I can write to the same memory location of the struct. When doing a flash write onto the start of the struct, the byStructValid turns into 0x11 (I know this is all very bad, because it is writing double word. But I am just trying to get the flash operations working first), however when I do an erase nothing happens. Is someone able to figure out what I am doing wrong?
I initialised the struct with 0xFF's and tried to perform a flash write. This was successful as the CAN message I received showed the data changed from 0xFF to 0x11.
I then tried to do a flash erase, but nothing happened. The device just carried on as normal. I don't have access to debug so it is hard to fully understand what is going on during this time.
I have tried moving the struct location around, so that it is on an 'even' page boundary (as specified in the datasheet) but this hasn't worked either.
I have also tried using an assembly version of the erase function, provided by the datasheet, this also doesn't work. The device just carries on as though there was no command for flash erase.
Below are some snippets of code that I have been using.
Any help would be greatly appreciated, thank you.
Note: I am unable to use the debugger. I use CAN messages to periodically send ‘debug’ messages, which contain data that is read from the flash location. This is so I can see if the write/erases are working.
#define MEMORY_USER_CALIBRATION_LOC 0x006000
typedef struct
{
byte byStructValid;
byte abyStructData[3];
}stFlashStruct_t;
volatile const __prog__ stFlashStruct_t stFlashStruct __attribute__((space(prog), address(MEMORY_USER_CALIBRATION_LOC))) =
{
.byStructValid = 0xFF,
.abyStructData = {50, 10, 20},
};
const byte padding[_FLASH_PAGE*2 - sizeof(stFlashStruct_t)] __attribute__((space(prog), address(MEMORY_USER_CALIBRATION_LOC + sizeof(stFlashStruct_t)))) = {0};
//FLASH Write
void FLASH_WriteDoubleWord(dword address, dword data[2])
{
word INTCON2Save;
word i;
//set WREN and ERASE settings for operation
NVMCON = 0x4001;
TBLPAG = 0xFA;
//set address to erase
NVMADR = address & 0xFFFF;
NVMADRU = (address >> 16) & 0x3F;
for (i = 0; i < 2; i++)
{
__builtin_tblwtl(i*2, data[i] & 0xFFFF);
__builtin_tblwth(i*2, (data[i] >> 16) & 0xFF);
}
//save the interrupt register
INTCON2Save = INTCON2;
// Disable interrupts for NVM unlock
__builtin_disable_interrupts();
__builtin_write_NVM();
// Start write cycle
while(NVMCONbits.WR == 1);
//restore interrupts
INTCON2 = INTCON2Save;
}
//FLASH Erase
void FLASH_ErasePageC(dword dwAddress)
{
word INTCON2Save;
//set WREN and ERASE settings for operation
NVMCON = 0x4003;
//set address to erase
NVMADRU = (dwAddress >> 16) & 0x3F;
NVMADR = dwAddress & 0xFFFF;
//save the interrupt register
INTCON2Save = INTCON2;
__builtin_disable_interrupts();
// Disable interrupts for NVM unlock
__builtin_write_NVM();
// Start write cycle
while(NVMCONbits.WR == 1);
//restore interrupts
INTCON2 = INTCON2Save;
}
byte temp_flash_write(void)
{
dword new_data[2] = {0x1111, 0x1111};
FLASH_WriteDoubleWord(&stCustomerCalibration, new_data);
return 0;
}
Your "dsPIC33 Flash Erase broken" issue is one of not understanding just how badly the Run Time Flash Programming (RTFP) method is described in the Microchip dsPIC33EP64GP503 data sheet and family reference manuals.
This post will not explain how any of this works. It does work but is really hard to comprehend.
What will be hard for you is that a program flash word can only be written one time after an erase. Writing to the same program flash word a second time will corrupt it and the next time it is read an ECC trap error will assert.
Attached is example code that allocates a 1024 instruction word page at address 0x6000. Declares a structure at the start of that page that is 2 instruction words in size. The code then erases that page then writes different data to the first 2 instruction words in that page.
/*
* File: main.c
* Author: Dan1138
*
* Description:
* Example for Run Time Self Programming (RTSP).
* This is very limited, useful as a test bench but not much more.
*
* Created on December 10, 2022, 2:05 PM
*/
/* Define the system oscillator frequency this code must configure */
#define FSYS (7372800ul)
#define FCY (FSYS/2ul)
// DSPIC33EP64GP503 Configuration Bit Settings
// 'C' source line config statements
// 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)
// FPOR
#pragma config ALTI2C1 = OFF // Alternate I2C1 pins (I2C1 mapped to SDA1/SCL1 pins)
#pragma config ALTI2C2 = OFF // Alternate I2C2 pins (I2C2 mapped to SDA2/SCL2 pins)
#pragma config WDTWIN = WIN25 // Watchdog Window Select bits (WDT Window is 25% of WDT period)
// FWDT
#pragma config WDTPOST = PS32768 // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128 // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON // PLL Lock Enable bit (Clock switch to PLL source will wait until the PLL lock signal is valid.)
#pragma config WINDIS = OFF // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable bit (Watchdog timer enabled/disabled by user software)
// FOSC
#pragma config POSCMD = NONE // Primary Oscillator Mode Select bits (Primary Oscillator disabled)
#pragma config OSCIOFNC = ON // OSC2 Pin Function bit (OSC2 is general purpose digital I/O pin)
#pragma config IOL1WAY = OFF // Peripheral pin select configuration (Allow multiple reconfigurations)
#pragma config FCKSM = CSECMD // 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 IESO = ON // Two-speed Oscillator Start-up Enable bit (Start up device with FRC, then switch to user-selected oscillator source)
// FGS
#pragma config GWRP = OFF // General Segment Write-Protect bit (General Segment may be written)
#pragma config GCP = OFF // General Segment Code-Protect bit (General Segment Code protect is Disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <libpic30.h>
#define MEMORY_USER_CALIBRATION_LOC (_FLASH_PAGE * 24)
typedef struct
{
uint8_t byStructValid;
uint8_t abyStructData[3];
} stFlashStruct_t;
volatile const __prog__ __attribute__((space(prog), address(MEMORY_USER_CALIBRATION_LOC))) union
{
uint16_t words[_FLASH_PAGE]; /* reserve the entire erase page. Note only the low 16-bits of the instruction word can be accessed with this method. */
struct {
stFlashStruct_t stFlashStruct; /* calibration structure */
};
} CalSpace =
{
.stFlashStruct.byStructValid = 0xFF,
.stFlashStruct.abyStructData = {50, 10, 20},
};
int main(void)
{
volatile stFlashStruct_t ReadBack;
/*
* application initialization
*/
ReadBack.byStructValid = CalSpace.stFlashStruct.byStructValid;
ReadBack.abyStructData[0] = CalSpace.stFlashStruct.abyStructData[0];
ReadBack.abyStructData[1] = CalSpace.stFlashStruct.abyStructData[1];
ReadBack.abyStructData[2] = CalSpace.stFlashStruct.abyStructData[2];
__builtin_software_breakpoint(); /* breakpoint here to inspect the ReadBack structure with the debugger */
Nop();
Nop();
/* Erase 1024 instruction words starting at address MEMORY_USER_CALIBRATION_LOC */
NVMCON = 0x4003;
NVMADR = __builtin_tbloffset(&CalSpace);
NVMADRU = __builtin_tblpage(&CalSpace);
__builtin_disi(5); // Disable interrupts for NVM unlock
__builtin_write_NVM(); // Start write cycle
while(NVMCONbits.WR == 1);
ReadBack.byStructValid = CalSpace.stFlashStruct.byStructValid;
ReadBack.abyStructData[0] = CalSpace.stFlashStruct.abyStructData[0];
ReadBack.abyStructData[1] = CalSpace.stFlashStruct.abyStructData[1];
ReadBack.abyStructData[2] = CalSpace.stFlashStruct.abyStructData[2];
__builtin_software_breakpoint(); /* breakpoint here to inspect the ReadBack structure with the debugger */
Nop();
Nop();
/* Update data in structure to be written */
ReadBack.byStructValid = 1;
ReadBack.abyStructData[0] = 2;
ReadBack.abyStructData[1] = 3;
ReadBack.abyStructData[2] = 4;
/* Write 2 instruction words starting at address MEMORY_USER_CALIBRATION_LOC */
NVMCON = 0x4001; // Set WREN and word program mode
TBLPAG = 0xFA; // write latch upper address
NVMADR = __builtin_tbloffset(&CalSpace.stFlashStruct);
NVMADRU = __builtin_tblpage(&CalSpace);
__builtin_tblwtl(0,*((uint16_t *)(&ReadBack)+0)); // load low 16-bits of first instruction word
__builtin_tblwth(0,0x00); // make high 8-bits of first instruction word zero
__builtin_tblwtl(2,*((uint16_t *)(&ReadBack)+1)); // load low 16-bits of second instruction word
__builtin_tblwth(2,0x00); // make high 8-bits of second instruction word zero
__builtin_disi(5); // Disable interrupts for NVM unlock sequence
__builtin_write_NVM(); // initiate write
while(NVMCONbits.WR == 1);
ReadBack.byStructValid = CalSpace.stFlashStruct.byStructValid;
ReadBack.abyStructData[0] = CalSpace.stFlashStruct.abyStructData[0];
ReadBack.abyStructData[1] = CalSpace.stFlashStruct.abyStructData[1];
ReadBack.abyStructData[2] = CalSpace.stFlashStruct.abyStructData[2];
__builtin_software_breakpoint(); /* breakpoint here to inspect the ReadBack structure with the debugger */
Nop();
Nop();
/*
* Application process loop
*/
for(;;)
{
Nop();
Nop();
Nop();
__delay_ms(100);
}
}
Actually I'm using a PIC24FJ128GB204 and I've have problems with DeepSleep.
My device is composed by 4 buttons and several LED (a colored torch). Have a button that make device Sleep until I want to use it, same button wakes up my device.
Consumption will all LED are off is 10mA.
I've tried Sleep mode, simply function that goes in basic sleep and than wakeup after selected pin is asserted. Measuring consumption in Sleep mode I've 2.50mA. Working very well.
I've started to work with DeepSleep, since I don't need any code retention and just need to keep my device in lowest possible consumption state (but avoiding to use a slide power switch). I've used Datasheet example codes to implement my function. As result I can enter in this state and than I've 0.45mA as consumption.
I've set an INT0 (as datasheet suggested) to wake up my device and associated it to correct wakeup PIN.
Problems starts now:
When I press wakeup button, my consumption goes to 10mA as normal, but I can't light ON any led. Seems that my device is not responsive.
If I press again Sleep button, my device goes in Sleep mode and not DeepSleep since my consumption back to 2.50mA. Again, if I wake up my device, it wakes up but are not responsive. Doesn't metter how much time I try again, but my device never go again to DeepSleep untill I power off and on again my device.
I've performed some test but can't understand what happen. Maybe after DeepSleep device should be manually reset (tried without success) or maybe some configuration bit need to be set again. Or maybe configuration bits are uncorrect?
Here's interested parts of code:
CONFIGURATION
// CONFIG4
#pragma config DSWDTPS = DSWDTPS3 // Deep Sleep Watchdog Timer Postscale Select bits (1: 256 (8.3 mS))
#pragma config DSWDTOSC = LPRC // DSWDT Reference Clock Select (DSWDT uses LPRC as reference clock)
#pragma config DSBOREN = ON // Deep Sleep BOR Enable bit (DSBOR Enabled)
#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 DSSWEN = ON // DSEN Bit Enable (Deep Sleep is controlled by the register bit DSEN)
#pragma config PLLDIV = DIVIDE2 // USB 96 MHz PLL Prescaler Select bits (Oscillator input divided by 2 (8 MHz input))
#pragma config I2C1SEL = DISABLE // Alternate I2C1 enable bit (I2C1 uses SCL1 and SDA1 pins)
#pragma config IOL1WAY = ON // PPS IOLOCK Set Only Once Enable bit (Once set, the IOLOCK bit cannot be cleared)
// CONFIG3
#pragma config WPFP = WPFP0 // Write Protection Flash Page Segment Boundary (Page 0 (0x00))
#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_PRI // PLL Secondary Selection Configuration bit (PLL is fed by the Primary oscillator)
#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset Enable)
#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 = HS // Primary Oscillator Select (HS Oscillator Enabled)
#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 = CSECME // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Clock switching is enabled, Fail-Safe Clock Monitor is enabled)
//#pragma config FCKSM = CSDCMD // Clock Switching and Fail-Safe Clock Monitor Configuration bits (Clock switching and Fail-Safe Clock Monitor are disabled)
#pragma config FNOSC = PRIPLL // Initial Oscillator Select (Primary Oscillator with PLL module (XTPLL,HSPLL, ECPLL))
#pragma config ALTRB6 = APPEND // Alternate RB6 pin function enable bit (Append the RP6/ASCL1/PMPD6 functions of RB6 to RA1 pin functions)
#pragma config ALTCMPI = CxINC_RX // Alternate Comparator Input bit (C1INC, C2INC and C3INC are on RB9 )
#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 = PS1024 // Watchdog Timer Postscaler Select (1:1,024)
#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 = PGx3 // Emulator Pin Placement Select bits (Emulator functions are shared with PGEC3/PGED3)
#pragma config LPCFG = OFF // Low power regulator control (Disabled - regardless of RETEN)
//#pragma config LPCFG = ON // Low power regulator control (Low voltage regulator controlled by RETEN bit)
#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)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
TURNOFF FUNCTION
void TurnOff(void)
{
T1CONbits.TON = 0;
IEC0bits.T1IE = 0;
/* turn off */
OC1CON1bits.OCM = 0;
OC2CON1bits.OCM = 0;
OC3CON1bits.OCM = 0;
OC4CON1bits.OCM = 0;
OC5CON1bits.OCM = 0;
// OC6CON1bits.OCM = 0;
if (!USB_BUS_SENSE)
{
USBMaskInterrupts();
USBModuleDisable();
OS_ENTER_CRITICAL();
T2CONbits.TON = 0;
IEC0bits.T2IE = 0;
TRISA = 0xffff;
TRISB = 0xffff;
TRISC = 0xffff;
// I2C1CONLbits.I2CEN = 0;
//
// SPI1CON1Lbits.SPIEN = 0;
// SPI2CON1Lbits.SPIEN = 0;
// SPI3CON1Lbits.SPIEN = 0;
//
// U1MODEbits.UARTEN = 0;
// U2MODEbits.UARTEN = 0;
// U3MODEbits.UARTEN = 0;
// U4MODEbits.UARTEN = 0;
//
// DMACONbits.DMAEN = 0;
//
// U1CONbits.USBEN = 0;
// PMD1 = 0xffff;
// PMD2 = 0xffff;
// PMD3 = 0xffff;
// PMD4 = 0xffff;
// PMD5 = 0xffff;
// PMD6 = 0xffff;
// PMD7 = 0xffff;
// PMD8 = 0xffff;
WDTDisable();
LPAppState = OFF_ST;
CNInit();
Nop();
Nop();
OS_EXIT_CRITICAL();
//#ifndef DEBUG_PENNA
{
// ENTRATA IN SLEEP MODE(pag 164)
// TEST 1
// DSCONbits.DSEN = 1;
// DSCONbits.DSEN = 1;
// __asm__ volatile("pwrsav #0");
// TEST 2 non funziona anche se c'è scritto così sul manuale (pag 164)
// __asm__ volatile("disi #7");
// __asm__ volatile("mov #8000, w2");
// __asm__ volatile("mov w2, DSCON");
// __asm__ volatile("mov w2, DSCON");
// __asm__ volatile("nop");
// __asm__ volatile("nop");
// __asm__ volatile("nop");
// __asm__ volatile("PWRSAV #0");
// TEST 3
DSCONbits.DSEN = 1;
DSCONbits.DSEN = 1;
__asm__ volatile("nop");
__asm__ volatile("nop");
__asm__ volatile("nop");
__asm__ volatile("PWRSAV #0");
// TEST 4 - LOW VOLTAGE (pag. 420) [provato sia con CONFIG LPCFG=1 e 0, l'effetto si ha con 1 anche se da manuale c'è scritto il contrario]
// RCONbits.RETEN = 1;
// __asm__ volatile("PWRSAV #0");
}
//#endif
USBDeviceInit();
}
WDTEnable();
T2CONbits.TON = 1;
IEC0bits.T2IE = 1;
}
INTERRUPT DECLARATION
//------------------------------------------------
/**
void INTERRUPT_Initialize (void)
*/
void INTERRUPT_Initialize(void)
{
// INT0I: INT0 - External Interrupt 0
// Priority: 1
IPC0bits.INT0IP = 1;
}
/**
Section: External Interrupt Handlers
*/
void __attribute__((weak)) EX_INT0_CallBack(void)
{
// Add your custom callback code here
// Verifico se il dispositivo è uscito dal Deep Sleep (pag.165 datasheet)
if (RCONbits.DPSLP == 1)
{
// Risveglio da deep sleep
RCONbits.DPSLP = 0;
DSCONbits.RELEASE = 0;
}
}
/**
Interrupt Handler for EX_INT0 - INT0
*/
void __attribute__((interrupt, no_auto_psv)) _INT0Interrupt(void)
{
//***User Area Begin->code: INT0 - External Interrupt 0***
EX_INT0_CallBack();
//***User Area End->code: INT0 - External Interrupt 0***
EX_INT0_InterruptFlagClear();
}
/**
Section: External Interrupt Initializers
*/
/**
void EXT_INT_Initialize(void)
Initializer for the following external interrupts
INT0
*/
void EXT_INT_Initialize(void)
{
/*******
* INT0
* Clear the interrupt flag
* Set the external interrupt edge detect
* Enable the interrupt, if enabled in the UI.
********/
EX_INT0_InterruptFlagClear();
EX_INT0_PositiveEdgeSet();
EX_INT0_InterruptEnable();
}
When I press wakeup button, my consumption goes to 10mA as normal, but
I can't light ON any led. Seems that my device is not responsive
Your problem is here:
TRISA = 0xffff;
TRISB = 0xffff;
TRISC = 0xffff;
You set the pins to input before entering deep sleep, but I don't see anywhere in your code where you set the pins up after you exit sleep so they are still acting as inputs and thus you won't be able to light an LED.
I am successfully programming PIC32MX250F128B using Pickit3. I have written a code where, when I press a I am getting 100 data from vibration sensor. Now if I want to get another 100 data, either I have to disconnect and then reconnect the 10k ohm pull up resistor connected to MCLR pin or have to run the program again.
Is there any other way I can reset the pickit?
Here is the code I am using:
#include <p32xxxx.h> // include chip specific header file
#include <plib.h> // include peripheral library functions
// Configuration Bits
#pragma config FNOSC = FRCPLL // Internal Fast RC oscillator (8 MHz) w/ PLL
#pragma config FPLLIDIV = DIV_2 // Divide FRC before PLL (now 4 MHz)
#pragma config FPLLMUL = MUL_20 // PLL Multiply (now 80 MHz)
#pragma config FPLLODIV = DIV_2 // Divide After PLL (now 40 MHz)
// see figure 8.1 in datasheet for more info
#pragma config FWDTEN = OFF // Watchdog Timer Disabled
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select
#pragma config JTAGEN = OFF // Disable JTAG
#pragma config FSOSCEN = OFF // Disable Secondary Oscillator
#pragma config FPBDIV = DIV_1 // PBCLK = SYCLK
// Defines
#define SYSCLK 40000000L
// Macros
// Equation to set baud rate from UART reference manual equation 21-1
#define Baud2BRG(desired_baud) ( (SYSCLK / (16*desired_baud))-1)
// Function Prototypes
int SerialTransmit(const char *buffer);
unsigned int SerialReceive(char *buffer); //, unsigned int max_size);
int UART2Configure( int baud);
short a2dvals[11000];
int adcptr,num_channels,k,i;
char sampling;
int ADC_RSLT0,totaldata,totaldata1,chunks_sent,data_count,l;
short temp;
BOOL a2don;
volatile unsigned int channel4;
void __ISR(_ADC_VECTOR, IPL2) TIMER3Handler(void) // Fonction d'interruption Timer 3
{
temp = ReadADC10(0);
a2dvals[k] = (temp);
k++;
if (k>totaldata1)// && sampling == 's')
{
T3CONCLR = 0x8000;
a2don=FALSE;
chunks_sent = 0;
totaldata = k/2;
k = 1;
}
mAD1ClearIntFlag();
}
int main(void)
{
char buf[1024]; // declare receive buffer with max size 1024
// Peripheral Pin Select
U2RXRbits.U2RXR = 4; //SET RX to RB8
RPB9Rbits.RPB9R = 2; //SET RB9 to TX
SYSTEMConfigPerformance(SYSCLK);
UART2Configure(9600); // Configure UART2 for a baud rate of 9600
U2MODESET = 0x8000; // enable UART2
ANSELBbits.ANSB2 = 1; // set RB2 (AN4) to analog
TRISBbits.TRISB2 = 1; // set RB2 as an input
//adcConfigureManual(); // Configure ADC
//AD1CON1SET = 0x8000; // Enable ADC
SerialTransmit("Hello! Enter 'a' to do ADC conversion \r\n");
unsigned int rx_size;
while( 1){
rx_size = SerialReceive(buf); //, 1024); // wait here until data is received
SerialTransmit(buf); // Send out data exactly as received
SerialTransmit("\r\n");
}
return 1;
} // END main()
/* UART2Configure() sets up the UART2 for the most standard and minimal operation
* Enable TX and RX lines, 8 data bits, no parity, 1 stop bit, idle when HIGH
* Input: Desired Baud Rate
* Output: Actual Baud Rate from baud control register U2BRG after assignment*/
int UART2Configure( int desired_baud){
U2MODE = 0; // disable autobaud, TX and RX enabled only, 8N1, idle=HIGH
U2STA = 0x1400; // enable TX and RX
U2BRG = Baud2BRG(desired_baud); // U2BRG = (FPb / (16*baud)) - 1
// Calculate actual assigned baud rate
int actual_baud = SYSCLK / (16 * (U2BRG+1));
return actual_baud;
} // END UART2Configure()
/* SerialTransmit() transmits a string to the UART2 TX pin MSB first
*
* Inputs: *buffer = string to transmit */
int SerialTransmit(const char *buffer)
{
unsigned int size = strlen(buffer);
while( size)
{
while( U2STAbits.UTXBF); // wait while TX buffer full
U2TXREG = *buffer; // send single character to transmit buffer
buffer++; // transmit next character on following loop
size--; // loop until all characters sent (when size = 0)
}
while( !U2STAbits.TRMT); // wait for last transmission to finish
return 0;
}
/* SerialReceive() is a blocking function that waits for data on
* the UART2 RX buffer and then stores all incoming data into *buffer
*
* Note that when a carriage return '\r' is received, a nul character
* is appended signifying the strings end
*
* Inputs: *buffer = Character array/pointer to store received data into
* max_size = number of bytes allocated to this pointer
* Outputs: Number of characters received */
unsigned int SerialReceive(char *buffer) //, unsigned int max_size)
{
//unsigned int num_char = 0;
/* Wait for and store incoming data until either a carriage return is received
* or the number of received characters (num_chars) exceeds max_size */
while(1)
{
while( !U2STAbits.URXDA); // wait until data available in RX buffer
*buffer = U2RXREG; // empty contents of RX buffer into *buffer pointer
if (*buffer == 'a')
{
int dummy,dummy1;
unsigned char tempstr[5];
SYSTEMConfig(SYSCLK, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE);
// the ADC ///////////////////////////////////////
// configure and enable the ADC
CloseADC10(); // ensure the ADC is off before setting the configuration
// define setup parameters for OpenADC10
// Turn module on | ouput in integer | trigger mode auto | enable autosample
// ADC_CLK_AUTO -- Internal counter ends sampling and starts conversion (Auto convert)
// ADC_AUTO_SAMPLING_ON -- Sampling begins immediately after last conversion completes; SAMP bit is automatically set
// ADC_AUTO_SAMPLING_OFF -- Sampling begins with AcquireADC10();
#define PARAM1 ADC_MODULE_ON|ADC_FORMAT_INTG32 | ADC_CLK_TMR | ADC_AUTO_SAMPLING_ON //
// define setup parameters for OpenADC10
// ADC ref external | disable offset test | disable scan mode | do 1 sample | use single buf | alternate mode off
#define PARAM2 ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_OFF | ADC_ALT_INPUT_OFF
//
// Define setup parameters for OpenADC10
// use peripherial bus clock | set sample time | set ADC clock divider
// ADC_CONV_CLK_Tcy2 means divide CLK_PB by 2 (max speed)
// ADC_SAMPLE_TIME_5 seems to work with a source resistance < 1kohm
#define PARAM3 ADC_CONV_CLK_SYSTEM | ADC_SAMPLE_TIME_5 | ADC_CONV_CLK_Tcy2 //ADC_SAMPLE_TIME_15| ADC_CONV_CLK_Tcy2
// define setup parameters for OpenADC10
// set AN4 and as analog inputs
#define PARAM4 ENABLE_AN4_ANA
// define setup parameters for OpenADC10
// do not assign channels to scan
#define PARAM5 SKIP_SCAN_ALL
// use ground as neg ref for A | use AN4 for input A
// configure to sample AN4
SetChanADC10( ADC_CH0_NEG_SAMPLEA_NVREF | ADC_CH0_POS_SAMPLEA_AN4 ); // configure to sample AN4
OpenADC10( PARAM1, PARAM2, PARAM3, PARAM4, PARAM5 ); // configure ADC using the parameters defined above
ConfigIntADC10(ADC_INT_PRI_2 | ADC_INT_ON);
EnableADC10(); // Enable the ADC
INTEnableSystemMultiVectoredInt();
OpenTimer3(T3_OFF | T3_SOURCE_INT | T3_PS_1_1 ,0x3e8);
num_channels = 1;
totaldata1 = 10500;
a2don=TRUE;
T3CONSET = 0x8000;
k=0;
while(1)
{
while(a2don);
for(i=0;i<100;i++)
{
dummy = a2dvals[i]/1000 ;
tempstr[0] = dummy + 0x30;
dummy1 = a2dvals[i]- dummy*1000;
dummy = dummy1/100;
tempstr[1] = dummy + 0x30;
dummy1 = dummy1 - dummy*100;
dummy = dummy1/10;
tempstr[2] = dummy + 0x30;
dummy1 = dummy1 - dummy*10;
tempstr[3] = dummy1 + 0x30;
//tempstr[4] = "\0";
printf("%c%c%c%c \n", tempstr[0],tempstr[1],tempstr[2],tempstr[3]);
}
a2don=TRUE;
}
}
}
return 1;
}// END SerialReceive()
enter image description here
Thanks for your advices.
You do not need to reset the Pickit. If anything, that might be the least efficient way to do it (arguably).
Rather try something like this. Please note this is high level. You will need to make it work yourself.
void(main){
// Setup your things here
while(1){ // Your infinite loop
// Check if you received 'a' here
if (received_a == 1){ // You received a 'a'
send_data(); // Send your data
}
}
}
Without providing actual code you have written we will not be able to help you.
You use while(1) loops everywhere, and if you don't use a break; or return command you stay in that loop forever.
I think you don't need while(1) loops in the functions except in main(). Remove these and it should work.
Try drawing out your program flow in a flow chart, it should clear things up. Also consider using a state machine using switch/case. It makes it a lot clearer where you are in the code and it's easier to debug. Also, it's probably even better to use interrupts for adc and the serial port. You free up the pic to do other stuff while peripherals are doing stuff that takes time.
I am working on project, and we need to establish a CAN communication between 4 nodes, 2 using a PIC 18F4580 and 2 using 18F25K80. In all those circuits, I'm using a Crystal oscillator 20MHz. The issue is when I test the communication between same PICs, it's working, but when I try with two different PICs it's not working.
The codes I used to test:
For the emitting PIC 18F4580 : Emitting a CAN message every 1 second :
int i;
unsigned char Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags; // can flags
unsigned char Rx_Data_Len; // received data length in bytes
char RxTx_Data[8]; // can rx/tx data buffer
char Msg_Rcvd; // reception flag
const long ID_cmd = 3, ID_led1 = 2; // node IDs
long Rx_ID;
void main() {
ADCON1=0xF;
TRISA=0xFF;
TRISD=0;
PORTD=0;
for(i=0;i<10;i++) {
PORTD=0xFF ^ PORTD; //Blinking Leds
Delay_ms(100);
}
Can_Init_Flags = 0; //
Can_Send_Flags = 0; // clear flags
Can_Rcv_Flags = 0; //
Can_Send_Flags = _CAN_TX_PRIORITY_0 & // form value to be used
_CAN_TX_XTD_FRAME & // with CANWrite
_CAN_TX_NO_RTR_FRAME;
Can_Init_Flags = _CAN_CONFIG_SAMPLE_THRICE & // form value to be used
_CAN_CONFIG_PHSEG2_PRG_ON & // with CANInit
_CAN_CONFIG_XTD_MSG &
_CAN_CONFIG_DBL_BUFFER_ON &
_CAN_CONFIG_VALID_XTD_MSG;
CANInitialize(1,3,3,3,1,Can_Init_Flags); // Initialize CAN module
CANSetOperationMode(_CAN_MODE_NORMAL,0xFF); // set NORMAL mode
for(i=0;i<10;i++) {
PORTD=0xFF ^ PORTD; //Blinking Leds
Delay_ms(100);
}
while(1){
PORTD.F7=PORTA.F0;
PORTD.F6=PORTA.F1;
PORTD.F5=PORTA.F2;
PORTD.F4=PORTA.F3; //LEDS := SWITCHS
CANWrite(ID_cmd, RxTx_Data, 1, Can_Send_Flags); // send incremented data back
Delay_ms(1000);
}
}
For the receiving Node PIC 18F25K80 : Blink after receiving any CAN message (Should blink every 1 second) :
unsigned char Can_Init_Flags, Can_Send_Flags, Can_Rcv_Flags; // can flags
unsigned char Rx_Data_Len; // received data length in bytes
char RxTx_Data[8]; // can rx/tx data buffer
char Msg_Rcvd; // reception flag
const long ID_led1 = 2, ID_cmd = 3; // node IDs
long Rx_ID;
void main() {
//OSCCON |= 0b01110010;
TRISC = 0;
Can_Init_Flags = 0; //
Can_Send_Flags = 0; // clear flags
Can_Rcv_Flags = 0; //
Can_Send_Flags = _CAN_TX_PRIORITY_0 & // form value to be used
_CAN_TX_XTD_FRAME & // with CANWrite
_CAN_TX_NO_RTR_FRAME;
Can_Init_Flags = _CAN_CONFIG_SAMPLE_THRICE & // form value to be used
_CAN_CONFIG_PHSEG2_PRG_ON & // with CANInit
_CAN_CONFIG_XTD_MSG &
_CAN_CONFIG_DBL_BUFFER_ON &
_CAN_CONFIG_VALID_XTD_MSG;
CANInitialize(1,3,3,3,1,Can_Init_Flags); // Initialize CAN module
CANSetOperationMode(_CAN_MODE_CONFIG,0xFF); // set CONFIGURATION mode
CANSetMask(_CAN_MASK_B1,-1,_CAN_CONFIG_XTD_MSG); // set all mask1 bits to ones
CANSetMask(_CAN_MASK_B2,-1,_CAN_CONFIG_XTD_MSG); // set all mask2 bits to ones
CANSetFilter(_CAN_FILTER_B2_F4,ID_cmd,_CAN_CONFIG_XTD_MSG);// set id of filter B2_F4 to 2nd node ID
CANSetOperationMode(_CAN_MODE_NORMAL,0xFF); // set NORMAL mode
while(1) { // endless loop
Msg_Rcvd = CANRead(&Rx_ID , RxTx_Data , &Rx_Data_Len, &Can_Rcv_Flags); // receive message
if ((Rx_ID == ID_cmd) && Msg_Rcvd) { // if message received check id
PORTC.F3=!PORTC.F3;
}
}
}
Any help would be greatly appreciated, thanks.
It's me again, it worked, the nodes must have the same oscillator value (in my case : 20MHz Crystal).
am using MPLAB to program my new microchip board and programming it programming it using pickit3
code:
// Include the necessary device header file
#include <p18f8722.h>
#pragma config OSC = HSPLL, //OSCS = OFF // HS-PLL Enabled, Internal External Osc. Switch Over OFF Disabled
#pragma config PWRT = OFF // Power Up Timer: OFF Disabled
//#pragma config BOR = OFF, BORV = 25 // Brown Out Reset: OFF, Brown Out Voltage: OFF Disabled
#pragma config WDT = OFF, WDTPS = 128 // Watchdog Timer: OFF Disabled, Watchdog Postscaler: 1:128
//#pragma config CCP2MUX = OFF // CCP2 Mux: OFF Disabled (RB3)
//#pragma config STVR = OFF // Stack Overflow Reset: OFF Disabled
#pragma config LVP = OFF // Low Voltage ICSP:OFF Disabled
#pragma config DEBUG = ON // Background Debugger Enable: OFF Disabled
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF // Code Protection Block 0-3: OFF Disabled
#pragma config CPB = OFF // Boot Block Code Protection: OFF Disabled
#pragma config CPD = OFF // Data EEPROM Code Protection: OFF Disabled
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF // Write Protection Block 0-3: OFF Disabled
#pragma config WRTB = OFF // Boot Block Write Protection: OFF Disabled
#pragma config WRTC = ON // Configuration Register Write Protection: OFF Disabled
#pragma config WRTD = OFF // Data EEPROM Write Protection: OFF Disabled
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF // Table Read Protection Block 0-3: OFF Disabled
#pragma config EBTRB = OFF // Boot Block Table Read Protection: OFF Disabled
// Function prototypes
void delay1(void);
// Main code section. Execution starts here.
void main(void){
// First some setup code for the LED
// The LED will be driven by port D, bit 0, driving the anode, cathode to ground
// First we should clear the port D, bit 0 data latch
LATDbits.LATD0=0;
// We need to set port D, bit 0 as an output
// Using TRISDbits instead of TRISD allows isolating a single bit leaving the other bits unchanged
TRISDbits.TRISD1=0; // 0 = output, 1 = input
// Set port D, bit 0 to off (driving the LED anode, cathode to ground)
PORTDbits.RD1=0;
// LED blinking loop that never ends since '1' never changes
while(1){
PORTDbits.RD1=1; // turn the LED on
delay1(); // call the delay function
PORTDbits.RD1=0; // turn the LED off
delay1(); // call the delay function
}
// end of main, but we will never get this far (endless loop)
}
// Start of our functions
void delay1(void){
/*
It is important to note that all variable declarations need to be placed before any code in
a function or the build will fail.
*/
// declare a long integer and set it to zero
long int loop1=0;
// count from zero to 30,000 then continue on
// Lower than 30000 for a faster blink, higher for a slower blink.
for(loop1=0;loop1<=30000;loop1++){
}
// The loop is done and execution has moved past the loop
}
this code didn't do anything , it compiled perfectly on high tech C compiler but it didn't workout as it was expected ,
maybe the problem is in the configuration bit ? any idea how to solve this ?
Judging by the controller and port, I am guessing that you are using the PIC18 Explorer board. If so, please verify that jumper JP1 is in place. This must be in place when using the onboard LED's.
If it is not this board, then could you be using the wrong port? For instance, the "low pin count" demo board I received with my pickit has the LED's on port C, not D.
Check if that pin also has an analog capability (ANx).
If it's the case, analog is the default setting and you cannot drive the pin. You should set it in digital mode first.