Jump to content

    
Sign in to follow this  
Я.К.

STM32F4, UART и лишний бит при чтении

Recommended Posts

C фронтами сигнала из прошлого поста я разобрался, но появились новые глюки.

 

Мой STM32F4 почему-то принимает целый лишний байт (!) в начале ответной посылки от периферии, общаясь с нею по UARTу.

 

Периферия говорит ему: FF, FF, 01, 02, 00, FB.

А микроконтроллер, зараза такая, принимает: FF, FF, FF, 01, 02, 00, FC.

 

Имею спросить: как бы мне это забороть?

 

 

P.S. Вот начало ответной посылки моей периферии. Тут явно видно, что посылают всё-таки два стартовых FF-байта, а не три.

 

post-42205-1456328464_thumb.png

 

Код инициализации UARTа:

void MX_UART5_Init(void)
{

  huart5.Instance = UART5;
  huart5.Init.BaudRate = 1000000;
  huart5.Init.WordLength = UART_WORDLENGTH_8B;
  huart5.Init.StopBits = UART_STOPBITS_1;
  huart5.Init.Parity = UART_PARITY_NONE;
  huart5.Init.Mode = UART_MODE_TX_RX;
  huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart5.Init.OverSampling = UART_OVERSAMPLING_8;
  HAL_HalfDuplex_Init(&huart5);

}

 

P.P.S. Код обращения к периферии (не бойтесь, printf там происходит уже после того, как получена ответная часть):

void PingServo(UART_HandleTypeDef* uartPtr)
{
 uint32_t timeout = 1000; // в миллисекундах

 uint8_t txData[6];

 uint8_t servoId = 1;
 uint8_t len = 2;
 uint8_t instruction = 1;
 uint8_t checksum = ~(servoId + len + instruction);

 txData[0] = 0xFF;
 txData[1] = 0xFF;
 txData[2] = servoId;
 txData[3] = len;
 txData[4] = instruction;
 txData[5] = checksum;

 HAL_StatusTypeDef txStatus = HAL_UART_Transmit(uartPtr, txData, 6, timeout);
 if(txStatus != HAL_OK)
 {
printf("TX ERROR\r\n");
 }


 uint8_t rxData[7];

 HAL_StatusTypeDef rxStatus = HAL_UART_Receive(uartPtr, rxData, 7, timeout);
 if(rxStatus != HAL_OK)
 {
printf("RX ERROR\r\n");
 }
 else
 {
uint8_t rxId = rxData[3];
uint8_t rxLen = rxData[4];
uint8_t rxErr = rxData[5];
uint8_t rxChecksum = rxData[6];
if(rxChecksum != checksum)
{
  printf("CHECKSUM ERROR: received %x vs sent %x\r\n", rxChecksum, checksum);
}
for(int i = 0; i < 7; i++)
{
  printf("rxData[%i] == %x\r\n", i, rxData[i]);
}
 }

 printf("\r\n\r\n");

}

 

P.P.P.S. Целиковый проект, на всякий случай:

TestUART.rar

Edited by IgorKossak
[codebox] для длинного кода, [code] - для короткого!!!

Share this post


Link to post
Share on other sites

Возможно, скажу глупость, но попробую высказаться.

Как раз недавно занялся новым проектом на stm32. Решил, что стоит попробовать работать с HAL.

В сети куча описаний, как работать с контроллером прерываний, куча примеров под STL, значительно меньше примеров с HAL. В даташите и в книжках написано, что нужно обязательно сбрасывать флаг прерывания при инициализации. В примерах с STL это свято выполняется, даже все коментарии указывают, что вот именно здесь мы сбрасываем флаги прерываний.

В примерах с HAL такого нет! Я был уверен, что сброс флагов происходит где-то внутри хитрозакрученных макросов (там чёрт ногу сломит, что и как делается). Но выяснилось, что в примерах посто решили не сбрасывать флаги прерываний.

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

 

P.S. Админам и гуру: если мои мысли не верны - удаляйте.

Share this post


Link to post
Share on other sites
Возможно, что у Вас тот же случай - прерывание срабатывает до того, как что-то пришло.

 

Дык, это, я же вроде никаких прерываний не устанавливаю, а просто пишу и читаю в блокирующем режиме? Или там внутри эти прерывания всё равно дёргаются, и вектор прерываний таки надо сбросить?

 

<навостряет уши>

Share this post


Link to post
Share on other sites
Дык, это, я же вроде никаких прерываний не устанавливаю, а просто пишу и читаю в блокирующем режиме? Или там внутри эти прерывания всё равно дёргаются, и вектор прерываний таки надо сбросить?

 

<навостряет уши>

Применительно к моему высказыванию задам дополнительный вопрос - у Вас ВСЕГДА прилетает лишний FF, или только после инициализации?

Share this post


Link to post
Share on other sites
Применительно к моему высказыванию задам дополнительный вопрос - у Вас ВСЕГДА прилетает лишний FF, или только после инициализации?

 

А что вы имеете в виду под инициализацией?

 

Я должен закомментировать HAL_HalfDuplexInit(&huart5) — или чего что?

Share this post


Link to post
Share on other sites
А что вы имеете в виду под инициализацией?

 

Я должен закомментировать HAL_HalfDuplexInit(&huart5) — или чего что?

Я имею ввиду другое. Если прилетает несколько посылок, то лишний байт есть всегда? Или только после рестарта системы? Если всегда, то нужно копать глубже. Если только после рестарта/инициализации - то Вы на пути к флагам.

Share this post


Link to post
Share on other sites
Я имею ввиду другое. Если прилетает несколько посылок, то лишний байт есть всегда? Или только после рестарта системы? Если всегда, то нужно копать глубже. Если только после рестарта/инициализации - то Вы на пути к флагам.

 

Увы, всегда. Я проделывал PingServo в цикле, и каждый раз было то же самое.

Share this post


Link to post
Share on other sites

Я вот на осциллограму глянул, и по ней похоже, что у Вас там стоит какой-то чип шины типа RS-485: там такая полочка в самом начале перед, якобы, первым стартовым битом (в нуль), словно кто-то из третьего состояния в активное "1" выходит. Может быть там-таки есть подальше слева, за кадром, нулевой импульс, который воспринимается как стартовый (это всего-то 1мкс на ваших 1Mbit), после чего идет IDLE, которое воспринимается как 0xFF. В момент, например, когда чип шины пассивируется ПОСЛЕ передачи и ПЕРЕД приемом при полудуплексе. Вы бы осциллограмму зафиксировали от начала передачи до конца приема...

 

Share this post


Link to post
Share on other sites
Дык, это, я же вроде никаких прерываний не устанавливаю, а просто пишу и читаю в блокирующем режиме? Или там внутри эти прерывания всё равно дёргаются, и вектор прерываний таки надо сбросить?

Я не смотрел реализации, Но если у вас би директ, то необходимо после передачи, переходить на приём. Соответственно это запрещение/ разрешение прерываний, возможно ещё что-то. Не работал с би директом.

Поэтому перед приёмом флаги надо сбрасывать. Это просто очевидно, на мой взгляд.

С таким простым устройством как UART работать через HAL, только дополнительные трудности, а не упрощение. На мой взгляд.

Share this post


Link to post
Share on other sites

Полные осциллограммы тоже сохранял. Вот, держите.

T0000CH1.rar

 

Но там небольшое повышение уровня сигнала (та самая полочка) возникает именно перед тем, как моя серва начинает передавать данные. И возникает из-за того, что она тоже включает какие-то свои пулл-апы, подтягивая сигнал к 5В.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this