Нестандартное использование UART в качестве генератора частоты

Недавно понадобилось подключить к устройству на MSP430 ультразвуковую микропомпу вместо привычной электромагнитной.
В общем-то, ничего особенного, нужно выдавать пачки меандра заданной частоты и в зависимости от требуемой интенсивности прокачки менять соотношение длительности пачек и пауз между ними. Если бы не пара нюансов.

1. Пьезоэлектрическая сущность новой качалки выливается в очень узкую полосу рабочих частот. Буквально 150-200Гц вправо-влево и качалка превращается в бестолковую шипелку и даже в стакане воды на глубине 2-3 см не может выдавить пузырик.
2. Рабочая частота 25,4кГц. С учетом п.1 получаем полосу в районе 25250-25600Гц.

Вроде бы, «как два пальца об асфальт». Заряжаем таймер, вешаем на хардварный выход одной из защелок нашу пищалку качалку (через повышающий драйвер, естественно, и с дифференциальным выходом), загоняем в CCR0 период, в CCR нужной защелки — полпериода, — профит!
Однако, не все так просто.

Во-первых, устройство серийное, а все хардварные выходы таймера B по несчастливой случайности были отданы под управление светодиодами. То есть, без хирургического вмешательства не обойтись. Оставшийся таймер А отдан целиком под задачу измерения, формирует хардварно серии импульсов с заданными параметрами.

Устройство достаточно сложное, и отдавать целый таймер под тупую генерацию монотонных импульсов совсем не хочется. Не говоря уже о том, что для отсчета системных временных интервалов остается только таймер вочдога с весьма скудными возможностями для выбора длительности генерируемых интервалов (одного из четырех жестко заданных).

Я уже был морально готов резать несчастного пациента и кромсать программу, как вдруг вспомнил про неиспользуемый UART1. Вернее, он когда-то использовался в качестве дебажного вывода на консоль. И в первую очередь почему-то мысль мелькнула про мастер-режим SPI. Если взять выход тактовой частоты (UCLK1), то при записи в буферный регистр данных какого-либо байта на данном выходе должна появиться пачка из 8 импульсов, тактирующих передачу. Далее разрешаем прерывание от UTXIFG (по опустошению буфера передатчика), и в нем кидаем в буфер новый байт (неважно, какой).
Дополнительный профит заключается в том, что можно в прерывании подсчитывать количество выданных байт, регулируя таким образом длительность пачки. Частота выходных импульсов устанавливается 16-разрядным счетчиком/делителем, и в этом отношении наш новоявленный «таймер» вполне идентичен обычному таймеру А или В.

Воодушевившись данной идеей, переделал плату (пришлось временно пожертвовать выходом на звуковую пищалку, который неудачно совпал с UCLK1) и стал пробовать. И все бы ничего, если бы не одно досадное обстоятельство: UART-SPI вставляет между байтами паузу в 2 такта. На слух это ощущается в виде противного писка в районе 3кГц (сама рабочая частота ухом не воспринимается) — это частота следования байтов. Учитывая, что данные дозаторы могут стоять в одном помещении десятками, заценил «какофонию», проникся жалостью к обслуживающему персоналу и стал искать другие пути.

А другой путь обозначился практически сразу же. Надо использовать не тактовые импульсы, а информационный выход. И не SPI, а UART.
То есть, привычный старт-стопный формат с одним стоповым битом и 0x55 в качестве информационного наполнения. Тактовую частоту UARTа нужно задавать в виде удвоенной выходной. Как оказалось, это был наилучший выбор из всех возможных. Во-первых, байты следуют без разрывов (видимо, в это время формируются стартовый и стоповый биты). Во-вторых, не пришлось ничего резать, т.к. UTXD1 был выведен только на тестовый разъём — осталось только кинуть перемычку в нужное место. Ну, и в заключение — в отличие от таймера и SPI, MSP-шный UART умеет формировать дробные битрейты с помощью специального регистра модулятора MCTL. А я неспроста вначале говорил про 25кГц.

Проведем несложный расчет:
тактовая частота от кварца — 4МГц.

делитель U1BR = 78; Fт = 51 282; Fout = 25 641;
делитель U1BR = 79; Fт = 50 632; Fout = 25 316;
делитель U1BR = 80; Fт = 50 000; Fout = 25 000;

Итого, дискретность установки частоты превышает 300Гц, что может оказаться неприемлемым при необходимости тонкой подстройки.
Модулятор повышает точность настройки частоты практически на порядок.

В сухом остатке, имеем выход «ненужного» UARTa, генерирующий нужную частоту, и следующий программный код:

/** Инициализация UART
*    FREQ - частота, Гц
*/
void SetUart1(unsigned int FREQ)
{	              
	U1CTL = CHAR | SWRST ;                            // 8bit, UART, reset

	U1TCTL = SSEL_2;                                  // en SMCLK to uart1
        U1RCTL =0;
        unsigned int freq = (SMCLK + (FREQ))/ (FREQ*2);
	U1BR0 = freq & 0xFF;		                  // low byte
	U1BR1 = (freq >> 8) & 0xFF;		          // hi byte
	U1MCTL = 0x00;                                
	U1IFG &= ~(URXIFG1 | UTXIFG1);                    // clear flag RXD
        ME2 |= UTXE1;    		                  // en TXD

	U1CTL &= ~SWRST;	                          // no_reset
        IE2 |= UTXIE1;                                    // en ISR
    
        com_dir |= TxD;                                   // configure out port
        com_sel |= TxD;
}

И ещё немножко:

/** UART TX ISR */
interrupt (USART1TX_VECTOR) usart1tx_int(void)
{
    U1TXBUF = 0x55;
}


Запускаем:

SetUart1(25300);
U1TXBUF = 0x5a;

… и понеслась!

Из данной истории можно вывести два следствия.

1. При желании и(ли) острой необходимости UART вполне может заменить таймер, как для задания временных интервалов, так и для вывода их наружу в виде импульсов.
То есть, теперь я уже вижу, что мог со спокойной душой взять вожделенные импульсы с выхода таймера, а системные тики формировать с помощью прерывания от UARTа.

2. При некоторой сноровке можно организовать ШИМ (в каментах уже написали)

Напоследок, вследствие прилива положительных эмоций, решил немного поглумиться:

#define     NOTE_DO         523
#define     NOTE_RE         587
#define     NOTE_MI         659
#define     NOTE_FA         698
#define     NOTE_SO         784
#define     NOTE_LA         880
#define     NOTE_SI         988
#define     NOTE_DO2        1046

static const unsigned int Notes[8] = {
NOTE_DO,
NOTE_MI,
NOTE_SO,
NOTE_DO2,
NOTE_DO2,
NOTE_SO,
NOTE_DO2,
NOTE_DO2
};

//...

//----------------- Включение питания ----------------------------
        PowerOn();

/** Музыкальная пауза */
        
        for(int i = 0; i<8; i++)
        {
            SetUart1(Notes[i]);
            Delay(100);
            ClearWatchDog();
        }
//------------------------
  • +2
  • 19 января 2012, 17:53
  • MrYuran

Комментарии (8)

RSS свернуть / развернуть
cut
0
Хыхых я как то писал про ШИМ на UART :)
0
Я когда был маленький и еще не знал что такое МК и UART, делал как-то ШИМ на КОМ порту компьютера. На TX диод, RC фильтр и на варикап УКВ приёмника. Сигнал точной настройки приемника через ключ на RI. И была прога, которая этим чудом рулила и осуществляла автонастройку на станции. Правда, когда комп сильно нагружался, частота отправки байтов в КОМ порт падала и настройка уезжала.
+1
Забавно. А что это за УЗ помпа, расскажи подробнее?
0
  • avatar
  • Vga
  • 19 января 2012, 19:13
На вид — как обычная пьезопищалка, только чуть потолще и с обратной от кристалла стороны закрыта пластмассовым корпусом с дырочкой посередине.
Все, что она делает — колеблет (колебает?) воздух мембранкой туда-обратно.
Ставим снаружи клапан типа «лягушка» — получаем качалку.
Работает практически бесшумно, не считая шипения воздуха. Но по сравнению с «б-рррр, б-рррр» прошлой качалки (простая катушка с магнитной мембранкой) это «п-шшш, п-шшш» просто за счастье. К тому же стоит в 4 раза дешевле (500р против 2000р российского производства и 150-200 евро немчура). Новая — типа яповская.
Ещё один профит — легкость замены.
0
Гм. Ты не совсем меня понял) Перефразирую.
Запили, плиз, про эту помпу статью в блог «Деталька». С фоточками и всем-всем-всем. Заодно и где купить.
Алсо, что у вас там эта помпа делает?
0
У нас там эта помпа дозирует реактив. Прокачивает пузыри воздуха через аммиак, а выходящие из ёмкости пары аммиака пузырятся в жидкость, подщелачивая её.
Подробнее пока вряд ли, т.к на эксперимент купили всего 5 штук, и они все уже упакованы в корпуса и поставлены на прогон. Разве что потом, когда в серию пойдет.
0
как-то раз понадобилось использовать передатчик spi в для передачи в данных в радиомодуль, у которого передача была своеобразно устроена: просто выведена нога управления модулятора, на приёме-то он сам клоки восстанавливал и данные по spi зачитать можно было.
но вот с передачей в MSP оказалось что при непрерывном запихивании данных в USCI вроде (не помню правда точно что именно там было) наружу они лезли не непрерывно, а с паузой в один бит между ними, что немного портило картину на приёме, потому что вместо 8 бит приходило девять, а spi ему всё равно, пока клоки и cs есть принимает байты подряд.
пришлось забирать их как есть в некий буфер, а потом лазить по нему и руками двигать и убирать лишние биты.
такие вот замечательные грабли.
0
  • avatar
  • _pv
  • 19 января 2012, 23:35
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.