View previous topic :: View next topic |
Author |
Message |
arelone
Joined: 06 Dec 2015 Posts: 42
|
Pointers and Arrays |
Posted: Wed Oct 23, 2019 9:00 am |
|
|
Hi,
I have code that requires to call set of functions (Task1, Task2, Task3 and Task4) which turns 4 leds sequentially. Actually the tasks are more than 16 and I simplify the code for discussion. My question is how to execute the tasks sequentially using for loop? I'm using ccs c compiler ver 5.010. Pls guide me as I am not a good programmer.
Arelone
Code: |
#include <30F6014A.h>
#fuses NOWDT, NOPROTECT, PUT64, BORV27
#use delay (clock=58982400, xtal=7372800)
#use rs232(baud=9600,UART1,ERRORS)
void task1()
{
delay_ms(1000);
output_high(PIN_D4);
}
void task2()
{
delay_ms(1000);
output_high(PIN_D5);
}
void task3()
{
delay_ms(1000);
output_low(PIN_D6);
}
void task4()
{
delay_ms(1000);
output_low(PIN_D7);
}
void main() //void=nothing, no return value
{
set_TRIS_D(0x0000);
while (true)
{
task1();
task2();
task3();
task4();
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Oct 23, 2019 1:13 pm |
|
|
arelone wrote: |
My question is how to execute the tasks sequentially using for loop?
|
You could have an array of function addresses and then use the 'i' iterator
in the for() loop to index into the array and call each function sequentially.
The function below displays the following in the Output Window of MPLAB
vs. 8.92 simulator:
Test program:
Code: | #include <18F46K22.h>
#use delay(internal=4M)
#use rs232(baud=9600, UART1, ERRORS)
void Func0(void)
{
printf("0");
}
void Func1(void)
{
printf("1");
}
void Func2(void)
{
printf("2");
}
typedef void (*_fptr)(void);
_fptr func_array[] = {Func0, Func1, Func2};
//=========================================
void main(void)
{
int8 i;
for(i=0; i < sizeof(func_array)/2; i++)
{
(*func_array[i])();
}
while(TRUE);
}
|
I tested this with CCS vs. 5.090. I don't know if it works with vs. 5.010.
That's a early version. It might work. Test it. |
|
![](templates/subSilver/images/spacer.gif) |
PrinceNai
Joined: 31 Oct 2016 Posts: 463 Location: Montenegro
|
|
Posted: Wed Oct 23, 2019 2:32 pm |
|
|
If this for loop is not obligatory, I'd always use a switch statement for that. State machine with 16 states, when one state is executed, call the next one. In the final stage you can just stay forever or loop back to the first one. Like this:
Code: |
while(1){
switch (my_functions){
case1:{
function1();
my_functions = case2;
break;
}
case2:{
}
.
.
.
}
} |
|
|
![](templates/subSilver/images/spacer.gif) |
arelone
Joined: 06 Dec 2015 Posts: 42
|
Pointers and Arrays |
Posted: Wed Oct 23, 2019 7:32 pm |
|
|
Hi,
Thanks for the example code. I compile the code and has no errors. In the given code what is *_fptr? I could not find it in the CCS help.
However all the leds are not turned ON even the D7 which outside the LOOP. Please advise.
Arelone
Code: |
#include <30F6014A.h>
#fuses NOWDT, NOPROTECT, PUT64, BORV27
#use delay (clock=58982400, xtal=7372800)
#use rs232(baud=9600,UART1,ERRORS)
void Func0()
{
delay_ms(1000);
output_high(PIN_D4);
}
void Func1()
{
delay_ms(1000);
output_high(PIN_D5);
}
void Func2()
{
delay_ms(1000);
output_high(PIN_D6);
}
typedef void (*_fptr)(void);
_fptr func_array[] = {Func0, Func1, Func2};
//=========================================
void main()
{
set_TRIS_D(0x0000);
output_high(PIN_D7);
int8 i;
while(TRUE);
{
for(i=0; i < sizeof(func_array)/2; i++)
{
(*func_array[i])();
}
}//end while
}//end main |
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Oct 23, 2019 8:08 pm |
|
|
Frankly, I don't know what the section in bold below does with the PCD
compiler, since I don't have that compiler.
Quote: |
for(i=0; i < sizeof(func_array)/2; i++)
{
(*func_array[i])();
}
|
Change it to this. It should work with any compiler:
Quote: | for(i=0; i < 3; i++)
{
(*func_array[i])();
}
|
arelone wrote: | In the given code what is *_fptr? I could not find it in the CCS help. |
It's the typedef-created type for a function pointer. |
|
![](templates/subSilver/images/spacer.gif) |
arelone
Joined: 06 Dec 2015 Posts: 42
|
Pointers and Arrays |
Posted: Wed Oct 23, 2019 8:26 pm |
|
|
Hi,
The result still same. I noticed that led (D7) also not functioning.
Quote: |
while(TRUE);
{
for(i=0; i<3; i++)
{
(*func_array[i])();
} |
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Oct 23, 2019 8:29 pm |
|
|
Maybe someone who has the PCD compiler can test it for you. All I know
is that it works with 18F. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Oct 24, 2019 12:20 am |
|
|
The 'nice' way to get the number of elements in the array, is to use sizeof
again. Tested with:
Code: |
#include <30F6014A.h>
#fuses NOWDT, NOPROTECT, PUT64, BORV27
#use delay (clock=60MHz, xtal=8MHz)
//Didn't have a 7.37Mhz crystal
#use rs232(baud=9600,UART1,ERRORS)
void Func0(void)
{
printf("0");
}
void Func1(void)
{
printf("1");
}
void Func2(void)
{
printf("2");
}
typedef void (*_fptr)(void);
_fptr func_array[] = {Func0, Func1, Func2};
//=========================================
void main(void)
{
int8 i;
for(i=0; i < sizeof(func_array)/sizeof(_fptr); i++)
//How to find the number of elements...
{
(*func_array[i])();
}
while(TRUE)
;
}
|
and it merrily works correctly. |
|
![](templates/subSilver/images/spacer.gif) |
arelone
Joined: 06 Dec 2015 Posts: 42
|
Pointers and Arrays |
Posted: Thu Oct 24, 2019 1:10 am |
|
|
Hi,
Thanks Ttelmah for the correction. What version of CCS C compiler are you using?
Arelone |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Oct 24, 2019 1:22 am |
|
|
That was tested on the current compiler. 5.090.
Just recompiled on 5.078, and it works the same. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Oct 24, 2019 1:44 am |
|
|
I installed his version, 5.010, but of the PCH compiler. It fails to run
the program in MPLAB 8.92 simulator. Not the same compiler. But still, a sign. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19369
|
|
Posted: Thu Oct 24, 2019 2:48 am |
|
|
Ah. Yes, 5.010, is before I considered V5 to be a 'working' compiler.
I must admit 'crossed threads' and thought he was using 5.078.... :( |
|
![](templates/subSilver/images/spacer.gif) |
arelone
Joined: 06 Dec 2015 Posts: 42
|
Pointers and Arrays |
Posted: Thu Nov 07, 2019 9:34 am |
|
|
Hi,
I have another questions. I created a code to read from 16 ADC channels and i noticed the using "printf" function takes approx. 1.52 seconds for 16 adc values which is slow. I'd guess the delays will mainly be due to the time needed to send the data serially using "printf" function.
I made simpler code for this discussion to read from 2 ADC channels using sprintf() function. How to format results in an array of character strings, then output the text later on after reading all the ADC values ? In this case the 2 array strings are sent out after finished read from ADC channel 6.
Arelone
Code: |
#include <30F6014A.h>
#device ADC=12
#include <float.h>
#include <string.h>
#fuses NOWDT, NOPROTECT, PUT64, BORV27
#use delay (clock=58982400, xtal=7372800)
#use rs232(baud=9600,UART1,ERRORS)
char adc_value_5[20];
char adc_value_6[20];
unsigned char ert_adc_value_5;
unsigned char ert_adc_value_6;
unsigned char ert_voltages_5;
unsigned char ert_voltages_6;
void task1()
{
set_adc_channel(5); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
//read_adc(ADC_START_ONLY);
ert_adc_value_5=read_adc(); //starts conversion & store it in value
ert_voltages_5=(ert_adc_value_5)*5000/4096;// last result of last conversion
//printf("Ch04=%u\n\r",ert_voltages_5);
sprintf(adc_value_5,"Ch05=<%u\r\n>",ert_voltages_5);
}
void task2()
{
set_adc_channel(6); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
//read_adc(ADC_START_ONLY);
ert_adc_value_6=read_adc(); //starts conversion & store it in value
ert_voltages_6=(ert_adc_value_6)*5000/4096;// last result of last conversion
//printf("Ch05=%u\r\n",ert_voltages_6);
sprintf(adc_value_6,"Ch05=<%u\r\n>",ert_voltages_6);
}
void main(void) //void=nothing, no return value
{
set_TRIS_D(0x0000);
SETUP_ADC(adc_OFF);
setup_adc_ports(ALL_ANALOG);
setup_adc_ports(sAN0 |sAN1|sAN2|sAN3|sAN4|sAN5|sAN6|sAN7|sAN8|sAN9|sAN10|sAN11|sAN12|sAN13|sAN14|sAN15, VSS_VDD);
setup_adc(ADC_CLOCK_DIV_64 | ADC_TAD_MUL_2);
//setup_adc(ADC_CLOCK_INTERNAL);
while(TRUE)
{
task1();
task2();
}//end while
}//end main
|
|
|
![](templates/subSilver/images/spacer.gif) |
|