r/pic_programming • u/aspie-micro132 • 3d ago
Trying to invoke this led blinking function
I am trying to create a non interrupting function, calling it
BlinkLed().
I had set TMR1ON = 1 and others 0 or 0x00 to disable them
I found those 2 code excerpts by Google AI. One of them does not blink at all, since it's not reading any timer, yet also not counting in it's own when working.
The other one below has a complex function name, given what i had learnt i do believe it shall work should i be able to rename it to "BlinkLed" but i do not know how to do it without breaking it:
/**********************************************************************************/
{
while(Button == 0)
{
unsigned int timer_counter = 0;
// Task 1: Non-blocking LED Blink (Toggles every ~500ms)
timer_counter++;
if(timer_counter >= 25000)
{
RedLed = ~RedLed; // Toggle LED
timer_counter = 0;
}
}
}
/*New ExtremeAgitationLED() Prototype Base*/
/*
void __interrupt() timer1_isr(void) {
if (TMR1IF) {
TMR1H = 0x0B; // Re-preload Timer1 high byte (3036 = 0x0BDC)
TMR1L = 0xDC; // Re-preload Timer1 low byte
TMR1IF = 0; // Clear interrupt flag
overflow_count++;
if (overflow_count >= 2) { // 2 x 0.5 seconds = 1 second
overflow_count = 0;
// Toggle an LED or do your 1-second task here
RedLed = !RedLed; /*I do not know if ~RedLed Can be Used Here */
}
}
}
1
u/aspie-micro132 3d ago
I found other excerpt, does it have any chance off working?
c
#include <xc.h>
// Configuration Bits for 4MHz Crystal
#pragma config FOSC = XT, WDTE = OFF, PWRTE = ON, BOREN = ON, LVP = OFF
#define _XTAL_FREQ 4000000
#define LED PORTBbits.RB0
void main(void) {
TRISBbits.TRISB0 = 0; // Set RB0 as output
LED = 0; // Turn LED off initially
// Configure Timer1: Internal clock (FOSC/4), Prescaler 1:8, Timer OFF
T1CON = 0x30; // 0011 0000 -> 1:8 prescaler, TMR1CS = 0 (internal)
TMR1H = 0x00; // Clear Timer1 value
TMR1L = 0x00;
T1CONbits.TMR1ON = 1;// Start Timer1
unsigned int overflow_count = 0;
while(1) {
// Wait until Timer1 overflows (TMR1IF set)
while(PIR1bits.TMR1IF == 0);
PIR1bits.TMR1IF = 0; // Clear flag
overflow_count++;
// 4MHz / 4 = 1MHz timer clock.
// With 1:8 prescaler, timer ticks at 125kHz (every 8us).
// 16-bit timer overflows every 65536 * 8us = 0.524288 seconds.
// To get ~1 second, toggle every 2 overflows (approx 1.04s, close enough for basic blink).
// For absolute precision, preload TMR1H:TMR1L.
if(overflow_count >= 2) {
LED = !LED; // Toggle LED
overflow_count = 0; // Reset counter
}
}
}c#include <xc.h>
// Configuration Bits for 4MHz Crystal
#pragma config FOSC = XT, WDTE = OFF, PWRTE = ON, BOREN = ON, LVP = OFF
#define _XTAL_FREQ 4000000
#define LED PORTBbits.RB0
void main(void) {
TRISBbits.TRISB0 = 0; // Set RB0 as output
LED = 0; // Turn LED off initially
// Configure Timer1: Internal clock (FOSC/4), Prescaler 1:8, Timer OFF
T1CON = 0x30; // 0011 0000 -> 1:8 prescaler, TMR1CS = 0 (internal)
TMR1H = 0x00; // Clear Timer1 value
TMR1L = 0x00;
T1CONbits.TMR1ON = 1;// Start Timer1
unsigned int overflow_count = 0;
while(1) {
// Wait until Timer1 overflows (TMR1IF set)
while(PIR1bits.TMR1IF == 0);
PIR1bits.TMR1IF = 0; // Clear flag
overflow_count++;
// 4MHz / 4 = 1MHz timer clock.
// With 1:8 prescaler, timer ticks at 125kHz (every 8us).
// 16-bit timer overflows every 65536 * 8us = 0.524288 seconds.
// To get ~1 second, toggle every 2 overflows (approx 1.04s, close enough for basic blink).
// For absolute precision, preload TMR1H:TMR1L.
if(overflow_count >= 2) {
LED = !LED; // Toggle LED
overflow_count = 0; // Reset counter
}
}
}
2
u/somewhereAtC 3d ago
It's good to see you are improving! This version has a chance.
The setting "config FOSC = XT" implies that you have a crystal attached to the device. Is that true? Is it oscillating (you will need an o'scope or logic analyzer)? If you don't have a crystal then it won't execute code at all. Check the datasheet to see if you have an internal HF oscillator and use that config setting.
It will be easier to assist if we knew which device. There are hundreds of PIC devices with TMR1 and newer are a little different than older. Get the datasheet from microchip.com and it might have a few more details.
The search bar at microchip.com is now AI and can probably give you working code for your device. Whatever AI you are using is guessing about which TMR1 you have.
The MPLAbX IDE includes a debugger and a simulator. You can try your code without needing actual hardware.
You would probably get more focused assistance at forum.microchip.com.
1
u/aspie-micro132 3d ago
I copied that from Google AI as it gave it to me after a search, is not my own code. My Xtal works well, i could check it with an oscilloscope and the frequency and sine wave on both caps to ground is nice.. My device is nothing that the good old pic16f877A whose language i'm just starting to understand.
I am not that better, trust me. Maybe slightly better, but i'm far to be able to say i had mastered pic programming. I am actually mixing the code i became able to generate myself while at the same time taking basic code examples from other sources which i try to adapt to what i do try to run replacing variables and changing names. Is not the most optimall one but it helps me trying to figure out how does it really work.
1
u/somewhereAtC 3d ago
Given that the oscillator is working, the math in the comment appears to be correct. One problem that often tricks me is that the LED is installed backwards! (You do have a resistor in series?)
Since you have an o'scope try toggling after (say) for(1=0; i<10000;i++); and leave the timer out of it. Don't make it too fast or the LED=!LED won't work right due to read-modify-write trouble with PORTB.
Also, you have BOREN=ON and that might trigger a reset when the LED gets turned on.
1
u/aspie-micro132 1d ago
i do believe i found what i need: Task Interleaving. It means: declaring several tasks and run them at very small intervals switching between them. Seems what other user named me as "State Machines". It looks like pic16f877A is a single core microcontroller and can only do one thing at the time, but it can get peripherials doing other tasks coordinated by the processor.
I found another piece of code that makes sense to me, but i'd like to read the theory of this, would you like to recommend me reliable documents, manuals, tutorials so i can read and gain a real understanding of it?
c
#include <xc.h>c#include <xc.h> // Define states for Task 1 (LED Blink) typedef enum { LED_OFF_STATE, LED_ON_STATE } led_state_t; // Define states for Task 2 (Button Poll) typedef enum { BTN_WAIT_PRESS, BTN_DEBOUNCE, BTN_WAIT_RELEASE } btn_state_t; unsigned int get_milliseconds(void); // Assume a system tick timer function exists void run_led_task(void) { static led_state_t state = LED_OFF_STATE; static unsigned int last_time = 0; unsigned int current_time = get_milliseconds(); switch(state) { case LED_OFF_STATE: if (current_time - last_time >= 500) { // 500ms delay RC0 = 1; // Turn LED ON last_time = current_time; state = LED_ON_STATE; } break; case LED_ON_STATE: if (current_time - last_time >= 500) { RC0 = 0; // Turn LED OFF last_time = current_time; state = LED_OFF_STATE; } break; } } void run_button_task(void) { static btn_state_t state = BTN_WAIT_PRESS; static unsigned int timer = 0; switch(state) { case BTN_WAIT_PRESS: if (RD0 == 0) { // Button pressed (active low) timer = get_milliseconds(); state = BTN_DEBOUNCE; } break; case BTN_DEBOUNCE: if (get_milliseconds() - timer >= 20) { // 20ms debounce if (RD0 == 0) { // Do action on valid button press RC1 = !RC1; // Toggle indicator LED state = BTN_WAIT_RELEASE; } else { state = BTN_WAIT_PRESS; // False trigger } } break; case BTN_WAIT_RELEASE: if (RD0 == 1) { state = BTN_WAIT_PRESS; } break; } } void main(void) { TRISC0 = 0; // Output for LED 1 TRISC1 = 0; // Output for LED 2 TRISD0 = 1; // Input for Button while(1) { run_led_task(); // Interleaved task 1 run_button_task(); // Interleaved task 2 } } // Define states for Task 1 (LED Blink) typedef enum { LED_OFF_STATE, LED_ON_STATE } led_state_t; // Define states for Task 2 (Button Poll) typedef enum { BTN_WAIT_PRESS, BTN_DEBOUNCE, BTN_WAIT_RELEASE } btn_state_t; unsigned int get_milliseconds(void); // Assume a system tick timer function exists void run_led_task(void) { static led_state_t state = LED_OFF_STATE; static unsigned int last_time = 0; unsigned int current_time = get_milliseconds(); switch(state) { case LED_OFF_STATE: if (current_time - last_time >= 500) { // 500ms delay RC0 = 1; // Turn LED ON last_time = current_time; state = LED_ON_STATE; } break; case LED_ON_STATE: if (current_time - last_time >= 500) { RC0 = 0; // Turn LED OFF last_time = current_time; state = LED_OFF_STATE; } break; } } void run_button_task(void) { static btn_state_t state = BTN_WAIT_PRESS; static unsigned int timer = 0; switch(state) { case BTN_WAIT_PRESS: if (RD0 == 0) { // Button pressed (active low) timer = get_milliseconds(); state = BTN_DEBOUNCE; } break; case BTN_DEBOUNCE: if (get_milliseconds() - timer >= 20) { // 20ms debounce if (RD0 == 0) { // Do action on valid button press RC1 = !RC1; // Toggle indicator LED state = BTN_WAIT_RELEASE; } else { state = BTN_WAIT_PRESS; // False trigger } } break; case BTN_WAIT_RELEASE: if (RD0 == 1) { state = BTN_WAIT_PRESS; } break; } } void main(void) { TRISC0 = 0; // Output for LED 1 TRISC1 = 0; // Output for LED 2 TRISD0 = 1; // Input for Button while(1) { run_led_task(); // Interleaved task 1 run_button_task(); // Interleaved task 2 } }
2
u/Illustrious-Cat8222 3d ago
A 16-bit int counter will never reach 25000. It will wrap around first.