Цитата(Dejmos @ Mar 20 2012, 14:31)

Что-то такое вспоминается, хотя давно это было. Попробуйте проверять флаги через USART_GetFlagStatus, а GetITStatus при проверке на RXNE перед чтением.
Совершенно верно! Я потратил три дня на разборки с USART в STM32 и теперь написал обработчик уверенно, который работает! В кратце, проблема в том, что некоторые биты в USART->SR многофункциональны и используются по разному в разных режимах. И библиотеки написаны так, что GetITStatus можно использовать только в определенных режимах, иначе нужно биты обрабатывать через GetFlagStatus да еще многие и "под эгидой" RXNE.
Но... Осталась непонятная проблема. Попробую объяснить, если кто-то захочет обсудить...
Есть два девайса, общаются по RS-485 (ADM485 на обоих). Управление прием/передача по одному проводу, т. е. либо прием, либо передача. Софт написан примитивный для скорости 9600. Этапы общения:
1. Мастер шлет пакет слэйву, например: 0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01.
2. Слэйв успешно его принимает и отправляет подтверждение 0x05,0x04,0x03,0x02,0x01.
3. Мастер это подтверждение принимает без ошибок, если слэйв отправляет это подтверждение с задержкой более 4-5мс относительно приема от мастера.
4. Если слэйв отправляет сразу же, то приходит: 0x05,0x04,0x05,0x04,0x03,0x02,0x01.
5. Если скорость USART увеличить с 9600 до 115200 - все работает нормально.
При этом обработчик одинаковый в обоих устройствах!!!
Вчера сидел целый день, никак не вкурю как так может быть, что слэйв реально отправляет 5 байт, а мастер получает 7 ??? И почему такая зависимость от задержки ответа? J-link'ом смотрел счетчик передаваемых/принимаемых байтов - так и есть, слэйв отправляет 5, мастер принимает 7. Не понимаю... Вот обработчик приема/передачи:
Код
// USART1 прием/передача пакетов
void USART1_IRQHandler(void){
/********************************** ПРИЕМ *************************************/
if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET){// линия RX свободна
USART_ReceiveData(USART1);// сброс PE,FE,NE,ORE,IDLE bits in USART_SR
Usart.RsCnt = 0;
}
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET){// получен некий байт
if(USART_GetFlagStatus(USART1,USART_FLAG_ORE) != RESET){// overrun
USART_ReceiveData(USART1);// сброс PE,FE,NE,ORE,IDLE bits in USART_SR
Usart.RsCnt = 0;
}else
if(USART_GetFlagStatus(USART1,USART_FLAG_NE) != RESET){// шум
USART_ReceiveData(USART1);// сброс PE,FE,NE,ORE,IDLE bits in USART_SR
Usart.RsCnt = 0;
}else
if (USART_GetFlagStatus(USART1,USART_FLAG_FE) != RESET){// конец пакета
USART_ReceiveData(USART1);// сброс PE,FE,NE,ORE,IDLE bits in USART_SR
Usart.RsCnt = 0;// сброс счетчика принятых байтов
if (RsBuf[1] == LOCALE_RS_ADR)// мой пакет
BITSET(Usart.Status,PackReady);
}else{// сохранение данных в буфере
RsBuf[Usart.RsCnt++] = USART_ReceiveData(USART1);
if (Usart.RsCnt >= RsBufSize)Usart.RsCnt = 0;
}
}
/********************************** ПЕРЕДАЧА **********************************/
if(USART_GetITStatus(USART1,USART_IT_TXE) != RESET){// передача байта
if (Usart.RsCnt < RsBuf[0]){// передача байта данных
USART_SendData(USART1,RsBuf[Usart.RsCnt++]);
}else{// конец пакета
USART_SendBreak(USART1);// признак конца пакета
USART_ITConfig(USART1,USART_IT_TXE,DISABLE);
USART_ITConfig(USART1,USART_IT_TC,ENABLE);
}
}
if(USART_GetITStatus(USART1,USART_IT_TC) != RESET){// передача завершена
PINCLR(RTX);// разрешить прием
Usart.RsCnt = 0;
USART_ITConfig(USART1,USART_IT_TC,DISABLE);
}
/******************************************************************************/
}