was successfully added to your cart.



Install AVR GCC via Homebrew or Ubuntu apt-get

By | AVR

Setting up AVR-GCC Toolchain on Linux and Mac OS X

Windows users have been enjoying various awesome tools to help with theirAVR development process like the Atmel Studio, Codevision AVR, WinAVR,IAR Embedded Workbench, etc. This doesn’t mean that Mac and Linux users are at any unfair advantage. The avr-gcc toolchain supports Unix based OS like Linux and Mac OS X inherently.
In this post I will show how to install the avr-gcc toolchain and avrdude on Mac OS X and Linux. If you are using a Mac and want to save the trouble of going through these steps, simply install CrossPack for AVR Developmentand follow the instructions in the manual. I might go over it sometime in future though.

Step 1: Install Homebrew (Mac OS X only)

This step is not required for Linux users since almost all Linux distribution comes with a package manager.
Homebrew is the new super-awesome package manager for Mac OS X. Install it by typing (or pasting) the following in terminal:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Step 2: Install avr-gcc toolchain

Mac OS X

First tap the repository:

brew tap osx-cross/avr

Then install the latest version of avr-libc (version 4.9.2 at the time of writing):

brew install avr-libc

This will pull avr-binutils and avr-gcc along with it as well. The second steps takes a little while to install everything, so go get yourself some tea in the meantime.
The Homebrew repository doesn’t has the avr-gdb formulae yet. If you need the avr-gdb debugger, go for the AVR CrossPack.


The following steps are for Debian/Ubuntu Linux. For other Linux distributions, please install read this.
It is usually a good idea to update all the packages you already have installed.

sudo apt-get update
sudo apt-get upgrade all

Then install the required packages.

sudo apt-get install gcc-avr binutils-avr avr-libc

You can also install gdb-avr is you like. It is useful for in-system debugging/emulation.

sudo apt-get install gdb-avr

Once done, type avr- in the terminal and press tab twice (do not hit enter). You should be able to see all the tools installed for you.

Step 3: Install avrdude

AVR-GCC is a toolchain that will help you with the software development process, but doesn’t do anything about burning the final executable (the hex file) to the microcontroller. For that we need to install AVR Downloader UploaDEr (avrdude).

Mac OS X

We will again use Homebrew to install it.

brew install avrdude --with-usb


The following steps are for Debian/Ubuntu Linux. For other Linux distributions, please install read this.

sudo apt-get install avrdude

This should be pretty quick. Once installed, type avrdude -v in the terminal to check if it is installed properly.

Step 4: Test the toolchain

That’s all we need for now. Let’s test whether it works or not. I have used the LED blinking code calledled.c for ATmega32 for demonstration. Refer tothis post to understand what it does.

Once the tools are installed no matter how, everything from here remains the same for both Mac OS X and Linux.

#ifndef F_CPU
#define F_CPU 16000000UL // or whatever may be your frequency
#include <avr/io.h>
#include <util/delay.h>                // for _delay_ms()
int main(void)
    DDRC = 0x01;                       // initialize port C
        // LED on
        PORTC = 0b00000001;            // PC0 = High = Vcc
        _delay_ms(500);                // wait 500 milliseconds
        //LED off
        PORTC = 0b00000000;            // PC0 = Low = 0v
        _delay_ms(500);                // wait 500 milliseconds

Assuming the name of the file is led.c, type the following in the terminal and check if the led.hex file is generated or not. The code should compile without any errors. Don’t worry if you don’t understand what the commands do or mean, we will discuss about them in detail in the next post.

avr-gcc -g -Os -mmcu=atmega32 -c led.c
avr-gcc -g -mmcu=atmega32 -o led.elf led.o
avr-objcopy -j .text -j .data -O ihex led.elf led.hex

Type cat led.hex in the terminal and see if the hex file is generated. If you see something like in the image below, you’re all set! 🙂

We will need the hardware to test avrdude, so let’s just skip it for now. In my next post, I’ll show you how you can use the avrdude to transfer the hex file generated above to run on an actual hardware. If you have any questions, please ask them below. Thank you.


Here’s what you gotta do on Mac OS X:

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew tap osx-cross/avr
brew install avr-libc
brew install avrdude --with-usb

And here’s what you gotta do on Debian/Ubuntu Linux:

sudo apt-get install gcc-avr binutils-avr gdb-avr avr-libc avrdude


AVR C 语言编程基础

By | AVR, C / C++

In this chapter you will explore some of the key concepts of C programming for AVR microcontrollers.

  1. 3.1   AVR Registers
  2. 3.2   Bits and Bytes
  3. 3.3   Bitwise Operations
  4. 3.4   Clearing and Setting Bits
  5. 3.5   The Bit Value Macro _BV()

3.1  AVR寄存器

A register is a special storage space in which the state of the bits in the register have some special meaning to the AVR microcontroller. Most of the registers are 8-bits wide (there are a few exceptions).

Each register has a name and individual bits may also have unique names. All of the register and bit names are described in the ATmega48/88/168/328 datasheet. The AVR Libc library will define identifiers for the register names and bit names so that they can be easily accessed in C.

Manipulating the bits in the various registers of the AVR is the basis for AVR programming. Everything from configuring the AVR device’s built-in peripherals to using the AVR’s pins for digital I/O is done by manipulating bits in these registers.

3.2  位和字节

A bit represents one of two possible states: 1 or 0 (aka: on/off, set/clear, high/low). Several bits together represent numerical values in binary, where each bit is one binary digit. An AVR microcontroller groups 8 bits together to form one byte wtih the Least Significant Bit (LSB) on the right. Each bit is numbered, starting from 0, at the LSB.

Consider the decimal number 15 for example. 15 represented in 8-bit binary is 00001111. The 4 least significant bits 0, 1, 2, and 3, are set.

Bits in a byte containing decimal value 15
Figure 3.1 – The decimal number 15 represented in 8 bits

If you do not already know how to convert numbers between decimal, binary, and hexadecimal, you can find numerous lessons online or use my Printable Decimal-Binary-Hex Conversion Chart

Another example, the decimal number 40 is represented in binary as 00101000. Bits 3 and 5 are set.

Bits in a byte containing decimal value 40
Figure 3.2 – The decimal number 40 represented in 8 bits

Numerical values in a C program for an AVR microcontroller may be defined using a decimal, hexadecimal, or binary notation depending on the context and the programmer’s preference. A hexadecmial number is defined using the 0x prefix and a binary number is defined using the 0bprefix.

The following C code shows 3 ways in which a variable might be initialized to the decimal value of 15.

uint8_t a = 15;         /* decimal */
uint8_t b = 0x0F;       /* hexidecimal */
uint8_t c = 0b00001111; /* binary */

The uint8_t data type is one of the fixed width integer types from the C99 standard. It defines an 8-bit unsigned integer. The C99 style data types will be used throughout this tutorial series.

3.3  位运算

Since individual bits often have a significant meaning when programming AVR microcontrollers, bitwise operations are very important.

A bitwise AND operation results in bits being set only if the same bits are set in both of the operands. In other words: bit n will be set in the result if bit n is set in the first operand and the second operand.

AVR microconroller bitwise AND
Figure 3.3 – Bitwise AND operation

A single ampersand character (&) is the bitwise AND operator in C.

uint8_t a = 0xAA; /* 10101010 */
uint8_t b = 0x0F; /* 00001111 */
uint8_t = a & b;  /* 00001010 */

A bitwise OR operation results in bits being set if the same bits are set in either of the operands. In other words: bit n will be set in the result if bit n is set in the first operand or the second operand.

AVR microconroller bitwise OR
Figure 3.4 – Bitwise OR operation

A single pipe character (|) is the bitwise OR operator in C.

uint8_t a = 0xAA; /* 10101010 */
uint8_t b = 0x0F; /* 00001111 */
uint8_t = a | b;  /* 10101111 */

A bitwise XOR operation (“exclusive or”) results in bits being set if, and only if, the same bit is set in one of the operands but not the other. In other words: bit n will be set in the result if bit n is exclusively set in only one of the operands.

AVR microconroller bitwise XOR
Figure 3.5 – Bitwise XOR operation

The caret character (^) is the bitwise XOR operator in C.

uint8_t a = 0xAA; /* 10101010 */
uint8_t b = 0x0F; /* 00001111 */
uint8_t = a ^ b;  /* 10100101 */

A NOT operation, also known as a one’s complement, is a unary operation. That means the operation is performed on a single value instead of two. The NOT operation will simply negate each bit. Every 1 becomes 0 and every 0 becomes 1.

AVR microconroller bitwise NOT
Figure 3.6 – Bitwise NOT operation

A tilde character (~) is the NOT operator in C.

uint8_t a = 0xAA; /* 10101010 */
uint8_t b = ~a;   /* 01010101 */

A shift operation shifts all of the bits to the left or the right. In a left shift, bits get “shifted out” on the left and 0 bits get “shifted in” on the right. The opposite goes for a right shift.

AVR microconroller bitwise shift
Figure 3.7 – Bitwise shift operation

Two less-than symbols (<<) is the left shift operator and two greater-than symbols (>>) is the right shift operator in C. The right side of the operator is the number of bits to shift.

uint8_t a = 0x99; /* 10011001 */
uint8_t b = a<<1; /* 00110010 */
uint8_t c = a>>3; /* 00010011 */

3.4  Clearing and Setting Bits

Setting and clearing a single bit, without changing any other bits, is a common task in AVR microcontroller programming. You will use these techniques over and over again.

When manipulating a single bit, it is often necessary to have a byte value in which only the bit of interest is set. This byte can then be used with bitwise operations to manipulate that one bit. Let’s call this a bit value mask. For example, the bit value mask for bit 2 would be 00000100 and the bit value mask for bit 6 would be 01000000.

Since the number 1 is represented in binary with only bit 0 set, you can get the bit value mask for a given bit by left shifting 1 by the bit number of interest. For example, to get the bit value mask for bit 2, left shift 1 by 2.

AVR microconroller bit value mask
Figure 3.7 – Bit value mask

To set a bit in C, OR the value with the bit value mask.

uint8_t a = 0x08; /* 00001000 */
                  /* set bit 2 */
a |= (1<<2);      /* 00001100 */

Use multiple OR operators to set multiple bits.

uint8_t a = 0x08;   /* 00001000 */
                    /* set bits 1 and 2 */
a |= (1<<2)|(1<<1); /* 00001110 */

To clear a bit in C, NOT the bit value mask so that the bit of interest is the only bit cleared, and then AND that with the value.

uint8_t a = 0x0F; /* 00001111 */
                  /* clear bit 2 */
a &= ~(1<<2);     /* 00001011 */

Use multiple OR operators to clear multiple bits.

uint8_t a = 0x0F;      /* 00001111 */
                       /* clear bit 1 and 2 */
a &= ~((1<<2)|(1<<1)); /* 00001001 */

To toggle a bit in C, XOR the value with the bit value mask.

uint8_t a = 0x0F; /* 00001111 */
                  /* toggle bit 2 */
a ^= (1<<2);      /* 00001011 */
a ^= (1<<2);      /* 00001111 */

3.5  The Bit Value Macro _BV()

AVR Libc defines a the _BV() macro which stands for “bit value”. It is a convenience macro to get the bit value mask for a given bit number. The idea is to make the code a little more readable over using a bitwise left shift. Using _BV(n) is functionally equivelent to using (1<<n).

/* set bit 0 using _BV() */
a |= _BV(0);

/* set bit 0 using shift */
a |= (1<<0);

Which method you choose is entirely up to you. You will see both in wide use and should be comfortable seeing either. Since the _BV(n) macro is unique to gcc, it is not as portable to other compilers as the (1<<n) method. However, that is not usually a concern for a hobbyist and the_BV(n) is often more comfortable for a beginner.

Arduino Due 输出 VGA 信号

By | Arduino, AVR

PIN 定义:

Due pin 2 -> VGA pin 13 (HSync)
Due pin 3 -> VGA pin 14 (VSync)

Due pin 25 -> 820R resistor -> VGA pin 3 (blue)
Due pin 26 -> 390R resistor -> VGA pin 3 (blue)

Due pin 27 -> 2k2 resistor -> VGA pin 2 (green)
Due pin 28 -> 1k resistor -> VGA pin 2 (green)
Due pin 14 -> 470R resistor -> VGA pin 2 (green)

Due pin 15 -> 2k2 resistor -> VGA pin 1 (red)
Due pin 29 -> 1k resistor -> VGA pin 1 (red)
Due pin 11 -> 470R resistor -> VGA pin 1(red)

Due pin GND -> VGA pins 5,6,7,8,10



inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;

volatile short line;
byte fb[240][320];

#define do20(x) x x x x x x x x x x x x x x x x x x x x
#define do80(x)  do20(x) do20(x) do20(x) do20(x) 
#define do320(x) do80(x) do80(x) do80(x) do80(x) 
#define MNOP(x) asm volatile (" .rept " #x "\n\t nop \n\t .endr \n\t")

void TC0_Handler()
    long dummy=REG_TC0_SR0; 

    if(line < 480){        
        byte * p=fb[line>>1];
        do320(REG_PIOD_ODSR = *p++;MNOP(2);)
        REG_PIOD_ODSR = 0;
    if(line==490) digitalWriteDirect(3,1); //or digitalWriteDirect(3,0); to invert vsync
    if(line==492) digitalWriteDirect(3,0); //or digitalWriteDirect(3,1); to invert vsync

    line++; if(line == 525) line=0;

void setup(){
  for(int i=0;i<320;i++)for(int j=0;j<240;j++)fb[j][i]=j+i;

  pinMode(3,OUTPUT);  pinMode(2,OUTPUT);                      // vsync=3 hsync=2
  pinMode(25,OUTPUT); pinMode(26,OUTPUT);                     // blue  (26=msb,25=lsb)
  pinMode(27,OUTPUT); pinMode(28,OUTPUT); pinMode(14,OUTPUT); // green (14=msb,28,27=lsb)
  pinMode(15,OUTPUT); pinMode(29,OUTPUT); pinMode(11,OUTPUT); // red   (11=msb,29,15=lsb)

  REG_PIOD_OWER= 0xff;
  REG_PMC_PCER0= 1<<27;  
  REG_PIOB_PDR = 1<<25; 
  REG_PIOB_ABSR= 1<<25; 
  REG_TC0_WPMR = 0x54494D00; 
  REG_TC0_CMR0 = 0b00000000000010011100010000000000;
//  REG_TC0_CMR0 = 0b00000000000001101100010000000000; // this inverts hsync
  REG_TC0_RC0  = 1334; 
  REG_TC0_RA0  = 1174;  
  REG_TC0_CCR0 = 0b101;    
  REG_TC0_IER0 = 0b00010000; 
  REG_TC0_IDR0 = 0b11101111; 

#include <complex>
using namespace std;

const byte cmap[]={0b00000000,0b11100000,0b11100100,0b11101000,0b11101100,0b11110000,0b11110100,0b11111000,0b11111100,
void loop(){
  for(int i=0;i<320;i++){
    for(int j=0;j<240;j++){     
      complex<float> z(0,0),c((i+180.0)/1280.0,(j+640.0)/1280.0);
      int n;


Arduino + WiShield 实现 TCP Socket 通信

By | Arduino, AVR
* Socket App
* A simple socket application example using the WiShield 1.0

#include <WiShield.h>
//#include <string.h>
extern "C" {   
  #include <uip.h>

//Wireless configuration defines ----------------------------------------

//Wireless configuration parameters ----------------------------------------

unsigned char local_ip[] = {192,168,22,202};   // IP address of WiShield
unsigned char gateway_ip[] = {192,168,22,1};   // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0};   // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"**********"};      // max 32 bytes
unsigned char security_type = 3;   // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"**********"};   // max 64 characters
// WEP 128-bit keys
prog_uchar wep_keys[] PROGMEM = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Key 0
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Key 1
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Key 2
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Key 3
// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;
unsigned char ssid_len;
unsigned char security_passphrase_len;

// End of wireless configuration parameters ----------------------------------------

boolean connectToServer(void);

boolean connectedToServer = false;
boolean inited = false;   
unsigned long   nextXMitTime;

void setup() {
  Serial.println("Starting Program..."); 
  connectedToServer = false; 

void loop() {

  if (millis() > nextXMitTime && inited && !connectedToServer) {
    Serial.print("Connecting to server...");
    if (connectToServer()) {
      connectedToServer = true;
      Serial.println("connection OK");
    } else {
      Serial.println("connection NOT OK");

// Make connection to
boolean connectToServer(void) {   
  struct uip_conn *conn;
  uip_ipaddr_t ipaddr;

  uip_ipaddr(&ipaddr, 192,168,22,101);
  conn = uip_connect(&ipaddr, HTONS(2323));

  return (conn != NULL);

extern "C" {

  void socket_app_init() {
    Serial.println("In socket_app_init...");
    inited = true;
    nextXMitTime = millis();

  void socket_app_appcall() {
    Serial.println("In socket_app_appcall...");
    if (uip_connected()) {
      uip_send("Hello!...\r\n", 11);   

    if (uip_aborted()) {
      connectedToServer = false;

    if (uip_timedout()) {
      connectedToServer = false;

    if(uip_closed() && !uip_newdata()) {
      if (connectedToServer) {
        nextXMitTime += 30000L;// XMit again in 30 seconds
        connectedToServer = false;

    if (uip_rexmit()) {
      uip_send("Hello...\r\n", 10);   

    if (uip_acked()) { 

    if(uip_newdata()) { 
      unsigned int len = uip_datalen();
      Serial.write((const uint8_t*)uip_appdata, len);

Arduino 控制继电器

By | Arduino, AVR


  1. Arduino 168P 开发板一个
  2. USB下载线一条
  3. LED一个
  4. 220欧姆电阻一个
  5. 继电器一个
  6. 面包板一块
  7. 面包板跳线若干条






  1. 按照以上电路正确搭建实验电路。
  2. 将我提供的调试程序下载到Arduino开发板中。
  3. 看LED的通断检验实验效果。


int relayPin = 13;//定义数字检测接
void setup()
void loop()


Arduino 封装好的 I2C 函数

By | Arduino, AVR, C / C++

IIC是单片机上常见的通信方式,IIC一般有两根信号线:SDA(数据线)和 SCL(时钟线)。
Arduino UNO、Duemilanove等使用ATmega328做主控IC的控制板中 SDA 为A4,SCL 为A5。
Arduino MEGA中SDA为 20 号脚,SCL为 21号脚。
Arduino Leonardo中 SDA为2号脚,SCL为3号脚。



Arduino 1.0 中使用 write() 和 read() 替代了在较早的arduino版本中的send() 和 receive() 来进行IIC通信。

通过互联网控制 Arduino pinMode

By | Arduino, AVR, C / C++


#include &lt;Ethernet.h&gt;
#include &lt;SPI.h&gt;
boolean reading = false;

  //byte ip[] = { 192, 168, 0, 199 };   //Manual setup only
  //byte gateway[] = { 192, 168, 0, 1 }; //Manual setup only
  //byte subnet[] = { 255, 255, 255, 0 }; //Manual setup only

  // if need to change the MAC address (Very Rare)
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

  EthernetServer server = EthernetServer(80); //port 80

void setup(){

  //Pins 10,11,12 &amp; 13 are used by the ethernet shield

  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);

  //Ethernet.begin(mac, ip, gateway, subnet); //for manual setup



void loop(){

  // listen for incoming clients, and process qequest.


void checkForClient(){

  EthernetClient client = server.available();

  if (client) {

    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    boolean sentHeader = false;

    while (client.connected()) {
      if (client.available()) {

          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          sentHeader = true;

        char c = client.read();

        if(reading &amp;&amp; c == ' ') reading = false;
        if(c == '?') reading = true; //found the ?, begin reading the info


           switch (c) {
            case '2':
              //add code here to trigger on 2
              triggerPin(2, client);
            case '3':
            //add code here to trigger on 3
              triggerPin(3, client);
            case '4':
            //add code here to trigger on 4
              triggerPin(4, client);
            case '5':
            //add code here to trigger on 5
              triggerPin(5, client);
            case '6':
            //add code here to trigger on 6
              triggerPin(6, client);
            case '7':
            //add code here to trigger on 7
              triggerPin(7, client);
            case '8':
            //add code here to trigger on 8
              triggerPin(8, client);
            case '9':
            //add code here to trigger on 9
              triggerPin(9, client);


        if (c == '\n' &amp;&amp; currentLineIsBlank)  break;

        if (c == '\n') {
          currentLineIsBlank = true;
        }else if (c != '\r') {
          currentLineIsBlank = false;


    delay(1); // give the web browser time to receive the data
    client.stop(); // close the connection:



void triggerPin(int pin, EthernetClient client){
//blink a pin - Client needed just for HTML output purposes.  
  client.print("Turning on pin ");

  digitalWrite(pin, HIGH);
  digitalWrite(pin, LOW);

AVR 教程 – Input & Output

By | AVR


You cannot imagine to use microcontroller without using any of its i/o pins. Finally its all about  : taking input , processing it and generating output ! Thus i/o registers and their correct settings is indispensable part while learning to program any uC.

We will learn how to use AVR ports and actually ‘code’  for writing/reading data to/from port pins. It is slightly confusing for beginners, however once you understand it, you will certainly appreciate the way it is designed.


NOTE : I will frequently refer to  ‘configuring pin’ or simply ‘pin’. Remember, a port has multiple pins. Thus in order to change setting for one port, you have to change setting for all port pins of that port. To change setting for one single pin of the port, you have to change a particular bit in associated register. Got that ? If not read this para again.


AVR is 8 bit microcontroller. All its ports are 8 bit wide. Every port has 3 registers associated with it each one with 8 bits. Every bit in those registers configure pins of particular port. Bit0 of these registers is associated with Pin0 of the port, Bit1 of these registers is associated with Pin1 of the port, …. and like wise for other bits.

These three registers are as follows :
(x can be replaced by A,B,C,D as per the AVR you are using)
– DDRx register
– PORTx register
– PINx register

DDRx register

DDRx (Data Direction Register) configures data direction of port pins. Means its setting determines whether port pins will be used for input or output. Writing 0 to a bit in DDRx makes corresponding port pin as input, while writing 1 to a bit in DDRx makes corresponding port pin as output.


to make all pins of port A as input pins :

  • DDRA = 0b00000000;

to make all pins of port A as output pins :

  • DDRA = 0b11111111;

to make lower nibble of port B as output and higher nibble as input :

  • DDRB = 0b00001111;