В микроконтроллерах семейства MSP430 (от Texas Instruments) каждый регистр, область памяти и периферийный модуль имеет фиксированный адрес в 16‑битовом адресном пространстве. Один из часто упоминаемых адресов – 0x0164 (в десятичной системе – 164). В этой статье мы подробно разберём, к чему относится этот адрес, какие функции он выполняет и как правильно работать с ним в проектах.
Содержание
- Общая карта памяти микроконтроллера
- Адрес 0x0164: назначение и регистр
- Практическое использование
- Примеры кода
- Отладка и типичные ошибки
- FAQ
MSP430 – это 16‑битовый микроконтроллер с низким энергопотреблением, широко используемый в портативных устройствах, измерительных приборах и IoT‑решениях. Ключевые особенности:
- 16‑битовый регистр‑счётчик (PC, SR, R0‑R15).
- Плоская модель памяти: регистровая область, периферийные регистры, Flash и RAM.
- Поддержка нескольких режимов сна (LPM0‑LPM4).
- Разнообразные периферийные модули: таймеры, UART, SPI, I2C, ADC, сравниватель, компаратор и др.
Все регистры периферии находятся в диапазоне 0x0100–0x01FF. Именно сюда попадает наш интересующий адрес 0x0164.
Общая карта памяти микроконтроллера
| Диапазон | Назначение |
|---|---|
| 0x0000‑0x00FF | Регистры ядра (R0‑R15, SR, CG, …) |
| 0x0100‑0x01FF | Регистры периферийных модулей (Timer_A, USCI, ADC12, …) |
| 0x0200‑0x02FF | Дополнительные регистры (если присутствуют) |
| 0x1100‑0xFFFF | Flash‑память (программный код) |
| 0x0200‑0x02FF | RAM (внутренняя оперативная память) |
Адрес 0x0164 находится в периферийной области. Точный регистр зависит от конкретного семейства (MSP430G2xx, MSP430F5xx, MSP430FR2xx и т.д.). Наиболее часто встречающийся вариант – это регистры таймера Timer_A или модуля USCI (UART/SPI/I2C).
Адрес 0x0164: назначение и регистр
Для большинства популярных микроконтроллеров семейства MSP430G2xx и MSP430F2xx адрес 0x0164 соответствует регистру TA0CCR2 – Capture/Compare Register 2 таймера Timer_A0. Ниже – детали:
- Имя регистра:
TA0CCR2 - Адрес:
0x0164(16‑битный, доступный какvolatile unsigned int) - Назначение: хранит значение сравнения/захвата для канала 2 таймера A0.
- Тип доступа: чтение/запись.
- Биты: 0‑15 – значение счётчика, которое сравнивается с текущим значением таймера.
Если вы используете микроконтроллер из семейства MSP430FR5xx/FR6xx, то 0x0164 может относиться к регистру UCA0BR1 (второй байт делителя скорости UART). Поэтому всегда проверяйте техническую документацию (datasheet) конкретного устройства.
Практическое использование
Настройка таймера для PWM
Регистры TA0CCR0, TA0CCR1 и TA0CCR2 часто используют для генерации ШИМ‑сигналов. Пример настройки канала 2 (адрес 0x0164) под 1 kHz PWM с 50 % скважностью:
// Предполагаем, что тактовая частота SMCLK = 1 MHz
TA0CCR0 = 1000 ― 1; // Период 1 ms (1 kHz)
TA0CCTL2 = OUTMOD_7; // Reset/Set – классический PWM
TA0CCR2 = 500; // 50 % скважность
TA0CTL = TASSEL_2 | MC_1; // SMCLK, Up‑mode
Захват входного импульса
Если таймер работает в режиме захвата, регистр TA0CCR2 будет автоматически заполняться временем появления фронта на соответствующем входе (TA0.2). Это удобно для измерения периода или ширины импульса.
Работа с UART (для FR5xx/FR6xx)
В микросхемах, где 0x0164 – это UCA0BR1, он задаёт старший байт делителя скорости UART. Пример установки скорости 9600 bd при SMCLK = 1 MHz:
UCA0BR0 = 104; // младший байт (0x68)
UCA0BR1 = 0; // старший байт (0x00) – адрес 0x0164
UCA0MCTL = UCBRS_1; // модуляция
UCA0CTL1 &= ~UCSWRST; // включаем UART
Полные примеры кода
Пример генерации PWM на канале 2
#include <ti/devices/msp430/driverlib/driverlib.h>
void main(void)
{
WDT_A_hold(WDT_A_BASE); // Отключаем watchdog
// Настройка тактовой частоты (SMCLK = 1 MHz)
CS_setDCOFreq(CS_DCO_FREQUENCY_1MHZ);
CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
// Конфигурация таймера A0
Timer_A_initUpModeParam upParam = {0};
upParam.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
upParam.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1;
upParam.timerPeriod = 1000 ⎻ 1; // 1 kHz
upParam.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;
upParam.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_DISABLE;
upParam.timerClear = TIMER_A_DO_CLEAR;
Timer_A_initUpMode(TIMER_A0_BASE, &upParam);
// Конфигурация канала 2 (CCR2) – PWM, Reset/Set
Timer_A_initCompareModeParam compParam = {0};
compParam.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2;
compParam.compareInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE;
compParam.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;
compParam.compareValue = 500; // 50 %
Timer_A_initCompareMode(TIMER_A0_BASE, &compParam);
// Запуск таймера
Timer_A_startCounter(TIMER_A0_BASE, TIMER_A_UP_MODE);
while (1) {
__no_operation; // Пустой цикл, PWM работает в фоне
}
}
Пример измерения периода импульса (захват)
#include <ti/devices/msp430/driverlib/driverlib.h>
volatile unsigned int lastCapture = 0;
volatile unsigned int period = 0;
void TA0_ISR(void)
{
unsigned int now = Timer_A_getCaptureCompareCount(TIMER_A0_BASE,
TIMER_A_CAPTURECOMPARE_REGISTER_2);
period = now ― lastCapture;
lastCapture = now;
Timer_A_clearCaptureCompareInterrupt(TIMER_A0_BASE,
TIMER_A_CAPTURECOMPARE_REGISTER_2);
}
int main(void)
{
WDT_A_hold(WDT_A_BASE);
CS_setDCOFreq(CS_DCO_FREQUENCY_1MHZ);
CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
// Таймер в режиме захвата, положительный фронт
Timer_A_initCaptureModeParam capParam = {0};
capParam.captureRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2;
capParam.captureMode = TIMER_A_CAPTUREMODE_RISING_EDGE;
capParam.captureInputSelect = TIMER_A_CAPTURE_INPUTSELECT_CCIxA;
capParam.synchronizeCaptureSource = TIMER_A_CAPTURE_SYNCHRONOUS;
capParam.captureInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_ENABLE;
capParam.captureOutputMode = TIMER_A_OUTPUTMODE_OUTBITVALUE;
Timer_A_initCaptureMode(TIMER_A0_BASE, &capParam);
// Разрешаем прерывание
Interrupt_enableInterrupt(INT_TA0_2);
__enable_interrupt;
while (1) {
// Здесь можно использовать переменную period
}}
Отладка и типичные ошибки
- Неправильный адрес в datasheet – убедитесь, что ваш микроконтроллер действительно использует 0x0164 для нужного регистра. В разных семействах адрес может относиться к разным модулям.
- Неинициализированный таймер – перед записью в
TA0CCR2необходимо включить таймер (регистрыTA0CTL) и задать период вTA0CCR0. Иначе запись будет игнорироваться. - Конфликт прерываний – если используете захват, не забудьте очистить флаг прерывания в ISR, иначе ISR будет вызываться бесконечно.
- Неправильный делитель частоты – при работе с UART убедитесь, что
UCA0BR0иUCA0BR1(0x0164) рассчитаны правильно, иначе получаете неверную скорость передачи. - Энергосбережение – при переходе в режим LPM убедитесь, что таймер/UART не отключаются, иначе регистр 0x0164 перестанет работать.
Диагностический чек‑лист
- Проверьте, что
#include <driverlib.h>соответствует вашему устройству. - Сверьте адрес 0x0164 в регистровой таблице вашего datasheet.
- Убедитесь, что тактовая частота SMCLK настроена правильно.
- Инициализируйте соответствующий модуль (Timer_A, USCI) до записи в регистр.
- Если используете прерывания – включите их в NVIC и очистите флаги.
Часто задаваемые вопросы (FAQ)
Что делать, если в datasheet указано, что 0x0164 – это UCA0STAT?
Это значит, что вы работаете с микросхемой, где UCA0STAT (статусный регистр UART) находится по этому адресу. В таком случае запись в 0x0164 будет менять статус, а не значение делителя. Перепроверьте семейство (например, MSP430FR5994) и используйте правильный регистр.
Можно ли использовать 0x0164 как обычную переменную в RAM?
Нет. Адрес 0x0164 относится к периферийному регистру, а не к RAM. Попытка использовать его как обычную переменную может привести к непредсказуемому поведению и конфликту с периферией.
Как быстро проверить, какой модуль занимает адрес 0x0164?
Откройте Technical Reference Manual (TRM) для вашего микроконтроллера, найдите раздел Memory Map и найдите строку с адресом 0x0164. Там будет указано имя регистра и модуль.
Почему при работе с PWM на канале 2 наблюдаю «мигание» LED?
Возможные причины:
- Неправильный режим
OUTMOD(должен бытьOUTMOD_7– Reset/Set). - Слишком маленькое значение
TA0CCR0(частота выше 20 kHz может быть не видна глазу, но LED может мерцать из‑за инерции). - Отсутствие подтягивающего резистора на выводе, если он открыт (floating).
Как изменить частоту PWM без перепрограммирования?
Можно изменить только регистр TA0CCR0 в рантайме:
TA0CCR0 = newPeriod ⎻ 1; // newPeriod – желаемый период в тактах SMCLK
Это не требует пересборки кода, но требует, чтобы таймер был уже запущен.
Адрес 0x0164 в микроконтроллерах MSP430 – это ключевой регистр, который может относиться к TA0CCR2 (таймер) или к UCA0BR1 (UART) в зависимости от семейства. Понимание его назначения, правильная инициализация и корректный доступ к регистру позволяют реализовать такие задачи, как генерация ШИМ‑сигналов, измерение импульсов и настройка скорости последовательного порта.
Всегда проверяйте техническую документацию конкретного устройства, используйте драйверную библиотеку DriverLib или CMSIS‑MSP430 для упрощения работы с регистрами, и не забывайте о тестировании в отладчике.
Удачной разработки!