I'm going to learn how to work with timers and interrupts using ARM micro-controllers. This is my code:
#include "LPC17xx.h"
int flag=0;
void TIMER0_RIQHandler(void)
{
if (flag == 0 )
{
LPC_GPIO1 -> FIOSET = 1 «28; //turn on LED
flag =1;
}
else
{
LPC_GPIO1 -> FIOCLR = 1 «28; //turn off LED
flag=1;
}
LPC_TIM0 -> IR = 1 ; //clear interrupt flag
}
int main()
{
LPC_TIM0 -> CTCR = 00; //set timer mode
LPC_TIM0 -> PR = 1;
LPC_TIM0 -> MR0 = 12000000;
LPC_TIM0 -> MCR = 3 ; //IF PC REACHES PR, TC will BE
//RESET AND INTERRUPT WILL BE GENERATE
LPC_TIM0 -> TCR = 2; //RESET TIMER
NVIC_SetPriority(TIMER0_IRQn , 0 );
NVIC_EnableIRQ(TIMER0_IRQn);
LPC_TIM0 ->TCR = 1; //ENABLE TIMER
LPC_GPIO1 -> FIODIR = 1 « 28 ;
LPC_GPIO1 -> FIOCLR = 1 « 28 ;
while (1)
{
}
}
it's supposed to turn on and turn off the LED every sec.
at the first the LED turns off but interrupt doesn't work.
what is wrong with my code ?
The name of your Interrupt Service Routine (ISR) is not correct. I believe it should be TIMER0_IRQHandler. It should match the name that appears in the startup file startup_LPC17xx.s
Because of this mismatch, the interrupt is triggered, but there is no corresponding ISR to be called.
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 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!
}
I need to program a PIC16F883 to blink / light up LED's at the same time. The oscillator is running at 3,2768, and I'm using TIMER0 to help me with the timing.
Right now, I have a prescaler set to 1:256, so I get an interrupt every 50ms, and I have a variable that is calculated from that, to display how many seconds has gone.
If the input is changed, the seconds variable is of course reset again.
Here is the assignment from my teacher:
If Input is 0 (Closed):
The Red And The Green LED should be turned on at the same time for 15 seconds. After this the green LED should be turned
off completely, and the red LED should blink every fifth second for 10 minutes
If input is 1 (Opened):
The red LED should be turned off completely, and the green LED should be turned on for 10 minutes, and after that
it should be turned off too.
My timer is working fine. I have tested that. The program runs fine too and keeps the 2 LED's turned off for 15 seconds, then turns them off, but my red LED isn't blinking. I have been sitting at my desk all day desperately trying to find the error in my code.
Picture of the print:
Here is my C Code. I am using MPLab and the HI-TECH C compiler :)
#include <pic.h>
//Variabler
int B = 0; //Definerer variablen B, used as a flag
int A = 0; //Definerer veriablen A, used as a flag
int E = 0;
int savedstatus = 1; //Definere variablen savedstatus used to check last status for input
int millicounter = 0; //Variabel to calculate seconds
int sec = 0; //Variabel holding seconds gone
int count = 0; //For counting seconds passed, used in input0 subroutine
int onesec = 0; //Used to counting seconds for blinking LED in input0 subroutine
int scount = 0;
//Variabler slut
void interrupt jesper(void)
{
T0IF = 0x00;
TMR0 = 96;
millicounter++;
if(millicounter == 20)
{
sec++;
millicounter = 0;
}
}
//Subrutines
void input0()
{
if(sec<=15 && E==0)
{
PORTA = 0x21;
}
else if(A==0)
{
scount = 0;
sec = 0;
count = sec;
A = 1;
E = 1;
}
else if(sec<=600 && sec>count)
{
count++;
if((scount+5)>=count)
{
if(B==0)
{
onesec = sec;
B = 1;
PORTA = 0x01;
}
else if(sec>onesec)
{
PORTA = 0x00;
B = 0;
scount = count;
scount;
}
else
{
PORTA = 0x01;
}
}
else
{
PORTA = 0x00;
}
}
else PORTA = 0x00;
}
void input1()
{
if(sec<=600)
{
PORTA = 0x20;
}
else
{
PORTA = 0x00;
}
}
//Subrutines over
int main(void)
{
TRISA = 0x00; //Sets all A-PORTS to output
TRISB = 0x01; //Sets all PORTB to output with the exception of BIT0
TRISC = 0x00; //Sets All PORTC to output
ANSEL = 0x00; //Disable Analog ports
ANSELH = 0x00; //Disable Analog ports
//Timer Config
PSA = 0x00;
PS0 = 0x01;
PS1 = 0x01;
PS2 = 0x01;
TMR0 = 0x60;
GIE = 0x01;
T0IE = 0x01;
T0IF = 0x00;
T0CS = 0x00;
//Timer Config Over
while(0x01)
{
if(savedstatus != RB0)
{
savedstatus = RB0;
sec = 0;
E = 0;
A = 0;
}
if(savedstatus == 1)
{
input1();
}
else
{
input0();
}
}
}
I really hope that you can help me here :)
Here is my flowchart for the subroutine input0 where my problem is. Btw some of my variables have different names in the code itself, but it shouldn't be hard to see.
Your main() calls input0() as often as possible. When input0() is in the flashing state it uses the conditional sec > count. I suspect that your intention is that input0() should only change the LED state at intervals of a second. But then on the else side of that conditional you turn both LEDs off. This else side is executing many times because main() is calling input0() so often. Try deleting the else condition where you turn the LEDs off.
void input0()
{
<snip>
else if(sec<=600 && sec>count)
{
<snip>
}
else PORTA = 0x00; // <-- delete this line so you're not always turning the LED off
}
I'm using the pic18F4550 with microchip v8.63 and with the C 18 compiler. I'm using a LDR that retrieve the value of the led (not on my picdem board) (red, green and blue) these values are stored in a variable after each conversion. Afther that when I press the button S2, I come into the method ISR: this part works.
But now: I try to compare the variable red, green and blue in the if's: but I think that it not happen, he just go to my 'else' (led RB3 on my picdem board burns).
#include <p18f4550.h>
/** V E C T O R R E M A P P I N G *******************************************/
extern void _startup (void); // See c018i.c in your C18 compiler dir
#pragma code _RESET_INTERRUPT_VECTOR = 0x001000
void _reset (void)
{
_asm goto _startup _endasm
}
#pragma code
void ISR (void);
#pragma code _HIGH_INTERRUPT_VECTOR = 0x001008
void _high_ISR (void)
{
_asm goto ISR _endasm
}
#pragma code _LOW_INTERRUPT_VECTOR = 0x001018
void _low_ISR (void)
{
;
}
#pragma code
/******************************************************************************/
// global variable, value off LDR.
unsigned int var1ADRESH = 0x00;
unsigned int color_red = 0;
unsigned int color_green = 0;
unsigned int color_blue = 0;
void main (void)
{
TRISD = 0x00; // PORTD als uitgang
RCONbits.IPEN = 0; // prioriteit uit
INTCONbits.GIE = 1; // enable interrupt
INTCONbits.RBIE = 1; // interrupt portB aan
//= set up port =
TRISAbits.TRISA0 = 1; // Set RA0/AN0 to input
//leds
TRISAbits.TRISA3 = 0;
TRISAbits.TRISA4 = 0;
TRISAbits.TRISA5 = 0;
LATAbits.LATA3 = 1;
LATAbits.LATA4 = 1;
LATAbits.LATA5 = 1;
ADCON0 = 0b00000000; // Set channel select to AN0
ADCON1 = 0b00001110; // Configure RA0/AN0 as analogue
ADCON2 = 0b10101010; // Right justified result
// TAD 12 and FOSC 32 - may need to adjust this
// depending on your clock frequency (see datasheet)
while(1)
{
_asm sleep _endasm
}
}
#pragma interrupt ISR
void ISR (void)
{
if (INTCONbits.RBIF==1) {
//conversie blauw
LATAbits.LATA3 = 0;
ADCON0bits.ADON = 1; // Enable ADC
// read LDR value.
ADCON0bits.GO = 1; // Set the GO bit of the ADCON0 register to start the conversion.
while (ADCON0bits.GO); // Wait until the conversion is complete.
ADCON2bits.ADFM = 0; // read result as 8-bit. (dus data in ADRESH) !
//= read data in ADRESH =
var1ADRESH = ADRESH; // reading value from LDR
color_blue = ADRESH; //waarde in blauw
//conversie rood
LATAbits.LATA3 = 1;
LATAbits.LATA4 = 0;
ADCON0bits.ADON = 1; // Enable ADC
// read LDR value.
ADCON0bits.GO = 1; // Set the GO bit of the ADCON0 register to start the conversion.
while (ADCON0bits.GO); // Wait until the conversion is complete.
ADCON2bits.ADFM = 0; // read result as 8-bit. (dus data in ADRESH) !
//= read data in ADRESH =
var1ADRESH = ADRESH; // reading value from LDR
color_red = ADRESH; //waarde in blauwe steken
//conversie groen
LATAbits.LATA4 = 1;
LATAbits.LATA5 = 0;
ADCON0bits.ADON = 1; // Enable ADC
// read LDR value.
ADCON0bits.GO = 1; // Set the GO bit of the ADCON0 register to start the conversion.
while (ADCON0bits.GO); // Wait until the conversion is complete.
ADCON2bits.ADFM = 0; // read result as 8-bit. (dus data in ADRESH) !
//= read data in ADRESH =
var1ADRESH = ADRESH; // reading value from LDR
color_green = ADRESH; //waarde in blauwe steken
// alles uitzetten
//PORTB = 0b1111111;
LATAbits.LATA5 = 1;
if(color_blue > color_red && color_blue > color_green){
//blauw
LATDbits.LATD0 = 1;
}
if(color_red > color_blue && color_red > color_green){
//rood
LATDbits.LATD1 = 1;
}
if(color_green > color_red && color_green > color_blue){
//groen
LATDbits.LATD2 = 1;
}
else {
LATDbits.LATD3 = 1;
}
}
INTCONbits.RBIF = 0;
}
Try to set all three of LATA3,4,5 before every readout?
Set TRIS for D0..2
I detect a few weird things (but I confess none might be the source).
Once you set the LATA bits, does the LDR immediately changes val? Of course not, but is it a matter of ns, us or ms?... I don't see any delays for LDR settling times.
You are always sleeping so it's probably required to set the ADON=1 (check DS). However, check the device DS for how long does the AD needs to get it's internals up and ready after setting ADON=1. On that subject, once ADON=1 you shouldn't and don't need to set it over again the the next two acquisitions.
The same thing about the format of the result. Set it once, and do it before the GO=1. Don't re-set every conversion.
If you're using only 8bit results, why the unsigned int? (btw, int is pretty dangerous in microcontrollers. Use short and chars and always explicit signdness).
Why the var1ADRESH assignment then color_xxx? when do the LATD bits eventually get =0?
Your If else only works on the last branch. I believe you intended a if{} else if{} else if... structure.