Using the UART for RS232 communication to a host PC

back to main tutorial page

Dr Nathan Scott & Dr Hiroyuki Kagawa July 2002

You should now have an AVR set up on a breadboard. In this section I will lead you through the steps to establish RS232 communication with a host PC (for example a Windows(TM) computer). This is a very useful technique because it means you can communicate with your AVR using a terminal program such as HyperTerminal or VersaTerm. This means you can use your Windows keyboard to control what the AVR does, and see output from the AVR on your computer screen.

ホストPCとRS232で通信するためのUARTの使い方

メインページに戻る

ネーサン・スコット香川博之   20027

ブレッドボードにこれまでやったようにAVRを取り付けておく。ここでは, RS232でパソコン(例えばWindows(TM) computer)と通信する方法について学ぶ。これは非常に役立つ技術であり,HyperTerminalVersaTermのようなターミナルソフトを使ってAVRと通信できるようになる。WindowsパソコンのキーボードによってAVRに何をさせるかを制御したり,AVRからの出力をコンピュータ画面に表示したりできることを意味している。


RS232 vs TTL/CMOS

RS232 is an old communication standard, invented in 1969. It has a few peculiarities that we have to cope with. In particular the signal in an RS232 cable is sent as pulses of +12V and -12V. This is not inherently compatible with the voltages in a modern microprocessor such as the AVR, which are 0V and 5V (CMOS levels). In other words, the AVR can't just plug into an RS232 port on a Windows(TM) computer, it would not work and it might damage the AVR.

Fortunately we do not have to build an adapting circuit, we can just buy one. The one I have been using is the MAX232 from Maxim Co. There is a data sheet in my collection, however you may find it difficult to locate the section of the data sheet that is about the MAX232, so here is the most important diagram:


RS232TTL/CMOS

 RS2321969年に発明された非常に古い通信方式であり,いくつかの制約がある。特に,RS232ケーブル中の信号電圧は+12V-12Vのパルスとして伝送される。これは,AVRのような最近のマイクロプロセッサーにおける電圧(CMOSレベルなら0V5V)とは本質的に互換性がない。言い換えれば,Windows(TM)コンピュータのRS232ポートに接続しただけではAVRが動作せず,AVRを破壊する可能性がある。

RS232を使うためには,都合のいいことに変換回路を作成する必要はなく,ひとつの部品を購入するだけでよい。マキシム社のMAX232を使うのも一つの方法である。データシート集の中からMAX232に関するものを見つけづらいかもしれないので,ここでは最も重要である概略図を示す。

Figure 1 MAX232 pinout diagram, from the data sheet. 
図1 
MAX232のピン配置図(データシートを参照)

For a long time I thought the "232" in the name "MAX232" referred to RS232. However it seems this is just a coincidence. Maxim Co. make many adapter chips for RS232 voltages e.g. MAX220, MAX231 etc.

The MAX232 chip has a very useful feature. It generates the +12V and -12V RS232 line levels from a single +5V supply using internal charge pumps. A charge pump is a clever circuit that can create a high voltage from a low voltage. This function is also sometimes called a "voltage inverter". The charge pumps require some external capacitors which are shown in Figure 1.

  • Put a MAX232 chip on your breadboard and connect up the VCC, earth, and capacitor lines.

長い間,「MAX232」の「232」は「RS232」に関係していると思っていたが,どうも偶然の一致だったようである。マキシム社RS232用のチップ(例えばMAX220, MAX231など)を作っている。

MAX232チップはとても便利な機能をもっている。内臓の昇圧器を使って+5V単一電源から+12V-12VRS232レベルの電圧を生成する。昇圧器は低い電圧から高い電圧を生成できる巧妙な電子回路である。この機能は「変圧器」と呼ばれることもある。昇圧器には図1のようにいくつかの外部コンデンサーが必要になる。

  • MAX232チップをブレッドボードに取り付け,VCCGND,そしてコンデンサーを接続する。


RS232 plug for host computer

The RS232 communication standard has been implemented several times over the years using different physical plugs. We will use one of the most common, the 9-pin version, but for the curious, here are some others. Note that a female plug is one with holes in it rather than little pins.


ホストコンピュータと接続するためのRS232プラグ


 RS232
通信方式は長年にわたって改良され,多くの異なるタイプのプラグが用いられてきた。ここでは,もっとも一般的に使われている9ピンタイプのプラグを使うことにする。参考までに 他のタイプについては,リンクしで示す。 雌プラグはピンよりも小さい穴をもつプラグのことであることに注意。

Figure 2: 9-pin RS232 plug, MAX232 adapter and AVR wiring diagram for RS232 serial communications
図2 RS232シリアル通信のための9ピンRS232プラグ,MAX232アダプターおよびAVRの配線図

  • Wire up your plug, MAX232 and AVR. Be sure to include all the usual AVR support wiring for power and the oscillator.
  • Connect the 9-pin plug to the back of your Windows(TM) computer. If it looks like it will fit in more than one socket, try to find one named "1" or "COM1".
  • MAX232AVRを配線で接続する。電源や発信器のための通常のAVRの配線も必ず行うこと。
  • 9ピンプラグをWindows(TM)コンピュータの背面に接続する。ソケットが2つ以上あれば「1」または「COM1」という名前のものを探す。 


Crystal speed

When I first used the AVR I always bought an 8MHz crystal, since that was the maximum speed. However I soon found that 8MHz is not always the best choice. The AVR generates the baud rate for the UART – meaning the number of bits sent or received per second – by dividing the main crystal speed. There is a register called UBRR that contains the dividing integer (well not exactly but this definition will do for now). It follows that only certain baud rates can be generated from a given crystal speed.

The usual RS232 baud rates are

2400 bits per second (baud)
4800
9600
14400
19200
28800
38400
57600
76800
115200

So we have to try to achieve one of these speeds. A small amount of error is acceptable but if the AVR generates a baud rate that is more than 1% different from one of those rates, there are going to be communication problems.

The data sheet for the AVR shows how to calculate the baud rate from the crystal speed and the UBRR ratio. There is also a helpful table (table 25) that gives pre-calculated values for UBRR. If an 8MHz crystal is used, the only standard baud rate that we can generate (with acceptable error) is 38400. That is OK but is a bit limiting. What if you want some other speed? As usual, someone has already thought of this problem. The solution is to choose the right crystal frequency.

If you can obtain a 7.3728 MHz crystal, you can generate any standard baud rate. Unfortunately the usual hobby electronics stores do not normally carry this speed and you may need to buy this part from a professional shop such as RS components or Farnell.


水晶発振子の周波数


 
AVRを使い始めたころには、最大実行速度になる8MHzの水晶発振子を購入していた。しかし,8MHzが常に最良の選択ではないことがわかった。AVRは水晶発振子の周波数を分周してUART用の転送速度(1秒あたりの送信及び受信ビット数)を設定する。UBRRというレジスタがあり,分周用の整数値を設定するようになっている(厳密ではないが当面この定義で実施する)。使用する水晶発振子の周波数によって、ある特定の転送速度のみを設定できることがわかる。


 通常の
RS232用の転送速度は

2400 bps (ボー)
4800
9600
14400
19200
28800
38400
57600
76800
115200

であり,上記のいづれかの速度に設定する必要がある。多少の誤差は許容されるが,1%以上になると通信トラブルを生じる。


 
AVRのデータシートには,水晶発振子の周波数とUBRRの比からどのように転送速度を計算するかについて示されており,UBRR用にあらかじめ計算された値をまとめた便利な表(表25を参照)も載っている。もし8MHzの水晶発振子を使えば,許容範囲の誤差で38400bpsの転送速度のみを実現できる。では,他の転送速度を実現するためにはどうしたよいのか? やっぱり,誰かが既にこの問題について考えていて,解決法は水晶発振子の周波数を適切な値に設定すればよいことがわかっている。


 もし,
7.3728 MHzの水晶発振子を手に入れることができれば,いかなる標準転送速度をも実現できることになる。残念ながら一般の趣味の電気屋ではこの周波数のものを取り扱っていないので,RSコンポーネンツやファーネルなどの専門店で購入する必要がある。


Software for AVR

The AVR is a general purpose microprocessor and, like a human baby, it is very smart but does not initially know much. It has hardware to support fast communication (called a UART) but we have to write a small amount of software to read and write data to the UART.


AVRのためのソフトウェア


 AVR
は一般的目的のマイクロプロセッサーであり,人体のように非常に賢いが,そのままではほとんど何もできない。UARTと呼ばれる高速通信をサポートしたハードウェアが備わっているが,UARTに対してデータを読み書きするためには,ほんの少しだけソフトウェアを作成しなければならない。

 

/*
    Code for a crash course in AVR programming
    Example "rs232.c"
    Dr Nathan Scott, July 2002
 
    This program shows how to use interrupt-driven UART code
    to establish RS232 communication with a Windows(TM) host
*/
 
 
 
#include "environment.h"
#include "delay.h"
#include "uart.h"
 
// define names for important numbers.
// It is easier to work with the names.
#define LED_pin 0
 
void prompt(char p)
{
    putch('\r'); putch('\n'); putch(p);
}
 
void Idle()
// This is the code which is called while we are waiting for a character
// to arrive from the terminal host. It means that nothing in particular
// is happening on the RS232 line and we can use this time to do something
// else.
// Do not do lengthy processing here, return as soon as you can, so that
// data sent from the terminal is not lost.
{
}
 
void ObeyCommand(char c)
{
    char i;
 
    switch (c)
    {
        case '0': // turn LED off
            putstr("off\r\n");
            PORTC &= ~BIT(LED_pin);
        break;
 
        case '1': // turn LED on
            putstr("on\r\n");
            PORTC |= BIT(LED_pin);
        break;
 
        case '?': // about
            putstr("AVR ready\r\n");
            // flash the LED a few times
            for (i = 0; i < 3; i++)
            {
                PORTC |= BIT(LED_pin);
                DelayMs(20);
                PORTC &= ~BIT(LED_pin);
                DelayMs(20);
            }
        break;
 
    } // end switch
}
 
void main()
{
    char c = 0;
 
    // set up hardware UART for serial communications. This is where we
    // specify the baud rate. See uart.h for more info.
    InitUART(UBRR38400);
 
    // set up control over PORTC so we can use it to flash the LED
    PORTC = 0; // put a definite start value into the register for PORTC
    // - it's best not to leave this to chance
 
    DDRC |= BIT(LED_pin); // set the direction of one pin of PORTC to
    // output mode so it can drive the LED.
 
    // initialisation is done, it is time to "flip the switch" by
    // setting the Global Interrupt Enable flag
    SEI();
 
    // from this point on, an interrupt can happen at any time.
 
    // show a welcome string on the terminal
    ObeyCommand('?'); // show "about" string
 
    while (c != 'x') // note that we can leave the "endless" loop!
    {
        prompt('>');
        c = ReceiveByte(); // calls Idle() while nothing is happening
        putch(c); // echo (send back to the terminal)
        putch(' '); // separate response from echoed command
 
        ObeyCommand(c);
    }
 
    putstr("exit\r\n");
    // OK, so what happens here? Run the program and find out!
}

Figure 3 Example program that uses the interrupt-driven UART library and can respond to some commands from the host
図3 プログラム例(割込み駆動UARTライブラリの利用とホストからのコマンドへの対応)

  • Open the project rs232.prj
  • Compile the project and download the hex file to the AVR.
  • Start a terminal program, for example VersaTerm, and configure it for
    • baud rate 38400 bits per second
    • 8 data bits
    • 1 stop bit
    • flow control OFF
  • Reset the AVR by grounding the RESET pin briefly. If all is well you should see "AVR ready" on the terminal window. Try typing the characters '0' and '1' (the number keys) on the keyboard and check that the LED turns on and off as you expect.
  • Try the other defined commands '?' and 'x' and see what happens.
  • rs232.prj」というプロジェクトファイルを開く。
  • そのプロジェクトをコンパイルし,HEXファイルをAVRに転送する。
  • VersaTermなどのターミナルソフトを起動し,下記の設定を行う。
    • 転送速度:38400 bps
    • データビット:8
    • ストップビット:1
    • フロー制御:OFF
  • RESET端子をグランドに短時間接続することによってAVRをリセットする。 もしもすべてがうまく行けばターミナル画面に「AVR ready」と表示される。キーボードの数字キーによって「0」と「1」を押せばLEDが点いたり消えたりする。
  • ?」と「x」コマンドを同様にキーボードで入力し,何が起こるかを確認する。

Exercises

  • Define a new command 'f' which will make the LED flash on and off. The LED must remain on for about 0.5 seconds and off for about 1 second. The '0' command should turn the flashing LED off, and the '1' command should turn it on in non-flashing mode. (Hint - think about how you can use the Idle() procedure)
  • Make sure your 'f' program above does not interfere with communications from the terminal. In other words, make sure that the program quickly leaves the Idle() procedure.
  • Expand the terminal program so that it will accept a command of up to 20 characters, which is only executed when the "enter" key on the keyboard is pressed. This is a standard terminal behaviour.
  • Advanced exercise: if you have a working multi-character command line, implement control over the LED flashing period using two commands: "on [time]" and "off [time]", where [time] represents some integer number of milliseconds. For example "on 320" should change the "on" time of the flashing LED to 320 ms.
  • Advanced exercise: implement a new command "clock" which will make the AVR return to the terminal an integer string which is the number of times the LED has come on since last reset.

演習

  • 新たに「f」コマンドを定義し,LEDが点滅するようにする。LEDは約0.5秒間オンの後で約1秒間オフになるようにする。「0」コマンドはLEDをオフにし,「1」コマンドはオンにするだけで点滅しない。 (ヒント:Idle()処理の使い方を考える)
  • 「f」コマンドがターミナルとの通信を邪魔しないことを確認する。言い換えれば, プログラムがIdle()処理を実行後直ちに開放することを確認する。
  • ターミナルプログラムを拡張し,最大で20文字までのコマンドを認識できるようにする。コマンドは「enter」キーを押したときだけ実行されるようにする。これは標準的なターミナル挙動である。
  • 応用演習: 複数文字コマンドが利用可能なとき,2つのコマンド「on [time]」と「off [time]」によってLEDの点滅時間を制御できるようにする。ここで[time]はミリ秒を表す整数とする。例えば,「on 320」はLEDの点灯時間が320msとなる。
  • 応用演習: リセットしてからこれまでにLEDが点灯した回数をAVRがターミナルに整数値で返すような「clock」コマンドを新たに作成する。

Dr Nathan Scott nscott@mech.uwa.edu.au