Перейти к содержанию
    

Не работает прерывание SPI1 dsPIC33FJ256GP710

Доброго времени суток! Столкнулся со следующей проблемой: при инициализации модуля SPI1 в режим SPI slave Framed slave контроллер не входит в прерывание по импульсам на ноге SS1. В других режимах работы модуля прерывание отрабатывает. Обмен происходит с АЦП, которая и генерирует клоки и импульсы кадровой синхронизации. Возможно в этом режиме прерывание и не должно срабатывать, но в дата- и эррата-шитах этого не нашел. Разработка ведется в среде MikroC for dsPIC/PIC24 ver.6.0. АЦП ADS1601, тактируется от LTC6903.

Привожу кусок кода программы:

void Start_ADC(void)                 //инициализация SPI1, прерывания от SPI1, и в конце - разрешение тактирования АЦП
{
sampling_flag = 1;


TRISF6_bit = 1; //SCK1
TRISF7_bit = 1; //SDO1
TRISF8_bit = 1; //SDI1
TRISB2_bit = 1; //SS1

SPI1STATbits.SPIEN = 0;

SPI1CON2bits.FRMDLY = 1;
SPI1CON2bits.FRMPOL = 1;
SPI1CON2bits.SPIFSD = 1;
SPI1CON2bits.FRMEN = 1;

SPI1CON1bits.PPRE = 4;
SPI1CON1bits.SPRE = 3;
SPI1CON1bits.MSTEN = 0;
SPI1CON1bits.CKP = 0;
SPI1CON1bits.SSEN = 0;
SPI1CON1bits.CKE = 1;
SPI1CON1bits.SMP = 0;
SPI1CON1bits.MODE16 = 1;
SPI1CON1bits.DISSDO = 1;
SPI1CON1bits.DISSCK = 0;

  SPI1STATbits.SPISIDL = 1;


IFS0bits.SPI1EIF = 0;
IFS0bits.SPI1IF = 0;
IEC0bits.SPI1IE = 1;
IPC2bits.SPI1IP = 4;

SPI1STATbits.SPIEN = 1;

oe_6903 = 1;        //start of SPI master
}



void SPI1Interrupt() iv IVT_ADDR_SPI1INTERRUPT ics ICS_AUTO             //Обработчик прерывания, сюда не входит
{
unsigned int aSample, tmp;
aSample = SPI1BUF;
IFS0bits.SPI1IF = 0;         //Clear Interrupt status of SPI1
SPI1STATbits.SPIROV = 0;
IEC0bits.SPI1IE =1;
}


void main() {

  Start_ADC();

  while (1) {
      //////////////////////// ничего больше не делаем

  }

}

 

Ниже приведены осциллограммы на SS1, SCLK1 и SDI1 соответственно (все ноги сконфигурированы на вход)

post-29871-1375765954_thumb.jpg

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проверьте есть ли питание на плате! Некоторые устройства (не все!) работают лучше, если их запитать электричеством.

Следующим шагом должна быть уже проверка напряжения - оно тоже должно быть, хотя бы приблизительно, близко к значению, которое указано в даташите!

Проверьте, случайно, программатор не находится ли в режиме "Hold in reset"!

Проверьте вообще имеется ли контроллер на испытываемой плате! Если забыли впаять, обязательно сделайте это!

Проверьте запрограммирован ли вообще контроллер! Запрограммируйте еще раз, на всякий случай! (программатором!)

Проверьте совпадает ли язык программирования с языком компилятора! Это важно!

Проверьте, наконец, правильно ли у вас подключены выводы SPI. "Правильно" означает что бы совпадали номера выводов в даташите и на вашей схеме.

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

Проверьте все!

Удачи!

 

ПП Перечитайте все последние темы в данном разделе! Начинается все с "Не работает высшая математика на моем контроллере, не извлекается квадратный корень из сферического коня в вакууме!".

А заканчивается на "Ой! Я забыл нажать кнопку "Release from Reset"."

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Проверьте есть ли питание на плате! Некоторые устройства (не все!) работают лучше, если их запитать электричеством.

Следующим шагом должна быть уже проверка напряжения - оно тоже должно быть, хотя бы приблизительно, близко к значению, которое указано в даташите!

Проверьте, случайно, программатор не находится ли в режиме "Hold in reset"!

Проверьте вообще имеется ли контроллер на испытываемой плате! Если забыли впаять, обязательно сделайте это!

Проверьте запрограммирован ли вообще контроллер! Запрограммируйте еще раз, на всякий случай! (программатором!)

Проверьте совпадает ли язык программирования с языком компилятора! Это важно!

Проверьте, наконец, правильно ли у вас подключены выводы SPI. "Правильно" означает что бы совпадали номера выводов в даташите и на вашей схеме.

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

Проверьте все!

Удачи!

 

ПП Перечитайте все последние темы в данном разделе! Начинается все с "Не работает высшая математика на моем контроллере, не извлекается квадратный корень из сферического коня в вакууме!".

А заканчивается на "Ой! Я забыл нажать кнопку "Release from Reset"."

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

Изменено пользователем MasterM12

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если Вам по делу нечего сказать...

Сударь! Нет здесь никакого дела! Каков вопрос - таков и ответ.

Вы утверждаете:

...при инициализации модуля SPI1 в режим SPI slave Framed slave контроллер не входит в прерывание по импульсам на ноге SS1. В других режимах работы модуля прерывание отрабатывает.

Не удосужитесь ли вы растолковать, как установили сей факт (что контроллер не входит в прерывание)?

Чудес, знаете, не бывает ...

Я бы вам порекомендовал проверить SPIROV. Если он выставлен, никакого приема данных не будет...

А потом можете прочитать документ 70206D, пункт 18.3.5. ...

If a new data word has been shifted into SPIxSR and the previous SPIxBUF contents have not

been read, the SPIROV bit (SPIxSTAT<6>) is set. Any received data in SPIxSR is not transferred,

and further data reception is disabled until the SPIROV bit is cleared. The SPIROV bit is not

cleared automatically by the module; it must be cleared by the user application.

В вашем куске кода не заметно что бы вы упразднили буфер SPI (прочитав его) до начала приема.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сударь! Нет здесь никакого дела! Каков вопрос - таков и ответ.

Вы утверждаете:

 

Не удосужитесь ли вы растолковать, как установили сей факт (что контроллер не входит в прерывание)?

Чудес, знаете, не бывает ...

Я бы вам порекомендовал проверить SPIROV. Если он выставлен, никакого приема данных не будет...

А потом можете прочитать документ 70206D, пункт 18.3.5. ...

Проверяю вход в прерывание выводом символа '*' по UART2

Вот обработчик прерывания. В первом посте вывод не описан, так как посчитал это лишней деталью, наверное зря, каюсь

 

void SPI1Interrupt() iv IVT_ADDR_SPI1INTERRUPT ics ICS_AUTO             //Обработчик прерывания, сюда не входит
{
unsigned int aSample, tmp; 
aSample = SPI1BUF;
UART2_Write('*');
IFS0bits.SPI1IF = 0;         //Clear Interrupt status of SPI1 
SPI1STATbits.SPIROV = 0;
IEC0bits.SPI1IE =1;
}

 

 

А за совет спасибо, действительно в инициализации SPIROV не обнуляю, может в этом собака зарыта, сейчас проверю.

P.S. сильно не бейте, в пиках пока что новичок

Изменено пользователем MasterM12

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

обнуление при инициализации SPIROV не помогло. Подскажите, кто-то использовал SPI в этом пике в таком режиме? Может он и не должен так работать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

обнуление при инициализации SPIROV не помогло...

 

Я вам не написал обнулять SPIROV, а прочитать буфер обмена SPI1BUF при инициализации.

Прерывание происходит когда заполняется этот буфер. Тогда выставляется флаг SPRBF.

Если при включении питания из-за инициализации системы (имею ввиду всякие переходные процессы или просто сдвиг порога логического уровня),

на вход SS и/или SCLK поступит импульс, это уже приведет к ошибке.

Я вам порекомендовал проверить SPIROV, а SPI1BUF прочитать, что бы НЕ выставился SPIROV.

С SPI все работают. И да, он должен работать именно так. Позволю себе перевести для вас кусок цитаты из моего предыдущего поста:

Если новое слово данных будет перемещено в SPIxSR (входной регистр сдвига) и предыдущее содержимое SPIxBUF(буферного регистра SPI) не прочтено,

флаг SPIROV (SPIxSTAT<6>) выставляется. Никакого дальнейшего приема данных больше не осуществиться (прием данных отключен), пока этот флаг не будет сброшен.

Бит SPIROV не сбрасывается автоматически модулем SPI; он должен быть сброшен потребительском приложением (программой).

Это означает, что если вы сбросили флаг SPIROV, но не устранили вызывающие его выставление условия (не прочитали/упразднили SPI1BUF) он выставится заново

при следжуюущей же отправки данных.

Повторюсь, не знаю тот ли у вас случай, но это обязательно делать и с SPI и с USART и с ADC, когда у него не один, а стек буферов (напр. у PIC24, где 16 АЦП буферов).

Возможно вы просто не учли какую-то мелочь и сейчас просто смотрите не туда, именно как в случаях, о которых я вам писал в первом своем посте (утрировал, да!).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Неправильно выразился, в инициализации сначала делаю фиктивное чтение, а потом обнуляю SPIROV (для надежности :)), а прерывание так и молчит. Сделал сейчас просто SPI Slave - все срабатывает, берутся семплы от АЦП, но пока не разобрался с фазой клоков, т.к. АЦП CS поднимает по 15 клоку, и 16-й клок проходит уже при поднятом CS. По идее старший бит должен теряться(в сдвиговый регистр вдвигается 15 бит вместо 16). Наверное вследствие этого в результатах проскакивает и старший и младший биты одновременно при КЗ входа АЦП, хотя по осциллограмме шумит 4 младших бита, остальные - в нулях.

Вобщем пошел разбираться с полярностью и фазой клоков, и в АЦП есть прямые и инверсные клоки, может что получится.

На рисунке осциллограмма данных с АЦП при подаче на вход 100 мВ.

post-29871-1375869741_thumb.jpg

P.S. Все же интересно, кто-то из форумчан заводил SPI в framed slave mode c прерываниями? У меня уже ощущение что это в принципе невозможно (баг камня).

 

Инициализация SPI теперь выглядит так:

void Start_ADC(void)
{
int tmp;
sampling_flag = 1;
//SPI1_Init_Advanced(_SPI_SLAVE, _SPI_16_BIT, _SPI_PRESCALE_SEC_4, _SPI_PRESCALE_PRI_4, _SPI_SS_ENABLE, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_IDLE_2_ACTIVE);

TRISF6_bit = 1; //SCK1
TRISF7_bit = 1; //SDO1
TRISF8_bit = 1; //SDI1
TRISB2_bit = 1; //SS1

SPI1STATbits.SPIEN = 0;

SPI1CON2bits.FRMDLY = 0;
SPI1CON2bits.FRMPOL = 0;
SPI1CON2bits.SPIFSD = 0;
SPI1CON2bits.FRMEN = 0;

SPI1CON1bits.PPRE = 4;
SPI1CON1bits.SPRE = 3;
SPI1CON1bits.MSTEN = 0;
SPI1CON1bits.CKP = 1;
SPI1CON1bits.SSEN = 1;
SPI1CON1bits.CKE = 1;
SPI1CON1bits.SMP = 0;
SPI1CON1bits.MODE16 = 1;
SPI1CON1bits.DISSDO = 1;
SPI1CON1bits.DISSCK = 0;

SPI1STATbits.SPISIDL = 1;
IFS0bits.SPI1EIF = 0;
IFS0bits.SPI1IF = 0;
IEC0bits.SPI1IE = 1;
IPC2bits.SPI1IP = 4;

tmp = SPI1BUF;                      // Фиктивное чтение буфера
SPI1STATbits.SPIROV = 0;       // Сброс флага SPIROV
SPI1STATbits.SPIEN = 1;

ADS1601_sync = 0;
ADS1601_PD = 1;
delay_ms(1000);
oe_6903 = 1;
}

Изменено пользователем MasterM12

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...т.к. АЦП CS поднимает по 15 клоку, и 16-й клок проходит уже при поднятом CS. По идее старший бит должен теряться...

 

Очень даже может быть. Но в таком случае, (ЕМНИП) в регистре настроек SPI была возможность выбирать фронт сигнала (полярность, скорее всего) SS.

 

P.S. Все же интересно, кто-то из форумчан заводил SPI в framed slave mode c прерываниями? У меня уже ощущение что это в принципе невозможно (баг камня).

 

В 99.9% из случаев - баг задклавиатурного устройства. ;)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...