Пробую впервые организовать обмен через USART1 между двумя устройствами, одно из которых MASTER, другое SLAVE.
MASTER передает SLAVE'у 1 раз в 5 секунд следующий пакет: IDLE, некоторое кол-во байт, BREAK.
Сижу j-link'ом на приемнике слейва и вижу как этот пакет успешно принимается, но проблема в том, что определить начало приема пакета и прием BREAK (конец пакета) не получается - флаги IDLE и FE в USART->SR не устанавливаются. Из-за этого правильно переинициализировать счетчик принятых байтов невозможно и принять правильно очередной пакет соответственно невозможно.
Вот часть кода обработчика прерываний от USART1, ответственная за прием:
Код
/********************************** ПРИЕМ *************************************/
// обнаружен IDLE ( начало нового пакета )
if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET){
Usart.RxCnt = 0;// сброс счетчика принятых байтов
}
// обнаружен BREAK
if(USART_GetITStatus(USART1,USART_IT_FE) != RESET){
Usart.RxCnt = 0;// сброс счетчика принятых байтов
// проверка целостности
if (RxBuf[1] != LOCALE_RS_ADR)return;// не мой пакет
else{// проверка CRC
unsigned int i,crc;
CRC_ResetDR();
for(i=0;i<RxBuf[0]-4;i++){CRC->DR = (unsigned int)RxBuf[i];}// CRC
crc = *(unsigned int*)RxBuf[RxBuf[0]-4];
if (CRC->DR != crc)return;// ошибка CRC
else BITSET(Usart.Status,PackReady);
}
}
// получен байт
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET){
unsigned char RxData;
RxData = USART_ReceiveData(USART1);// чтение байта данных
// запись байта данных в буфер
if (Usart.RxCnt <= RxBufSize-1){
RxBuf[Usart.RxCnt] = RxData;Usart.RxCnt++;
}else Usart.RxCnt = 0;// сброс счетчика принятых байтов
}
/******************************************************************************/
// обнаружен IDLE ( начало нового пакета )
if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET){
Usart.RxCnt = 0;// сброс счетчика принятых байтов
}
// обнаружен BREAK
if(USART_GetITStatus(USART1,USART_IT_FE) != RESET){
Usart.RxCnt = 0;// сброс счетчика принятых байтов
// проверка целостности
if (RxBuf[1] != LOCALE_RS_ADR)return;// не мой пакет
else{// проверка CRC
unsigned int i,crc;
CRC_ResetDR();
for(i=0;i<RxBuf[0]-4;i++){CRC->DR = (unsigned int)RxBuf[i];}// CRC
crc = *(unsigned int*)RxBuf[RxBuf[0]-4];
if (CRC->DR != crc)return;// ошибка CRC
else BITSET(Usart.Status,PackReady);
}
}
// получен байт
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET){
unsigned char RxData;
RxData = USART_ReceiveData(USART1);// чтение байта данных
// запись байта данных в буфер
if (Usart.RxCnt <= RxBufSize-1){
RxBuf[Usart.RxCnt] = RxData;Usart.RxCnt++;
}else Usart.RxCnt = 0;// сброс счетчика принятых байтов
}
/******************************************************************************/
Что-то здесь не так с анализом флагов? Дальнейшее изучение показало, что библиотечными функциями типа USART_GetITStatus можно проанализировать только один флаг при приеме очередного байта, остальные флаги, так необходимые для анализа правильности приема, сбрасываются!!!! Т. е. один раз прочитал USART1->SR с помощью USART_GetITStatus и пипец, все биты (PE,ORE,FE,IDLE) сбросились! Вопрос - нафига так сделано? И почему библиотеки написаны соотв образом? В обработчике было бы корректно прочитать ВЕСЬ регистр USART1->SR в самом начале и потом уже разбираться с его содержимым... но я не уверен что все здесь правильно понимаю...
Упростил ПО, теперь MASTER каждые 5 сек шлет только BREAK, а я пытаюсь его ловить слейвом. Теперь по входу в обработчик видно, что в USART1->SR устанавливаются биты FE,IDLE,LBD,TXE,TC. Т.е. все правильно: детектится и IDLE и framing error как и должно. Все это подтверждает вышесказанное... Остается вопрос - как же все-таки правильно организовать обработчик прерывания?