// Mode change for LED
// LED output at B3
// INT button at B0
int mode1;
int modecount;
signed int i = 0;
sbit LCD_RS at RA0_bit;
sbit LCD_EN at RA1_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISA0_bit;
sbit LCD_EN_Direction at TRISA1_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
char message1[] = "Mode 1";
char message2[] = "Mode 2";
char message3[] = "Mode 3";
char message4[] = "Unicorn Banshee HG";
void main()
{
CMCON = 0x07;
TRISA = 0; // To configure PORTC as output port
TRISB = 0x01;
OPTION_REG.INTEDG = 1; // Set Rising Edge Trigger for INT
INTCON.GIE = 1; // Enable The Global Interrupt
INTCON.INTE = 1; // Enable INT
PWM1_Init(5000); // Initialize PWM frequency
PWM1_Set_Duty(127);
PWM1_Start();
mode1 = 0x00;
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // OFF cursor
Lcd_Cmd(0x01); // Clear display
Lcd_Cmd(0x03); //cursor home
while(1)
// Loop:
{
if( eeprom_read(0) == 0x01) // Mode2
{
Lcd_out(1,1,message4);
Lcd_out(2,1,message2);
for(i = 0; i < 256; i += 250)
{
PWM1_Set_Duty(i);
Delay_ms(200);
}
for(i = 250; i >= 0; i -= 250)
{
PWM1_Set_Duty(i);
Delay_ms(200);
}
}
else if (eeprom_read(0) == 0x02) // Mode 3
{
Lcd_out(1,1,message4);
Lcd_out(2,1,message3);
for(i = 0; i < 256; i += 5)
{
PWM1_Set_Duty(i);
Delay_ms(140);
}
for(i = 253; i >= 0; i -= 5)
{
PWM1_Set_Duty(i);
Delay_ms(120);
}
}
else if (eeprom_read(0) == 0x03) // Mode 4
{
PORTB.F1 = 1;
delay_ms(500);
PORTB.F1 = 0;
delay_ms(500);
}
else // Default mode1
{
Lcd_out(1,1,message4);
Lcd_out(2,1,message1);
mode1 = 0x00;
for(i = 0; i < 256; i += 250)
{
PWM1_Set_Duty(i);
Delay_ms(1000);
}
for(i = 250; i >= 0; i -= 250)
{
PWM1_Set_Duty(i);
Delay_ms(1000);
}
}
}
}
void interrupt() // ISR
{
INTCON.INTF=0;
// mode1 +1;
modecount = 0x01;
mode1 = mode1 + modecount;
eeprom_write(0,mode1);
//goto Loop;
// asm
// {
// reset;
// }
delay_ms(50);
}
Timer interrupts have to be used for modes. If large delays are executing then even if you use INTx pin to detect mode change then it will only get applied after the Delay_ms(1000) gets executed. You can use while() which tests for mode and you can change mode in TNTx interrupt. If mode changes then program execution comes out of the loop and enters next valid mode loop.
asm{
reset;
}
Sorry, it is not TNTx. It is INTx only. In INTx interrupt change the modes and use while() loops with condition to test modes. One loop for one mode. Still if Delays inside while loops are executing then mode test will be done after delay executes.
Hi,
I don´t see a debounce function in your code. Do you have hardware debounce.
You need one of both.
****
Only a couple of modes are defined. EEPROM_Value 0x01, 0x02, 0x03, all others are processed as MODE0.
Why don´t you limit the EEPROM value to 0x01 to 0x03?
for example: If mode1 = 4 then mode1 = 1 (pseudocode)
Klaus
Hi,
Yes, in the interrupt function.
Btw: is the interrupt level_triggered or edge_triggered?
*******
An idea:
Maybe you could set up a timer to time out every 20ms (or any other useful value)
Make the main loop to run according this value.
Instead of using busy delay routines you can just count loops.
Then you don't need a debounce function.
Example for a 1 s blink: use a counter set it to 24 and decrement it every run. When zero: toggle LED and set it to 24.
This enables you to do a lot of things at virtually the same time.
It's more PLC style with a fixed timing.
Klaus
if( eeprom_read(0) == 0x01) // Mode2
{
Lcd_out(1,1,message4);
Lcd_out(2,1,message2);
for( k=0; k < 10; k++ )
{
for(i = 0; i < 256; i += 250)
{
PWM1_Set_Duty(i);
Delay_ms(100);
}
}
for (k >= 10; k < 20; k++)
{
for(i = 250; i >= 0; i -= 250)
{
PWM1_Set_Duty(i);
Delay_ms(100);
}
}
for ( k >= 20; k <21; k = 0)
{
return;
}
}
Hi.
I am how sure whether it is level triggered or state triggered. May I know how can i check this?
INTEDG_bit value or INTEDGx_bit value.
Hi,
It seems you posted the wrong code....at least it has nothing to do with my recommendations.
Klaus
An idea:
Maybe you could set up a timer to time out every 20ms (or any other useful value)
--> I don´t see this in your code.
Make the main loop to run according this value.
--> I don´t see this in your code.
At the beginnin of the main loop you need to wait for the timer event.
It shouldn´t be a problem to wait until the timer flag is set. Then clear the flag and run the main routine
Instead of using busy delay routines you can just count loops.
--> You still use busy waits.
Don´t use delay_ms at all - it just consumes processing power and it can´t do anything else druing this time.
Do you mean using interrupt timer?
It just sets a flag when timed out.set up a timer to time out every 20ms
Hi,
As already said:
It just sets a flag when timed out.
No need to generate an interrupt --> No need or an ISR.
I´m not familiar with PICs, therefore I don´t know the name of the flag. But the function is similar in almost all microcontrollers.
Klaus
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?