I am trying to communicate with a device using PIC18F26K83. Max freq for SCL is 1 Mhz according to devices datasheet. When I set I2C clock to HFINTOSC (1 Mhz) it can communicate with a device (As long as my system clock is between 250 Khz and 1 Mhz). I do not change anything I just change system clock from 500 Khz to 1 Mhz and it stops working. How can it be? I use HFINTOSC which is set to 1 Mhz for I2C clock, is that depend on the system clock?
And my other question is again related to I2C clock. Like I said when I use HFINTOSC for I2C clock, it works as long as system clock is 500 kHz. However, When I try to use Fosc or MFINTOSC with (500 kHz or 1 MHz system clock) it does not work. Can anyone guide me in here? Because I am stuck and I do not why how can this happen.
Codes for setting up the internal oscillator:
// OSCCON1 REGISTER
NOSC2_BIT=1;
NOSC1_BIT=1;
NOSC0_BIT=0;//HF INTERNAL OSC
//OSCFRQ REGISTER HFINTOSC FREQ. SELECTION
FRQ3_BIT=0;
FRQ2_BIT=0;
FRQ1_BIT=0;
FRQ0_BIT=0; // 0010 : 4 MHz , 0000:1 MHZ
NDIV3_BIT=0;
NDIV2_BIT=0;
NDIV1_BIT=0;
NDIV0_BIT=1;//DIVIDE BY 2
Codes for I2C configartion:
//MODULE ENABLE
I2C1CON0.B7 = 1;
delay_ms(500);
I2C1CON0.B7 = 1; //MODULE ENABLE
I2C1CON0.B6 = 0; //RSEN=0,RESTART ENABLE
I2C1CON0.B2 = 1;
I2C1CON0.B1 = 0;
I2C1CON0.B0 = 0; //MASTER MODE 7 BIT*/
I2C1CON1 = 0X80;
// SDA SCL pin ayarları
TRISC.RC4 = 0; //I2C:SDA
TRISC.RC3 = 0; //I2C:SCL
LATC.RC4 = 0;
LATC.RC3 = 0;
ANSELC = 0XE7; // Clear RC3,RC4 analog inputs
ODCC4_BIT = 1; //open drain control register, sink current only
ODCC3_BIT = 1;
WPUC4_BIT = 0;
WPUC3_BIT = 0; // WEAK PULL UP DISABLE
//RXYI2C SLEW RATE PULLUP VS
RC3I2C = 0X01;
RC4I2C = 0X01;
SLRCONC.B4 = 0; //NO SLEW RATE LIMITING
SLRCONC.B3 = 0;
//PPS AYARLARI
PPSLOCK = 0X55; //UNLOCK SEQUENCE
PPSLOCK = 0XAA;
PPSLOCKED_BIT = 0;
RC3PPS = 0b00100001; //SCL OUTPUT RC3
I2C1SCLPPS = 0b00010011; //SCL INPUT RC3
RC4PPS = 0b00100010; //SDA OUTPUT RC4
I2C1SDAPPS = 0b00010100; //SDA INPUT RC4
PPSLOCK = 0X55; //LOCK SEQUENCE
PPSLOCK = 0XAA;
PPSLOCKED_BIT = 1;
//
I2C1CON2 = 0X04;
And codes for I2C clock selection:
// I2C CLOCK
I2C1CLK.B3 = 0;
I2C1CLK.B2 = 0;
I2C1CLK.B1 = 0;
I2C1CLK.B0 = 1; //0010 HFINT OSC 0001 FOSC
//I2C FREQUENCY=1000/5=200KHz
//FME=0 MEANS DIVISION=5
This is the image of SCL pin when I use 500 Kbps system clock and HFINTOSC for I2Cx CLK.
I checked what I see with MFINTOSC or Fosc as I2CxCLK and it is empty. 0V. No clock unfortunately.
Related
I am new to this PIC programming and currently using C to program because ASM would take a bit time to learn. However, it seems like i am running into the most basic issue of all. The counter i setup with TMR0 is not working correctly and touch sensor does not seem to does anything which it supposed to reset the counter. Can anyone tell me where I did wrong? Been stuck on this for quite a bit. Thanks!
for PIC10F320
[Update]
Hi All, the thanks to the error caught by Kozmotronik. Recalculation was done + reassign bits as global interrupt seems to overflow for some reason. Also option_reg was taken out since T0CS was a 8 bit timer by default. simulation done in proteus for 10secs and timer looks fine now!
The only thing left is the reset from the touch sensor i am still figuring out. Attached a photo from my circuit and temporality replaced the touch sensor with normal button as there is no model for touch sensor. Please take a look if possible.Proteus circuit
// CONFIG
#pragma config FOSC = INTOSC // Oscillator Selection
#pragma config BOREN = OFF // Brown-out Reset
#pragma config WDTE = OFF // Watchdog Timer
#pragma config PWRTE = OFF // Power-up Timer
#pragma config MCLRE = OFF // MCLR Pin Function Select bit->MCLR pin function is digital input, MCLR internally tied to VDD
#pragma config CP = OFF // Code Protection
#pragma config LVP = OFF // Low-Voltage Programming
#pragma config LPBOR = OFF // Brown-out Reset Selection bits
#pragma config BORV = LO // Brown-out Reset Voltage Selection
#pragma config WRT = OFF // Flash Memory Self-Write Protection
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#include <pic10f320.h>
#define _XTAL_FREQ 8000000
#define SWITCH PORTAbits.RA2
#define PWMPin PORTAbits.RA1
#define LEDPin PORTAbits.RA0
unsigned long cnt;
/*
Main application
*/
void setup(void)
{
/**
LATx registers
*/
LATA = 0x00;
/**
TRISx registers
*/
TRISA = 0x04;
/**
ANSELx registers
*/
ANSELA = 0x00;
//Clear out the duty cycle registers
PR2 = 255;
T2CONbits.T2CKPS = 0b00;
T2CONbits.TMR2ON = 0x01;
/*
* My Calculations:
* At 8MHz, Tosc is 125ns, Tcyc=4*Tosc=500ns.
* With PR2=52decimal, prescaler=1, the PWM period is Tcyc(PR2+1) = 500ns*53 = 26.5us.
* For 100% duty cycle,
* PulseWidth = PWMxDCH/L (10bits) * Tosc * 1(prescaler) giving
* 26.5us/125ns=PWMxDCH/L = 212decimal
* PWMxDCH = d4h
* PWMxDCL = 00h
*
* For 75% duty cycle, the duty cycle registers must count off 26.5us*0.75=19.9us.
* PulseWidth = PWMxDCH/L (10bits) * Tosc * 1(prescaler) giving
* 19.9us/125ns=PWMxDCH/L = 159decimal
* PWMxDCH = 9fh
* PWMxDCL = 00h
*/
//Setting timer-0 for the generation of the delay
TMR0 = 0xFF; //Set TMR0 to 0
// OPTION_REG = 0x07;
//INTCON = 0xA0;
> INTCONbits.TMR0IF = 0; //Clear the TMR0 interrupt flag
> INTCONbits.TMR0IE = 1;
OPTION_REGbits.T0CS = 0; //Set TMR0 Clock source to FOS
OPTION_REGbits.PSA = 1; //Assign No-Prescaler to TMR0
/*
* My formulas is:
Fosc/4 = 8MHZ/4 = 2MHZ
period for a tick= 1 / 2MHZ = 0.0000005s
time for 8 bit count = 0.0000005 * 256 = 0.000128s
*
* Overflows every 128us
* for one second delay loop cnt = 1000000*(1/128) = 8
* LC = 7812.5*60 = 480 for 1 minute
* LC = 468750*60 = 28800 for 1 hour
* LC = 28125000*12 = 345600 for 12 hours
*/
}
void main(void)
{
setup();
cnt = 0;
//OSCCON = 2;
while(1){
PWMPin = 1;
LEDPin = 1;
if(SWITCH==1){
cnt++;
}
if(INTCONbits.TMR0IF){
cnt++; //Reset the timer
//100% Duty Cycle on RA1
> TMR0 = 0 ; /// reset TMR0 value
INTCONbits.TMR0IF=0; //Reset Timer Interrupt Flag
}
//If 10sec minute limit is reached (change this number to change the delay)
if(cnt>78125){
//75% Duty Cycle on RA1
// PWM1POL active_hi; PWM1OE enabled; PWM1EN enabled;
PWM2CON = 0xC0;
PWM1CONbits.PWM1OE = 0x01; //PWM1 Turn on
PWM1CONbits.PWM1EN = 0x01; //PWM1 Enable Output
PWM2DCH = 0x00;
PWM2DCL = 0x00;
PWM1DCH = 0x00;
PWM1DCL = 0x00;
PWM2DCH = 0xBF;
PWM2DCL = 0x00;
//LED breathing effect
for(int i=0;i<212;i++){
PWM1DCH = i;
__delay_ms(25);
}
for(int i=212;i>0;i--){
PWM1DCH = i;
__delay_ms(25);
}
}
}
}
Your timer overflow formula seems to be wrong.
Overflows every 128ms
is not true, I think you confused here. Time for 8 bit count is 0.000128s which is 128 microseconds for each timer overflow. So your loop count must be:
for one second delay loop cnt = 1000000*(1/128) = 7812,5
You must re-calculate the rest based on this corrected value. For the touch input you must ensure that you receive proper touch signals because we cannot diagnose it without seeing.
I have given the following C-Code to test a 60V DC motor with gear box ratio 16:1 and incremental encoder to see if the code calculates the speed by reading the Pulse signal as feedback for µcontroller from encoder. The µcontroller is ATmega88A-UA. The encoder RE56-3-1000 TI signals 1000 ppr.
The DC motor on special occasions needs to be run at 3-4 RPM for specific task.
At lower speed such as less than 5V where motor has starting voltage of 1.8V, the software seems to calculating the incorrect speed values.
When at low speeds the mode is TCCR1B == 0x02, the speed value is relatively higher ranging from 255 - 1071 at 2V-5V and frequency 751Hz -3.6kHz accordingly.
When the mode is switched to TCCR1B == 0x01, the speed values calculated/observed (by debugging) ranges from 471 - 1140 at 8V - 20V and frequency from 6.2kHz - 17.4kHz.
What I have also observed that the mode TCCR1B keep switching between 0x01 & 0x02 specially at frequency between 2kHz and 4kHz.
Does any one understands what might be the trouble with incorrect value calculations. Is there some sort of timing problem? The speed variable used is an unsigned int. I need your help.
There is a great possibility that things might not be well explained. I'll try my best to give right answers. The prodcut links are included in the description.
Any kind of help/suggestions would be very much appreciated. Thanks
#include "iom88.h"
#include "main.h"
unsigned int Test_Speed_low; //For testing only!!
unsigned int Test_Speed_1; //For testing only!!
unsigned int Test_Speed_2; //For testing only!!
unsigned int Test_Value_Timer_2; //For testing only!!
int main(void)
{
// 1 rpm -> 1000 / 60 = 16,6 Pulse/s -> 1000 / 16,6 = 60,25 ms/Pulse
// 10 rpm -> 10000 / 60 = 166 Pulse/s -> 1000 / 166 = 6,025 ms/Pulse
// 120 rpm -> 120000 / 60 = 2000 Pulse/s -> 1000 / 2000 = 0,5 ms/Pulse
// 2000 rpm -> 2000000 / 60 = 33333 Pulse/s -> 1000 / 33333 = 0,03 ms/Pulse
// 8 Mhz -> 0,125 us / Takt
// Timer1 CLK/8 -> 1 us / Timer cycle -> 65535 * 1 us = 62 ms -> ~ 1 rpm
// If pulse is faster than 0.5 ms then measure 10 im pulses with
// Timer1 CLK/1 -> 0,125 us / Timer cycle -> 65535 * 0,125 us = 8192 us = 8 ms
// 120 rpm -> 120000 / 60 = 2000 Pulse/s -> 10 Pulse = 5 ms -> 5000 us / 0,125 us = 40000 Timerticks
// 2000 rpm -> 2000000 / 60 = 33333 Pulse/s -> 10 Pulse = 0,3 ms -> 300 us / 0,125 us = 2400 Timerticks
PORTB = 0x00; // No Pullups
DDRB = 0x03; // PORTB_Bit0 = 1k3, Bit1 = 0R
PORTC = 0;
DDRC = 0x1F; // Out_0-4 Outputs 47k, 22k, 11k, 5k6, 2k7
PORTD = 0x20; // Pull-Up T1 (Bit5)
DDRD = 0x00;
ACSR = 0x80; // Disable Analog Comparator
DIDR1 = 0x03; // Disable input register on AIN0/AIN1
ADCSRA = 0xC7; // Clock / 128 slower is not possible, no INT
ADMUX = 0xC5; // Int 1,1V Ref, ADC5
DIDR0 = 0x20; // Disable input register on ADC5
TCCR0A = 0x02; // T0 CRC mode
TCCR0B = 0x06; // T0 External clock source on falling edge
OCR0A = 1; // CRC int after 1 clocktick
TIMSK0 = 0x02; // Timer 0 Compare match A int
TCCR1A = 0x00; // T1 normal mode
TCCR1B = 0x02; // clk/8 source on T1
TIMSK1 = 0x01; // Timer 1 Overflow int
Value_TCCR1B = TCCR1B;
Value_Timer1 = 60000;
Min_Timer1 = 60000;
Max_Timer1 = 0;
Counter_Timer1 = 0;
Test_Speed_1 = 0; //For testing only!!
Test_Speed_2 = 0; //For testing only!!
Test_Speed_low = 0; //For testing only!!
EAL = 1;
while(1)
{
if (TCCR1B == 0x02) {
if (Value_Timer1 <= 500) { // < 0,5 ms / Pulse
OCR0A = 8; // CRC int after 8 clocktick
TCNT0 = 0; // Reset timer 0 value
TCCR1B = 0; // stop T1
TCNT1 = 0; // Reset timer 1 value
TCCR1B = 1; // clk/1 source on T1
Value_TCCR1B = TCCR1B;
}
} else {
if (Value_Timer1 > 40000) { // > 0,5 ms / 10 Pulse //Slow Mode
OCR0A = 1; // CRC int after 1 clocktick
TCNT0 = 0; // Reset timer 0 value
TCCR1B = 0; // stop T1
TCNT1 = 0x1FF;
TCCR1B = 2; // clk/8 source on T1
Value_TCCR1B = TCCR1B;
}
}
if (Counter_Timer1 > 2) {
if (Value_Timer1 < Min_Timer1) {
Min_Timer1 = Value_Timer1;
}
if (Value_Timer1 > Max_Timer1) {
Max_Timer1 = Value_Timer1;
}
if (Counter_Timer1 > 1000) {
Counter_Timer1 = 0;
Min_Timer1 = 60000;
Max_Timer1 = 0;
}
}
if (TCCR1B == 0x02)
{
Test_Value_Timer_2 = (Value_Timer1/10); //For testing
Speed = (60000/Test_Value_Timer_2); // 0,1 RPM, at 60000 uS -> 1 RPM
Test_Speed_low = Speed;
}
else
{
if (Value_Timer1 > 10000)
{
Test_Value_Timer_2 = (Value_Timer1/100); //For Testing
Speed = (48000/Test_Value_Timer_2); // 1 RPM, at 5000 uS -> 120 RPM
Test_Speed_1 = Speed; //For testing only!!
}
else
{
Test_Value_Timer_2 = (Value_Timer1/10); //For testing
Speed = (48000/Test_Value_Timer_2); // 1 RPM, at 5000 uS -> 120 RPM
Speed *= 10;
Test_Speed_2 = Speed; //For testing only!!
}
}
}
}
#pragma vector=INT0_vect
__interrupt void INT0_int(void)
{
}
#pragma vector=INT1_vect
__interrupt void INT1_int(void)
{
}
#pragma vector=TIMER0_COMPA_vect
__interrupt void TIMER0_COMPA_int(void)
{
TCCR1B = 0; // Timer1 Stop
Value_Timer1 = TCNT1;
TCNT1 = 0; // Reset timer 1 value
TCCR1B = Value_TCCR1B;
Counter_Timer1++;
Counter_Int = 1;
}
#pragma vector=TIMER1_OVF_vect
__interrupt void TIMER1_OVF_int(void)
{
if (Timer1_OVF == 2) // Speed < 1,0 RPM
{
Speed = 0;
}
else
{
Timer1_OVF++;
}
}
I would say there are a few problems with the code, even if it is not very clear how the code reads the encoder.
First, fiddling with TCNT1 should be made only in interrupt, when you know the value of TCNT1 (about 0). Otherwise, you overwrite the counter and produce a data loss.
Second, you observed that TCCR1B switches quite fast, while it should not. Probably there is a need for some latency in this switching mechanism, otherwise when the speed of the motor is near the threshold, things get unstable.
Third, maybe it is not relevant, but: when is Timer1_OVF cleared?
Lastly, it seems to me that all the code is overly complicated, written and patched without a clear intent. For example, the variable Value_TCCR1B seems not useful...
If possible, I would try to start over: run the motor with a few different speeds, and measure those with the two possible values of TCCR1B; then look well at the data and try to reformulate the algorithm.
Just a thought; good luck!
I am using MPLAB XC8 to program pic18f45k22 to read data from 2 thermocouples. The code showed 2 problems, The first is that during simulation, the data from the sensor is shifted (sent to the second address)
for Example: if I have 2 addresses 0x0D and 0x0F, and 2 values 100 and 95, and 100 should got to 0x0D and 95 to 0x0F. However 100 goes to 0x0F and 95 to 0x0D.
**The second ** appears after uploading the code to the MCU, and it is that the MCU cannot Read any data from the sensors.
this is the main code:
void main(void) {
//SPI configuration
spiInit();
ANSELB = 0x00; //PORTB bits as digital
TRISB3 = 0; //GPIO as CS output
TRISB4 = 0;
TRISB5 = 0;
LATBbits.LATB3 = 1;
LATBbits.LATB4 = 1;
LATBbits.LATB5 = 1;
timer1init(); //initiate timer1
uartinit(9600); //initiate UART
__delay_ms(100);
while(1){
switch (cnt){ //timer interrupt routine every 1 second
//thermocouple code
case 50:
LATB3 = 0; //turn on CS
thercoup1 = spiRead(0)<<8; //Read first byte
thercoup1 |= spiRead(0); //add second byte with first one
LATB3 = 1; //turn off CS1
thercoup1 = (thercoup1>>4);
//thercoup1 = (thercoup1>>3)*0.25; //another method for calculating thermocouple value
LATB4 = 0; //turn on CS1
thercoup2 = spiRead(0)<<8; //Read first byte
thercoup2 |= spiRead(0); //add second byte with first one
LATB4 = 1; //turn off CS1
thercoup2 = (thercoup2>>4); //right shift of the reading
HMT_WriteVPN16(0x08000C, thercoup1); //send thermocouple1 data to 0x08000C
HMT_WriteVPN16(0x08000E, thercoup2); //send thermocouple2 data to 0x08000E
cnt = 0; //reset timer
break;
}
}
}
void __interrupt() ISR (void){
timer();
UART_Read();
}
And This is the configuration code of SPI module.
void spiInit(void)
{
ANSELC = 0x00;
SSP1STATbits.SMP = 0; //input Data is sampled at the middle
SSP1STATbits.CKE = 0; //Transmission occurs from Idle to Active
//Master mode Fosc/4
SSP1CON1bits.SSPM0 = 0;
SSP1CON1bits.SSPM1 = 0;
SSP1CON1bits.SSPM2 = 0;
SSP1CON1bits.SSPM3 = 0;
//
SSP1CON1bits.CKP = 1; //clock polarity is high
SSP1CON1bits.SSPEN = 1;//Serial communication is Enabled
SSP1CON1bits.SSPOV = 0;//Overflow is off
SSP1CON1bits.WCOL = 0;//Write collision is off
TRISCbits.RC5 = 1; //SDO is Disabled
TRISCbits.RC4 = 1; //SDI is Enabled
TRISCbits.RC3 = 0; //SCK is Enabled
}
unsigned short spiRead(unsigned char dat) //REad the received data
{
SSPBUF= dat; //the data loaded on the SSPBUF are not important.
while(!SSPSTATbits.BF); //save the received data from the slave.
return(SSPBUF);
}
As the tittle states I am trying to initialize PWM for PB4 on the TM4C123 microcontroller using Keil as the IDE. So far I have been able to initialize PB6 and PB7 but i'm not sure why PB4 isn't working. Do you guys know whats I'm doing wrong? Thanks in advance for your help. I have posted my working code for initalizing port B6 and the one that isnt working for port B4.
// PWM clock rate = processor clock rate/SYSCTL_RCC_PWMDIV
// = BusClock/16
// = 80 MHz/16 = 5 MHz
// Output on PB7/M0PWM1
void PWM0B4_Init(uint16_t period, uint16_t duty)
{
volatile unsigned long delay;
SYSCTL_RCGCPWM_R |= 0x01; // 1) activate PWM0
SYSCTL_RCGCGPIO_R |= 0x02; // 2) activate port B
// delay = SYSCTL_RCGCGPIO_R; // allow time to finish activating
while((SYSCTL_PRGPIO_R&0x02) == 0){};
GPIO_PORTB_AFSEL_R |= 0x10; // enable alt funct on PB4
GPIO_PORTB_PCTL_R &= ~0x000F000; // configure PB4 as M0PWM2
GPIO_PORTB_PCTL_R |= 0x0004000;
GPIO_PORTB_AMSEL_R &= ~0x10; // disable analog functionality on PB4
GPIO_PORTB_DEN_R |= 0x10; // enable digital I/O on PB4 ** double check **
SYSCTL_RCC_R = 0x00100000 | // 3) use PWM divider
(SYSCTL_RCC_R & (~0x000C0000)); // configure for /16 divider
PWM0_1_CTL_R = 0; // 4) re-loading down-counting mode
PWM0_1_GENB_R = (PWM_1_GENB_ACTCMPBD_ONE|PWM_1_GENB_ACTLOAD_ZERO);
// PB4 goes low on LOAD
// PB4 goes high on CMPB down
PWM0_1_LOAD_R = period - 1; // 5) cycles needed to count down to 0
PWM0_1_CMPB_R = duty - 1; // 6) count value when output rises
PWM0_1_CTL_R |= 0x00000001; // 7) start PWM0
PWM0_ENABLE_R |= 0x00000004; // enable PB4/M0PWM2 **** check
}
// change duty cycle of PB4
// duty is number of PWM clock cycles output is high (2<=duty<=period-1)
void PWM0B4_Duty(uint16_t duty)
{
PWM0_1_CMPB_R = duty - 1; // 6) count value when output rises
}
void PWM0B6_Init(uint16_t period, uint16_t duty)
{
SYSCTL_RCGCPWM_R |=0x01; // 1) activate PWM0
SYSCTL_RCGCGPIO_R|=0x02; // 2) activate portB
while ((SYSCTL_PRGPIO_R&0x02) == 0) {};
GPIO_PORTB_AFSEL_R |= 0x40; // enable alt funct on PB6
GPIO_PORTB_PCTL_R &= ~0x0F000000; // configure PB6 as PWM0
GPIO_PORTB_PCTL_R |= 0x04000000;
GPIO_PORTB_AMSEL_R &= ~0x40; // disable analog functionality on PB6
GPIO_PORTB_DEN_R |= 0x40; // enable digital I/O on PB6
SYSCTL_RCC_R = 0x00100000 | // 3) use PWM divider
(SYSCTL_RCC_R & (~0x000C0000)); // configure for /16 divider to C
PWM0_0_CTL_R = 0; // 4) re-loading down-counting mode
PWM0_0_GENA_R = 0xC8; // low on LOAD, high on CMPA down
// PB6 goes low on LOAD
// PB6 goes high on CMPA down
PWM0_0_LOAD_R = period - 1; // 5) cycles needed to count down to 0
PWM0_0_CMPA_R = duty - 1; // 6) count value when output rises
PWM0_0_CTL_R |= 0x00000001; // 7) start PWM0
PWM0_ENABLE_R |= 0x00000001; // enable PB6/M0PWM0
}
// change duty cycle of PB6
// duty is number of PWM clock cycles output is high (2<=duty<=period-1)
void PWM0B6_Duty(uint16_t duty)
{
PWM0_0_CMPA_R = duty - 1; // 6) count value when output rises
}
Hi I have a PIC32MX370F512L from microchip.
I want to use TIMER2 and TIMER3 as a 32-bit timer for interrupts.
I CAN use 16-bit Timer interrupt but CAN'T use 32-bit Timer interrupt, I will show you both codes:
16-bit timer:
void init16(){
T2CONbits.ON = 0; //Timer disabled
T2CON = 0; //Stop any 16-bit Timer2 operation
T2CONbits.T32 = 0; //16 bit mode on, tmr2
T2CONbits.TCKPS = 0b100; //prescaler
T2CONbits.TCS = 0; //Select internal peripheral clock
PR2 = 0x0000FFFF;
TMR2 = 0; //Clear contents of TMR2
T2CONbits.ON = 1; //Timer enable
//====INTERRUPT PART========
IEC0bits.T2IE = 0; //Disable interrupt
IPC2bits.T2IP = 1; //Priority 1
//IPC3bits.T3IS = 0; //Sub-priority 3
IFS0bits.T2IF = 0; //Interrupt flag putted at zero
//IFS0bits.T3IF = 0; //Interrupt flag putted at zero
IEC0bits.T2IE = 1; //Enable interrupt
}
32-bit timer:
void init32(){
T2CONbits.ON = 0; //Timer disabled
T2CON = 0; //Stop any 16/32-bit Timer2 operation
T3CON = 0; //Stop any 16-bit Timer3 operation
T2CONbits.T32 = 1; //32 bit mode on, tmr2 + tmr3
T2CONbits.TCKPS = 0b100; //Prescaler
T2CONbits.TCS = 0; //Select internal peripheral clock
PR2 = 0x000FFFFF;
//PR3 = 0;
TMR2 = 0; //Clear contents of TMR2 and TMR3
T2CONbits.ON = 1; //Timer enable
//====INTERRUPT PART========
IEC0bits.T3IE = 0; //Disable interrupt
IPC3bits.T3IP = 1; //Priority 1
//IPC3bits.T3IS = 0; //Sub-priority 0
IFS0bits.T3IF = 0; //Interrupt flag putted at zero
//IFS0bits.T3IF = 0; //Interrupt flag putted at zero
IEC0bits.T3IE = 1; //Enable interrupt
}
main :
#include <stdio.h>
#include <stdlib.h>
#include <p32xxxx.h>
#include <plib.h>
#include "timer32Interrupt.h"
#include <xc.h>
/* Disable JTAG to use RA0 */
#pragma config JTAGEN = OFF
#pragma config FWDTEN = OFF //Watchdog disabled
/* Device Config Bits in DEVCFG1: */
#pragma config FNOSC = FRCPLL //Fast RC Osc with PLL
#pragma config FSOSCEN = OFF //Secondary Oscillator disabled
#pragma config POSCMOD = XT //Primary Oscillator mode: Resonator, crystal or resonator
#pragma config OSCIOFNC = ON //CLKO Output Signal Active on the OSCO Pin
#pragma config FPBDIV = DIV_2 //Peripheral Clock Divisor: PBCLK is SYSCLK divided by 2
/* Device Config Bits in DEVCFG2: */
#pragma config FPLLIDIV = DIV_2 //PLL Input Divider
#pragma config FPLLMUL = MUL_20 //PLL Multiplier
#pragma config FPLLODIV = DIV_2 //System PLL Output Clock Divider: PLL Divide by 2
void main(){
TRISA = 0;
LATA = 0;
LATAbits.LATA0 = 1;
//LATAbits.LATA0 =~LATAbits.LATA0
INTEnableSystemMultiVectoredInt();
init32();
//init16();
while(1){
int i = 0;
if(TMR2 >= PR2 - 10 ){
//LATAbits.LATA0 =~LATAbits.LATA0;
//LATAbits.LATA2 =~LATAbits.LATA2;
LATAINV = 0b10;
}
}
}
void __ISR(_TIMER_2_VECTOR, ipl1)Timer32Handler(void){
LATAINV = 0b101;
IFS0bits.T3IF = 0; //Interrupt flag putted at zero
IFS0bits.T2IF = 0; //Interrupt flag putted at zero
}
The 16 bit implementation works and the 32 not, enabling interrupt on TIMER3 and not on TIMER2 is required in the data-sheet, section 14.3.4 of the timers.
Like said by #Sudhee for making the code work I should replace only this part:
_TIMER_2_VECTOR became _TIMER_3_VECTOR
void __ISR(_TIMER_3_VECTOR, ipl1)Timer32Handler(void){
LATAINV = 0b101;
IFS0bits.T3IF = 0; //Interrupt flag putted at zero
IFS0bits.T2IF = 0; //Interrupt flag putted at zero
}