Controlling a DC motor with a PIC 18 PWM - c

Im using the PIC 18 microcontroller to control the speed of a DC Motor using PWM. I have managed to get it to spin using the code below. And I have tested that my H-Bridge is 100% functional.
However, when I switch on my circuit, 12V to the Motor and 5V to the logic, And I send a command to the circuit using my RS232 communication module, (which I have tested and it recieves and transmits correctly), the program resets and the current on the bench power supply falls to 0A. Sometimes the motor jerks slighty, almost as if its trying to spin, but then stops.
Any ideas where I could be going wrong?
/*
* File: serial.c
* Author: Chris Lombaard
*
* Created on September 13, 2013, 2:39 PM
*/
#pragma config FOSC = INTIO7 // Oscillator Selection bits (Internal oscillator block, CLKOUT function on OSC2)
#pragma config PLLCFG = OFF // 4X PLL Enable (Oscillator used directly)
#pragma config PRICLKEN = ON // Primary clock enable bit (Primary clock is always enabled)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)
#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)
#pragma config PWRTEN = OFF // Power-up Timer Enable bit (Power up timer disabled)
#pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled))
#pragma config BORV = 190 // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)
#pragma config WDTEN = OFF // Watchdog Timer Enable bits (WDT is always enabled. SWDTEN bit has no effect)
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
#pragma config CCP2MX = PORTC1 // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON // PORTB A/D Enable bit (PORTB<5:0> pins are configured as analog input channels on Reset)
#pragma config CCP3MX = PORTB5 // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)
#pragma config HFOFST = ON // HFINTOSC Fast Start-up (HFINTOSC output and ready status are not delayed by the oscillator stable status)
#pragma config T3CMX = PORTC0 // Timer3 Clock input mux bit (T3CKI is on RC0)
#pragma config P2BMX = PORTD2 // ECCP2 B output mux bit (P2B is on RD2)
#pragma config MCLRE = EXTMCLR // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled if MCLRE is also 1)
#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))
#pragma config CP0 = OFF // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)
#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)
#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)
#pragma config WRT0 = OFF // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)
#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)
#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)
#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)
#pragma config EBTR0 = OFF // Table Read Protection Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)
#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)
#include <P18F45K22.h>
#include <xc.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000
#define length(x) (sizeof(x) / sizeof(x[0])) //Length of array
void writeUART(const unsigned char string[]);
void setup(void);
void inputCheck(void);
void stepF(void);
void stepB(void);
unsigned char buffer[8] = {'\0'};
unsigned char prevPos = 0;
unsigned char currPos = 0;
unsigned char bufferLength;
unsigned char direction = 0;
unsigned char speed = 0;
unsigned char isSetup = 0;
char main(void){
if(isSetup == 0){
setup();
writeUART("ERD 320 Practical 2 ----- Group 1\n");
writeUART("JC Lombaard - 11028786\n");
writeUART("VFDC Henriques - 11100232\n");
writeUART("William Reeler - 11228866\n");
writeUART("FAN POSITION: 1");
PORTDbits.RD1 = 1;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 0;
PORTAbits.RA6 = 0;
}
while(1){
if(PORTEbits.RE1 == 1)
stepB();
if(PORTEbits.RE0 == 1){
writeUART("\nFan calibrated!\n");
break;
}
}
bufferLength = 0;
while (1);
return (EXIT_SUCCESS);
}
void interrupt high_priority isr_high(void) {
if(PIR1bits.RC1IF == 1){
if(RCREG1 == '\n'){
buffer[bufferLength++] = '\0';
bufferLength = 0;
inputCheck();
}else{
buffer[bufferLength++] = RCREG1;
PIR1bits.RC1IF = 0;
}
}
}
void interrupt low_priority isr_low(void){
PIR1bits.TMR2IF = 0;
TMR2 = 0;
}
void inputCheck(void) {
const unsigned char commands[11][3] = {"S0", "S1", "S2", "S3", "S4", "P1", "P2", "P3", "P4", "R", "F"};
unsigned char choice = 0;
for(; choice < 11; choice++)
if (strcmp(buffer, commands[choice]) == 0){
break;
}
switch(choice){
case 0:
writeUART("FAN SPEED: 0% DC");
PORTA = 0b00111111;
speed = 0;
if(direction == 0){
CCPR1L = 0x00;
}else{
CCPR2L = 0x00;
}
break;
case 1:
writeUART("FAN SPEED: 10% DC");
PORTA = 0b00000110;
speed = 0b01101110 ;
if(direction == 0){
CCPR1L = 0b11010000 ;
__delay_ms(100);
CCPR1L = 0b01101110 ;
}else{
CCPR2L = 0b11010000 ;
__delay_ms(100);
CCPR2L = 0b01101110 ;
}
break;
case 2:
writeUART("FAN SPEED: 30% DC");
PORTA = 0b01011011;
speed = 0b10001100;
if(direction == 0){
CCPR1L = 0b11010000;
__delay_ms(100);
CCPR1L = 0b10001100;
}else{
CCPR2L = 0b11010000 ;
__delay_ms(100);
CCPR2L = 0b10001100 ;
}
break;
case 3:
writeUART("FAN SPEED: 60% DC");
PORTA = 0b01001111;
speed = 0b10101101;
if(direction == 0){
CCPR1L = 0b11010000 ;
__delay_ms(100);
CCPR1L = 0b10101101 ;
}else{
CCPR2L = 0b11010000 ;
__delay_ms(100);
CCPR2L = 0b10101101 ;
}
break;
case 4:
writeUART("FAN SPEED: 90% DC");
PORTA = 0b01100110;
speed = 0b11010000 ;
if(direction == 0){
CCPR1L = 0b11010000;
}else{
CCPR2L = 0b11010000;
}
break;
case 5:
currPos = 1;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
}
writeUART("FAN POSITION: 1");
PORTDbits.RD1 = 1;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 0;
prevPos = currPos;
break;
case 6:
prevPos = currPos;
currPos = 2;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
for(int i = currPos+1; i > prevPos; i--)
stepF();
}
writeUART("FAN POSITION: 2");
PORTDbits.RD1 = 0;
PORTDbits.RD0 = 1;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 0;
prevPos = currPos;
break;
case 7:
prevPos = currPos;
currPos = 3;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
for(int i = currPos+1; i > prevPos; i--)
stepF();
}
writeUART("FAN POSITION: 3");
PORTDbits.RD1 = 0;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 1;
PORTCbits.RC0 = 0;
prevPos = currPos;
break;
case 8:
prevPos = currPos;
currPos = 4;
if(prevPos > currPos){
for(int i = prevPos+1; i > currPos; i--)
stepB();
}else{
for(int i = currPos+1; i > prevPos; i--)
stepF();
}
writeUART("FAN POSITION: 4");
PORTDbits.RD1 = 0;
PORTDbits.RD0 = 0;
PORTCbits.RC3 = 0;
PORTCbits.RC0 = 1;
prevPos = currPos;
break;
case 9:
direction = 1;
CCP1CON = 0b00000000;
CCP2CON = 0b00111100;
CCPR2L = speed;
writeUART("FAN DIRECTION: REVERSED");
break;
case 10:
direction = 0;
CCP1CON = 0b00111100;
CCP2CON = 0b00000000;
CCPR1L = speed;
writeUART("FAN DIRECTION: FORWARD");
break;
default:
break;
}
}
void stepF(void){
for(int i = 0; i < 1; i++){
PORTB = 0b0001;
__delay_ms(100); //Delay between transitions
PORTB = 0b0010;
__delay_ms(100); //Delay between transitions
PORTB = 0b0100;
__delay_ms(100); //Delay between transitions
PORTB = 0b1000;
__delay_ms(100); //Delay between transitions
}
}
void stepB(void){
for(int i = 0; i < 1; i++){
PORTB = 0b1000;
__delay_ms(100); //Delay between transitions
PORTB = 0b0100;
__delay_ms(100); //Delay between transitions
PORTB = 0b0010;
__delay_ms(100); //Delay between transitions
PORTB = 0b0001;
__delay_ms(100); //Delay between transitions
}
}
void defaultPos(void){
PORTB = 0b1000;
__delay_ms(100); //Delay between transitions
PORTB = 0b0100;
__delay_ms(100); //Delay between transitions
PORTB = 0b0010;
__delay_ms(100); //Delay between transitions
PORTB = 0b0001;
__delay_ms(100); //Delay between transitions
}
void writeUART(const unsigned char string[]){
for(unsigned char j = 0; j < strlen(string); j++){
TXREG1 = string[j];
__delay_us(1000);
}
}
void setup(void){
isSetup = 1;
//PORTC
PORTC = 0x00;
LATC = 0x00;
TRISC = 0xC0; //Set RC6 & RC7 as inputs for EUSART
TRISCbits.RC6 = 0;
TRISCbits.RC7 = 1;
ANSELC = 0x00;
//PORTD
PORTD = 0x00;
LATD = 0x00;
TRISD = 0x00;
ANSELD = 0x00;
//PORTE
PORTE = 0x00;
LATE = 0x00;
TRISEbits.RE0 = 1;
TRISEbits.RE1 = 1;
ANSELE = 0x00;
//PORTB
PORTB = 0x00;
LATB = 0x00;
TRISB = 0x00;
ANSELB = 0x00;
PORTA = 0x00;
LATA = 0x00;
TRISA = 0x00;
ANSELA = 0x00;
//Oscillator
OSCCON = 0b01011100; //4 MHz oscillator
//EUSART
TXSTA1bits.BRGH = 1; //Highspeed baudrate
BAUDCON1bits.BRG16 = 0;
SPBRG1 = 12; //Baudrate of 19230 (FOSC = 4 MHz, BRGH = 1, BRG16 = 0)
TXSTA1bits.SYNC = 0; //Asynchronous
RCSTA1bits.SPEN = 1; //Enable rx & tx pins as serial pins
RCSTA1bits.CREN = 1; //Enable continuous reception, enable receiver
TXSTA1bits.TXEN = 1; //Enable transmitter
TXREG1 = 0x00;
RCREG1 = 0x00;
//Interrupts
RCONbits.IPEN = 1; //Enable priorities
INTCONbits.GIE_GIEH = 1; //Enable high priority interrupts
INTCONbits.PEIE_GIEL = 1; //Enable low priority interrupts
PIE1bits.TMR2IE = 1;
IPR1bits.TMR2IP = 0;
PIE1bits.RC1IE = 1; //Enable RX interrupt
PIR1bits.RC1IF = 0; //Clear interrupt flag
IPR1bits.RC1IP = 1; //High priority for RX interrupts
//PWM
PR2 = 0b11111001 ;
T2CON = 0b00000100; //1 KHz pulse frequency on CCP1 pin
CCPR1L = 0x00;
CCPR2L = 0x00;
CCP1CON = 0b00111100;
CCP2CON = 0b00000000;
TMR2 = 0;
}

A few suggestions,
Oscilliscope?
test with a light bulb rather than a DC motor, less current and voltage drop
this smells like a hardware problem

Related

error: (1089) recursive function call to "_forward_flight" XC8 compiler

I am trying to emulate a pingpong game with LED's showing the flight of the ball. Two players using buttons connected to RA0 and RA1 control the flight of the ball. Game starts with either pressing their respective button. I have two functions, forward_flight and reverse_flight which light the led's from player one two player 2 and vice versa. Player 2 has two return the ball by pressing his button when Led connected to RB7 is on and player 1 has to return the ball when led at RB0 is on. The game continues until one of them reaches a score of 9. I am using PORTB as output for the LED's. I am using PIC16F873A programming it in c. Below is the configuration and source code:
// PIC16F873A Configuration Bit Settings
// 'C' source line config statements
// CONFIG
#pragma config FOSC = XT // Oscillator Selection bits (XT oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#include <xc.h>
#define _XTAL_FREQ 20000
unsigned char x = 0;
unsigned char y = 0;
unsigned char h;
unsigned char sc;
unsigned char lookup(unsigned char sc);
void forward_flight();
void reverse_flight();
void game_Over();
void forward_flight(){
PORTBbits.RB0 = 1;
__delay_ms(50);
PORTBbits.RB0 = 0;
PORTBbits.RB1 = 1;
__delay_ms(50);
PORTBbits.RB1 = 0;
PORTBbits.RB2 = 1;
__delay_ms(50);
PORTBbits.RB2 = 0;
PORTBbits.RB3 = 1;
__delay_ms(50);
PORTBbits.RB3 = 0;
PORTBbits.RB4 = 1;
__delay_ms(50);
PORTBbits.RB4 = 0;
PORTBbits.RB5 = 1;
__delay_ms(50);
PORTBbits.RB5 = 0;
PORTBbits.RB6 = 1;
__delay_ms(50);
PORTBbits.RB6 = 0;
PORTBbits.RB7 = 1;
while(PORTBbits.RB7){
if(PORTAbits.RA1==1){
reverse_flight();
}
else if(PORTAbits.RA1==0){
__delay_ms(50);
PORTBbits.RB7 = 0;
x++;
if(x<=9){
PORTC = lookup(x);
}else{
game_Over();
break;
}
}
}
return;
}
void reverse_flight(){
PORTBbits.RB7 = 1;
__delay_ms(50);
PORTBbits.RB7 = 0;
PORTBbits.RB6 = 1;
__delay_ms(50);
PORTBbits.RB6 = 0;
PORTBbits.RB5 = 1;
__delay_ms(50);
PORTBbits.RB5 = 0;
PORTBbits.RB4 = 1;
__delay_ms(50);
PORTBbits.RB4 = 0;
PORTBbits.RB3 = 1;
__delay_ms(50);
PORTBbits.RB3 = 0;
PORTBbits.RB2 = 1;
__delay_ms(50);
PORTBbits.RB2 = 0;
PORTBbits.RB1 = 1;
__delay_ms(50);
PORTBbits.RB1 = 0;
PORTBbits.RB0 = 1;
while(PORTBbits.RB0){
if(PORTAbits.RA0==1){
forward_flight();
}
else if(PORTAbits.RA0==0){
__delay_ms(50);
PORTBbits.RB0 = 0;
y++;
if(y<=9){
PORTC = lookup(y);
}else{
game_Over();
break;
}
}
}
return ;
}
unsigned char lookup(unsigned char sc){
switch(sc){
case 0: sc = 0x00; break;
case 1: sc = 0x01; break;
case 2: sc = 0x02; break;
case 3: sc = 0x03; break;
case 4: sc = 0x04; break;
case 5: sc = 0x05; break;
case 6: sc = 0x06; break;
case 7: sc = 0x07; break;
case 8: sc = 0x08; break;
case 9: sc = 0x09; break;
}
return (sc);
}
void game_Over(){
x = 0;
y = 0;
}
void main(){
ADCON1 = 0xFF;
TRISAbits.TRISA0 = 1;
TRISAbits.TRISA1 = 1;
TRISB = 0x00;
PORTB = 0x00;
TRISC = 0x00;
PORTC = 0x00;
while(x <9 && y<9){
if(PORTAbits.RA0 == 1){
forward_flight();
}
else if(PORTAbits.RA1==1){
reverse_flight();
}
}
}
And this is the error I get.
source.c:14:: error: (1089) recursive function call to "_forward_flight"
source.c:66:: error: (1089) recursive function call to "_reverse_flight"
make[2]: *** [dist/default/production/Pingpong.X.production.hex] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2
(908) exit status = 1
nbproject/Makefile-default.mk:154: recipe for target 'dist/default/production/Pingpong.X.production.hex' failed
make[2]: Leaving directory 'C:/Users/PAKO MOARO/MPLABXProjects/Pingpong.X'
nbproject/Makefile-default.mk:91: recipe for target '.build-conf' failed
make[1]: Leaving directory 'C:/Users/PAKO MOARO/MPLABXProjects/Pingpong.X'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed

Why is my Timer2 interrupt not working? Am I missing any register configs?

I am working on a project with the pic10f322 microcontroller. I've made a very basic communication protocol - there is a start pulse (10 ms) followed by a number of 5ms pulses (2 pulses - turns on a red light, 3 turns on yellow and 4 - green). So the following code is trying to read the communication protocol and turn on the respective light. I'm using TMR0 to measure the length of the pulse and count it. I have a bicolour LED (Red and Green) so I need to alternate the two to create the yellow. I was hoping to use TMR2 as an interrupt to allow me to pulse the yellow light separately from the rest of the code, so that it doesn't get in the way of my main function detecting start pulses.
I have no idea why it isn't working. I've checked the registers (although please do double check incase I'm blind to something). The code compiles.
I turned the light on at various stages of the code to check it, and the light turns on in every case statement, include the last one where I set the LedColour enum variable to the respective colour. When I try to turn the light on in the interrupt function, it never turns on.
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <pic.h>
#include <stdbool.h>
#include <pic10f322.h>
// crystal oscilator
define _XTAL_FREQ 1000000
// CONFIG
#pragma config FOSC = INTOSC // Oscillator Selection bits
#pragma config BOREN = OFF // Brown-out Reset disabled
#pragma config WDTE = OFF // WDT disabled
#pragma config PWRTE = OFF // PWRT disabled
#pragma config MCLRE = OFF // MCLR pin function
#pragma config CP = OFF // Code Protection disabled
#pragma config LVP = ON // Low-voltage programming enabled
#pragma config LPBOR = OFF // Brown-out Reset disabled
#pragma config BORV = LO // Brown-out Reset Voltage, low trip point
#pragma config WRT = OFF // Flash Memory Write protection off
void timer2_isr(void);
#pragma code high_vector=0x08;
void interrupt (void)
{
asm("GOTO timer2_isr");
}
#pragma code
#pragma interrupt timer2_isr
#define RED_LED 0x01
#define GREEN_LED 0x02
#define SetBit(bit) (PORTA |= bit )
#define ClearBit(bit) (PORTA &= ~bit)
#define TestBit(bit) ( PORTA&bit)
int clkval = 0;
int pulsecnt = 0;
enum {
Red,
Green,
Yellow,
Off,
} LedColor = Off;
void timer2_isr (void)
{
PORTA = 0b1101; //This turns a green light on if it enters this function
if (PIR1 == 0x02)
{
PIR1 = 0x00;
}
}
void main(int argc, char** argv)
{
OSCCON = 0x30; //1MHz Clk
TRISA = 0x0C;
ANSELA = 0x00;
PORTA = 0x0C;
OPTION_REG = 0x06;
T2CON = 0x04; //Timer2 Registers Prescaler= 1 - TMR2 PostScaler = 1 - PR2 = 254 - Freq = 980.39 Hz - Period = 0.001020 seconds
PIE1 = 0x02;
PIR1 = 0x00;
TMR0 = 0;
TMR2 = 0;
PR2 = 254;
INTCON = 0xC0;
__delay_ms(2000);
enum {
WaitForStart,
CountPulses,
SelectColor,
} State = WaitForStart;
while (1)
{
switch (State)
{
case WaitForStart: //wait for start pulse
if ( (PORTA & 0x04) != 0x04 )
{
TMR0 = 0;
while ((PORTA & 0x04) != 0x04)
{
clkval = TMR0;
}
if (18 < clkval < 22)
{
State = CountPulses;
pulsecnt = 0;
}
}
break;
case CountPulses: // found start pulse, now count pulses or reset
if ( (PORTA & 0x04) != 0x04 )
{
TMR0 = 0;
while ((PORTA & 0x04) != 0x04)
{
clkval = TMR0;
}
if (8 < clkval < 12)
{
pulsecnt++;
}
}
if ((PORTA & 0x04) == 0x04)
{
clkval = 0;
TMR0 = 0;
while ((PORTA & 0x04) == 0x04 && clkval < 45)
{
clkval = TMR0;
if ((44 < clkval) || (pulsecnt > 4)) //no pulses noticed in over 22ms comparison or if you have surpassed the max number of pulses you are supposed to reach
{
if (pulsecnt > 0)
{
State = SelectColor;
} //if there has been a long delay, and pulses have been detect (so pulsecnt is greater than 0) then move to next case
else
{
State = WaitForStart;
} // if long delay and no pulses have been detected, restart and check for start pulse again
}
}
}
break;
case SelectColor: // if pulses have been detected, this state will be visited after long delay ( >22ms)
if (pulsecnt == 2)
{
LedColor = Red;
//PORTA = 0b1110;
State = WaitForStart;
}
else if (pulsecnt == 3)
{
LedColor = Yellow;
State = WaitForStart;
}
else if (pulsecnt == 4)
{
LedColor = Green;
//PORTA = 0b1101;
State = WaitForStart;
}
else
{
LedColor = Off;
State = WaitForStart;
}
break;
default:
State = WaitForStart;
break;
}
}
}
I used "PORTA = 0b1101", which turns the green light on. as a test line to step through the code and make sure it's reach certain points. Right now it is at the beginning of the interrupt, so it should turn on and stay on righht after the first interrupt which would happen within approximately 2.5ms I think? Or relatively quickly anyway, but it never gets inside the interrupt function or the function before which uses assembly to tell it to goto this function.
In PIC16, you need to start the timer separately from the rest of the config, like that:
T2CONbits.TMR2ON = 1;
Also, check that you have enabled the interrupts:
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;
I suggest using the above notation for initialization; what you have is hard to verify.
The PIC 10 has got only one interrupt vector and that is on address 0x04 (not 0x08 as you expected).
Try somethig like this:
void interrupt myISR(void)
{
........
}
This init function gets a TMR2 interrupting at high priority
on a PIC18F25K80
void pwm_mosfet_stepper_init() {
TMR2 = 0;
RCON |= (1<<7); // IPEN = 1;
PR2 = 100; // 100; // 100==#16uS 1.6ms
//
INTCON |= ( (1<<6) | (1<<7) ); // GIE/GIEH PEIE/GIEL i.e. both low and high enabled
// .......................... post4 ON pre4
//T2CON = 0x1D; // 2us tick ON 11 1 01
// .......................... post4 ON pre16
T2CON = 0x1F; // 16us tick ON 11 1 1X
IPR1 |= (1<<1); // TMR2IP = 1; HIGH PRIORITY
PIE1 |= (1<<1); // TMR2IE = 1; // interrupts are GO!
}

Can not take Analog read in PIC 12F675

In my code I want to read voltage from a battery and if the voltage greater than 3V then it off the LEDs.But the LED always on even when the voltage is 5v and when I add more LED in different GPIO and turn them 0/1 then the GPIO2 become off. I am using PIC12F675.
AN1 is my analog reader pin which is GPIO1.
GPI02 is my LED output pin.
// CONFIG
#pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/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 = ON // MCLR
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#define _XTAL_FREQ 4000000 // 4MHZ crystal
void main(void) {
unsigned int adcVal;
double voltage;
int i=0;
TRISIObits.TRISIO1 = 1;
TRISIObits.TRISIO2 = 0;
TRISIObits.TRISIO3 = 0;
ANSELbits.ADCS0 = 1;
ANSELbits.ADCS1 = 0;
ANSELbits.ADCS2 = 1; //FOSC/16
ANSELbits.ANS1 = 1; //channel 2
ADCON0bits.CHS0 = 1;
ADCON0bits.CHS1 = 0; //AN1
ADCON0bits.ADON = 1; //Turn it on
ADCON0bits.GO = 1;
ADCON0bits.ADFM = 1;
while (1) {
__delay_us(5);
ADCON0bits.ADON = 1;
GO_nDONE = 1;
while (GO_nDONE); //Wait for ADC to complete
adcVal = (((unsigned int) ADRESH << 8) + ADRESL);
ADCON0bits.ADON = 0;
voltage = ((double) (adcVal / 1023)*5.0);
if (voltage >= 3.0) {
GPIObits.GP2 = 0; //LED off
} else {
GPIObits.GP2 = 1; // LED On/
}
}
}
Your calculation adcVal/1023 is an integer calculation and for a range 0 ... 1023 for adcVal always 0 (or 1 for 1023).
Best thing is to avoid the float calculatin at all:
// CONFIG
#pragma config FOSC = INTRCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/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 = ON // MCLR
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
#pragma config CP = OFF // Code Protection bit (Program Memory code protection is disabled)
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled)
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
#include <xc.h>
#define _XTAL_FREQ 4000000 // 4MHZ crystal
void main(void) {
unsigned int adcVal;
double voltage;
int i=0;
TRISIObits.TRISIO1 = 1;
TRISIObits.TRISIO2 = 0;
TRISIObits.TRISIO3 = 0;
ANSELbits.ADCS0 = 1;
ANSELbits.ADCS1 = 0;
ANSELbits.ADCS2 = 1; //FOSC/16
ANSELbits.ANS1 = 1; //channel 2
ADCON0bits.CHS0 = 1;
ADCON0bits.CHS1 = 0; //AN1
ADCON0bits.ADON = 1; //Turn it on
ADCON0bits.GO = 1;
ADCON0bits.ADFM = 1;
while (1) {
__delay_us(5);
ADCON0bits.ADON = 1;
GO_nDONE = 1;
while (GO_nDONE); //Wait for ADC to complete
adcVal = (((unsigned int) ADRESH << 8) + ADRESL);
ADCON0bits.ADON = 0;
if (adcVal >= 614) { //value for 3.0V
GPIObits.GP2 = 0; //LED off
} else {
GPIObits.GP2 = 1; // LED On/
}
}
}

TIMER 32-bit on pic32 can't use interrupts

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
}

Can't get PWM to work on PIC16F877 (PICC)

I've been trying to use the PWM module on a PIC16F877 MCU but all I get is a flat low level on both CCP1/CCP2 pins.
The code configuring and starting the PWM module is the following.
// Configure PWM
// Timer 2 (PWM timebase)
TMR2 = 0; //Clear timer
TOUTPS0 = 0;
TOUTPS1 = 0;
TOUTPS2 = 0;
TOUTPS3 = 1; //Postscaler -> 8 (previously set to 0)
T2CKPS0 = 0;
T2CKPS1 = 1; //Prescaler -> 16
TMR2IF = 0;
TMR2IE = 1; //Interrupt
PR2 = 233; //~2.5ms
//PWM1 config
CCPR1L = 0x0F;
CCP1X = 0;
CCP1Y = 0; //PWM1 duty cycle
TRISB2 = 0; //CCP1 pin is output (Error is here, see below)
TMR2ON = 1; //Enable timer
CCP1CON = 0x0c; //CPP1 is a PWM
Any code (PICC) which can successfully start the PWM on pic16 devices whould be useful.
CCP1 Pin was not being correctly set. 'TRISB2 = 0' should be 'TRISC2 = 0'
// Timer 2 (PWM timebase)
TMR2 = 0; //Clear timer
TOUTPS0 = 0;
TOUTPS1 = 0;
TOUTPS2 = 0;
TOUTPS3 = 1; //Postscaler -> 8
T2CKPS0 = 0;
T2CKPS1 = 1; //Prescaler -> 16
TMR2IF = 0;
TMR2IE = 1; //Interrupt
PR2 = 233; //~2.5ms
//PWM1 config
CCPR1L = 0xFF;
CCP1X = 1;
CCP1Y = 1; //PWM1 duty cycle
TRISC2 = 0; //Previously was TRISB2
TMR2ON = 1;
CCP1CON = 0x0c; //CPP1 is a PWM

Resources