Apologies. I based my assumption on: switch((u16)buf[0]
Well, I'm stuck with it. Unless the C18 is *so* bad that I can make a case for the client spending more money. Any opinions here on how the C18 measures up?
I am in no way allergic to anything that will save coding time - but I do worry about how much code space, RAM and CPU cycles general purpose tools will consume.
Happy to lose points if I gain time!
Didn't find your answer? Ask the community — no account required.
F
Frank Buss
If your protocol is simple, e.g. "command arg1 arg2 ..." newline "command arg1 arg2 ...", I would just start with something like Rocky described:
void hello(void) { // you can parse command arguments here printf("hello "); }
If this is too slow, sort the commands alphabetically and use a binary search.
For most projects C18 produces code which is fast enough. Don't worry about speed until it is too slow :-) E.g. if you have a 100 ms measure cycle, it doesn't matter if a function needs 100 us or 1 ms and writing code which is easy to read and to maintain is more important.
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
J
Joe Chisolm
The C18 compiler will compile your construct but will generate a lot of instructions to handle it. The PIC architecture does not have a bunch of general registers for C18 to use for register allocation, it only has an accumulator (the W reg) and a few other registers you can use.
The free C18 compiler does not do sub-expression elimination and some other common optimization techniques but does generate reasonably tight code. It wont beat carefully crafted assembler but I know of only
3 or 4 compilers I've ever run into that could beat hand generated assembler for code density. You will generally find that the 2K SRAM is enough. I've had some pretty big projects using serial, USB, driving LEDs and relays along with a bunch of other stuff and not used more than 1000 to 1200 bytes of SRAM. The IDE has some tools to help you watch memory usage.
Lookup tables, constants, etc can be forced into flash locations to reduce runtime SRAM requirements. But you suffer a hit having to do a flash read. Since you are new to PIC, carefully study the manual regarding the various run time libraries, pay close attention to the string functions, memory functions and printf. There are different flavors depending on if the source (or destination) is in flash.
I have also found that the default IDE libraries are compiled for 24 bit pointers and you suffer a hit with this. They work but you have to make sure your code memory model matches the library's LARGE model. Anytime I load the IDE I recompile the libraries with the SMALL memory model which gives me 16 bit pointers. This works for all the low end PICs that have less than 64K of flash.
Joe Chisolm
Marble Falls, Tx.
P
Paul Keinanen
In practice, accurate timing is only required in multidrop slaves. Multiple PCs are seldom used as slaves on the same RS-485 bus.
When the PC acts as a Modbus master or a point-to-point slave, the connection works well with conservative timing, although there might be a few performance in throughput.
Paul
C
ChrisQ
Sorry, but must disagree :-). The problem with the above is that you still have inband data embedded in the code. The only way to make the code completely reusable is to separate form and function. In this case, all the parser needs to know about is the *structure* of the data, not it's content.
I would rewrite the code to allow this:
eStatus = eParseExec (&sRootCommandNode);
Where sRootCommandNode is the command parser table root and the command functions are called via the table contents. It might seem a trivial change, but can have a major impact w/regard to future maintenance and spec change.
The command parser is completely encapsulated and can be replaced in the same application if the command format changes. Being encapsulated, with no global data, it's easy to make it into a library module. After all, who has the time to rewrite the same stuff over and over again ?.
Taking the time to design good data structures is worthwhile, imo and is the key to a robust design...
Regards,
Chris
P
Paul Carpenter
I tend to use a command function that returns an integer/byte (depending on architecure). Reason being if you return an error code you can do some common error reporting for the parsing such as using return values for
0 Success 1 first argument missing ... 'n' max argument number missing 0x81 first argument invalid 0x8n max argument invalid 0xFF hardware failure I normally make the first command tried a 'help' command to list in short form valid commands accepted, and two other commands to return strings of product name and software version. These of course normally return no errors. This way you prove the structure of the code before proving the more complicated commands.
....
or error = command->function(); // insert common argument function error handling here
Paul Carpenter | paul@pcserviceselectronics.co.uk
PC Services
Timing Diagram Font
GNU H8 - compiler & Renesas H8/H8S/H8 Tiny
For those web sites you hate
M
Mikael Nordman
Even if you want to use C, may I suggest FlashForth, a 16 bit Forth Operating System for the PIC18/PIC30/soonPIC24. It has an inbuilt command interpreter and compiler. It also has an round robin multitasker allowing you to have background tasks in addition to the operator task. Forth code for I2C is provided as an example.
With the compiler you design new command langauges to your liking. These new commands can then interpreted by the interpreter.
formatting link
-- Mikael
N
Neil
If you can live with out an RTOS. Mature tools, lots of fourms, lots of code samples, A bigger selection of parts, dirt cheap. Sometimes a cheap lame CPU fits the bill.
N
Neil
Or you could use bit vatiables.
Join the Discussion
Have something to add? Share your thoughts — no account required.
Didn't find your answer?
Ask the community — no account required
Report Content
You are reporting this content to the moderators. They will look at it
ASAP.