реклама на сайте
подробности

 
 
> Почему передатчик SSC смещает влево на 1 бит передаваемое 32-битное слово, at91sam7s
Bulat
сообщение Dec 28 2009, 11:00
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 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);
}

Заранее благодарен!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
aaarrr
сообщение Jan 5 2010, 10:04
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 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. У меня сейчас нет возможности проверить в железе, поэтому могу предложить только теоретические измышления.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Jan 5 2010, 11:35
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 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 при первом клоке?
Прикрепленное изображение

Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 5 2010, 12:43
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 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 в мануале как-то обойдена стороной sad.gif

Что можно еще попробовать:
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. Если ничего из перечисленного не поможет, задействовать еще и приемник.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Jan 6 2010, 07:46
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 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?
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 6 2010, 11:39
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 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 на смещение данных?
Go to the top of the page
 
+Quote Post
Bulat
сообщение Jan 6 2010, 13:25
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 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 пуст
}
}
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jan 6 2010, 13:45
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Bulat @ Jan 6 2010, 16:25) *
Вы имеете в виду аппаратный AND? Можно поподробнее?).

Ну да, аппаратный (1G08 какой-нибудь). Заводим на него TF и TK с последней картинки, и получаем клок с нужными паузами на выходе.

Цитата(Bulat @ Jan 6 2010, 16:25) *
Я решил сделать проще, раз от клока для DATDEF никуда не деться, то использовать поле для передачи первого бита слова.

ИМХО, не стоит так делать: во-первых, сложно, во-вторых - не факт, что поведение клока в какой-то момент не исправят.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Bulat   Почему передатчик SSC смещает влево на 1 бит передаваемое 32-битное слово   Dec 28 2009, 11:00
- - aaarrr   Цитата(Bulat @ Dec 28 2009, 14:00) данные...   Dec 28 2009, 13:30
|- - Bulat   aaarrr Слово смещено влево на 1 бит (то есть 32 би...   Dec 28 2009, 18:37
|- - aaarrr   Цитата(Bulat @ Dec 28 2009, 21:37) А как ...   Dec 28 2009, 19:36
|- - Bulat   Цитата(aaarrr @ Dec 29 2009, 00:36) Расши...   Dec 29 2009, 06:30
|- - Bulat   Первый тактовый импульс на желтой эпюре (смотри ри...   Dec 29 2009, 10:24
|- - aaarrr   Цитата(Bulat @ Dec 29 2009, 13:24) Получа...   Dec 29 2009, 15:50
|- - Bulat   Цитата(aaarrr @ Dec 29 2009, 20:50) Может...   Dec 29 2009, 19:59
|- - Bulat   Цитата(Bulat @ Dec 30 2009, 00:59) Осцилл...   Jan 4 2010, 07:07
- - Bulat   Цитата(aaarrr @ Jan 6 2010, 18:45) Ну да,...   Jan 7 2010, 10:39


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 14:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01519 секунд с 7
ELECTRONIX ©2004-2016