|
This FAQ contains the top 68 questions and techniques asked by PIC micro students about Hi-Tech C for the PIC16Fx, PIC18Fx and PIC24Fx micros from the University of Canterbury.
View the latest questions and answers on www.MicrochipFault.com, under the tag: HiTechCFAQ
This FAQ contains over 100k of pure text.
Enjoy – I sincerely hope this advice saves you a lot of time and effort.
Fundamentals of PIC and Hi-Tech C
Q. What are the most commonly used features of a PIC micro?
Q. So, how do I use the features listed in the previous question?
Q. Tell me how to drive the pins on a PIC micro
Researching Data
Q. How do I find suppliers of Microchip parts?
Q. How to I do research on a new project?
|
Q. How do I express numbers in decimal, hexadecimal or binary?
Q. Whats wrong with the following code …?
Q. Whats wrong with the following code …?
Q. What datatypes are available on a PIC?
Q. How do I switch bits on and off in a variable?
Q. How do I test bits in a variable?
Q. How do I divide or multiply by two efficiently?
Q. How do I reference one of the bytes in an integer?
Q. Doesn’t ‘x>>=8’ have 8 shifts?
Q. Why don’t you use pointers to look at individual bytes in an integer?
Q. Can I use inline code for functions?
Q. Whats wrong with my port initialization code?
Watching the values of variables
Q. How do I watch variables in MPLab?
Q. How do I watch an array of variables in MPLab?
Q. I cannot view local variables in the watch window
Errors and what they mean
Q. I get the following errors or line of errors when I compile
Q. PORTA doesn’t work when reading logic levels
Q. Port RA4 doesn’t work
Q. My A/D doesn’t work
Q. Unexplained Operation and Stack Levels
Interesting quirks of Hi-Tech C
Q. Whats wrong with the following program? It gives errors
|
Q. I’m communicating to a PC with a serial port. It wont work. How do I fix it?
Q. My serial port sometimes dies completely, it wont receive anything more
Q. I want a routine to do a serial port in software
Interrupts
Q. How do I use interrupts?
Q. My interrupt routine is not working
Q. How do I tell what pin on RBIF the interrupt came from?
Q. How do I execute some code precisely every 800us at 4MHz?
Q. How do I speed up my interrupts?
Q. How do I time exact intervals?
Q. Whats wrong with the following interrupt code?
Simulator/Emulator Breakpoint Problems
Q. I cant seem to get a breakpoint in the right spot
Emulator Problems
Q. My circuit works with the emulator, but not if I plug in a programmed chip
Q. My program works with the ICEPIC 2000 but not the ICD emulator
Watchdog Timer
Q. What is the watchdog timer and why do I want it?
Q. My programmed PIC, restarted itself every couple of seconds
Q. Have you got any delay routines?
Q. How do I measure the time code takes?
Q. How do I make a variable oscillate, ie: go 1-0-1-0
Q. How do I reset the micro?
Q. How do I tell what the compilers called a variable in the manual?
Q. Whats the rule of thumb for timeouts?
Q. I need more space in the micro – 8k is not enough for a 16F876
Q. Can I use printf() when talking to a PC computer via the RS232 serial port
Q. Why cant I print long (32 bit) variables with printf()?
Q. How do I store large amounts of data?
Hardware for PIC
Q. Can I control 2 LEDs from one port?
Q. I want to protect my circuit from overcurrents and shorts
Q. How do I save power in my embedded micro system?
Q. My PIC sometimes resets by itself
Bootloader for PIC16F87x
Q. How do I do a bootloader for the flash based 16F87x?
Simple Multitasking Kernel for PIC under Hi-Tech C
Q. Example of simple multitasking system
Q. How do I embed the programming configuration words within my C program?
Q. The programmer doesn’t seem to work – it doesn’t program
Q. It always loses settings for the programmer when I exit
Using Libraries with MPLab
Q. What is a library, consisting of a ".lib" file, and how do I use it?
Q. How do I make a library file?
Q. I make a library file ending in ".lib" but I cant tell MPLab how to get to it
Serial Numbers with Hi-Tech C
Q. How do I add serial numbers to a program coded in Hi-Tech C?
Incremental Compiles under Hi-Tech C
Q. How do I do incremental compiles under Hi-Tech C?
The PIC12Cx67x
Q. How do I set the OSCCAL calibration bits?
Fundamentals of PIC with Hi-Tech C
Q. What are the most commonly used features of a PIC micro?
- Output ports for driving LEDs, etc.
- Input ports for reading logic levels.
- Timers that count in the background
- External interrupts that trigger the interrupt routine if a port changes.
- Internal interrupts that trigger the interrupt routine if a timer overflows
- Serial port USART for communicating with a PC
- A/D ports for reading voltages
- Capture ports that can precisely capture the exact time of a port logic change.
- I2C, a standard by Philips that allows comms to multiple devices on a 2-wire bus
- SPI, transferring data using a CLK and DATA line
- Counters, can count external pulses in hardware and give the result a register
- SLEEP mode, to reduce power consumption.
- Watchdog timer, to increase reliability by resetting micro if it crashes.
Q. So, how do I use the features of the PIC micro listed in the previous question?
A. Well, this may sound obvious, but the best way is to follow through the Microchip microprocessor manual. Do it step by step. Dont succumb to the urge to do it now - complete the reading first, then do programming. This way, you avoid missing crucial pieces of information that you will need to get it working.Rule of thumb: When using a new feature of the PIC micro for the first time, read every word in that section of the manual. To skim read it means you will miss out some crucial feature, and waster time inthe long run.
For example, to use the A/D port, look up the manual, and follow through it. All the variables like ADCON1, etc have the same name in C. To get a list of all the equivalent names for the registers in C, go to c:\ht-pic\include subdirectory and look at the header files. This is very useful file to have for reference.Q. Tell me how to drive the pins on a PIC micro.
A. Take the PIC16F876, a 28-pin micro. Then look at port A for example. This is a row of 6 pins, going down the side of the micro. Each pin can output 5V or 0V, or read whether the input is 5V or 0V. Here is sample C code to write a logic level to a port. A value of 1 will product 5V, a 0 will produce 0V.
//(c)Shane Tolmie, http://www.microchipc.com/, distribute freely for non commercial use on the condition that you include this web link somewhere in your document.
#include
main()
{
#define OUTPUT 0
#define INPUT 1
ADCON1=7; //switch all pins in port A to digital (otherwise it tries to do A/D)
TRISA0=OUTPUT; //change port RA0 direction to output
RA0=1; //produce 5V on RA0, pin 2 of micro
RA0=0; //produce 0V on RA0, pin 2 of micro
}
Alternatively, you can read the value of the logic level on a port. If it is 0V, it will return a 0, it it is 5V, it will return a 1. Here is sample C code.
//(c)Shane Tolmie, http://www.microchipc.com/, distribute freely for non commercial use on the condition that you include this web link somewhere in your document.
#include
main()
{
unsigned char x;
#define OUTPUT 0
#define INPUT 1
ADCON1=7; //switch port A to digital (otherwise it tries to do A/D)
TRISA0=INPUT; //change the port direction to input
x=RA0; //now x=0 if RA0=0 volts, and x=1 if RA0=5V.
}
Researching Data
Q. How do I find suppliers of Microchip parts?
A. Go to the Microchip web site and look up the list of distributors in your country. This technique works for any company – get their info on who distributes for them. Also, try http://www.findchips.com/ or http://www.freetradezone.com/. I have found this site to be helpful for comparisons between companies/products and within the microchip line itself. It has been very helpful to see right at the beginning that the chips are so easy to get, cheap, and varied.
Q. How to I do research on a new project?
A. Well, there are many places to find information on what you intend to do.
1. Read books and magazines. The advantage of these over the internet are that the signal-to-noise ratio is extremely high, and the articles are likely to be more correct. For books, search http://www.amazon.com/ for ‘pic micro’ then get it out at your local library or buy it. Good magazines are Circuit Cellar, Electronics Australia, Popular Science and Popular Mechanics, among others.
2. Look up previous years projects for other students that have completed 3rd pro design. By reading their report, you can gain sample code and ideas from their writeup.
3.Collect application notes. All the major manufacturers like Philips, Motorola, Atmel, Microchip, Intel, National Semiconductor, TI and Zilog have sample projects to illustrate the use of their devices. Look on their web sites under ‘Application Notes’, or do a search for 'application notes'.
4. Find the official standards. It may be nice to download information off the web compiled by some well meaning person, but in my experience don’t be satisfied until you have the official documentation. Information compiled by a private individual may be only mostly correct.
5. Put out a request for information on the web.
- For the best results, go to http://www.copernic.com/ and download their search program. It is better than web based searches and extremely fast. I use it exclusively now, as it gets the best results, culled and sorted from the best search engines.
- You can use newsgroups on the internet such as comp.arch.embedded.
- The Hi-Tech site, http://www.htsoft.com/ has an inhouse newsgroup devoted to PIC questions on their compiler.
- Subscribe to piclist, http://www.piclist.com/ to ask any question of thousands of PIC enthusiasts.
- Search the piclist archive, from http://www.piclist.com/ to look at previous postings.
- Look at the PIC webring http://nav.webring.com/cgi-bin/navcgi?ring=picmicro;list which is a collection of sites related to the PIC micro.
- Search for ‘pic micro’ on http://www.google.com/, one of the best web-based search engines out there.
Tips for using features of C on a PIC micro
Q. How do I express numbers in decimal, hexadecimal or binary?
A. Use the following code:
unsigned char x; //8 bits on PIC
x=255;
x=0xFF; //give hex number, x=255
x=0b11111111; //give binary number, x=255
Q. Whats wrong with the following code?
unsigned char x;
x=0b1111111; //set x to 0xFF or 255
A. Can you figure it out without looking at the answer? It’s a simple error, but its easy to glance over and miss. Throughout history, it has caused countless hours of wasted time. 0b1111111=127, not 255, as the last 1 is missing. Binary values always come in groups of 8 bits, and one should always mentally check that 8 bits have been entered.
Q. Whats wrong with the following code?
unsigned char i;
for (i=7;i>=0;i--) { }; //BAD BUG – will loop forever
A. A very insidious bug. When it gets to zero, it decrements it and then checks to see whether its still higher than zero. But, of course, since its unsigned it has already rolled over to 255. Thus it will loop until the next blue moon. Change variable i to signed, as below:
signed char i;
for (i=7;i>=0;i--) { }; //works correctly
Note that when counting up from 0, chars can be both signed and unsigned as there is no rollover problem.
Q. What datatypes are available on a PIC?
A. The following:
unsigned char a; //8 bits, 0 to 255
signed char b; //8 bits, -128 to 127
unsigned int c; //16 bits, 0 to 65535
signed int d; //16 bits, -32768 to 32767
long e; //32 bits, -2147483648 to 2147483647
float f; //24 or 32 bits, depending on options under ‘edit project’
Q. How do I switch bits on and off in a variable?
A. Use the following code for turning single bits on or off in a variable. Remember that the bits in an 8-bit variable are always numbered from right to left, 0 to 7. For example, bit 0 of 0b00000001 is 1. Bit 1 is 0.
/*for turning single bits on/off in a variable. Use ~0 instead of 0xFFFF, etc, because this ensures machine independence, if int changes from 16-bit to 32-bit. Remember that the bits in an 8-bit variable are always numbered from right to left, 0 to 7. For example, bit 0 of 0b00000001 is 1. Bit 1 is 0, through to the most significant bit 7 on the left.
Example C:
unsigned char x=0b0001;
bit_set(x,3); //now x=0b1001;
bit_clr(x,0); //now x=0b1000;*/
#define bit_set(var,bitno) ((var) |= 1 << (bitno))
#define bit_clr(var,bitno) ((var) &= ~(1 << (bitno)))
Use the following code for turning multiple bits on or off in a variable, according to mask.
/*for turning multiple bits on/off according to mask. Use ~0 instead of 0xFFFF, etc, because this ensures machine independence if int changes from 16-bit to 32-bit.
Example C:
unsigned char x=0b1010;
bits_on(x,0b0001); //now x=0b1011
bits_off(x,0b0011); //now x=0b1000 */
#define bits_on(var,mask) var |= mask
#define bits_off(var,mask) var &= ~0 ^ mask
Q. How do I test bits in a variable?
A. Use the following code:
/*for testing single bits in a variable. Remember that the bits in an 8-bit variable are always numbered from right to left, 0 to 7. For example, bit 0 of 0b00000001 is 1. Bit 1 is 0, through to the most significant bit 7 on the left.
Example C:
x=0b1000; //decimal 8 or hexadecimal 0x8
if (testbit(x,3)) a(); else b(); //function a() gets executed
if (testbit(x,0)) a(); else b(); //function b() gets executed
if (!testbit(x,0)) b(); //function b() gets executed
*/
#define testbit_on(data,bitno) ((data>>bitno)&0x01)
Q. How do I divide or multiply by two efficiently?
A. To multiply by two, use x = x << 1 or x<<=1. The second version is shorthand. If x=2, or 0b10 in binary, shifting left gives 0b100 or 4. To multiply by four, use x<<=2. By eight, x<<=3. To divide by two, use x>>=1. To divide by four, use x>>=2.
Having said this, most compilers would optimise a x=x/2 into a shift anyway.
Q. If an integer is 16 bits on a PIC, and a byte is 8 bits, how do I reference one of the bytes in an integer?
A. Use the following code:
unsigned int x;
unsigned char y;
#define hibyte(x) (unsigned char)(x>>8)
#define lobyte(x (unsigned char)(x & 0xFF)
x=0x1234;
y=hibyte(x); //now y=0x12
y=lobyte(x); //now y=0x34
/*note: the above method is as efficient as pointers, as with Hi-Tech C the optimiser picks out the right byte of course, (x>>7) would result in 7 shifts. Local and Global optimisations must be on*/
Note the use of typecasting – when converting any variable to another type, one should typecast it. Read a book on C to explain this further. Note, unions are not necessary and are not recommended because passing variables to functions is made more difficult.
The above method is good for looking at any variable in any bank of memory. Unfortunately, it cannot be used to alter a byte in an int. For this, pointers are needed. A different #define is needed to alter variables in each bank.
#define lobyte_atbank0(x) (unsigned char)(*(((unsigned char *)&x)+0))
#define hibyte_atbank0(x) (unsigned char)(*(((unsigned char *)&x)+1))
#define lobyte_atbank1(x) (unsigned char)(*(((bank1 unsigned char *)&x)+0))
#define hibyte_atbank1(x) (unsigned char)(*(((bank1 unsigned char *)&x)+1))
Q. Is the following code inefficient? Doesn’t ‘x>>=8’ have 8 shifts?
unsigned int x;
unsigned char y;
x=0xFF00;
y=(unsigned char)(x>>8); //now y=0xFF
A. No. Its very efficient – the Hi-Tech C compiler goes through and just refers directly to the top byte out of the int. Local and global optimisations must be on in the project. Of course, y=x>>7 would have 7 shifts and take a long time on a PIC.
Q. Instead of using (unsigned char)(x>>8) as per the previous question, why don’t you use pointers?
A. It is possible, but because there is 4 banks of memory it needs a different #define for variables in each bank. Its simpler and effectively the same to use (unsigned char)(x>>8), unless you’re altering the variable.
Q. Whats the difference between the following two lines of code:
x++; if (x>=4) x=0;
x++; if (x==4) x=0;
A. It’s a very minor point, but the first statement is more robust. If a rogue pointer or a chip brownout corrupts x, it will count all the way up to the max before wrapping around. Of course, one may want such errors to show up, so the second one may be more preferable.
No comments:
Post a Comment