суббота, 26 июля 2014 г.

Запускаем UART на MSP430 Launchpad

Это рукодство посвящено тому как запустить аппаратный UART на плате MSP430-Launchpad. Мы будем рассматривать старый Launchpad для контроллеров ValueLine. Он идёт в комплекте с двумя МК: MSP430G2452 и MSP430G2553. Аппаратный UART имеется только в микроконтроллере MSP430G2553, поэтому использовать будем его. Все действия я буду выполнять для ОС Linux, поэтому используется компилятор msp430-gcc. Предполагается что читатель знаком с базовыми принципами работы с MSP430 в ОС Linux, про которые можно прочитать например в серии статей вот здесь . Итак, под катом будет пример работающего кода для коммуникации MSP430 по UART.
Плата Launchpad иммет в своём составе преобразователь USB/UART. За эту функцию отвечает микросхема TUSB3410. UART выведен на джамеперы, котрыми соединяется верхняя и нижняя чать платы. Далее линии RX и TX апаратного UART подведены к ножкам P1.1. и P1.2 микроконтроллера. Возможна установка джамперов для аппартного и программного UART. Для работы с аппаратным UART они должны быть установлены горизонтально, так как показано на картинке, иначе ничего не зарботает. К сожалению, разработчики платы Launchpad ввели ограничение на скорость работы UART. Поэтому номально работает эта плата только на скоростях ниже 9600 бод. Более высокие скорости не работают.


















В ОС Linux Launchpad опознаётся как виртуальный последовательный порт /dev/ttyACM0. Вот вывод dmesg при поключении платы к USB:
vvk@linux-bmx0:~/MSP430/msp430-examples/uart> dmesg|tail
[ 6993.966349] usb 2-1.2: USB disconnect, device number 4
[ 6997.205366] usb 2-1.2: new full-speed USB device \
number 5 using ehci_hcd
[ 6997.315988] usb 2-1.2: New USB device found, \
idVendor=0451, idProduct=f432
[ 6997.315999] usb 2-1.2: New USB device strings: \
Mfr=1, Product=2, SerialNumber=3
[ 6997.316005] usb 2-1.2: Product: Texas Instruments MSP-FET430UIF
[ 6997.316012] usb 2-1.2: Manufacturer: Texas Instruments
[ 6997.316017] usb 2-1.2: SerialNumber: 56FF49ABB1C31F4B 
[ 6997.322097] cdc_acm 2-1.2:1.0: This device cannot \
do calls on its own. It is not a modem.
[ 6997.322107] cdc_acm 2-1.2:1.0: No union descriptor,\
 testing for castrated device
[ 6997.322151] cdc_acm 2-1.2:1.0: ttyACM0: USB ACM device
Здесь видим, что обнаружено новое USB-устройство и для него создан файл устройства виртуального последовательного порта /dev/ttyACM0.
В микроконтроллерах MSP430 за UART, SPI и I2C отвечает модуль USCI, и чтобы настроить UART нужно правильно установить его регистры. Возможна работа модуля только в одном из этих трёх режимах. То есть на одном канале можно задействовать или UART, или SPI, или I2C. За работу UART отвечает модуль UCA, а за I2C и SPI --- модуль UCB. Более подробно обо всех этих режимах можно прочитать в даташите
Теперь рассмотрим пример, реализующий работу с UART на скорости 9600 бод. Пример для работы с UART взят с сайта gpio.kaltpost.de и немного адаптирован. Автор оригинального пооекта --- Stefan Wendler. Пример состоит из четырёх файлов uart.h uart.c main.c и Makefle. Привожу их содержание с комментариями здесь.
Файл uart.h
#ifndef __UART_H
#define __UART_H

//Инициализация UART
void uart_init(void);

//Установить обработчик прерывания по приёму данных на UART
void uart_set_rx_isr_ptr(void (*isr_ptr)(unsigned char c));

//Считать один символ с UART
unsigned char uart_getc();

//Переслать один символ по UART
void uart_putc(unsigned char c);

//Переслать строку на UART
void uart_puts(const char *str);

#endif
Файл uart.с Здесь собственно и производится настройко UART.
#include "msp430.h"
#include "uart.h"

#define RXD  BIT1 // линии порта P1
#define TXD  BIT2 // задействованные под UART

/**
 * Callback handler for receive
 */
void (*uart_rx_isr_ptr)(unsigned char c);

void uart_init(void)
{
 uart_set_rx_isr_ptr(0L);

 P1SEL  = RXD + TXD;      // настраиваем линии порта                 
   P1SEL2 = RXD + TXD;                       
   UCA0CTL1 |= UCSSEL_2;  // Источник тактирования UART --- SMCLK
   UCA0BR0 = 104;         // Настраиваем скорость 1MHz 9600
   UCA0BR1 = 0;           // 1MHz 9600
   UCA0MCTL = UCBRS0;     // Модуляция UCBRSx = 1
   UCA0CTL1 &= ~UCSWRST;  // Инициализируем модуль USCI
   IE2 |= UCA0RXIE;       // Разрешаем прерывания от UART.
}

void uart_set_rx_isr_ptr(void (*isr_ptr)(unsigned char c))  
// Назначает обработчик прерывания от UART
{
 uart_rx_isr_ptr = isr_ptr; 
}

unsigned char uart_getc()
{
    while (!(IFG2&UCA0RXIFG));  // Буфер приёмника USCI_A0 готов?
 return UCA0RXBUF;
}

void uart_putc(unsigned char c)
{
 while (!(IFG2&UCA0TXIFG)); // Буфер передатчика готов
   UCA0TXBUF = c;  // TX
}

void uart_puts(const char *str)
{
     while(*str) uart_putc(*str++);
}

void usci0rx_isr(void) __attribute((interrupt(USCIAB0RX_VECTOR)));

void usci0rx_isr(void)
{
 if(uart_rx_isr_ptr != 0L) { // Если пришёл символ 
  (uart_rx_isr_ptr)(UCA0RXBUF); // то вызывам обработчик
 }
}
Нужно обратить внимание как настраивается скорость UART. Она задаётся регистрами UCA0BR0 и UCA0BR1 и вычисляется по формуле:

Baud = (Fclk)/(UCA0BR0 + 256*UCA0BR1)
То есть в нашем случае для источника тактирования SMCLK тактовая частота Fclk=1 MHz=1000000 Hz. Получаем:
Baud = (1000000)/(104 + 256*0)=9615
Это примерно равно скорости 9600 бод. Для другой скорости нужно пересчитать значения данной пары регистров. Для типовых скоростей они указаны в даташите.
Файл main.c
#include "msp430.h"
#include "uart.h"

#define LED_RED BIT0
#define LED_GREEN BIT6

void uart_rx_isr(unsigned char c) 
{
    switch (c) { // Обработчик прерывания от UART
    case '1': P1OUT ^=LED_RED; // Если пришла единица
              uart_puts("Red led toggled\n"); // то переключим красный 
              break; // светодиод
    case '2': P1OUT ^= LED_GREEN; // Если пришла двойка
              uart_puts("Green led toggled\n"); // то переключим зелёный
              break; 
    default: uart_putc(c); 
             break;
    }
}
 
int main(void)
{
    WDTCTL  = WDTPW + WDTHOLD; // Стопорим WatchDog Timer
    BCSCTL1 = CALBC1_1MHZ;     // Тактовая частота 1MHz
    DCOCTL  = CALDCO_1MHZ;
 
    P1DIR  = LED_RED + LED_GREEN; // Настраиваем GPIO
    P1OUT  = LED_RED + LED_GREEN; // Включим светодиоды

    uart_init(); // Инициализируем UART

    // register ISR called when data was received
    uart_set_rx_isr_ptr(uart_rx_isr); 
    // Регистрируем обработчик прерывания по UART

    __bis_SR_register(GIE);

    uart_puts("\n***************\n"); // Напечатем приветствие
    uart_puts("MSP430 harduart\n");
    uart_puts("***************\n");

    __bis_SR_register(LPM0_bits+GIE); 
    // уходим в спячку и ждём прерывания
    
    for(;;); 

}
Файл Makefile
CC=msp430-gcc
LD=msp430-gcc
MCU=msp430g2553
CFLAGS= -mmcu=$(MCU) -Wall -Os -c

TARGET=demo-uart.elf

$(TARGET): main.o uart.o
 $(LD) -mmcu=$(MCU) main.o uart.o -o $(TARGET)

main.o: main.c
 $(CC) $(CFLAGS) main.c -o main.o

uart.o: uart.c uart.h
 $(CC) $(CFLAGS) uart.c -o uart.o

install:
 mspdebug rf2500 "prog $(TARGET)"

clean:
 rm -f *.o *.elf
Все четыре файла нужно положить в один каталог. Компилируем проект командой make.
Для проверки работы нашей программы требуется терминальная программа. Для начинающего можно использовать например простую и понятную программу CuteCOM. В ней нужно установить скорость и параметры порта. Она уже наверняка есть в вашем дистрибутиве Linux. В openSUSE её можно установить командой
zypper in cutecom
Теперь прошиваем плату командой make install и в итоге мы должны получить вот такой вывод в эмуляторе терминала. В качестве устройства последовательного порта в CuteCOM нужно указать /dev/ttyACM0 : ***************
MSP430 harduart
***************
Green led toggled
Red led toggled

Вот скриншот CuteCOM:
В следующей части будет рассказано, как управлять последовательным портом на плате Launchpad из консоли Linux.
Исходники для данного проекта доступны на Гитхабе.

1 комментарий:

  1. т.е. в самом типовом случае применения микроконтроллеров: аппаратный интерфейс/конвертер USBSerial->GPIO/SPI вся линейка MSP430G в пролете т.к. не умеет аппаратно в UART+SPI?

    ОтветитьУдалить