Fenriz
Feb 24 2006, 16:08
Подскажите:
1. Я сконфигурировал SPI в 4-х проводный мастер.
Пины : P3SEL=0x0F: P3.0 - STE
P3.1 - SIMO
P3.2 - SOMI
P3.3 - UCLK
Перед передачей MASTER - > SLAVE подаём на STE сигнал низкого уровня. Как это правильно сделать в коде?
Мой вариант: P3DIR|=0x01;
P3OUT|=0x00; не прошёл.
2. Дайте ссылу на литературу где можно подробнее почитать о 4-wire SPI для MSP430. Я пользовался slau056e и msp430f*44* там очень поверхностно
Заранее спасибо.
rezident
Feb 24 2006, 17:42
Если вы используете 4-проводной SPI, то для мастера STE это входной сигнал, а не выходной. STE предназначен для устранения конфликтов на шине, когда транзакцию одного мастера хочет прервать другой мастер. При этом вероятен конфликт когда два выхода SIMO будут работать на одну линию. Чтобы предотвратить эту ситуацию второй мастер может подать лог 0 на вход STE первого мастера. При этом сигналы SIMO и UCLK первого мастера переводятся в режим ввода, а в регистре RxCTL устанавливается бит FE. То бишь STE в режиме 4-ware можно использовать как входной сигнал CS, но не как выходной сигнал управления CS-ом слейва. Для управления CS-ом слейва нужно использовать другой пин GPIO.
Все это вполне понятно описано в User's Guide MSP430x1xx Family. У меня они почти всех ревизий есть. ИМХО более внятно описано в ранних ревизиях.
Fenriz
Feb 26 2006, 01:26
Дело в том, что я подключаю к микроконтроллеру датчик. Он точно сконфигурирован как SLAVE - у него 4 провода в том числе и STE . Сам SLAVE может послать такой сигнал?
Fenriz
Feb 26 2006, 10:43
Проанализировал драйвер датчика там STE как input. Используется для зазрешения передачи и приёма slave и инициируется master-ом.
rezident
Feb 26 2006, 11:34
В режиме слейва STE функционирует как входной сигнал CS. Лог. 0 разрешает работу выхода SOMI. Т.е. для вашего случая мастер надо в 3-ware режиме использовать.
А что за датчик, если не секрет?
Fenriz
Feb 26 2006, 15:13
Да нет никакого секрета - датчик отпечатков пальцев.
То есть вы предлагаете сделать вот так для мастера:
P3SEL=0x0E; // конфигурим пины SPI
P3DIR=0x01;// P3.0 как универсальный I/O на выход и держим высокий уровень
P3OUT=0x01;//
P3OUT&=~0x01; // перед началом передачи посылаем низкий уровень
p3OUT=0x01; // по окончанию передачи опять востанавливаем высокйй ?
rezident
Feb 26 2006, 15:56
Угу. Примерно так. Только не забудьте сам USART сконфигурировать в 3-ware режиме как мастер.
Код
U0CTL|=SWRST; // сброс USART
U0CTL|=CHAR+SYNC+MM; //SPI, 8-бит, master
U0TCTL=CKPL+SSEL1+STC; //SPI3, UCLK=SMCLK, 3-ware
ну и т.д.
Датчик для сканирования отпечатка пальца или для распознавания образа? На MSP430???
Fenriz
Feb 27 2006, 15:41
для сканирования отпечатка. К контроллеру подключается датчик с одной стороны, с другой модем. Должно получиться что-то типа модуля для передачи отпечатков пальцев.
Скажите, а при установке источника тактирования:
1) UTCTL=SSEL1+SSEL0; (1 1 - SMCLK);
2) UTCTL=SSEL1; (1 0 - SMCLK)
есть разница между 1 и 2 случаем?
rezident
Feb 27 2006, 16:20
Цитата(Fenriz @ Feb 27 2006, 20:41)

Скажите, а при установке источника тактирования:
1) UTCTL=SSEL1+SSEL0; (1 1 - SMCLK);
2) UTCTL=SSEL1; (1 0 - SMCLK)
есть разница между 1 и 2 случаем?
Нет разницы. Выбирается один и тот же источник тактирования. Но это лишь для мастера. Для слейва в любом случае входным тактовым сигналом будет UCLK.
Ещё один вопрос:
когда в Rg FLL_CTL бит XTS_FLL=0 - используется низкочастотный режим.
при нём определяется значение битов XCAPxPF.
В примерах кодов texas нашёл 2 случая:
FLL_CTL0|=XCAP18PF;
FLL_CTLO|=XCAP14PF;
(Я по началу думал что это ёмкость (в пФ) нагрузочных конденсаторов для кварцевого резонатора, но в документации определено всего 4 значения: 1,6,8,10)
Что означают 18 и 14 в записях и по какому принципу они выбираются?
rezident
Mar 2 2006, 10:30
Все верно. XCAPxxPF соответствуют значению конденсатора в pF.
Дело в том, что значения 1pF, 6pF, 8pF и 10pF вы видимо прочитали в User's Guide, которое одно на все семейство MSP430x4xx. Но в даташите MSP430F427 указаны другие значения этих конденсаторов, конкретно для этого кристалла: 0pF, 10pF, 14pF и 18pF. см. таблицу crystal oscillator, LFXT1 oscillator. Параметры подобные этому всегда нужно уточнять в datasheet конкретного кристалла, а не брать из руководства.
Посмотрел даташит на f499 - c частотами всё так как вы сказали. Но пояснение дано только на использование 0pF при наличие внешних емкостей. 32кГц кристал можно включить пользуясь только XCAPxxPF без внешних емкостей. Разница в емкостях 10, 14, 18 не велика - получается нет принципиальной разницы в использовании?
rezident
Mar 2 2006, 21:54
Цитата(Fenriz @ Mar 2 2006, 20:17)

Разница в емкостях 10, 14, 18 не велика - получается нет принципиальной разницы в использовании?
Есть конечно разница! Кварцы-то ведь тоже разные бывают, предназначеные для работы на различную емкостную нагрузку. Читайте Application Note под номером
slaa225 - MSP430 LFXT1 Oscillator Accuracy. Еще можно у Maxim/Dallas глянуть пояснение на эту же тему (точность хода RTC в зависимости от типа кварца 32kHz)
App Note 58.
У меня в устройстве:
P3.4 для подачи сигнала STE на датчик
P3.5 для подачи RESET перед началом инициализации датчика с контроллера
P3.6 как IN. К нему подключена кнопка (по нажатию которой мастер инициирует передачу со slave)
и STE и RESET низкого уровня
P3.6 - активный уровень высокий.
начальные значения такие:
P3DIR=0x30; на выход
P3OUT=0X30; держим высокий уровень
Можно ли сбросить каждый бит в отдельности (чтоб состояние других осталось прежним) таким образом:
P3OUT&=~0x20; // reset
P3OUT=0x30; // восстанавливаем прежнее значение
P3OUT&=~0x10; // ste
P3OUT=0x30; // по окончанию передачи
а также независимо проверять содержимое бита для P3.6 (while (P3IN=0x00) {...}) ??????????????
P.S. спасибо за ссылку на литературу по кристалам - очень помогла.
rezident
Mar 3 2006, 09:11
Если вы работаете с отдельными битами, то накладывайте маску при операциях с портами во всех случаях.
Не
Код
P3OUT=0x30;
а
Код
P3OUT|=0x30;
или
Код
P3OUT|=BIT4+BIT5;
Не
Код
while (P3IN=0x00) {....}
а
Код
while ((P3IN&0x40)==0) {...}
или
Код
while ((P3IN&BIT6)==0) {...}
Макросы BITx определены в заголовочном файле msp430x4xx.h
То есть запись P3OUT|=0x30;
определяет, что конфигурируются только пины P3.4 P3.5 в остальных сохранится значение по умолчанию после PUC
и тогда сброс одного из них будет выглядеть как P3OUT&=~BIT4;?
P.S. подскажите у Texas есть докумментация по языку СИ для MSP430? - очень бы хотелось освоить его
rezident
Mar 3 2006, 15:23
Отвечу с конца. У TI нет документации по СИ, т.к. фирма TI в основном производит полупроводниковые изделия, а не компиляторы

Для изучения Си начните с азов. Например, прочтите отцов-основателей
Керниган, Ричи. "Язык C". В Интернете легко найдете.
После этого все будет вполне понятно. В т.ч. и порядок действий в описанных выражениях.
Выражение
Код
P3OUT|=0x30;
означает, что
- в качестве аргумента берется содержимое регистра P3OUT;
- затем выполняется операция побитового сложения P3OUT и константы 0x30;
- результат операции записывается снова в регистр P3OUT.
В целом выражение эквивалентно такой записи.
Код
P3OUT=P3OUT|0x30;
BIT4 во втором вашем выражении на самом деле определен макросом вида
Код
#define BIT4 0x10
и компилятор вместо совокупности символов
BIT4 везде подставляет его значение
0x10Выражение
Код
P3OUT&=~BIT4;
эквивалентно
Код
P3OUT=P3OUT&(~0x10);
где
~0x10, в свою очередь, компилятор преобразует в его инверсию
0xEF. Т.е. выражение можно было бы записать как
Код
P3OUT=P3OUT&0xEF;
Интересно, а как вы сами ранее в ваших же примерах использовали операцию P3OUT&=~0x20;? По наитию что ли?

Или по аналогии с чем-то?
=) блин, ну я и дал маху.
Я по выражению UCTL&=~SWRST решил что это обычная бит-инверсия и даже не обратил внимание на знак логического умножения.
Тогда получается что при P3OUT|=0x30; Добится сброса P3.4 можно исклфчающим или P3OUT^=0x10;?
Тогда по этому же вопрос когда пишем условие while((P3IN&BIT6)==0) запись в скобках имеет значение P3IN&0x40 и проверяется равно ли оно 0?
rezident
Mar 4 2006, 21:42
Цитата(Fenriz @ Mar 4 2006, 09:21)

Тогда получается что при P3OUT|=0x30; Добится сброса P3.4 можно исклфчающим или P3OUT^=0x10;?
Можно конечно, но только если есть некая определенность этот бит был ранее сброшен и/или что в каком-нибудь другом месте программы этот бит не будет изменен. Накладывание маски по ИЛИ или по И более определено по результату, чем инверсия по XOR.
Цитата(Fenriz @ Mar 4 2006, 09:21)

Тогда по этому же вопрос когда пишем условие while((P3IN&BIT6)==0) запись в скобках имеет значение P3IN&0x40 и проверяется равно ли оно 0?
Да, P3IN&BIT6 это то же самое P3IN&0x40, если ранее BIT6 определен как 0x40. Цикл внутри while будет выполняться до тех пор, пока 6-й бит сброшен. Можно было бы это же записать как
Код
while !(P3IN&BIT6)
, но такая запись не очень наглядная и в каких-то компиляторах возможно будет обрабатываться неверно. Я вообще не спец по компиляторам, может поэтому последняя запись меня обычно заставляет морщить лоб, в отличие от предыдущей
Я не совсем понял про "исключающее или". Не могли бы вы объяснить по-конкретнее?
И ещё вопрос: при выборе частоты тактирования для SPI:
кристал 32кГц, fMCLK - 1МГц.
В режиме SPI модуляция не используется и мы UMCTL=0. Нужно ли запретить модуляцию битом SCFQ_M в регистре SCFQCTL (установить бит в 1) или это не обязательно?
В Rg UBR0 и UBR1 можно задать любой целый коэффициент деления частоты (не менее 2)?
rezident
Mar 6 2006, 09:57
Fenriz, извините, но тема все более скатывается для раздела "начинающих". Вы попробуйте все же самостоятельно почитать необходимую литературу. Или как некоторые любят "выражопываться"
RTFM.

Без обид, но чтение справочника по Си и User's Manual
MSP430x1xx (
MSP430x4xx) Family даст 100% ответы на все ваши вопросы.
Скажу только про модуляцию. Вы видимо путаете регистр модуляции USART и модуляцию в FLL. Читайте оба раздела внимательно.
Я всё понимаю. Спасибо, вы и так мне сильно помогли.
Fenriz
Mar 11 2006, 05:33
Не могу понять в чём дело:
У меня при приходе данных через SPI должно генерироваться прерывание по которому идёт передача с интерфейса SPI на UART.
Текст такой
void main (void) {
WDTCTL=WDTPW+WDTHOLD;
P3SEL=0x0E; // для SPI (USART0)
U0CTL=CHAR+SYNC+MM+SWRST;
U0TCTL=CKPL+SSEL1+SSEL0+STC;
U0BR0=0x02;
U0BR1=0x00;
U0MCTL=0x00;
ME1=USPIE0;
U0CTL&=~SWRST;
IE1|=URXIE0;
P4SEL=0x03; // для UART (USART1)
ME2 |= UTXE1 + URXE1;
U1CTL |= CHAR+SWRST;
U1TCTL |= SSEL1+SSEL0+URXSE;
U1BR0=0x09;
U1BR1=0x00;
U1MCTL=0x08;
U1CTL&=~SWRST;
IE2 |= URXIE1;
_EINT();
while (1) {
while (!(IFG1&UTXIFGO)); // проверяем буфер
TXBUF0=0xFF;
}
__interrupt void usart0_rx (void);
USART0RX_ISR (usart0_rx)
__interrupt void usart0_rx (void){
while (!(IFG1&URXIFG0)); // проверяем принят ли символ целиком
while (!(IFG2&UTXIFG1)); // свободен ли TXBUF у UART
TXBUF1=RXBUF0;}
Среда маркерует строку
USART0RX_ISR (usart0_rx)
__interrupt void
и выдаёт "the operation is unavailable on the current selection".
С чем это может быть связано?
rezident
Mar 11 2006, 21:46
Я не совсем понял каким компилятором вы пользуетесь, но, например, в IAR EW430 прерывание оформляется так
Код
#pragma vector=UART1RX_VECTOR
#pragma type_attribute=__interrupt
void uart1_rx_isr(void)
{
......
}
либо так
Код
#pragma vector=UART1RX_VECTOR
__interrupt void uart1_rx_isr(void)
{
......
}
мнемонику обозначения векторов (адрес) можно взять из хидера файла.
Например, в
msp430x44x.h в самом конце файла есть блок дефайнов
Код
/************************************************************
* Interrupt Vectors (offset from 0xFFE0)
************************************************************/
#define BASICTIMER_VECTOR (0 * 2u) /* 0xFFE0 Basic Timer */
#define PORT2_VECTOR (1 * 2u) /* 0xFFE2 Port 2 */
#define USART1TX_VECTOR (2 * 2u) /* 0xFFE4 USART 1 Transmit */
#define USART1RX_VECTOR (3 * 2u) /* 0xFFE6 USART 1 Receive */
#define PORT1_VECTOR (4 * 2u) /* 0xFFE8 Port 1 */
#define TIMERA1_VECTOR (5 * 2u) /* 0xFFEA Timer A CC1-2, TA */
#define TIMERA0_VECTOR (6 * 2u) /* 0xFFEC Timer A CC0 */
#define ADC12_VECTOR (7 * 2u) /* 0xFFEE ADC */
#define USART0TX_VECTOR (8 * 2u) /* 0xFFF0 USART 0 Transmit */
#define USART0RX_VECTOR (9 * 2u) /* 0xFFF2 USART 0 Receive */
#define WDT_VECTOR (10 * 2u) /* 0xFFF4 Watchdog Timer */
#define COMPARATORA_VECTOR (11 * 2u) /* 0xFFF6 Comparator A */
#define TIMERB1_VECTOR (12 * 2u) /* 0xFFF8 Timer B CC1-6, TB */
#define TIMERB0_VECTOR (13 * 2u) /* 0xFFFA Timer B CC0 */
#define NMI_VECTOR (14 * 2u) /* 0xFFFC Non-maskable */
#define RESET_VECTOR (15 * 2u) /* 0xFFFE Reset [Highest Priority] */
#define UART1TX_VECTOR USART1TX_VECTOR
#define UART1RX_VECTOR USART1RX_VECTOR
#define UART0TX_VECTOR USART0TX_VECTOR
#define UART0RX_VECTOR USART0RX_VECTOR
#define ADC_VECTOR ADC12_VECTOR
Fenriz
Mar 12 2006, 15:18
Я пользуюсь CodeComposer. Когда я вектор задавал как:
#pragma vector=UART0RX_VECTOR
__interrupt void uart0_rx_isr(void)
{
......
}
Среда жалуется на грамматику и говорит что значение #pragma vector для неё не определено.
В случае когда
__interrupt void usart0_rx (void);
USART0RX_ISR (usart0_rx)
__interrupt void usart0_rx (void){
......
}
жалоб на грамматику нет (лог problems говорит что ошибки и замечания отсутствуют). Но строка маркерутся и при просмотре деклорации для неё "вылазит" та дрянь о которой я писал ранее
Да, чуть не забыл у меня в msp430x44x.h описание несколько отличается.
* Interrupt Vectors (offset from 0xFFE0)
************************************************************/
#define BASICTIMER_ISR(func) ISR_VECTOR(func, ".int00") /* 0xFFE0 Basic Timer */
#define PORT2_ISR(func) ISR_VECTOR(func, ".int01") /* 0xFFE2 Port 2 */
#define USART1TX_ISR(func) ISR_VECTOR(func, ".int02") /* 0xFFE4 USART 1 Transmit */
#define USART1RX_ISR(func) ISR_VECTOR(func, ".int03") /* 0xFFE6 USART 1 Receive */
#define PORT1_ISR(func) ISR_VECTOR(func, ".int04") /* 0xFFE8 Port 1 */
#define TIMERA1_ISR(func) ISR_VECTOR(func, ".int05") /* 0xFFEA Timer A CC1-2, TA */
#define TIMERA0_ISR(func) ISR_VECTOR(func, ".int06") /* 0xFFEC Timer A CC0 */
#define ADC12_ISR(func) ISR_VECTOR(func, ".int07") /* 0xFFEE ADC */
#define USART0TX_ISR(func) ISR_VECTOR(func, ".int08") /* 0xFFF0 USART 0 Transmit */
#define USART0RX_ISR(func) ISR_VECTOR(func, ".int09") /* 0xFFF2 USART 0 Receive */
#define WDT_ISR(func) ISR_VECTOR(func, ".int10") /* 0xFFF4 Watchdog Timer */
#define COMPARATORA_ISR(func) ISR_VECTOR(func, ".int11") /* 0xFFF6 Comparator A */
#define TIMERB1_ISR(func) ISR_VECTOR(func, ".int12") /* 0xFFF8 Timer B CC1-6, TB */
#define TIMERB0_ISR(func) ISR_VECTOR(func, ".int13") /* 0xFFFA Timer B CC0 */
#define NMI_ISR(func) ISR_VECTOR(func, ".int14") /* 0xFFFC Non-maskable */
#define RESET_ISR(func) ISR_VECTOR(func, ".int15") /* 0xFFFE Reset [Highest Priority] */
#define UART1TX_VECTOR USART1TX_VECTOR
#define UART1RX_VECTOR USART1RX_VECTOR
#define UART0TX_VECTOR USART0TX_VECTOR
#define UART0RX_VECTOR USART0RX_VECTOR
#define ADC_VECTOR ADC12_VECTOR
rezident
Mar 12 2006, 18:10
Не пользовался я CC для MSP430. Поэтому не могу прокомментировать. Читайте описание/help. Или поищите дальше в библиотеках или header-ах, как там ISR_VECTOR трактуется. Может там __interrupt вообще лишнее?
Fenriz
Mar 13 2006, 08:01
Вам случайно не приходилось встречаться с Olimex development board MSP430?
rezident
Mar 13 2006, 12:13
Живьем - нет, не приходилось.
Fenriz
Mar 29 2006, 14:06
Необходим совет:...........
приём данных с SPI-slave у меня осуществляется по прерыванию (IE1|=URXIE0), но в некоторых случаях в процессе передачи данных на мастер прерывание необходимо запретить. Можно ли это организовать с помощью команд _DINT(); _EINT();?
_DINT();
.... инициация передачи данных на приход которых прерывание не требуется;
_EINT();
rezident
Mar 29 2006, 14:14
Если вам неважно, что будут запрещены все прерывания, а не только от SPI, то можно.
_DINT(); и _EINT(); это команды работы с битом GIE, который запрещает/разрешает все немаскируемые прерывания.
Аналогичные по результату команды _BIC_SR(GIE); и _BIS_SR(GIE);
Fenriz
Mar 30 2006, 06:12
Уважаемый resident, пытаюсь отладить программу, но пока безуспешно. МК инициализируется успешно - проверил состояние регистров после прошивки всё соответствует. У меня складывается впечатление, что после выполнения функции обработки прерывания, МК не возвращается к выполнению прерваной операций в main. Можно ли это сделать по средствам команды (или это автоматический процесс)?
rezident
Mar 30 2006, 10:21
Во-первых, проверьте что вы выключаете WDTimer.
Во-вторых, обозначьте в своей программе ВСЕ вектора прерываний, даже те которые вы не используете. Пускай там даже только по одной команде _NOP(); будет. Зато у вас будет возможность выяснить не улетает ли программа на какой-то неиспользуемый вектор.
Можно попытаться определить, где висит программа. Например так (независимо, на С написано или на asm).
; тело программы
MAIN
команда_1
...
команда_101 <-- тут breakpoint
...
идти_на_MAIN
; тело обработчика прерывания UART0RX
UART0_RX
команда_1
...
какой-то_цикл
команда_51
...
команда_101 <-- и тут breakpoint
выход_из_прерывания
Запустить это дело, подождать некоторое время и прервать работу (или же работа сама прервется по bp).
Возможны варианты. Основное тело программы (main) не выполняется.. Программа уходит в прерывание, выходит из него и сразу же снова входит. Или же, если в обработчике прерывания есть некий цикл, то возможно зависание внутри него, т.е. не происходит даже выхода из прерывания.
Кстати, очень помогает в некоторых точках программы "дергание" определенной ножкой процессора (простой xor). На осциллографе удобно можно смотреть процесс (не)работы программы
Уважаемый resident, по поводу векторов прерывания вы были правы. В тексте программы было разрешено прерывание, функция обработки которого не была определена - как следствие reset vector и контроллер вставал на месте. Ошибку исправил - устройство работает нормально.
У меня есть вопрос:
По документации к MSP430x4xx следует, что SPI делает сдвиг (передачу) байта данных, начиная со старшего бита (MSB) и принимает подобным же образом. Можно ли организовать приём на SPI начиная с младшего бита (LSB) - (битреверсию)???????????
CAHTA_1939
Nov 5 2007, 23:47
всем доброй ночи =)
у меня есть 2шт msp430f1611 соединенные между собой через SPI , и к этомуже SPI подключена память at25f2048... у этой память есть пин CS, т.е. проблемы пнуть микруху, чтоб она поняла что данные для нее, нет. но вот как поступить со вторым 1611 ? если один пин у нее отвести для CS и при вызове прерывания проверять его состояние, то это будет не зер гуд!
подскажите, как лучьше поступить?
rezident
Nov 6 2007, 19:26
Цитата(CAHTA_1939 @ Nov 6 2007, 04:47)

подскажите, как лучьше поступить?
Без фреймовой синхронизации использовать SPI не разумно. Тем более, когда на этом же интерфейсе "висит" еще одно устройство.
Для просмотра полной версии этой страницы, пожалуйста,
пройдите по ссылке.