Microchip PIC 12F617; calculating delay using TMR2 - c

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.

Related

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.

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.

Cannot send or receive data through UART on PIC24F development board

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.

Sleep mode(PIC 18f46j50) with internal oscilator

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).

Why this simple PWM doesn't work in xc8

I know there are a lot of examples in internet, but what does need this code to work ?
frecuency oscillator = 4mhz
periode = 0.25us
duty_cicle = 250
Prescale = 16
PR2 = 124
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <pic16f88.h>
#pragma config FOSC = HS // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = ON // Brown-out Detect Enable bit (BOD enabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
void main ()
{
while (1)
{
CCP1CON = 0x2C; /*activate PWM mode*/
PR2 = 0x7C; /*124 (DECIMAL)*/
T2CON = 0X06; /*prescale 16 */
CCPR1L = 0X3E;
}
}
I want to see :
Period of PWM = 2ms
Dutycicle = 1ms
Sincerilly
NIN
First off topic:
Don't include pic16f88.h, it's included by xc.h.
Little more off topic:
If you use a more modern part (e.g. PIC16f1619), you can use the MPLAB Code Configurator to generate the TMR2 and CCP code for you. It'll also cost less and have more flash/ram. That device is on the curiosity board ($20).
On Topic:
Your first stop is the datasheet.
The PWM section has the setup for PWM operation.
Step1:
The timer 2 takes Fosc/4 as an input, which is 1mhz in your case.
Target frequency is 500Hz. 1e6/500 = 2k.
I'd suggest a prescaler of 16, and pr value of 125. This will give you exactly 500Hz.
Step2:
We want a 50% duty cycle. CCP1L floor(125/2) = 62. CCP1X:CCP1Y = 0.5 * 4 = 2.
Step 3:
Clear the tris bit.
Step4 and 5:
Turn it on
// Step 1
TMR2ON = 0;
TOUTPS = 0;
T2CKPS = 2;
PR2 = 250U;
// Step 2
CCP1L = 62U;
CCP1X = 1;
CCP1Y = 0;
// Step 3
TRISB3 = 0;
// Step 4
TMR2ON = 1;
// Step 5
CCP1M = 0xC;
Hope that helps.
The datasheet states:
In Pulse-Width Modulation (PWM) mode, the CCP1 pin
produces up to a 10-bit resolution PWM output. Since
the CCP1 pin is multiplexed with the PORTB data latch,
the TRISB bit must be cleared to make the CCP1
pin an output.
So you must set the TRIS bit for the CCP1 pin to output:
TRISB &= ~(1 << 3); //Clear bit RB3/CCP1 in TRISB, makes PORTB3/CCP1 output.
This assumes CCPMX: CCP1 Pin Selection bit in the configuration word is clear. If set, then CCP1 is on RB0 in stead of RB3 but since I see no mention of CCPMX in your configuration pragma's i assume it is cleared.

Resources