Where I illustrate developing code for the ATmega328P using a new Standard C framework.
- Github: Programming the Arduino Uno in C
- Microchip AVR ATmega328 Go to this page for the datasheet, you will need it.
- Definitive UNO pinout
- avr-libc Standard AVR C Library
The Github repository referenced above is a new Standard C framework which mimics a subset of the Arduino framework. [Note: Standard C refers to using a standardized version of C, in this case, avr-gcc (ANSI C) as compared to Arduino C++, which is a combination of C, C++ and Arduino classes and templates. Many universities have an expectation of their students to understand C in the context of ANSI C.] The intent of the repository is to provide the capability for someone to use Standard C in programming an Arduino Uno (or similar type of microcontroller.)
The differences between using the Arduino Framework and this (AVR_C) framework are:
- The AVR_C framework is standard C compliant. It doesn’t use C++ or unique Arduino code, which means you are learning C and not a variant of C/C++.
- The code is much smaller which allows you to do more in the small memory configurations of the ATtiny microcontrollers.
- In some situations such as serial printing, AVR_C is far more simple. The AVR_C approach uses the Standard C functions of puts(), getchar() and printf() as compared to the laborious Serial.print() classes.
The best way to use this repository (or any Github repository) is to install git and add the repository by cloning. This allows you to update it easily when the repository is updated.
SideNote: Install git
Use the package manager of choice:
- macOS: homebrew install git
- Linux Ubuntu: sudo apt install git
- Windows WSL: sudo apt install git
NOTE: I no longer recommend using the Windows command line for this set of tools. I recommend using Windows Subsystem for Linux 1, which provides Linux capability as well as serial connectivity.
- Go to git for Windows
- Download the installer.
- Double-click on the installer to run it. I selected all of the defaults in the installation except for the default editor. I chose Notepad++ in the dropdown instead of vim.
- When using make, I recommend using the command prompt (cmd.exe) vs. git bash, as that is how you installed make, avr-gcc etc in Setup. I had issues using git bash and none using command prompt.
# go to folder where you want your github repositories to be, i.e; Documents/github. # I'll start by making a repository folder mkdir github cd github # go to the repository site as in github.com/lkoepsel/AVR_C # click on the green Code button and copy either the HTTPS link or SSH link git clone email@example.com:lkoepsel/AVR_C.git cd AVR_C
The alternative is to download the ZIP file and extract it to where you want to use it. This will require you to periodically replace it with a new version.
Once you have the folder local to your computer. I recommend you read the README file to get an overview of the repository.
Once you are in the repository, you will want to begin testing your setup. In this case, it is ensuring tool chain, serial connection and your board all work together to enable C code creation.
Note: My assumption on this page, is that you have already completed Setup for your respective platform. And by completed, you have been successful using your favorite code editor, make and an Arduino/compatible board. You are able to make changes to the led program and load it on the UNO. If you haven’t done this, please go the Setup page and complete the steps for your platform, otherwise, the rest of this page will be impossible.
The repository has two main folders, Library and examples. Each folder in examples is a simple example as to how to use an aspect of the Library. In each one of these examples there are two files, a c file, main.c and a make file, Makefile.
The first step is to ensure the Makefile is setup properly for your serial connection and your board.
The easiest method to determine your serial connection to your board is to use the Arduino IDE (yes, this is ironic). In the IDE, use Tools -> Port -> (list of ports) to identify the port connected to your board. Typically, the Arduino will call out the name of the board next to the port name.
Ultimately, you will want to have the system specific name of the serial port. For Linux/macOS, it will be similar to /dev/ttyACM0 or /dev/cu.usbmodem4301, respectively. For Windows, it will be something like COM3. Once you have identified the serial port, make the change on the 5th line of the Makefile:
5 SERIAL = /dev/cu.usbmodem3101
If your board is an Arduino UNO or one that is quite similar, then you don’t need to make any adjustments to line 10 “MCU = atmega328p”. If you have a different processor, for example if you are using an ATtiny84 board, use “attiny84”, for the MCU parameter.
Let’s try delayTest as the first test. It is the Arduino “blink” example, however it uses the C Library code, instead of the Arduino framework. It will help ensure the Library is being used for your code.
To run the code:
# switch to the example folder cd delayTest # compile code and upload to make flash # the above command will compile, link and load the Uno # just as the Upload command would do in the Arduino IDE
If there are errors in compiling the code, you will need to confirm a change in the Makefile. We are adding the Library to the compilation, so we need to confirm the location of the Library to the Makefile.
# Make sure line 18 is uncommented 18 LIBDIR = ../../Library # and line 65 has -I$(LIBDIR) at the end 65 CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
The avr-gcc tool chain brings a much better serial communications capability to the Library. Once the uart code has been added to support the ATmega328P processor, you are able to use the standard C input/output commands such as getchar(), puts() and printf().
To begin testing the serial port, open the examples/serialio folder. Run make flash as you normally do. To see the output and provide input to the program you will need a serial monitor. Consider using the following based on your platform: (You can also use the Arduino Serial Monitor on all three platforms.)
- Linux: moserial, minicom or serial
- macOS: serial(text-based), Serial(gui-based), or minicom
- Windows: puTTY
A couple of notes on serial I/O using Standard C. The current simple approach for serial I/O uses polling, where the input/output routines wait for a char to be received/sent, respectively. This makes the I/O very slow (9600 baud), is blocking (no I/O, nothing happens) and requires some upfront initialization. This is fine for now, as we’re more interested in developing Standard C programs then production code.
For the last point regarding I/O (initialization), this does mean one needs to do the following: (Use the serialio example for guidance.)
At the top of the file, add #include <stdio.h> #include "uart.h" # Inside of main(), add prior to your I/O init_serial(); // this is a macro, so no () are required
Note: As noted in the README file in the repository, I have found a serial application, which seem to have an issue with this serial I/O approach. On Linux, using minicom, the serialio program wouldn’t respond with input. I tested the serialio using the Arduino serial monitor and it worked well. I haven’t seen the issue on any other combinations.
The Makefile in each folder has a variety of options which can be quite useful. Here are a few of them:
# Same as Verify in Arduino IDE, simply compiles the main.c program make # Same as Upload in Arduino IDE, compiles, links and uploads the code to the UNO make flash # Create a an assembly listing of the code complete with C source code make disassembly # Show the size of the code created in great detail make size # Remove all files except source files (main.c and Makefile) make all_clean # Remove all the current object files in the Library make LIB_clean