Home › Forums › Microcontrollers › PIC Microcontroller › PIC Microcontroller Non-Blocking Delay Implementation
- This topic has 7 replies, 2 voices, and was last updated 8 years, 10 months ago by Ligo George.
-
AuthorPosts
-
February 1, 2016 at 1:16 pm #12100emufambirwiParticipant
I am doing a project which requires that I turn on and off two LED’s independently from a computer using serial port communication. I send a character like ‘A’ via the serial port and turn on one LED for say 1 minute and send another character like ‘B’ and turn on another LED for 2 minutes. My problem is that when using Timer0 of pic 18F87k22, I can’t implement the 1 minute and 2 minute delays independently. When I turn on the one LED the other one doesn’t respond and vice versa. I am simulating using Proteus and my code is is in MikroC as shown below:
char uart_rd; char cnt; void interrupt () { if (TMR0IF_bit) { cnt++; // increment counters TMR0IF_bit = 0; // clear TMR0IF TMR0L = 0xDC; // set TMR0 for aproximetly 1 sec TMR0H = 0x0B; } } void one_min_delay () { TRISB = 0; // PORTB is output TMR0H = 0x0B; TMR0L = 0xDC; // Timer0 initial value T0CON = 0x84; // Set TMR0 to 8bit mode and prescaler to 256 GIE_bit = 1; // Enable global interrupt TMR0IE_bit = 1; // Enable Timer0 interrupt cnt = 0; // Initialize cnt do { if (cnt >= 60) { LATB = 0x00; // turnoff PORTB LEDs cnt = 0; // Reset cnt } }while(1); } void two_min_delay () { TRISB = 0; // PORTB is output TMR0H = 0x0B; TMR0L = 0xDC; // Timer0 initial value T0CON = 0x84; // Set TMR0 to 8bit mode and prescaler to 256 GIE_bit = 1; // Enable global interrupt TMR0IE_bit = 1; // Enable Timer0 interrupt cnt = 0; // Initialize cnt do { if (cnt >= 120) { LATB = 0x00; // turnoff PORTB LEDs cnt = 0; // Reset cnt } }while(1); } void main() { UART1_Init(9600); // Initialize UART module at 9600 bps Delay_ms(100); // Wait for UART module to stabilize TRISB = 0x00; while (1) { if (UART1_Data_Ready()) { // If data is received, uart_rd = UART1_Read(); } if (uart_rd=='A') { LATB = 0x01; one_min_delay(); } else if (uart_rd == 'B') { PORTB = 0x02; two_min_delay (); } uart_rd ='\0'; } }
February 1, 2016 at 9:55 pm #12102Ligo GeorgeKeymasterMy logic will be by using 2 variables.
- Increment each variable after a fixed delay or timer overflow if the corresponding LED is ON.
- Check each variable for the limit.
- If the limit is reached, turn OFF the corresponding LED and reset the variable to zero.
February 2, 2016 at 12:18 pm #12103emufambirwiParticipantThanks for the reply. I hope I get you well. The number of variables is the same as the number of LED’s to be controlled. Let me change my code and try that and I will give you feedback.
Another question is: Is there any other way to do this without the use of interrupts?
February 2, 2016 at 2:03 pm #12105emufambirwiParticipantThis is how I have changed my code and the result is still the same :
char uart_rd; char cnt, cnt1; void interrupt () { if (TMR0IF_bit) { cnt++; // increment counters cnt1++; TMR0IF_bit = 0; // clear TMR0IF TMR0L = 0xDC; // set TMR0 for aproximetly 1 sec TMR0H = 0x0B; } } void one_min_delay () { TRISB = 0; // PORTB is output TMR0H = 0x0B; TMR0L = 0xDC; // Timer0 initial value T0CON = 0x84; // Set TMR0 to 8bit mode and prescaler to 256 GIE_bit = 1; // Enable global interrupt TMR0IE_bit = 1; // Enable Timer0 interrupt cnt = 0; // Initialize cnt do { if (cnt >= 60) { LATB = 0x00; // turnoff PORTB LEDs cnt = 0; // Reset cnt } }while(1); } void two_min_delay () { TRISB = 0; // PORTB is output TMR0H = 0x0B; TMR0L = 0xDC; // Timer0 initial value T0CON = 0x84; // Set TMR0 to 8bit mode and prescaler to 256 GIE_bit = 1; // Enable global interrupt TMR0IE_bit = 1; // Enable Timer0 interrupt cnt1 = 0; // Initialize cnt1 do { if (cnt1 >= 120) { LATB = 0x00; // turnoff PORTB LEDs cnt1 = 0; // Reset cnt } }while(1); } void main() { UART1_Init(9600); // Initialize UART module at 9600 bps Delay_ms(100); // Wait for UART module to stabilize TRISB = 0x00; while (1) { if (UART1_Data_Ready()) { // If data is received, uart_rd = UART1_Read(); } if (uart_rd=='A') { LATB = 0x01; one_min_delay(); } else if (uart_rd == 'B') { PORTB = 0x02; two_min_delay (); } uart_rd ='\0'; } }
February 3, 2016 at 1:04 pm #12108Ligo GeorgeKeymasterSorry, I don’t understand your code. You have 3 infinite loops in your program. One in main loop, one in 1 min delay loop and other in 2 min delay loop.
You can try like this :
void main() { unsigned int a, b; UART1_Init(9600); // Initialize UART module at 9600 bps Delay_ms(100); // Wait for UART module to stabilize TRISB = 0x00; while (1) { if (UART1_Data_Ready()) { // If data is received, uart_rd = UART1_Read(); } if (uart_rd=='A') { LATB = 0x01; a = 100; } else if (uart_rd == 'B') { LATB = 0x02; b = 200; } uart_rd ='\0'; if(a > 0) { Delay_ms(1); a--; } else LATB = 0; if(b > 0) { Delay_ms(1); b--; } else LATB = 0; } }
February 3, 2016 at 1:41 pm #12109emufambirwiParticipantThanks Mr George, now I can control the LED’s independently but they are forever ON. Let me see if I can do something about the timing
February 3, 2016 at 5:21 pm #12110emufambirwiParticipantSorry, my mistake, I had left some } in the code. But 1st LED blinks fast
February 3, 2016 at 6:32 pm #12111Ligo GeorgeKeymasterYou can adjust the delay by changing the 100 and 200 constants assigned to a and b respectively.
-
AuthorPosts
- You must be logged in to reply to this topic.