FT232HLを使って、パソコンとNiosでシリアル通信

FPGA

パソコンとFT232HL、Nios単体でシリアル通信をやってきましたが、今回はFT232HLを使ってパソコンとNiosでシリアル通信をやってみました。

関連記事 第1回 NiosにUART(RS-232 Serial Port)を実装してみる
関連記事 第2回 NiosにUART(RS-232 Serial Port)を実装してみる
関連記事 USB-シリアル変換モジュールFT232HLでシリアル通信してみる

スポンサーリンク

目標機能

今回の目標機能は、パソコンからNiosにコマンドを送信し、そのコマンドに応じてDE0-Nanoボード上のLEDを点灯させます。

関連記事と同様で、NiosはDE0-Nanoボード上にFPGA(Cyclone IV)に実装しています。

Terasic DE0-NANO開発ボード 【P0082】

新品価格
¥14,520から
(2020/6/25 22:01時点)

NiosはLEDを点灯させたら、そのLEDの番号をパソコン側に送信させます。

LED1を点灯させたら、パソコンに”LED1″と送信します。

パソコン側のアプリ

パソコン側のシリアル通信アプリはVisual Basicで作成しました。

シリアル通信のソースコードは、ネットで検索してマネさせていただきました。

通信アプリの外観は以下です。

Openボタン・・・COMポートをオープン
Closeボタン・・・COMボートをクローズ
Sendボタン・・・隣のテキストボックスの文字列を送信(今回は未使用)
LED1ボタン・・・’1’を送信。LED1を点灯、LED2~LED8を消灯させるコマンド。
ーーー
LED8ボタン・・・’8’を送信。LED8を点灯、LED1~LED7を消灯させるコマンド。

一番下はListBoxで、受信したデータをここに表示させます。

Niosのシリアル通信設定

Niosには、”UART (RS-232 Serial Port) Intel FPGA IP”を実装します。

実装方法は、過去に記事にしているので、そちらをご参照いただきたいと思います。

関連記事 第2回 Nios IIで遊ぼう Quartus Platform Designer編
関連記事 第1回 NiosにUART(RS-232 Serial Port)を実装してみる
関連記事 第2回 NiosにUART(RS-232 Serial Port)を実装してみる

Niosに”UART (RS-232 Serial Port) Intel FPGA IP”を実装したら、次はソフトウェアの設計です。ソフトウェアの設計はEclipseを使用しますが、こちらも詳細は過去の記事を参照いただければと思います。

関連記事 第3回 Nios IIで遊ぼう Nios II Software Build Tools for Eclipse編

Niosの通信ソースコード以下のようにしました。

#include "sys/alt_stdio.h"
#include "system.h"
#include <stdio.h>
#include <string.h>

#include "altera_avalon_uart_regs.h"
#include "sys/alt_irq.h"


unsigned char ReadData;

void uart_irq_handler()
{

	ReadData = IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE);

}

int main()
{
	int i=0;
	int reg;
	int context_uart1;
	unsigned char buf;

	alt_printf("Hello World !! \n");

	//LED OFF
	*(volatile unsigned char *) LED_OUTPUT_BASE = 0x00;


	alt_ic_isr_register(UART_0_IRQ_INTERRUPT_CONTROLLER_ID, UART_0_IRQ,uart_irq_handler,&context_uart1,0x0 );
	alt_ic_irq_enable(UART_0_IRQ_INTERRUPT_CONTROLLER_ID, UART_0_IRQ);

	buf=0;

   while(1){

	   //SW Input
	   reg = *(volatile unsigned char *) SW_INPUT_BASE;

	   if(buf != ReadData){
		   buf = ReadData;

		   switch(buf){
	   	   	   case '1':	//LED1
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x01;
	   	   		   Send_LED(buf);
	   	   		   break;

	   	   	   case '2':	//LED2
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x02;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '3':	//LED3
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x04;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '4':	//LED4
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x08;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '5':	//LED5
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x10;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '6':	//LED6
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x20;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '7':	//LED7
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x40;
	   	   		   Send_LED(buf);
	   			   break;

	   	   	   case '8':	//LED8
	   	   		   *(volatile unsigned char *) LED_OUTPUT_BASE = 0x80;
	   	   		   Send_LED(buf);
	   			   break;

		   }

	   }


   }

   return (0);
}

void Send_LED(unsigned char buf)
{
	unsigned char LED[] = {'L','E','D'};
	int i;

	for(i=0;i<sizeof(LED);i++){
		IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE, LED[i]);
		usleep(1000);
	}
	IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE, buf);

}

ひどいソースコードかもしれませんが、試行錯誤の結果であり、ソフトはあまり得意ではないのでご了承を。。。

102行目のIOWR_ALTERA_AVALON_UART_TXDATAでデータをパソコンに送っていますが、その後にwait時間を挿入しています。

本来なら、送信バッファが空になったことを確認してから次のデータを送るべきですが、今回はwait時間で代用しました。

追記 送信バッファのステータスチェックをするプログラムも作ってみました。

通信テスト結果

通信テストの結果です。

まずパソコン側のアプリですが、OpenボタンでCOMポートを開き、LED1ボタンを押したら、ListBoxにLED1と表示されました。

次にDE0-NanoのLEDです。

LED1だけ点灯し、LED2~LED8は消灯でした。

通信成功です。

まとめ

無事に通信成功しました。

ただ、wait時間を変えたりすると、表示がうまくいかなかったり、文字の取りこぼしが発生したりと、まだまだ改良の余地はありそうです。

タイトルとURLをコピーしました