Программирование контроллеров tms320 несколько отличается подходом от остальных.
Инженеры их Техаса подошли к задаче более креативно. Нам предлагают использовать структуры для регистров.
Например для GPIO:
struct GPIO_CTRL_REGS { union GPACTRL_REG GPACTRL; // GPIO A Control Register (GPIO0 to 31) union GPA1_REG GPAQSEL1; // GPIO A Qualifier Select 1 Register (GPIO0 to 15) union GPA2_REG GPAQSEL2; // GPIO A Qualifier Select 2 Register (GPIO16 to 31) union GPA1_REG GPAMUX1; // GPIO A Mux 1 Register (GPIO0 to 15) union GPA2_REG GPAMUX2; // GPIO A Mux 2 Register (GPIO16 to 31) union GPADAT_REG GPADIR; // GPIO A Direction Register (GPIO0 to 31) union GPADAT_REG GPAPUD; // GPIO A Pull Up Disable Register (GPIO0 to 31) Uint32 rsvd1; // reserved union GPBCTRL_REG GPBCTRL; // GPIO B Control Register (GPIO32 to 38) union GPB1_REG GPBQSEL1; // GPIO B Qualifier Select 1 Register (GPIO32 to 38) Uint32 rsvd2; // reserved union GPB1_REG GPBMUX1; // GPIO B Mux 1 Register (GPIO32 to 38) Uint32 rsvd3; // reserved union GPBDAT_REG GPBDIR; // GPIO B Direction Register (GPIO32 to 38) union GPBDAT_REG GPBPUD; // GPIO B Pull Up Disable Register (GPIO32 to 38) Uint16 rsvd4[24]; // reserved union AIO_REG AIOMUX1; // Analog IO Mux 1 Register (AIO0 to 15) Uint32 rsvd5; // reserved union AIODAT_REG AIODIR; // Analog IO Direction Register (AIO0 to 15) Uint16 rsvd6[5]; // reserved };
При этом каждая структура при помощи определённых директив и скрипта компоновщика размещается в нужном месте памяти контроллера. Таким образом записывая бит в определенное поле структуры вы меняете значение в регистре.
Но это еще не все. Каждая структура регистра объявлена при помощи объединения union, что дает возможность объявить отдельные биты регистра. Вы можете записывать в регистр слово целиком (как мы привыкли это делать в AVR, STM), а можете устанавливать только определённый бит.
GpioCtrlRegs.GPADIR.all = 0xFFFFFFFF; // Все как выход GpioCtrlRegs.GPADIR.bit.GPIO12 = 0; // вход
Также это дает огромные приимущества при отладке. Очень не удобно отслеживать один бит в регистре. А вот при описанной выше структуре можно добавить в watch window выражение типа
GpioCtrlRegs.GPADIR.bit.GPIO12
и следить только за определённым битом.
Говорить о том, что так намного проще освоить данное семейство микроконтроллеров думаю много не стоит. По названию поля легко понять назначение бита.
При чем все это транслируется в одну команду:
Т.е Вы избавлены от цикла считывание-изменение-запись.
В общем данный подход это что-то сверхъестественное. Попробуйте и оно вам понравиться.
Рассмотрим структуру GPIO.
Ниже в статье я буду использовать сокращенные названия для групп регистров.
Например в tms320 есть регистры GPADIR, GPBDIR и GPCDIR. Отличаются они тем, что первый предназначен для выводов GPIO31-GPIO0, второй для GPIO63-GPIO32, третий — GPIO87-GPIO64.
Чтобы не перечислять каждый раз все регистры, буду писать просто GPxDIR. При этом если нужно будет указать еще номер, то буду добавлять букву n.
GPIO в tms320 довольно развита, хотя думаю это и из схемы понятно. Самой крутой плюшкой я считаю регистры для подавления дребезга. Представьте себе, Вам больше не нужно писать подавление дребезга! Нужно просто настроить порт.
Но давайте рассмотрим работу с портами ввода-вывода. Поморгаем светодиодами платы.
Для начала нужно включить тактирование соответствующего модуля.
Регистры защищены. Для того, чтобы изменить содержимое необходимо использовать специальные инструкции.
EALLOW; SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1; // GPIO EDIS;
Теперь нужно настроить направление работы порта ввода-вывода. Для этого предназначены регистры GPxDIR
Тут 1 – выход, 0 – вход.
Каждая ножка контроллера может работать как порт ввода-вывода или вывод какого либо из блоков периферии. Для определения функции используется регистр GPxMUXn:
Каждое поле в данном регистре имеет размер 2 бита. И каждая комбинация определяет какая периферия будет подключена к данной ножке. В случае порта ввода-вывода менять ничего не нужно. Оставляем нули.
Теперь поговорим о пресловутом подавлении дребезга. Вот как выглядит схема данного модуля:
А вот как это работает:
Сигнал приходит на ножку и синхронизируется с частотой SYSCLKOUT. После чего выбирается несколько семплов сигнала. И если все хорошо (D) значение в регистре данных меняется. Если же изменение вызвано шумом (А), то изменений не будет.
Период выборки семплов настраивается при помощи квалификационного периода (битов QUALPRDn в регистре GPxCTRL) и количества семплов (GPAQSELn).
Значения битов QUALPRDn описаны на изображении ниже. Это своего рода делитель системной частоты. После деления данная частота используется для выборки семплов.
Количество семплов можно поменять в регистре GPxQSELn. Можно использовать 1 семпл, 3 семпла и шесть.
Например, при квалификационных битах равных нулю, частота семплирования будет равна системной частоте. Тогда если она равна 200МГц (например), т.е. семпл будет выбран с частотой 200МГц или 5нс.
Если же делитель максимален (GPxCTRL[QUALPRDn] = 0xFF), то частота семплирования
f(SYSCLKOUT) × 1 ÷ (2 × GPxCTRL[QUALPRDn])
Для системной частоты 200Мгц, частота семплирования будет 200МГц / (2 * 255) или каждые 2.55 мкс.
Итак, шум отфильтровали. Можно получать данные. Для этого предусмотрен регистр GPxDAT.
Тут можно считать данные со входов и записать на выход.
Кроме того можно установить уровень на ножке при помощи регистров GPASET, GPACLEAR, GPATOGGLE.
Каждый бит в которых устанавливает, убирает и переключает потенциал на соответствующем выводе соответственно.
О подтяжках. Все внутренние подтягивающие резисторы по умолчанию включены. Для выключения используется регистр GPxPUD.
Думаю теперь описывать еще программу было бы излишне. Вот проект с комментариями.
Скачать
Если что пишите там внизу.
Документация от TI по GPIO: https://www.dropbox.com/s/beaycayg28ozit5/tms320_gpio.pdf
Спасибо. Я как раз что то подобное искал