|
Почему передатчик SSC смещает влево на 1 бит передаваемое 32-битное слово, at91sam7s |
|
|
|
Dec 28 2009, 11:00
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Передатчик SSC отправляет 32-битные слова в непрерывном режиме с паузой 40мкс, частота тактирования 100 кГц. По прерыванию (TXRDY) буфер передатчика обновляется. Непрерывную передачу с заданной паузой получить удалось, но данные почему-то смещены в сторону старшего бита на 1. Почему так происходит? CODE //++++++++++++++++++++++++++--SSC--+++++++++++++++++++++++++++++++++++++++++++++ __ramfunc void SscHandler() { AT91C_BASE_SSC->SSC_THR = dat_buf; //обновление буфера передатчика unsigned int dummy = AT91C_BASE_SSC->SSC_SR; }
void AT91F_SSC_Conf () { // Setup ssc AT91F_SSC_CfgPMC(); /* Enable MCK clock */ // pio Special configuration AT91F_SSC_CfgPIO(); //* Disable interrupts AT91C_BASE_SSC->SSC_IDR = 0xfff;
//* Reset receiver and transmitter AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST | AT91C_SSC_TXDIS ;
//* Define the Clock Mode Register AT91C_BASE_SSC->SSC_CMR = 240; //100 кГц
//* Write the Transmit Clock Mode Register AT91C_BASE_SSC->SSC_TCMR = (17 << 24) & AT91C_SSC_PERIOD | (5<<16) & AT91C_SSC_STTDLY | AT91C_SSC_START_RISE_RF | (0x2 << 6) | AT91C_SSC_CKI | AT91C_SSC_CKO_DATA_TX | AT91C_SSC_CKS_DIV;
//* Write the Transmit Frame Mode Register AT91C_BASE_SSC->SSC_TFMR = AT91C_SSC_FSOS_POSITIVE | (31<<0) & AT91C_SSC_DATLEN; }
void AT91F_SSC_Start(void) { //* Open SSC interrupt AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SSC] = (unsigned int)SscHandler; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SSC] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | SSC_INTERRUPT_LEVEL; AT91C_BASE_AIC->AIC_IECR = (1UL << AT91C_ID_SSC); AT91C_BASE_SSC->SSC_IER = AT91C_SSC_TXRDY; AT91C_BASE_SSC->SSC_CR = AT91C_SSC_TXEN; AT91C_BASE_SSC->SSC_THR = dat_buf; } //++++++++++++++++++++++++++--SSC--+++++++++++++++++++++++++++++++++++++++++++++ ramfunc int main(void) { AT91F_SSC_Conf(); AT91F_SSC_Start(); while(1) write(dat_buf); }
Заранее благодарен!
|
|
|
|
|
Dec 29 2009, 06:30
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Цитата(aaarrr @ Dec 29 2009, 00:36)  Расширьте PERIOD. По Юзергайду "a period signal is generated at each 2 x (PERIOD+1) Transmit Clock", то есть STTDLY + DATLEN = 2 x (PERIOD+1) STTDLY = 4, DATLEN = 31, отсюда PERIOD = 17. То есть я просто STTDLY уменьшил на 1 по сравнению с первоначальным вариантом в этом посте. Но как я заметил, при такой конфигурации SSC, как я привел в этом посте, значение поля STTDLY не влияет на паузу, так как PERIOD включает в себя длину 32-битного слова и 4-битную паузу, а в поле CKO у меня Transmit Clock only during data transfers. То есть, на выводе TK пояаляются имульсы только, когда в буфер загружается слово, а так как слово (32 бита) на 4 бита меньше периода TF (36), то и появляется пауза. И всетаки, почему передаваемое слово смещается влево (в сторону старшего бита) на 1 относительно того, что я записываю в регистр THR? Я прикрепил картинку с эпюрами. Желтый сигнал - вывод TK, розовый - TD. В буфер THR я записываю число 0х2000, а по эпюре видно, что 1 на выводе TD появилась только при 15 такте TK, то есть на выходе SSC уже число 0х4000 (смещено на 1 в сторону старшего).
Эскизы прикрепленных изображений
|
|
|
|
|
Dec 29 2009, 19:59
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Цитата(aaarrr @ Dec 29 2009, 20:50)  Может и 32. Давайте сделаем так: добавьте к своей осциллограмме сигнал TF и напишите точную конфигурацию регистров SSC. Точная конфигурацию регистров SSC: CODE //* Disable interrupts AT91C_BASE_SSC->SSC_IDR = 0xfff;
//* Reset receiver and transmitter AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST | AT91C_SSC_TXDIS ;
//* Define the Clock Mode Register AT91C_BASE_SSC->SSC_CMR = 240; //100 кГц
//* Write the Transmit Clock Mode Register AT91C_BASE_SSC->SSC_TCMR = (17 << 24) & AT91C_SSC_PERIOD | (4<<16) & AT91C_SSC_STTDLY | AT91C_SSC_START_RISE_RF | (0x2 << 6) | AT91C_SSC_CKI | AT91C_SSC_CKO_DATA_TX | AT91C_SSC_CKS_DIV;
//* Write the Transmit Frame Mode Register AT91C_BASE_SSC->SSC_TFMR = AT91C_SSC_FSOS_POSITIVE | (31<<0) & AT91C_SSC_DATLEN;
Осциллограмма TF представляет собой последовательность коротких импульсов с периодом 360 мкс, длительность импульса 10 мкс, то есть в период TF укладывается 36 бит - 32-бита данных и 4 бита паузы. К сожалению, сегодня не смогу снять эпюру с TF(
|
|
|
|
|
Jan 4 2010, 07:07
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Цитата(Bulat @ Dec 30 2009, 00:59)  Осциллограмма TF представляет собой последовательность коротких импульсов с периодом 360 мкс, длительность импульса 10 мкс, то есть в период TF укладывается 36 бит - 32-бита данных и 4 бита паузы. К сожалению, сегодня не смогу снять эпюру с TF( Прикрепляю картинку с тремя эпюрами, снятых на выводах передатчика TK,TD и TF. Период TF составляет 360 мкс, то есть 36 (32 импульсов бита данных и 4 бита паузы) с частотой 100кГц, как и должно быть. Бит данных (TD) смещен на 1 в сторону старшего бита (первым передается младший бит) по сравнению с тем, что было записано в буфер THR. Как я писал выше, первый тактовый импульс, а, следовательно, и первый передаваемый бит данных по TD соответствует значению поля DATDEF регистра TFMR, а не первому биту передаваемого слова. Как исключить из передачи этот лишний бит?
Сообщение отредактировал rezident - Jan 4 2010, 17:11
Причина редактирования: Нарушение п.3.4 Правил форума.
Эскизы прикрепленных изображений
|
|
|
|
|
Jan 5 2010, 10:04
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Странно, откуда вообще берутся клоки, если в поле CKG прописано "Transmit Clock enabled only if TF High", а TF во время передачи в нуле? А что будет, если попробовать передать 0x2000 при такой конфигурации: Код //* Write the Transmit Clock Mode Register AT91C_BASE_SSC->SSC_TCMR = (17 << 24) & AT91C_SSC_PERIOD | (4<<16) & AT91C_SSC_STTDLY | AT91C_SSC_START_RISE_RF | AT91C_SSC_CKO_DATA_TX | AT91C_SSC_CKS_DIV;
//* Write the Transmit Frame Mode Register AT91C_BASE_SSC->SSC_TFMR = AT91C_SSC_FSOS_POSITIVE | (31<<0) & AT91C_SSC_DATLEN | (3 << 16) & AT91_SSC_FSLEN | AT91C_SSC_DATDEF; P.S. У меня сейчас нет возможности проверить в железе, поэтому могу предложить только теоретические измышления.
|
|
|
|
|
Jan 5 2010, 11:35
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Цитата(aaarrr @ Jan 5 2010, 15:04)  Странно, откуда вообще берутся клоки, если в поле CKG прописано "Transmit Clock enabled only if TF High", а TF во время передачи в нуле? Судя по приведенным мною эпюрам в предыдущем ответе, клоки появляются только при загрузке буфера THR (AT91C_SSC_CKO_DATA_TX), а TF на синхронизацию никак не влияет. TF влияет только на период передаваемых слов и на паузу между словами (личные наблюдения). Цитата а TF во время передачи в нуле? Да, TF во время передачи равен 0. Во время передачи TF=1, если AT91C_SSC_FSOS_HIGH, но в этом случае вообще ничего не работает) Цитата А что будет, если попробовать передать 0x2000 при такой конфигурации: Код //* Write the Transmit Clock Mode Register AT91C_BASE_SSC->SSC_TCMR = (17 << 24) & AT91C_SSC_PERIOD | (4<<16) & AT91C_SSC_STTDLY | AT91C_SSC_START_RISE_RF | AT91C_SSC_CKO_DATA_TX | AT91C_SSC_CKS_DIV;
//* Write the Transmit Frame Mode Register AT91C_BASE_SSC->SSC_TFMR = AT91C_SSC_FSOS_POSITIVE | (31<<0) & AT91C_SSC_DATLEN | (3 << 16) & AT91_SSC_FSLEN | AT91C_SSC_DATDEF; Эпюры для этого варианта я прикрепил. При добавлении поля (3 << 16) & AT91_SSC_FSLEN расширяется импульс TF, да еще и пауза между клоками в виде длинной 1, а мне ноль нужен. При добавлении поля AT91C_SSC_DATDEF первым битом TD является 1, что меня тоже не устраивает. Вообще, единственное, что меня не устраивает в конфигурации SSC, что я привел в предыдущем ответе, так это первый бит на выводе данных TD. Первым битом передаваемых данных как с вашей конфигурацией, так и с моей является значение поля DATDEF, из-за этого то и происходит смещение данных и потеря 32 бита, так как всего передается 32 бита. То есть, SSC почему-то после загрузки буфера THR сначало передает бит, который должен висеть на TD при отключенном передатчике SSC (поле DATDEF), а затем уже слово данных, но при этом на все это выделяется всего 32 клока! Как исключить передачу DATDEF при первом клоке?
Эскизы прикрепленных изображений
|
|
|
|
|
Jan 5 2010, 12:43
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Bulat @ Jan 5 2010, 14:35)  ...пауза между клоками в виде длинной 1, а мне ноль нужен. Там не "1", а третье состояние, поэтому уровень в паузах будет зависеть от бита CKI. Но в любом случае снаружи потребуется pull-down, если нужен честный ноль. Цитата(Bulat @ Jan 5 2010, 14:35)  При добавлении поля AT91C_SSC_DATDEF первым битом TD является 1, что меня тоже не устраивает. Я его специально добавил, чтобы видеть границы реального слова. Цитата(Bulat @ Jan 5 2010, 14:35)  То есть, SSC почему-то после загрузки буфера THR сначало передает бит, который должен висеть на TD при отключенном передатчике SSC (поле DATDEF), а затем уже слово данных, но при этом на все это выделяется всего 32 клока! Как исключить передачу DATDEF при первом клоке? Он не "передает DATDEF", а почему-то неправильно гейтирует клок (со сдвигом на один такт). Сейчас попробуем разобраться. Увы, работа CKO/CKG в мануале как-то обойдена стороной  Что можно еще попробовать: 1. Привязать старт к уровню вместо фронта. Возможно, это изменит поведение CKO. 2. Отказаться от CKO и использовать вместо него CKG: Код //* Write the Transmit Clock Mode Register AT91C_BASE_SSC->SSC_TCMR = (17 << 24) & AT91C_SSC_PERIOD | (4<<16) & AT91C_SSC_STTDLY | AT91C_SSC_START_RISE_RF | (0x1 << 6) | AT91C_SSC_CKI | AT91C_SSC_CKS_DIV;
//* Write the Transmit Frame Mode Register AT91C_BASE_SSC->SSC_TFMR = AT91C_SSC_FSOS_POSITIVE | (31<<0) & AT91C_SSC_DATLEN | (3 << 16) & AT91_SSC_FSLEN | AT91C_SSC_DATDEF; Возможно, придется отинвертировать TF, если передатчик действительно отказывается работать при 0x1 в CKG: Код //* Write the Transmit Clock Mode Register AT91C_BASE_SSC->SSC_TCMR = (17 << 24) & AT91C_SSC_PERIOD | (4<<16) & AT91C_SSC_STTDLY | AT91C_SSC_START_FALL_RF | (0x2 << 6) | AT91C_SSC_CKI | AT91C_SSC_CKS_DIV;
//* Write the Transmit Frame Mode Register AT91C_BASE_SSC->SSC_TFMR = AT91C_SSC_FSOS_NEGATIVE | (31<<0) & AT91C_SSC_DATLEN | (3 << 16) & AT91_SSC_FSLEN | AT91C_SSC_DATDEF; 3. Если ничего из перечисленного не поможет, задействовать еще и приемник.
|
|
|
|
|
Jan 6 2010, 07:46
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Цитата(aaarrr @ Jan 5 2010, 17:43)  1. Привязать старт к уровню вместо фронта. Возможно, это изменит поведение CKO. Пробовал, ничего не изменилось. Цитата(aaarrr @ Jan 5 2010, 17:43)  2. Отказаться от CKO и использовать вместо него CKG: Код //* Write the Transmit Clock Mode Register AT91C_BASE_SSC->SSC_TCMR = (17 << 24) & AT91C_SSC_PERIOD | (4<<16) & AT91C_SSC_STTDLY | AT91C_SSC_START_RISE_RF | (0x1 << 6) | AT91C_SSC_CKI | AT91C_SSC_CKS_DIV;
//* Write the Transmit Frame Mode Register AT91C_BASE_SSC->SSC_TFMR = AT91C_SSC_FSOS_POSITIVE | (31<<0) & AT91C_SSC_DATLEN | (3 << 16) & AT91_SSC_FSLEN | AT91C_SSC_DATDEF; Вывод TK вообще не подает признаков жизни. Цитата(aaarrr @ Jan 5 2010, 17:43)  Возможно, придется отинвертировать TF, если передатчик действительно отказывается работать при 0x1 в CKG: Код //* Write the Transmit Clock Mode Register AT91C_BASE_SSC->SSC_TCMR = (17 << 24) & AT91C_SSC_PERIOD | (4<<16) & AT91C_SSC_STTDLY | AT91C_SSC_START_FALL_RF | (0x2 << 6) | AT91C_SSC_CKI | AT91C_SSC_CKS_DIV;
//* Write the Transmit Frame Mode Register AT91C_BASE_SSC->SSC_TFMR = AT91C_SSC_FSOS_NEGATIVE | (31<<0) & AT91C_SSC_DATLEN | (3 << 16) & AT91_SSC_FSLEN | AT91C_SSC_DATDEF; Аналогично, на TK нет сигнала без кофигурации CKO. Попробовал к этой конфигурации просто добавить CKO_CONTINOUS, эпюры приведены на прикрепленной картинке. При такой конфигурации по TD действительно передается такое же слово, что и записано в THR 0х2000 (без смещения), но при этом во время паузы между словами передаются синхроимпульсы, да к тому же на время паузы клок не останавливается, что меня не устраивает. Складывается впечатления, что CKG вообще не оказывает влияние на передатчик. К тому же поле CKG почему-то забыли описать в хедере AT91SAM7S256.h. Цитата(aaarrr @ Jan 5 2010, 17:43)  3. Если ничего из перечисленного не поможет, задействовать еще и приемник. То есть вывод TF настроить как вход, а синхросигналы подавать с вывода RF?
Эскизы прикрепленных изображений
|
|
|
|
|
Jan 6 2010, 11:39
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Bulat @ Jan 6 2010, 10:46)  Попробовал к этой конфигурации просто добавить CKO_CONTINOUS, эпюры приведены на прикрепленной картинке. При такой конфигурации по TD действительно передается такое же слово, что и записано в THR 0х2000 (без смещения), но при этом во время паузы между словами передаются синхроимпульсы, да к тому же на время паузы клок не останавливается, что меня не устраивает. Зато теперь можно выкрутиться, добавив одногейтовый AND для клока. Цитата(Bulat @ Jan 6 2010, 10:46)  Складывается впечатления, что CKG вообще не оказывает влияние на передатчик. К тому же поле CKG почему-то забыли описать в хедере AT91SAM7S256.h. Да, все правильно: судя по картинке, он действует только на внутренний Transmit Clock. А вот с CKO явно что-то не так. Беда в том, что при нормальной работе (т.е. общении с кодеками) эти функции никому особо не нужны. Цитата(Bulat @ Jan 6 2010, 10:46)  То есть вывод TF настроить как вход, а синхросигналы подавать с вывода RF? Т.е. настроить приемник так, чтобы на RK сформировалась нужная картина, а передатчик запустить от сигналов приемника с нужным смещением. Да, и раз уж пошла такая пьянка: не влияет ли бит MSBF на смещение данных?
|
|
|
|
|
Jan 6 2010, 13:25
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Цитата(aaarrr @ Jan 6 2010, 16:39)  Зато теперь можно выкрутиться, добавив одногейтовый AND для клока. Вы имеете в виду аппаратный AND? Можно поподробнее?). Цитата(aaarrr @ Jan 6 2010, 16:39)  Да, и раз уж пошла такая пьянка: не влияет ли бит MSBF на смещение данных? Смещение данных всеравно есть, просто данные перевернуты, то есть теперь теряется первый бит. Я решил сделать проще, раз от клока для DATDEF никуда не деться, то использовать поле для передачи первого бита слова. То есть, перед записью слова в THR я формирую слово данных без первого бита, сещенное на 1 в сторону младшего бита. А в зависимости от значения первого бита слова данных я изменяю поле DATDEF. В принципе, эта схема у меня работает, но для слов, у которых первый байт равен 0xfe и 0xff происходит сбой алгоритма. По идее, если первый байт передаваемого слова равен 0xfe, то в поле DATDEF записывается 0, а если первый байт 0xff, то 1. У меня же происходит все наоборот, но только для этих двух значений, все остальные варианты слов данных передаются нормально. CODE
__ramfunc void SscHandler() { jj=0; //dat_buf пуст if(fb) AT91C_BASE_SSC->SSC_TFMR |= AT91C_SSC_DATDEF; //Установка поля DATDEF при fb=1 (первый бит передаваемого слова равен 1) else AT91C_BASE_SSC->SSC_TFMR &= ~(AT91C_SSC_DATDEF); AT91C_BASE_SSC->SSC_THR = dat_buf; unsigned int dummy = AT91C_BASE_SSC->SSC_SR; }
void AT91F_SSC_Conf () { ...
//* Write the Transmit Clock Mode Register AT91C_BASE_SSC->SSC_TCMR = (17 << 24) & AT91C_SSC_PERIOD | (4<<16) & AT91C_SSC_STTDLY | AT91C_SSC_START_RISE_RF | AT91C_SSC_CKI | AT91C_SSC_CKO_DATA_TX | AT91C_SSC_CKS_DIV; //* Write the Transmit Frame Mode Register AT91C_BASE_SSC->SSC_TFMR = AT91C_SSC_FSOS_POSITIVE | (31<<0) & AT91C_SSC_DATLEN; }
//Первоначальный запуск передатчика void AT91F_SSC_Start(void) { //* Open SSC interrupt AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SSC] = (unsigned int)SscHandler; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SSC] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | SSC_INTERRUPT_LEVEL; AT91C_BASE_AIC->AIC_IECR = (1UL << AT91C_ID_SSC); AT91C_BASE_SSC->SSC_IER = AT91C_SSC_TXRDY; AT91C_BASE_SSC->SSC_CR = AT91C_SSC_TXEN; if(fb) AT91C_BASE_SSC->SSC_TFMR |= AT91C_SSC_DATDEF; //Установка поля DATDEF при fb=1 (первый бит передаваемого слова равен 1) else AT91C_BASE_SSC->SSC_TFMR &= ~(AT91C_SSC_DATDEF); AT91C_BASE_SSC->SSC_THR = dat_buf; }
__ramfunc void Write_TRA() { //Считывание 32-битного слова данных из UDP unsigned int byte1 = regUDP->UDP_FDR[AT91C_EP_OUT]; unsigned int byte2 = regUDP->UDP_FDR[AT91C_EP_OUT]; unsigned int byte3 = regUDP->UDP_FDR[AT91C_EP_OUT]; unsigned int byte4 = regUDP->UDP_FDR[AT91C_EP_OUT]; fb = byte1&0x1; //Запись значения первого бита слова byte1 = byte1 >> 1; //Избавляемся от первого бита слова данных dat_buf = (byte4<<23)|(byte3<<15)|(byte2<<7)|byte1; //подготовка 31 бита слова данных, за исключением первого бита jj = 1; //dat_buf заполнен if(ii==1) {AT91F_SSC_Start(); ii=0;} //Первоначальный запуск передатчика, далее он не останавливается length = length-5; }
int main(void) { while(1) { if(jj==0) Write_TRA(); //если буфер передатчика SSC пуст } }
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|