Playing with Arduino board and its graphical development environment I felt the urge to work closer to the hardware, stepping away from the default library and the Java IDE and using the compiler directly from the command line. Fortunately all the tools are there, because the Arduino IDE uses them under the hood. So I tried to use the avr-gcc compiler and the avrdude uploading tool, directly with pure C code.
To make it simple I implemented the classic blink program that toggles the output pin connected to the on-board LED. The Arduino Uno schematics indicate that the LED is connected to the PB5 pin of the Atmega328p chip, so that’s the pin I need to control. The AVR compiler is complemented with a C library: avr-libc, which contains useful functions and headers to develop for AVR chips without using assembly language. Inside the avr-libc manual and the Atmega328p datasheet there are many examples on how to toggle IOs, and with them I prepared the following code:
#include <avr/io.h>
#include <util/delay.h>
enum {
BLINK_DELAY_MS = 1000,
};
int main (void)
{
/* set pin 5 of PORTB for output*/
DDRB |= _BV(DDB5);
while(1) {
/* set pin 5 high to turn led on */
PORTB |= _BV(PORTB5);
_delay_ms(BLINK_DELAY_MS);
/* set pin 5 low to turn led off */
PORTB &= ~_BV(PORTB5);
_delay_ms(BLINK_DELAY_MS);
}
return 0;
}
The Port “B” of the microcontroller can be changed bit by bit with special instructions called “sbi” and “cbi“, and the compiler recognizes those kind of accesses generating optimized assembly in case of bit-wise operations. The ports definitions and useful macros (like “_BV“)can be found in the “/usr/lib/avr/include/avr/iom328p.h” and “/usr/lib/avr/include/avr/sfr_defs.h” headers.
In order to compile a program and upload it to the Arduino Uno, I need to create an IHEX file and use the avrdude tool to load it inside the Flash. Most of the parameters and options of the avr-gcc and the avrdude tools for the Uno board can be found in the “hardware/arduino/boards.txt” file from inside the Arduino IDE installation directory, and some other information is present in the avrdude manual. The commands that I used to compile and upload the “led.c” code above are:
$ avr-gcc -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o led.o led.c $ avr-gcc -mmcu=atmega328p led.o -o led $ avr-objcopy -O ihex -R .eeprom led led.hex $ avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:w:led.hex avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e950f avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed To disable this feature, specify the -D option. avrdude: erasing chip avrdude: reading input file "led.hex" avrdude: input file led.hex auto detected as Intel Hex avrdude: writing flash (88 bytes): Writing | ################################################## | 100% 0.02s avrdude: 88 bytes of flash written avrdude: safemode: Fuses OK avrdude done. Thank you.
The code is uploaded and the led starts blinking. Well that was easy, mostly due to the fact that the tools have good support for the Arduino.
It is also possible to do a backup of the Atmega328p Flash content by using this command:
$ avrdude -F -V -c arduino -p ATMEGA328P -P /dev/ttyACM0 -b 115200 -U flash:r:flash_backup.hex:i
See also:
- Can’t hack, won’t hack: Programming the Arduino in Pure C
- Johannes Hoff: Arduino on the command line
- Martin’s Atelier: Arduino from the command line
Entries
Lev Abalkin
2011/04/24
Thank you.
Please update adruino.cc with this piece of information.
Balau
2011/04/30
I added this post in Code Library and Tutorials.
Dipesh
2011/09/30
Thank you very much for this very short and effective getting started guid.
Ernesto
2011/11/29
could you post how to create/modify a code to create a switch between a small microphone with two outpust, one being speakers and the other being headphones.
Balau
2011/11/29
I haven’t played with audio yet, so I can’t really help you very much.
I think you have two ways to do it:
The first is to use electronics (amplifiers, transistors, …) to bring the signal from the mic to the speakers and the headphones, and use the Arduino only to switch on/off some transistors to make the sound go where you want to go.
In this case the code should be quite simple, you set one GPIO as an input button and two as outputs (one high one low). Then you poll the input button, and when it is pressed, you switch the logic level of the two output GPIOs.
The second is to sample the audio with the Arduino using the ADC and creating the sound with two PWM outputs that you enable/disable based on an input button connected to a GPIO. For better sound I suppose you need to raise the ADC sampling frequency by setting the prescaler to a low level; see this page: Faster Analog Read?. To output the audio, see this introduction: Play Melody
In this forum you can find people who can help you better than I can:
Using Arduino – Audio
ed
2012/01/01
Good to know. But I presume using AVRDude to ‘get it into the Flash’ means getting an AVR programmer?
Balau
2012/01/01
Actually Arduino has a built-in way to program the flash, using a chip placed between the USB and the AVR microcontroller. avrdude is able to use the “Arduino way” of uploading the code, without using a programmer.
ed
2012/01/01
I know I can use an Arduino to program an AVR micorcontroller and actually have done so already, but that is still from within the ARduino IDE, using the Arduino as a programmer.
But how to do that with a hexfile instead of a pde, using an Arduino as programmer, I would not know.
Could you expand? Would really be helpful. Which ‘chip’ betweem the USB and the AVR? is that the to be programmed chip or the chip that does the programming?
Balau
2012/01/02
If you use the Arduino IDE, go into File->Preferences, and enable verbose output during compilation and upload. It will show in the lower command window what happens under the hood. And under the hood the Arduino IDE actually uses avrdude. It transforms the pde file into a C++ source file and compiles it (using avr-gcc) with the libraries to create an ELF file, which is then converted into an hex file by avr-objcopy. The hex file is then uploaded with avrdude.
In my last comment I forgot to tell that other than the USB-to-serial chip (which is an FTDI or small AVR) there is also a bootloader inside the AVR flash that allows to program the AVR without a programmer. See also these pages:
http://arduino.cc/en/Hacking/Bootloader
http://arduino.cc/en/Tutorial/Bootloader
ed
2012/01/02
Thanks Balau. I am familiar with that, but maybe I did not pose my question clearly.
From your article I understood that you could use the Arduino IDE to upload (‘program’) a hex file to an AVR chip.
It still is not clear to me:
-I write a program in C -> that gives me a hex file. I know the exact name of that hex file even without verbose Arduino
-How to get that hexfile into the Arduino board if not with a Programmer?
-If there is a way to get that hexfile programmed into an arduino with the Arduino IDE (as yr article seems to suggest) I’d be glad to learn that.
Tnx
ed
2012/01/02
Just additional: as I said before: I know how to program an AVR chip with an arduino, but then I use a pde file (yes, under the hood that is converted to hex and then uploaded with avrdude)
But if you only have the c generated hexfile, so not a .pde or .ino file, but a hexfile, developed in a C compiler. How to get that into a chip with the arduino?
Balau
2012/01/02
OK sorry if I don’t understand, you know, new year’s eve…
So your objective is to upload an HEX file into an AVR chip, using an Arduino as the programmer.
I never did it, but I don’t think it can be done in the IDE, because the “workflow” is quite fixed, or at least I don’t know how to do it. Instead I think it can be done with avrdude. To upload an HEX file into an AVR chip, you can use an Arduino as an ISP with this sketch that emulates an avrisp programmer:
https://github.com/rsbohn/arduinoisp
You upload it on the Arduino with the IDE, but be aware that it does not work on all Arduinos (Uno is excluded for example)
Then when the program is uploaded, you connect the chip in a way similar to that explained here:
http://arduino.cc/en/Tutorial/ArduinoISP
Then the way to use Arduino as ISP with avrdude is presented here:
http://code.google.com/p/mega-isp/wiki/AvrispArduino
The complete command should be something like this:
avrdude -F -V -c avrisp -p ATMEGA328P -P /dev/ttyACM0 -b 19200 -U flash:w:myprogram.hexIf you substitute myprogram.hex with your HEX file, ATMEGA328P with the AVR chip you want to program, “
/dev/ttyACM0” with the serial port on which is connected the Arduino, it should work.ed
2012/01/02
Thanks,
I know how to use the IDE+Arduino as an AVR programmer (and have done so many times), but that only works for IDE developed programs
, not (to my knowledge) for externally developed Hex files.
I don’t think it can be done either and that is why I asked, coz it is what your article seemed to suggest
The method you describe now, is however an interesting one and it may well work, provided one first loads the ‘Arduino as ISP programmer’ sketch (otherwise one might reprogram the arduino chip.
I am gonna give that a try
Balau
2012/01/02
In my article above I show that it is possible to upload an HEX file on an Arduino board that still has the bootloader in flash, using avrdude and no programmers, and my objective was to avoid the IDE and Arduino libraries completely. I am sorry if I unintentionally misled you.
Good luck!
ed
2012/01/02
Balau, no apologies necessary. That was sort of what I thought you were doing, But I thought you were trying to get a hexfile in an empty chip, without a programmer.
Sorry for the confusion, but thanks for the info
Phil
2012/01/04
Balau,
Is it possible to program the ATmega328 in assembly rather than C?
Balau
2012/01/05
Absolutely. The “
avr-as” program can be used to compile assembly files.If you run compilation of my example with “
avr-gcc -save-temps -DF_CPU=16000000UL -mmcu=atmega328p -Os -c -o led.o led.c” then it will create “led.s” that contains an example on how to write a main in assembler.One thing to take into account with respect to C programming is that you might want to override the “crt” library, which contains the boot code and the interrupt vectors. If you add “-nostartfiles” to the linking command, it will not link the “crt” library included in the toolchain. I am assuming that if you want to program an AVR in assembler, you know what you are doing.
Phil
2012/01/11
Thanks for you reply Balau! I’m actually relatively inexperienced with assembly but wanted to learn avr’s assembly language rather than x86 assembly so forgive my lack of knowledge. So once I have an object file generated by avr-as I can use avrdude to write that object file to flash on my microcontroller?
Balau
2012/01/12
From the assembly file you create an object file (“.o”), then you use avr-gcc as a linker to create the “executable” file, and then from the executable you can create an hexadecimal file with avr-objcopy. The hexadecimal file can be uploaded with avrdude.
avr-as can be called directly, or it can be called implicitly if you use avr-gcc to compile the assembly file.
See this guide, especially chapter 11:
http://www.network-theory.co.uk/docs/gccintro/
Most of the things you can find anywhere for GCC can be applied to avr-gcc and the AVR toolchain.
Giancarlo Colasante
2012/03/13
Hello Balau,
how do you uses ADC in pure C?
Balau
2012/03/13
You can find everything you need in the ATmega328P manual.
When you want to start a conversion you write the ADCSRA with the ADEN and ADSC set to 1.
Then you wait that the ADSC bit returns to 0, and after that you read ADCL (low part) and ADCH (high part) to compose the digital reading.
It is also possible to use interrupt to understand when the conversion is complete (using bit ADIE of register ADCSRA) and it is also possible to start the next conversion automatically using the “Free running mode” with bit ADATE of register ADCSRA.
RrrPi
2012/04/06
Hi there!
First of all thanks for this great how-to!
Could you please recomend me a good book or so to learn to program my Arduino in the proper AVR-way? I mean the Arduino IDE is great for quick n dirty prototypes, but I’d like to optimise my code in terms of energy consumption and things like that.
Thank you in advance.
Balau
2012/04/07
I don’t own this book, but from what I can pre-view it seems to be what you are searching for: Embedded C Programming and the Atmel AVR
For something free and non specific to AVR, these two online books cover very similar principles for PICs, and are very well done in my opinion:
PIC microcontrollers
PIC microcontrollers programming in C
RrrPi
2012/04/07
Thank you!
To be honest I had an unsuccessful attempt with a demo board built around a PIC18 and the PICkit 3. Maybe the lack of linux support maybe I wasn’t determinate enough, it was a pain in the a**. Than I purchase an Arduino and it was instant success. But as I said above I would like to gain some deeper knowledge on microcontrollers.
Should I give an another go for the PIC?
Balau
2012/04/07
Well, Arduino also removes the hassle of using a programmer to upload the code. In my opinion you should stick with it for now.
I was just suggesting the PIC books because they are one of the best free online resources that explain how to program a microcontroller in C.
Other than that, I think the only necessary document for you should be the AVR datasheet that I mentioned in the post.
RrrPi
2012/04/08
Ok. I guess my main problem -beside the lack of electronics knowledge- is I have a high level programing background. Therefore I am unable to write chip specific codes, just a generic mess. That’s why I found FPGAs and Verilog extremly hard as well.
Thanks again. Btw, Happy Easter!
Arunkumar Vasudevan (@arunkumarv)
2012/08/23
is there any way to work with arduino ethernet shield in pure C. I am using arduino UNO and arduino ethernet shield for my project.
Balau
2012/08/23
It surely can be done, but I’m afraid it’s not easy.
As you know there is an Ethernet library, which contains C++ files (The Arduino package installed the source code in /usr/share/arduino/libraries/Ethernet, or anyway you should have it installed with Arduino IDE).
It’s not always possible to call C++ code from C, and in this case the Ethernet library is not made to be called from C.
I think you have three alternatives:
The best way depends on your situation. For example if your program is small and you have some experience (even small) in C++, you can choose the first.
If your goal is pure speed, maybe the second option could give you more control of what is going on, but it may require the most effort.
The third could be the fastest way to do it, if you know how to write a wrapper. See here:
http://developers.sun.com/solaris/articles/mixing.htmlhttp://www.oracle.com/technetwork/articles/servers-storage-dev/mixingcandcpluspluscode-305840.html and I suggest first trying to write a wrapper of a small C++ class that you write yourself.[Edit: dead link]
rafi levent
2012/10/20
dear Mr
i have the arduino uno usb+the video experimenter shild+a rotary encoder, model E6A2 and a
Triple Axis Accelerometer Breakout – ADXL335.
i orderd this parts because i wanted to lay on a video sorce(camos camera)that is mounted on a crawler and conected to a control station with a monitor by a cable. ,some data.
the first one is i want the encoder to be mounted on the cable so i can see how meny meters of cable went out and came back in.(on the screen)
and i want to know the degree of the road\way(on the screen)
for the begining i want to know how to conect the encoder to the board and how do i program the arduino to recognaiz it.
then i want to conect the 3axis to the arduino and program it.
is ther a special program to the video shild?
all the best
rafi
Balau
2012/10/20
So, if I understand correctly you have 3 questions:
I never used these products, so I can just try to give you some pointers of what I would try, but I don’t know if what I am suggesting is correct.
The E6A2 seems to have different versions with different supply voltages, let’s assume you have a 5V one.
You should connect the E6A2 ground to the Arduino ground, and the E6A2 VCC to 5V.
Then the two pins A and B of the phase of the E6A2 should be connected to two digital inputs of the Arduino.
Your code should check if the A and B signals are high or low, and from that you can understand how the shaft is turning.
The ADXL335 seems to have three analog outputs and runs on 3.3V.
You should connect the ground (seems to be called “common”) and then the Vs to a 3.3 voltage supply.
Then connect the AREF pin of the Arduino to the same 3.3 supply and the X, Y, Z pins of the ADXL335 to three analog inputs of the Arduino.
Your code could use analogRead to check the voltage of the XYZ pins.
I don’t know about the video shield, but their site seems to be full of examples, so you should ask their forum for help.
vito
2012/11/01
Hi Balau,
great site… thank you for sharing!
For anyone interested in compiling and uploading the above program to Arduino Mega ADK, the mmcu option passed to the compiler should be -mmcu=atmega2560, while the command for upload will be something like:
avrdude -F -V -c stk500v2 -p m2560 -P /dev/ttyACM0 -b 115200 -U flash:w:led.hex:i
Bye,
vito
vito
2012/11/01
Ah, in my previous post I forgot to say that on Arduino Mega ADK the on-board led is connected to PORTB, pin 7.
Rafi
2012/11/01
Thank you all
I have faund over hear someone that wrot me all the program for les then 200$
As you all know… Time is many.
And like I saied before I have time
Best regards to all of you foxe
Rafi
fjrg76
2012/11/01
Hi, I got an Arduino Uno and I’d like to program it as you did, in plain C (it’s funnier). I have a doubt: when you upload the app to the board, what happens with the Arduino’s bootloader? Is it still usable?
Balau
2012/11/01
When you launch
avrdudewith thearduinooption, it will load the program in the same way as the Arduino IDE, which is by communicating with the bootloader. The procedure does not modify the bootloader and can be repeated as many times as the AVR chip can bear.Rafi levent
2012/11/01
Dear friend
I can promis you that the moment all my program will be redy, every one can have it for free
Rafi
Iordache Cristian
2012/12/05
Here is a nice tutorial for using Arduino Uno as an ordinary ISP programmer for nearly any target AVR:
see: http://pdp11.byethost12.com/AVR/ArduinoAsProgrammer.htm
kavya
2013/03/12
hi, is it possible to write a .dll file for a new component on arduino…? thankyou
Balau
2013/03/12
If you mean a software library, you can follow these guides:
http://arduino.cc/en/Hacking/LibraryTutorial
http://playground.arduino.cc/Code/Library
It’s not really a “.dll” because DLLs are Windows dynamic libraries, these are software libraries for the AVR chip.
You can also take a look in Arduino source code to see how they do it: https://github.com/arduino/Arduino/tree/master/libraries
kavya
2013/03/12
thak you verymuch ….also i have a tool called arduino uno programmer tool 1.1.8 where i need to upload .hex files…i searched a lot and no such files are available , so are such files available or do we need to write them..?
thankyou
Balau
2013/03/12
Once you compile a program, you can create a text file with hexadecimal data (see here: http://en.wikipedia.org/wiki/Intel_HEX) using avr-objcopy like I did in my post.
JSergeant
2013/03/15
Hi Balau, is it possible to upload to the arduino from Amtel/AVR Studio without have to using avrdude at the command prompt? James
Balau
2013/03/15
I never used Atmel AVR Studio, but I suppose that they support a subset of programmers. Arduino does not use a “programmer” but a “boot loader” that can be accessed with avrdude.
I see from “Using AVR Studio 5 with Arduino projects” that you can configure avrdude as an external tool.
kavya mc
2013/03/16
hello…. In my project, I need to read data input from a pressure sensor npc 1220, and send some sort of indication to arduino everytime when the output of the sensor changes.I have done the first part. Is it possible to create interrupt,to inform the microcontroller when the sensor value changes? or is there any other method?
thankyou
Balau
2013/03/17
Arduino’s microcontroller is an ATMega328P, which has an Analog Comparator that can trigger an interrupt.
I never used this comparator so I can’t give you direct advice. I’m also not familiar with that pressure sensor.
It seems to me that the that the sensor is an analog sensor that should be amplified: it has 50mV of Full-Scale Output while Arduino analog pins can convert 0-3.3V of input. Other than that, the interrupt can be used if you need to sense a threshold, but if you need to check if pressure changed at all, then it’s probably better to poll with a decent time interval and not use the interrupt.
See here for an example of using Analog Comparator interrupt in Arduino: http://www.gammon.com.au/forum/?id=11916&page=999
For more info you can take a look at ATMega328P datasheet.
kavya mc
2013/03/19
hi to read data from my code i wrote the code as below, void setup() {
Serial.begin(9600); }
void loop() {
int sensorValue1 = analogRead(A0); int sensorValue2 = analogRead(A1); Serial.println(“voltage value=”); Serial.println(sensorValue1); Serial.println(sensorValue2); delay (1000); } am getting the output as below. It is very inconsistent and random…as per theworking of my sensor he voltage values must increase when the pressure increases. Is there any mistake in prgramming or the way that i have connected the sensor to board? i connected +out pin to A0 and -out pin to A1. any suggestion will be helpful thankyou my output:
voltage value= 374 379 voltagevalue= 359 365 . . . . . voltage value= 42 43
Balau
2013/03/19
As I said I’m not familiar with that pressure sensor. Maybe you need to measure the difference in voltage between +out and -out, so in your case you have -5 -6 and -1 as readings. Try to understand the mV of resolution of the Arduino analog pins given that the values go from 0 to 1023, and you can measure the mV that you are seeing as readings.
For an example of capturing an analog signal see my blog post Capturing an analog signal with Arduino and python.
kavya
2013/03/21
thankyou sir,
i tried reading the difference value from the sensor and got positive
readings only.but I have two doubts.
1. In my above experiment I had not given any input to AREF pin. Does
the circuit work in this case? I have attached the crude diagram of
circuit.
2. the sensor power supply is 10v and for arduino its 5v(since I am
powering it through USB) does this cause any problem? If so what
should i do?
3. I have connected the output pins of sensor directly to arduino
analog pinsA0 and A1 is that ok?my guide told me some sort of bridging
circuit is required.can you please comment on this?
thankyou very much.
Balau
2013/03/22
1. As explained in analogReference() description, the default analog reference is of 5 volts (on 5V Arduino boards) or 3.3 volts (on 3.3V Arduino boards), and it has nothing to do with AREF. There doesn’t seem to be any crude diagram attached.
2. I don’t know if that’s a problem. It depends if the voltage levels of the signals that are connected to the Arduino are respecting the I/O specifications that can be found on the corresponding datasheet.
3. I already commented on this: “It seems to me that the that the sensor is an analog sensor that should be amplified: it has 50mV of Full-Scale Output while Arduino analog pins can convert 0-3.3V of input.“. As I said two times already I’m not familiar with that pressure sensor. If your guide told you some sort of bridging is required than I would assume that some bridging is required.
If you have a guide it means you have work assigned to you, so I can’t do it for you. Moreover I’m not comfortable with giving you more pointers because that’s your guide’s job, I don’t want to steal anyone’s job and they probably get paid to do it.