|
|
View previous topic :: View next topic |
Author |
Message |
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
|
MassaM
Joined: 08 Jun 2019 Posts: 31
|
|
Posted: Sat Jun 08, 2019 8:59 pm |
|
|
temtronic wrote: | http://www.ccsinfo.com/forum/viewtopic.php?t=23837
took me a bit to find it....
Jay |
Great. Will check it out. Thank you.
Meanwhile, I found this by "PCM programmer" with a big Thank you! here:
https://www.ccsinfo.com/forum/viewtopic.php?t=53600
and coded a simple test with a timer interrupt version with two buttons.
I still am going to make it into an array of switches and leds timer/interrupts based polling as per the demo i managed to code.
Tested and working full code below.
Code: |
#include <18F4520.h>
#fuses INTRC_IO, BROWNOUT, PUT, NOWDT
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
#define FOSC getenv("CLOCK") // Get PIC oscillator frequency
#define TIMER0_PRELOAD (256 - (FOSC/4/256/100))
#define BUTTON1 PIN_B0
#define BUTTON2 PIN_B1
#define LED1 PIN_D0
#define LED2 PIN_D1
void timer0_init(void)
{
setup_timer_0(T0_INTERNAL | T0_DIV_256 | T0_8_BIT);
set_timer0(TIMER0_PRELOAD);
clear_interrupt(INT_TIMER0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
}
int8 switch1_is_down = FALSE,
switch2_is_down = FALSE;
#int_timer0
void timer0_isr(void)
{
int8 active_state1, previuos_state1,
active_state2, previuos_state2;
set_rtcc(TIMER0_PRELOAD); // Reload Timer0 for 10ms rate
active_state1 = input(BUTTON1); // Read the button
active_state2 = input(BUTTON2); // Read the button
if((previuos_state1 == 1) && (active_state1 == 0))
{
switch1_is_down = TRUE;
}
if((previuos_state2 == 1) && (active_state2 == 0))
{
switch2_is_down = TRUE;
}
previuos_state1 = active_state1; // Save current value for next time
previuos_state2 = active_state2; // Save current value for next time
}
void main()
{
timer0_init();
while(TRUE)
{
if(switch1_is_down == TRUE)
{
switch1_is_down = FALSE; // Clear the switch is pushed flag
output_toggle(LED1);
}
if(switch2_is_down == TRUE)
{
switch2_is_down = FALSE; // Clear the switch is pushed flag
output_toggle(LED2);
}
}
}
|
Hope it helps others and would appreciate any inputs and help.
MassaM _________________ while(!dead)
{
keepLearning();
} |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Sun Jun 09, 2019 7:26 am |
|
|
Well done.
Looks quite tidy.
As a comment, your flags for switchx_is_down, might as well be int1's.
The processor has inbuilt instructions for testing and branching on a bit,
so using these may well be more efficient, and will save space.
One of the things that has to be learnt on the PIC, is that you only have
a very small amount of RAM, so saving is always worthwhile. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Sun Jun 09, 2019 8:38 am |
|
|
As one more comment, why are you using such an old chip?.
The 16F877A, is 'not recommended for new designs'. It came out around
about 2000, and there are newer PIC's, that use less power, have more
peripherals, are faster, have more RAM, and are cheaper!...
It's amazing how many people still carry on using such old chips.
I don't know whether you have PCH or only PCM, but the PCH chips
(PIC18's), also have a much tidier actual architecture. The 16F877A was
a reasonable chip to use 15 years ago, but now is making things harder
for yourself than they need to be... |
|
|
MassaM
Joined: 08 Jun 2019 Posts: 31
|
|
Posted: Sun Jun 09, 2019 9:28 am |
|
|
Ttelmah wrote: | Well done.
Looks quite tidy. |
Thank you!
Ttelmah wrote: | As a comment, your flags for switchx_is_down, might as well be int1's.
The processor has inbuilt instructions for testing and branching on a bit,
so using these may well be more efficient, and will save space.
One of the things that has to be learnt on the PIC, is that you only have
a very small amount of RAM, so saving is always worthwhile. |
All you mentioned are priceless, very well noted and will be put into action for future PIC adventures!
With gentlemen such as yourself, and this community of course, learning PIC and CCS-C will be an easy task and I found it to be the right choice.
Bless all.
MassaM _________________ while(!dead)
{
keepLearning();
} |
|
|
MassaM
Joined: 08 Jun 2019 Posts: 31
|
|
Posted: Sun Jun 09, 2019 9:37 am |
|
|
Ttelmah wrote: | As one more comment, why are you using such an old chip?.
The 16F877A, is 'not recommended for new designs'. It came out around
about 2000, and there are newer PIC's, that use less power, have more
peripherals, are faster, have more RAM, and are cheaper!...
It's amazing how many people still carry on using such old chips.
I don't know whether you have PCH or only PCM, but the PCH chips
(PIC18's), also have a much tidier actual architecture. The 16F877A was
a reasonable chip to use 15 years ago, but now is making things harder
for yourself than they need to be... |
I agree. It's just the beginning for me and PIC, most tutorials use it, and added that I have couple of those laying in the boxes from those days!
Will definitely shift to the latest ones to benefit from the features as you mentioned of course.
Cheers! _________________ while(!dead)
{
keepLearning();
} |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Sun Jun 09, 2019 9:44 am |
|
|
Just a caution about int1:
I've experienced something where with larger projects that have more variables and more int1's scattered around, they don't work properly for some reason.
There is some brief discussion about this in the beginning of this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=57881&postdays=0&postorder=asc&start=0
So if you suddenly start to have problems with int1 flags, then this may be it. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Sun Jun 09, 2019 10:04 am |
|
|
The issues here were with a very early V5 compiler, that was still really a
'beta' at best. |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Sun Jun 09, 2019 10:06 am |
|
|
Ttelmah wrote: | The issues here were with a very early V5 compiler, that was still really a
'beta' at best. |
Hmm... There must be something else at play for me then. I was experiencing it in 5.082. I still haven't gone to investigate that yet. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Sun Jun 09, 2019 10:20 am |
|
|
Do you possibly have them in structures?.
There is an 'insidious' problem sometimes with int1's used in structures.
Seems not to happen if you use bit fields instead. So in a structure
declaration:
Code: |
//instead of
struct something {
int1 something;
}
//use
struct something {
int8 something:1;
}
|
|
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Sun Jun 09, 2019 10:25 am |
|
|
Ttelmah wrote: | Do you possibly have them in structures?.
There is an 'insidious' problem sometimes with int1's used in structures.
Seems not to happen if you use bit fields instead. So in a structure
declaration:
Code: |
//instead of
struct something {
int1 something;
}
//use
struct something {
int8 something:1;
}
|
|
I may have... I don't actually remember which ones of my flags initially caused the problem. I just know that I switched them all to int8 for my current project. I will try the tip with bit fields when I have some time. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Sun Jun 09, 2019 3:51 pm |
|
|
I recall a 'quirky problem that dealt with bits (int1s) and the 'cure' seemed to be to have 8 int1 even though you only needed, say 5. I assuming this forced the compiler to use a whole byte and data was 'aligned'.
While this was probably fixed, I've always used the 'full' byte method.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19549
|
|
Posted: Mon Jun 10, 2019 1:49 am |
|
|
This may well relate.
Using bit fields, the bits are generated as bits in a byte. Hence the 'int8'
at the start of the declaration. If you don't use all the bits, a byte as an
entity is still allocated. Now, while you perhaps would expect the int1
declaration to do the same, if it doesn't, and the 'optimiser' tries then
to save space by using 'spare' bits elsewhere, I can easily see errors
occurring (particularly perhaps with bank switching when these are accessed). |
|
|
MassaM
Joined: 08 Jun 2019 Posts: 31
|
Interrupts disabled during call to prevent re-entrancy |
Posted: Mon Jun 10, 2019 1:45 pm |
|
|
The Problem:
A code redo for array based compiles with the two warnings below with a halt on the timer0 interrupt init on actual test!
Code: | >>> Warning 216 "main.c" Line 139(1,2): Interrupts disabled during call to prevent re-entrancy: (@READBITA)
>>> Warning 216 "main.c" Line 139(1,2): Interrupts disabled during call to prevent re-entrancy: (@WRITEBITA) |
The Success:
The non-array version posted earlier compiles clean and works fine.
The Notes:
I searched and read many posts here on the subject issue, and that the CCS C compiler does not support this kind of thing, and sort of understood that they were suggesting to change the entire code routine and structure.
Below is the code here for a review and request for valuable guidances.
Code: |
/*
// ************************************************ Array version ************************************************ //
Project: Demo Controller Board - 8 Channels Relay with status LEDs and push buttons for an ON/OFF toggle
Compiler: CCS-C-PIC - PCWHD Version 5.076
Author: MassaM, June 2019
Chip: PIC16F877A@20Mhz
Copyright: No copy-rights nor copy-wrongs! :)
Request: Make it better and post it back on this thread, so we all learn please!
*/
#include <16F877A.h>
#fuses XT, BROWNOUT, PUT, NOWDT
#use delay(clock=20M)
#use rs232(stream=SERIAL, baud=19200, xmit=PIN_C6, rcv=PIN_C7, parity=N, bits=8) // settings for Serial/Terminal outputs
#define FOSC getenv("CLOCK") // Get PIC oscillator frequency
#define TIMER0_PRELOAD (256 - (FOSC/4/256/100))
/* ****************************************************************************************************************** */
// Array version variables
int16 switches[] = {PIN_B0,PIN_B1,PIN_B2,PIN_B3,PIN_B4,PIN_B5,PIN_B6,PIN_B7};
int16 leds[] = {PIN_D0,PIN_D1,PIN_D2,PIN_D3,PIN_D4,PIN_D5,PIN_D6,PIN_D7};
int8 switch_is_down[] = {FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE};
/* ****************************************************************************************************************** */
/* ****************************************************************************************************************** */
// Array version functions
/* ****************************************************************************************************************** */
void clearSwitches_Array()
{
int8 i;
for(i=0; i < 8; i++)
{
switch_is_down[i] = FALSE; // Clear the switch is pushed flag
//printf("[Cleared]:\r\n");
//printf("Switch No: %d\r\n", switch_is_down[i]);
}
}
void pollSwitches_Array()
{
int8 i;
for(i=0; i < 8; i++)
{
if(switch_is_down[i] == TRUE)
{
switch_is_down[i] = FALSE; // Clear the switch is pushed flag
output_toggle(leds[i]);
//printf("[Polled] switch No: %d\r\n", switch_is_down[i]);
}
}
}
void checkStates_Array()
{
int8 active_state[], previous_state[];
int8 i;
for(i=0; i < 8; i++)
{
active_state[i] = input(switches[i]); // Read the button
if((previous_state[i] == 1) && (active_state[i] == 0))
{
switch_is_down[i] = TRUE;
}
previous_state[i] = active_state[i]; // Save current value for next time
//printf("[Timer0] switch No: %d, previous_state %d, active_state %d\r\n", i, previous_state[i], active_state[i]);
}
}
void timer0_init(void)
{
setup_timer_0(T0_INTERNAL | T0_DIV_256 | T0_8_BIT);
set_timer0(TIMER0_PRELOAD);
clear_interrupt(INT_TIMER0);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
//printf("[initAll]:\r\n"); // It hangs here with the array version
//printf("T0_INTERNAL: %d\r\nT0_DIV_256: %d\r\nT0_8_BIT: %d\r\n", T0_INTERNAL , T0_DIV_256 , T0_8_BIT);
//printf("set_timer0: %d\r\nenable_interrupts: %d\r\nGLOBAL: %d\r\n", TIMER0_PRELOAD ,INT_TIMER0, GLOBAL);
}
#int_timer0
void timer0_isr(void)
{
set_rtcc(TIMER0_PRELOAD); // Reload Timer0 for 10ms rate
//printf("\r\n[timer0_isr] (%d) Waiting...\r\n", get_rtcc());
checkStates_Array(); // This not working aka hangs
}
void initAll(){
timer0_init();
clearSwitches_Array();
}
void main()
{
initAll();
printf("-------------------------------------------------\r\n");
printf("Ready!\r\n");
while(TRUE)
{
/*
Notes:
-> Array version compiles with the two warnings below with a halt on the timer0 interrupt init on actual test! :(
-> Non Array version posted earlier compiles clean and works fine.
>>> Warning 216 "main.c" Line 139(1,2): Interrupts disabled during call to prevent re-entrancy: (@READBITA)
>>> Warning 216 "main.c" Line 139(1,2): Interrupts disabled during call to prevent re-entrancy: (@WRITEBITA)
*/
pollSwitches_Array(); // <- Warnings and notes as above
} // while true
} // main
|
Appreciated.
MassaM _________________ while(!dead)
{
keepLearning();
} |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Mon Jun 10, 2019 1:57 pm |
|
|
Are you trying to use printf's to debug within your interrupts?
They are very slow and will mess with you. It is much better to set a flag in the ISR, and print in your main loop instead. A good rule for ISRs are to get in, set/check flags or increment counters, and then get out as soon as possible.
Also, in checkStates_Array():
You are using a int8 array to loop through store your switch states, when in fact you could store all of the values within a single int8 using the function input_b(). That will capture the value of all the pins on that port and store them in a single variable so you don't need to loop through.
Then you can do a bitwise comparison of previous and current states.
Another thing is that you are declaring previous_state[] inside the function, but you have not assigned anything to it. Therefore, previous_state's values can be just about anything by the next time you run checkStates_array(). You should either make that a global variable or static variable so its lifetime lasts beyond the function. Otherwise once the function returns, something else can use that memory area and you will get unexpected results. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|