Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Удаленная работа
Помощь проекту

Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей...

 
Опции темы
Непрочитано 13.07.2020, 13:54  
Andrejchukov
Частый гость
 
Регистрация: 28.02.2011
Сообщений: 33
Сказал спасибо: 1
Сказали Спасибо 13 раз(а) в 12 сообщении(ях)
Andrejchukov на пути к лучшему
Печаль STM32F030 опять проблема со SPI 8-bit

Всем привет.
В очередной раз подниму избитую тему особенности SPI модуля STM32F030.
Проблема такая: у меня есть устройство на STM32F103 оно отлажено и работает. Я попытался перенести его в f030 камень и столкнулся с проблемой чтения по SPI 8-bit.
С отправкой по SPI проблем нет. Всё отправляется как положено, проверено логическим анализатором. А вот с приёмом засада. Из FIFO байты читаются абы как. Особенно при нечётном количестве прочитанных байт.
Настроен модуль у меня на 8_bit:
Код:
SPI1-›CR1 |= SPI_CR1_MSTR |SPI_CR1_SSI | SPI_CR1_SSM;
SPI1-›CR2 |= SPI_CR2_DS_2 | SPI_CR2_DS_1 | SPI_CR2_DS_0;
SPI1-›CR2 &= ~SPI_CR2_DS_3;
SPI1-›CR2 |= SPI_CR2_FRXTH;
SPI1-›CR1 |= SPI_CR1_SPE;
FRXTH установлен, DS[3:0] = 0111 - т.е. всё настроено на 8-битный пакет. Также пробовал:
Код:
(*(__IO uint8_t *)((uint32_t)&(SPI1-›DR)))
и просто
Код:
*(uint8_t *)&(SPI1-›DR)
, как написано в RM на эту линейку.
При софтовом ногодрыге всё читается адекватно, то есть на остальную программу я не грешу. Тем более она отлажена на f103 камне.
Кто смог победить данную проблему? Помогите советом.

PS: заметил что при последовательном чтении большого количества байт, сначала читаются четыре пустых байта (0xFF), а затем вся последовательность, т.е сначала читается пустой FIFO, он как раз 32 бита.
Реклама:

Последний раз редактировалось Andrejchukov; 13.07.2020 в 14:41.
Andrejchukov вне форума  
Непрочитано 13.07.2020, 15:00  
Andrejchukov
Частый гость
 
Регистрация: 28.02.2011
Сообщений: 33
Сказал спасибо: 1
Сказали Спасибо 13 раз(а) в 12 сообщении(ях)
Andrejchukov на пути к лучшему
Смех Re: STM32F030 опять проблема со SPI 8-bit

Проблема решилась сама собой.
Кому интересно: загвоздка была именно в FIFO буфере.
У меня функции чтения и отправки байта - отдельные. А FIFO заполняется как при чтении с шины, так и при записи на шину, так как, как известно, по SPI пока ничего не отправишь - ничего не получишь. При этом при отправке каждого байта на шину FIFO всё-равно заполняется. А потом при чтении сначала выдаёт своё содержимое, а только потом через четыре байта (или сколько успели записать) свежепрочитанные.
Поэтому в stm32f030 нужно 1) либо использовать общую функцию записи/чтения, 2) либо в функции записи - проверять RXNE и вычитывать содержимое SPIx-›DR - что, в принципе, превращает функцию записи - в функцию записи/чтения (возвращаемся к пункту 1). Второй вариант подходит при переносе кода с другой линейки МК (мой случай), чтобы не переписывать кучу кода.
В общем, сам спросил - сам ответил.
Andrejchukov вне форума  
Непрочитано 13.07.2020, 15:09  
-Alan-
Прописка
 
Аватар для -Alan-
 
Регистрация: 05.12.2008
Адрес: Россия, Омск
Сообщений: 132
Сказал спасибо: 37
Сказали Спасибо 24 раз(а) в 18 сообщении(ях)
-Alan- на пути к лучшему
По умолчанию Re: STM32F030 опять проблема со SPI 8-bit

FIFO не может читаться пустым. Если он пуст - будут 0xFF. Если байт не принят - будут 0xFF.
Читайте байты по прерываниям, или внимательно следите за флагами SPI-›SR & SPI_SR_RXNE + SPI-›SR & SPI_SR_FRLVL.
Плюс, настройте:
SPI-›CR2 |= SPI_CR2_FRXTH;


Если хочется гарантированно обмениваться по одному байту, то вот процедура:
Код:
uint8_t SPI_Ex_Byte(uint8_t Byte) {
	uint8_t Res;
// Ожидание освобождения SPI. Если ещё не свободен (мало ли).
	while(SPI1-›SR & SPI_SR_FTLVL) { };	// No more data to transmit
	while(SPI1-›SR & SPI_SR_BSY) { };	// Last frame processed
	while(SPI1-›SR & SPI_SR_RXNE) {
		(void)SPI1-›DR;
	};
// в 99.995% сразу доходим до вброса байта в периферию
	*(volatile uint8_t *)&(SPI1-›DR) = Byte;
	while(SPI1-›SR & SPI_SR_FTLVL) { };	// No more data to transmit
	while(SPI1-›SR & SPI_SR_BSY) { };	// Last frame processed
	while(!(SPI1-›SR & SPI_SR_RXNE)) { };	// Delay for end of receive
	Res = *(volatile uint8_t *)&(SPI1-›DR);
	return Res;
};
Работает медленно. Ждёт окончания передачи и приёма байта.
Если же хочется с хорошей скоростью обмениваться данными - то смотрите в сторону DMA.

Последний раз редактировалось -Alan-; 13.07.2020 в 15:11.
-Alan- вне форума  
Непрочитано 13.07.2020, 15:44  
Andrejchukov
Частый гость
 
Регистрация: 28.02.2011
Сообщений: 33
Сказал спасибо: 1
Сказали Спасибо 13 раз(а) в 12 сообщении(ях)
Andrejchukov на пути к лучшему
По умолчанию Re: STM32F030 опять проблема со SPI 8-bit

Спасибо за ответ.
DMA в моём случае не нужен. Не те объёмы.
А на счёт буфера FIFO, я так и писал: пустой, т.е. читается 0xFF.
Andrejchukov вне форума  
Непрочитано 14.07.2020, 19:23  
NewWriter
Почётный гражданин KAZUS.RU
 
Аватар для NewWriter
 
Регистрация: 07.09.2014
Сообщений: 2,587
Сказал спасибо: 211
Сказали Спасибо 1,302 раз(а) в 798 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию Re: STM32F030 опять проблема со SPI 8-bit

Вот тут:
while(SPI1-›SR & SPI_SR_BSY) { }; // Last frame processed
while(SPI1-›SR & SPI_SR_RXNE) {

лишнее действие по причине того, что RXNE однозначно указывает на приеб майта, а BSY - он может не соответствовать реальному положениею дел.

Далее привожу гуглоперевод из референс-мануала полностью:
Нажмите, чтобы открыть спойлер

Процедуры передачи и приема данных

RXFIFO и TXFIFO

Все транзакции данных SPI проходят через 32-битные встроенные FIFO. Это позволяет SPI работать в непрерывном потоке и предотвращает переполнение при коротком размере кадра данных. Каждое направление имеет свой собственный FIFO, называемый TXFIFO и RXFIFO. Эти FIFO используются во всех режимах SPI, за исключением режима только приемника (ведомого или главного) с включенным расчетом CRC (см. Раздел 24.4.14: Расчет CRC).Обработка FIFO зависит от режима обмена данными (дуплекс, симплекс), формата кадра данных (количество битов в кадре), размера доступа, выполняемого в регистрах данных FIFO (8-битный или 16-битный), и от того, или нет упаковка данных используется при доступе к FIFO (см. раздел 24.4.13: режим TI).Доступ для чтения к регистру SPIx_DR возвращает самое старое значение, хранящееся в RXFIFO, которое еще не было прочитано. Доступ для записи к SPIx_DR сохраняет записанные данные в TXFIFO в конце очереди отправки. Доступ на чтение всегда должен быть выровнен с порогом RXFIFO, настроенным битом FRXTH в регистре SPIx_CR2. Биты FTLVL 1: 0] и FRLVL [1: 0] указывают текущий уровень занятости обоих FIFO.Доступ на чтение к регистру SPIx_DR должен управляться событием RXNE. Это событие вызывается, когда данные сохраняются в RXFIFO и достигается порог (определяется битом FRXTH). Когда RXNE очищается, RXFIFO считается пустым. Аналогичным образом, доступ для записи кадра данных, который должен быть передан, управляется событием TXE. Это событие вызывается, когда уровень TXFIFO меньше или равен половине его емкости. В противном случае TXE очищается и TXFIFO считается заполненным. Таким образом, RXFIFO может хранить до четырех фреймов данных, тогда как TXFIFO может хранить только три, когда формат фрейма данных не превышает 8 бит. Это различие предотвращает возможное повреждение 3x 8-битных фреймов данных, уже сохраненных в TXFIFO, когда программное обеспечение пытается записать больше данных в 16-битном режиме в TXFIFO. События TXE и RXNE могут опрашиваться или обрабатываться прерываниями. См. Рис. 255 - Рис. 258.Другим способом управления обменом данными является использование DMA (см. Раздел 10.2: Основные функции DMA).Если следующие данные получены, когда RXFIFO заполнен, происходит событие переполнения (см. Описание флага OVR в Разделе 24.4.10: Флаги состояния SPI). Событие переполнения может быть опрошено или обработано прерыванием.Устанавливаемый бит BSY указывает текущую транзакцию текущего кадра данных. Когда тактовый сигнал работает непрерывно, флаг BSY остается установленным между кадрами данных на главном устройстве, но становится низким в течение минимальной продолжительности одного тактового сигнала SPI на ведомом устройстве между каждой передачей кадра данных.


Диаграммы связи
В этом разделе описаны некоторые типичные временные схемы. Эти схемы действительны независимо от того, обрабатываются ли события SPI с помощью опроса, прерываний или прямого доступа к памяти. Для простоты здесь в качестве общего предположения используется настройка LSBFIRST = 0, CPOL = 0 и CPHA = 1. Полная конфигурация потоков DMA не предоставляется.
Следующие пронумерованные примечания являются общими для рисунков 255 на стр. 658 - рисунка 258 на стр. 661.

1. Слэйв начинает управлять линией MISO, поскольку NSS активен, а SPI включен, и отключается от линии, когда один из них отключается. Должно быть достаточно времени, чтобы подчиненное устройство подготовило данные, предназначенные для мастера, до начала его транзакции.
На главном устройстве периферийное устройство SPI получает управление сигналами MOSI и SCK (иногда также и сигналом NSS), только если включен SPI. Если SPI отключен, периферийное устройство SPI отключается от логики GPIO, поэтому уровни в этих линиях зависят исключительно от настроек GPIO.
2. На ведущем устройстве BSY остается активным между кадрами, если связь (тактовый сигнал) непрерывна. На ведомом устройстве сигнал BSY всегда снижается в течение по крайней мере одного тактового цикла между кадрами данных.
3. Сигнал TXE сбрасывается, только если TXFIFO заполнен.
4. Процесс арбитража DMA начинается сразу после установки бита TXDMAEN. Прерывание TXE генерируется сразу после установки TXEIE. Поскольку сигнал TXE находится на активном уровне, передача данных в TxFIFO начинается до тех пор, пока TxFIFO не станет полным или пока не завершится передача DMA.
5. Если все передаваемые данные могут поместиться в TxFIFO, флаг DMA Tx TCIF может быть поднят даже до того, как начнется обмен данными по шине SPI. Этот флаг всегда повышается до завершения транзакции SPI.
6. Значение CRC для пакета вычисляется непрерывно кадр за кадром в регистрах SPIx_TxCRCR и SPIx_RxCRCR. Информация CRC обрабатывается после завершения всего пакета данных либо автоматически с помощью DMA (канал Tx должен быть установлен на количество обрабатываемых кадров данных), либо с помощью SW (пользователь должен обрабатывать бит CRCNEXT во время последней обработки кадра данных) ,
В то время как значение CRC, вычисленное в SPIx_TxCRCR, просто отправляется передатчиком, полученная информация CRC загружается в RxFIFO и затем сравнивается с содержимым регистра SPIx_RxCRCR (здесь может быть установлен флаг ошибки CRC при любой разнице). Вот почему пользователь должен позаботиться о том, чтобы сбросить эту информацию из FIFO, либо с помощью программного обеспечения, считывающего весь сохраненный контент RxFIFO, либо с помощью DMA, когда для канала Rx предварительно установлено надлежащее количество кадров данных (количество кадров данных + число кадров CRC) (см. настройки в примере предположения).
7. В режиме упаковки данных события TxE и RxNE являются парными, и каждый доступ на чтение / запись к FIFO имеет ширину 16 битов, пока количество кадров данных не станет четным. Если TxFIFO - ¾ полный, статус FTLVL остается на полном уровне FIFO. Вот почему последний нечетный кадр данных не может быть сохранен до того, как TxFIFO заполнится на 1/2. Этот кадр сохраняется в TxFIFO с 8-битным доступом либо программно, либо автоматически DMA, когда установлено управление LDMA_TX.
8. Чтобы получить последний нечетный кадр данных в упакованном режиме, пороговое значение Rx должно быть изменено на 8-разрядное при обработке последнего кадра данных, либо с помощью программной установки FRXTH = 1, либо автоматически с помощью внутреннего сигнала DMA, когда установлен LDMA_RX.
NewWriter вне форума  
Непрочитано 14.07.2020, 19:32  
Andrejchukov
Частый гость
 
Регистрация: 28.02.2011
Сообщений: 33
Сказал спасибо: 1
Сказали Спасибо 13 раз(а) в 12 сообщении(ях)
Andrejchukov на пути к лучшему
Радость Re: STM32F030 опять проблема со SPI 8-bit

Спасибо за ответ.
RM я читал)))
Поэтому и додумался позже сам, в чём была проблема.
Дело не в том, какие флаги проверять, а в том, что и при чтении, и при записи на шину надо читать регистр SPI-›DR. Иначе при отправке данных на шину FIFO также заполнится, как и при чтении.
Andrejchukov вне форума  
Непрочитано 14.07.2020, 19:41  
Andrejchukov
Частый гость
 
Регистрация: 28.02.2011
Сообщений: 33
Сказал спасибо: 1
Сказали Спасибо 13 раз(а) в 12 сообщении(ях)
Andrejchukov на пути к лучшему
По умолчанию Re: STM32F030 опять проблема со SPI 8-bit

Вообще F030 линейка очень странная. После перехода с F103 доставляет много геморроя. Казалось бы, один производитель, SPL, HAL, просто чуть-чуть подправь код. Ан нет! Намутили. В SPI засунули FIFO, в I2C придумали Reload да ещё и на 255 раз. С USART тоже не мало геморроя, намучался с прерыванием по приёму байта, оказалось, что просто не надо сбрасывать флаг в прерывании, он сам сбрасывается при чтении регистра USART-›RDR. Мелочь, а отняла много времени!
Только, по ходу, с таймерами особо ничего нового не придумали, кроме как их нумерации.
Andrejchukov вне форума  
Непрочитано 14.07.2020, 21:28  
NewWriter
Почётный гражданин KAZUS.RU
 
Аватар для NewWriter
 
Регистрация: 07.09.2014
Сообщений: 2,587
Сказал спасибо: 211
Сказали Спасибо 1,302 раз(а) в 798 сообщении(ях)
NewWriter на пути к лучшему
По умолчанию Re: STM32F030 опять проблема со SPI 8-bit

F1 линейка была самая первая. Позже появились другие линейки, в том числе и F0. И в них уже существенно пересмотрели подход к периферии. Заменили неудобные "половинчатые" регистры настройки режима портов, улучшили I2C, который стал гораздо более эффективным. И это "повторить до 255 раз" - это как раз для более удобной коммуникации, позволяющей автоматически формировать стоп-бит на линии.
В F1 коммуникация по I2C не самая удачная, много процессорного времени отнимает.

Нумерация таймеров во всех линейках одинаковая. Стандартно, TIM1, TIM8 - самые навороченные таймеры для реализации двухтактных трехфазных генераторов и для BLDC-моторов. TIM2-TIM5 - общего назначения. TIM2 имеет 32-битный диапазон счета (в этом отличие от F1). Ну и остальные таймеры аналогичны, как и везде - TIM6, TIM7 - самые простые и примитивные, но зато имеют триггер запуска DAC.

В F0 RTC имеют аппаратный календарь с форматом BCD, в отличие от F1, в котором RTC является лишь счетчиком секундных интервалов, а корректную дату/время приходится вычислять через преобразование unix-time. С другой стороны, в F1 есть секундный импульс, очень даже полезный.

Ну и прочие усовершенствования типа тач-сенсорного контроллера или аналогового компаратора. Однако, из-за более слабого ядра в F0 значительно уменьшились вычислительные возможности. Пропало аппаратное деление, уменьшилось число приоритетов прерываний, уменьшился размер ОЗУ, а число выводов не превышает 64 (зато появился 20-выводный).
Так что F0 - это просто другая линейка, со своими плюсами и минусами.

Кстати, недавно появился довольно интересный гибридный МК STSPIN32F0 со встроенной силовой частью для управления BLDC-моторами напрямую и с STM32F031C6 внутри.
NewWriter вне форума  
Непрочитано 15.07.2020, 19:19  
dr.doc
Частый гость
 
Регистрация: 24.07.2010
Сообщений: 27
Сказал спасибо: 6
Сказали Спасибо 14 раз(а) в 7 сообщении(ях)
dr.doc на пути к лучшему
По умолчанию Re: STM32F030 опять проблема со SPI 8-bit

Вставлю свои мучения. Чип STM32F030:
Инициализация:
Нажмите, чтобы открыть спойлер

#ifdef hardware
RCC-›APB2ENR |= RCC_APB2ENR_SPI1EN;
// clock SPI enable

GPIOA-›MODER &=~
(GPIO_MODER_MODER6_Msk
|GPIO_MODER_MODER5_Msk
|GPIO_MODER_MODER4_Msk
|GPIO_MODER_MODER7_Msk); // Input Mode
//---------------------------------------------------------
GPIOA-›OTYPER = 0;
GPIOA-›PUPDR |= (GPIO_PUPDR_PUPDR4_0|GPIO_PUPDR_PUPDR5_1|GPIO_PUPD R_PUPDR6_1|GPIO_PUPDR_PUPDR7_1);
//---------------------------------------------------------
GPIOA-›MODER |=\
GPIO_MODER_MODER4_0| // General purpose output mode
GPIO_MODER_MODER5_1| // Alternate function mode
GPIO_MODER_MODER6_1|
GPIO_MODER_MODER7_1;

GPIOA-›OSPEEDR |=\
GPIO_OSPEEDR_OSPEEDR4_0|
GPIO_OSPEEDR_OSPEEDR5_0|
GPIO_OSPEEDR_OSPEEDR6_0|
GPIO_OSPEEDR_OSPEEDR7_0; // High speed

SPI1-›CR1 = 0‹‹SPI_CR1_LSBFIRST_Pos //MSB first
| SPI_CR1_SSM //Программное управление SS
| SPI_CR1_SSI //SS в высоком состоянии
// | SPI_CR1_BIDIOE | SPI_CR1_BIDIMODE
// | SPI_CR1_BR_0
| SPI_CR1_BR_1
// | SPI_CR1_BR_2//Скорость передачи: F_PCLK/4 - 8MHz
| SPI_CR1_MSTR //Режим Master (ведущий)
| SPI_CR1_CPOL
| SPI_CR1_CPHA; //Режим работы SPI: 0

SPI1-›CR2 = SPI_CR2_DS_2|SPI_CR2_DS_1|SPI_CR2_DS_0|SPI_CR2_FRX TH;
SPI1-›CR1 |= SPI_CR1_SPE; // enable SPI
/*
Настроили вот так: 8 бит, MSB first, CPOL/CPHA 00. Стоит обратить особое внимание на SSM и SSI.
Инициализация модуля SPI в режиме Master возможна только при сигнале SS равном единице. Почему
это так объяснять не буду, скажу только, что это идет из режима Multimaster mode. Сигнал SS может
быть получен либо с вывода NSS, либо бита SSI регистра CR1. Если SSM установлен в ноль (значение
по-умолчанию), то при включении SPI он будет производить проверку состояния NSS, а NSS по-умолчанию
настроен как Input floating. Таким образом, если на выводе NSS будет логическая единица, то
инициализация завершится успешно, в противном случае ни чего не получится и в регистре SR установится
бит MODF, который говорит об ошибке режима. Кроме того, даже после успешной инициализации низкий
уровень на NSS отключит SPI и сбросит бит MSTR (из режима master переключится в slave). А если NSS
будет просто болтаться в воздухе, то система будет вообще неработоспособной. Поэтому устанавливаем
SSM и SSI в единицы.
*/
#endif
}

Передача байта
Нажмите, чтобы открыть спойлер
void transmit_byte(char m)
{
#ifdef hardware
while (!(SPI1-›SR & SPI_SR_TXE)); /* Test Tx empty */

/* Will inititiate 8-bit transmission if TXE */
*(__IO uint8_t *) (&SPI1-›DR) = m; //SPI1-›DR = data; untranslatable pun!!!!!
while(((SPI1-›SR & SPI_SR_RXNE) == 0));
uint8_t v = SPI1-›DR;
while(SPI1-›SR & SPI_SR_BSY); // ready for buffer empty
#endif


Прием байта:
Нажмите, чтобы открыть спойлер
#ifdef hardware
while (!(SPI1-›SR & SPI_SR_TXE)); /* Test Tx empty */
CLRCS_MAX6675; // Chip select
/* Will inititiate 8-bit transmission if TXE */
*(__IO uint8_t *) (&SPI1-›DR) = 0xFF; //SPI1-›DR = data; untranslatable pun!!!!!
while(!(SPI1-›SR & SPI_SR_RXNE)); // ready for buffer empty
data = (SPI1-›DR)‹‹8;

while (!(SPI1-›SR & SPI_SR_TXE)); /* Test Tx empty */
/* Will inititiate 8-bit transmission if TXE */
*(__IO uint8_t *) (&SPI1-›DR) = 0xFF; //SPI1-›DR = data; untranslatable pun!!!!!
while(!(SPI1-›SR & SPI_SR_RXNE)); // ready for buffer empty
// while((SPI1-›SR & SPI_SR_RXNE) == SPI_SR_RXNE); // ready for buffer empty
data |= (uint8_t)SPI1-›DR;
while(SPI1-›SR & SPI_SR_BSY); // ready for buffer empty

#endif
SETCS_MAX6675;

Если при приеме не дожидаться флага SPI_SR_BSY и снимать SETCS_MAX6675 - данные теряются. Это - без прерываний. У меня на шине два устройства - MAX6675 & MAX7219. Все работает.
dr.doc вне форума  
 

Закладки

Метки
spi, stm32f030
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблема: 64 bit & USB driver proteus'a Prorokeus Proteus 15 18.12.2013 06:51
Проблема с SPI mcp3550 :? dnpdz Proteus 5 30.05.2011 23:44
Снова проблема с кодом - чего я опять не учел? greafuger Микроконтроллеры, АЦП, память и т.д 3 27.04.2008 07:25
Проблема с SPI АТ25256 Leonid68 Микроконтроллеры, АЦП, память и т.д 5 11.08.2005 23:26
Не удаётся запустить SPI на At90S8515 Coder Микроконтроллеры, АЦП, память и т.д 3 30.03.2005 14:17


Часовой пояс GMT +4, время: 22:25.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd. Перевод: zCarot