Интернет-магазин

Просмотр корзины
В корзине:

товаров - 0 шт.



§ 36. WoodmanUSB. Скоростные возможности порта PORTB в асинхронном режиме

Дмитрий Иванов, 10 Декабря 2013

Файлы к статье скачать
Имя: KA036.zip (ZIP архив)
Размер: 63 КБ

Поговорив вдоволь о теоритических аспектах работы с модулем и проверки этих аспектов на простеньком микроконтроллре PIC16F877, где мы получали скорости не более 300 КБайт/с, пора перейти на несколько более высокий уровень. В этой статье я хотел бы показать Вам на практическом примере те порядки скоростей передачи, которые можно получить от модуля WoodmanUSB в асинхронном режиме.

Как это будет все реализованно? Нам нужно некое внешнее устройство, которое могло бы с высокой частотой подавать управляющие сигналы на выводы модуля PB_WR (передача на ПК) или PB_RD (прием из ПК). Тут конечно можно использовать ПЛИС или процессор, но поскольку в этом тесте нам важна только оценка скорости а сами передаваемые данные не очень важны - предлагаю сам порт PORTB "проигнорировать". Т.е. мы будем только генерировать сигналы чтения/записи. При этом выводы порта PORTB будут просто болтаться в воздухе. В качестве источника сигналов чтения/записи предлагаю использовать простой кварцевый генератор прямоугольных импульсов. Он должен быть хорошо знаком тем, кто работает с ПЛИС.

Внешне такой генератор выглядит вот так. У него всего 4 вывода: выход сигнала, земля, +5 В и последний вывод не используется. Т.е. реально применяются только 3 вывода.


Схема тестового макета очень проста: вывод тактового сигнала кварцевого генератора подключается либо к выводу PB_WR при тестировании чтения данных на ПК или к PB_RD при тестировании передачи данных из ПК. Генератор для данного теста советую взять не более чем на 20 МГц, т.к. с большей частотой тактирования модуль в данном режиме (асинхронный) не справится. Также поскольку в данном тесте возможные потери пакетов из-за переполнения буферов нас не интересуют, выводы PORTB_FF и PORTB_FNE не анализируются.


А вот и код тестовго приложения. Оно консольное для простоты и наглядности работы. Думаю, дополнительных комментраиев оно не требует, кроме разве того что при перестчете нужно помнить что 1 МБайт = 1048576 байт = 8 МБит.

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include "WUSBdrv.h"

void TestWriteSpped()
{
	printf("\nTest Write Speed: \n");

	WUSB_SetupPortB(ASYNC_MODE);	

	char buf[65535];
	unsigned int dwWrite = 0;
	unsigned int ByteCounter = 0;	

	int t1 = clock();
	for(int i = 0; i < 1000; i++)
	{
		WUSB_WritePortB(buf, sizeof(buf), &dwWrite);
		ByteCounter += dwWrite;
	}
	int t2 = clock();

	double WriteTime = ((double)(t2 - t1))/1000.0; //[sec]
	double RateMbyt  = ((double)ByteCounter)/(1048576.0)/WriteTime;
	double RateMbit  = RateMbyt*8;

	printf("Time:		%d ms\n", t2-t1);
	printf("ByteCounter:	%d byte\n", ByteCounter);
	printf("Rate:		%f MBit_s\n", RateMbit);
	printf("		%f MByte_s\n", RateMbyt);
}


void TestReadSpped()
{
	printf("\nTest Read Speed: \n");

	WUSB_SetupPortB(ASYNC_MODE);

	char buf[65024];
	unsigned int dwRead;
	unsigned int ByteCounter = 0;	

	int t1 = clock();
	for(int i = 0; i < 1000; i++)
	{
		WUSB_ReadPortB(buf, sizeof(buf), &dwRead);
		ByteCounter += dwRead;
	}
	int t2 = clock();

	double ReadTime  = ((double)(t2 - t1))/1000.0; //[sec]
	double RateMbyt  = ((double)ByteCounter)/(1048576.0)/ReadTime;
	double RateMbit  = RateMbyt*8;

	printf("Time:		%d ms\n", t2-t1);
	printf("ByteCounter:	%d byte\n", ByteCounter);
	printf("Rate:		%f MBit_s\n", RateMbit);
	printf("		%f MByte_s\n", RateMbyt);
}


int main()
{
	int status = WUSB_Open();
	if(status == WUSB_ERROR)
	{
		printf("ERROR! Can`t open WodmanUSB device...\n");
		getch();
		return false;
	}
	else
	{
		printf("WodmanUSB Open Ok!\n");		
	}

	TestWriteSpped();
	//TestReadSpped();

	getch();
	WUSB_Close();
	return true;
}

Итак, если мы хотим протестировать передачу даных их ПК в модуль WoodmanUSB необходимо использовать функцию TestWriteSpped() в программе и подключить выход генератора к выводу модуля PB_RD. Если тестируем чтение данных, используем функцию TestReadSpped() и вывод модуля PB_WR. Запускаем программу сначала тестируя запись данных, заием чтение. У меня получилось что-то вроде такого:

Ну чтож, 17 МБайт/с это вполне не плохо. С такими скоростями уже можно делать довольно итересные системы передачи данных. Например, компьютерный осциллограф с частотой дискритезации мегагерц этак на 15. До этого мы тоже дойдем. А пока хотел обратить Ваше внимание на некоторые интересные моменты. В представленном коде я использую максимально возможный размер пакета для записи (65535 байт) и чтения (65024 байт). А что будет если уменьшить его до минимального, т.е. 512 байт? Запускаем тако еприложение и получаем скорость порядка 1.3 МБайт/с. Плоховато. Если увеличивать размер пакета и постоить график зависимость скорости передачи от этого размера поличится что-то вот такое:

Почему так происходит? Дело в том, что чем больше размер паекта, тем реже происходят обращения приложения к драверу WUSBdrv.sys, а также обращения последнего к системному драйверу USB. Например, мы запросили прочесть 65535 байт. Запрос ущел один раз на уровень ядра и один раз пришел обратно с заполненным буфером. А теперь просим 512 байт. По отношению к 65535 это аж 128 обращений. Каждая перекачка буфера с пользовательского уровня на уровень ядра и обратно - дело для системы Windows хлопотливое и времязатратное. Поэтому для получения максимальных скоростей передачи необходимо применять максимально возможные размеры буферов для операций чтения/записи.


Есть еще одна причина, по которой лучше брать буфер побольше. На двух рисунках ниже показн график загрузки центрального процессора. Первый из них получен при размере пакета 512 байт, последний при максимальном для операции записи - 65535 байт. Думаю, комментарии излишни.


Полученная скорость в 130 МБит/с не является для модуля WoodmanUSB максимальной. Он может работать на скоростях до 220 МБит/с! Чтобы получать такие характеристики необходимо переходить на использование синхронного режима передачи данных, это раз, и для получения полного максимума применять специализированные функции чтения/записи: WUSB_RawWritePortB(), WUSB_RawReadPortB(). Но об этом чуть позже. Пока для ближайших статей нам и 130 Мбит вполне хватит.


© Дмитрий Иванов
10 Декабря 2013 года
http://www.kernelchip.ru



© KERNELCHIP 2006 - 2017