Difference between revisions of "Documents/LED Blink"
(→Building the Application Code) |
|||
Line 181: | Line 181: | ||
If everything worked well, your LED should start blinking. | If everything worked well, your LED should start blinking. | ||
− | [[ | + | [[Documents/LED Hardware|Previous]] [[Documents/LED Tutorial|Contents]] |
</div> | </div> |
Revision as of 17:55, 13 July 2017
Contents
Nut/OS LED Tutorial
We will now start with our first application. It will initialize the port bit and then switch on and off the LED in an endless loop.
ATmega Ports
Almost all digital ports of the ATmega128 can be individually configured for input or output. Three registers are used to control or monitor each port.
- Port register
When the port is configured for output, we can clear each bit to drive the corresponding output low or set the bit to drive it high.
- Pin register
When the port is configured for input, then each bit reflects the status at the corresponding input pin. The bit is zero, when the input is low or set if the input is driven high.
- Data direction register
This register is used to configure the mode of each port pin. When the bit is set, then the port pin works in output mode.
All registers are 8 bits wide and three of them are available at the [[../hardware/expansion.html|Ethernut expansion port]] , named B, D and E.
Initialization
Standard C does not provide functions to access port registers. But the AVR library, that comes with your compiler, offers such capabilities. Almost all AVR compilers allow to handle ports like predefined variables. To set bit 2 of data direction register of Port E, we can write
DDRE |= 0x04;
In addition a bit value macro is supported as well, which often makes the code easier to read.
DDRE |= _BV(2);
However, using predefined variables to access port registers makes the code less portable. With Nut/OS we prefer to use macros instead. To set bit 2 of the data direction register, we use
sbi(DDRE, 2);
and
cbi(DDRE, 2);
could be used to clear it again.
Blinking LED
Setting and clearing the output pin can be done in a similar way:
for { cbi(PORTE, 2); sbi(PORTE, 2); }
This loop will rapidly drive the output pin 41 of the expansion port to low and back to high. Driving the output low will lit the LED, driving it high will switch the LED off. However, the switching occurs so fast, that we would not be able to notice anything but a glowing LED. At this point Nut/OS jumps in. It offers a function named NutSleep(), which suspends the current thread for a specified number of milliseconds. You may now ask yourself: "What thread?". Take it easy, we will explain this in detail later. Until then it is sufficient to understand, that our application will stop running for a given amount of time.
Building the Application Code
You should have created a sample application directory by following the Ethernut Software Manual. Within this directory create a new subdirectory named led01. Within this directory create a new C source file name led01.c and put in the following contents.
/* * This header contains the Nut/OS timer function * prototypes. We need it for calling NutSleep. */ #include <sys/timer.h> /* * Ethernut LED example #1. */ int main(void) { /* * Configure port E bit 2 as an output. */ sbi(DDRE, 2); /* * An endless loop. */ for (;;) { /* * Set port E bit 2 to low. This will lit the LED. */ cbi(PORTE, 2); /* * Sleep 1000 milliseconds. */ NutSleep(1000); /* * Setting port E bit 2 to high switches off the LED. */ sbi(PORTE, 2); /* * Sleep for another 1000 milliseconds. */ NutSleep(1000); } }
If you're using the ImageCraft IDE, then you will probably create a project. Again, check the Ethernut Software Manual for specific project settings.
For the GCC compiler we need to create a file name Makefile in the same directory, which contains:
PROJ = led01 include ../Makedefs SRCS = $(PROJ).c OBJS = $(SRCS:.c=.o) LIBS = $(LIBDIR)/nutinit.o -lnutos -lnutdev $(ADDLIBS) TARG = $(PROJ).hex all: $(OBJS) $(TARG) include ../Makerules
Next open a command line shell (DOS box), change to our new directory. On Linux the PATH is usually correctly configured. On Windows you may have to execute
SET PATH=C:\ethernut\nut\tools\win32;C:\WinAVR\bin;C:\WinAVR\utils\bin;%PATH%
Replace the given directories with the paths used when you installed Nut/OS and WinAVR on your machine. Now simply enter
make
on the command line. The resulting output on your environment may vary, but in general should look like
avr-gcc -c -mmcu=atmega128 -Os -fno-delete-null-pointer-checks -Wall -Wstrict-prototypes -Wa,-ahlms=led01.lst -D__HARVARD_ARCH__ -DETHERNUT2 -IC:/ethernut-3.9.8/nutbld-21b/include -IC:/ethernut-3.9.8/nut/include led01.c -o led01.o avr-gcc led01.o -mmcu=atmega128 -Wl,--defsym=main=0,-Map=led01.map,--cref -LC:/ethernut-3.9.8/nutbld-21b/lib C:/ethernut-3.9.8/nutbld-21b/lib/nutinit.o -lnutos -lnutdev -o led01.elf avr-objcopy -R .eeprom -O ihex led01.elf led01.hex rm led01.elf
Once again, the Ethernut Software Manual will be helpful with creating Nut/OS applications. As a result you'll find several new files in your application directory. The most important one is led01.hex, which contains the code to be transfered to the Ethernut Board in Intel Hex Format.
Running the Application Code
It's time to attach the programmer and power up your Ethernut.
The ImageCraft compiler offers an integrated programming tool. With GCC you can use
make burn
Your output may vary again, but should look similar to
uisp -dprog=stk500 -dserial=/dev/ttyS0 -dspeed=115200 -dpart=atmega128 --erase --upload if=led01.hex Firmware Version: 49.48 Atmel AVR ATmega128 is found. Uploading: flash
If everything worked well, your LED should start blinking.